This seems like another question I answered: xul: panel position on multiple monitors
I was able to achieve what you want using the external DLL loaded / used by js-ctypes. To control the focus of the window at the OS level, you will need to do two things:
- find the Firefox window of interest (
find_window javascript function below) and - focus the window (
window_focus below).
I found the easiest way to find a window handle to change the window title to something predictive that will not conflict with other window titles (say, sum MD5 "your-app"+(new Date()) ) and then list everything OS level windows looks for a window with this title ( find_window ).
Once you have a window handle, you can call window_focus (defined below) to focus the OS level window.
Example for Win32:
The following are the basics for linking an external DLL to JavaScript. This example covers only Win32, but the same process applies to everyone.
There are 3 parts:
- Preferred JavaScript code for loading / binding platform-specific (e.g. Win32) APIs
- CPP header file for our external dll
- Source CPP file for our external dll
I am creating a simple GUI DLL project in VS2010 with the later two files and compiled wmctrl.dll, depending on msvcr100.dll, and used Dependency Walker to find the "plain C" characters exported by the DLL for using js-ctypes.
In privileged JavaScript code (for example: in your addon code):
// import js-ctypes const {Cc,Ci,Cu} = require("chrome"); // you probably don't need this line. var file=null, lib=null, ctypes = {}; Cu.import("resource://gre/modules/ctypes.jsm", ctypes); var ctypes = ctypes.ctypes; // build platform specific library path (yours will be named/located differently) var filename = ctypes.libraryName("wmctrl"); var comp = "@mozilla.org/file/directory_service;1"; // read the docs for this!!! var file = Cc[comp].getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile); file.append("browser_code"); // a sub-folder file.append(filename); // get the JavaScript library interface (load the library) var lib = ctypes.open(file.path); // wmctrl_find_window: returing unsigned 32bit (long) "window handle" // takes string "window title". var find_window = lib.declare(" ?wmctrl_find_window@ @ YAKPAD@Z ", ctypes.stdcall_abi, ctypes.uint32_t, ctypes.char.ptr); // wmctrl_window_focus: takes unsigned 32bit (long) "window handle". var window_focus = lib.declare(" ?wmctrl_window_focus@ @ YAXK@Z ", ctypes.stdcall_abi, ctypes.void_t, ctypes.uint32_t);
wmctrldll.h
#ifdef WMCTRLDLL_EXPORTS #define WMCTRLDLL_API __declspec(dllexport) #else #define WMCTRLDLL_API __declspec(dllimport) #endif WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title); WMCTRLDLL_API void wmctrl_window_focus (unsigned long wid);
wmctrldll.cpp
typedef struct { HWND hWnd; char title[255]; } myWinSpec; BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) { char String[255]; myWinSpec* to_find = (myWinSpec*) lParam; // not a window if (!hWnd) return TRUE; // not visible if (!IsWindowVisible(hWnd)) return TRUE; // no window title if (!GetWindowTextA(hWnd, (LPSTR)String, 255)) return TRUE; // no title match if (strcmp(String, to_find->title) != 0) return TRUE; to_find->hWnd = hWnd; return FALSE; } WMCTRLDLL_API void wmctrl_window_focus(unsigned long wid) { SetForegroundWindow((HWND) wid); } WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title) { myWinSpec to_find; sprintf_s(to_find.title, sizeof(to_find.title), "%s", find_title); to_find.hWnd = 0; EnumWindows(EnumWindowsProc, (LPARAM)&to_find); return (unsigned long) to_find.hWnd; }
I also did this for Linux (X11) and Mac OS X without much difficulty.