Background:
When I was developing a mutli-monitor application based on XULRunner to work, I found that you simply could not predict where the window manager will place the windows launched after the first launch of your main application / browser window.
XULRunner correctly gave me:
- geometry (width, height) for full screen display
- window position for this window on a display with multiple monitors
- Window status (MAXIMIZED, MINIMIZED, none) for this window
- the ability to (not) maximize the window
He didnβt really respect the geometry of several monitors when I set a set of window coordinates that would place the window on a specific monitor (rather, the window manager placed a new window wherever he liked).
This left me with the task of somehow doing the following:
- The location of the window relative to the display with multiple monitors and
(since moving the window sometimes lost window focus) - Window focusing.
I managed to achieve both using an external DLL loaded / used by js-ctypes.
Example for Win32:
The following are the basics for linking an external DLL to JavaScript. This example only applies to Win32, but I also did it for Linux and for MacOSX (which were simpler and more complicated than Win32).
There are 3 parts:
- Preferred JavaScript code for loading / binding Win32 API
- CPP header file for our external dll
- Source CPP file for our external dll
I create a simple GUI DLL project with the later two files and compile wmctrl.dll , depending on msvcr100.dll , and use Dependency Walker to find the "plain C" characters exported by the DLL for using js-ctypes.
I also created a JavaScript library around the APIs that allowed me to manipulate, track, and maintain the window state / geometry for multiple windows over several application launches, but this has little to do with this simple example.
In privileged JavaScript code:
// get js-ctypes, you do this part a bit differently from browser chrome const {Cc,Ci,Cu} = require("chrome"); var file=null, lib=null, ctypes = {}; Cu.import("resource://gre/modules/ctypes.jsm", ctypes); var ctypes = ctypes.ctypes; // build platform specific library path var filename = ctypes.libraryName("wmctrl"); var comp = "@mozilla.org/file/directory_service;1"; var file = Cc[comp].getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile); file.append("browser_code"); 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); // wmctrl_window_move: takes unsigned 32bit (long) "window handle", // and two (x & y) signed 32bit ints. var window_move = lib.declare(" ?wmctrl_window_move@ @ YAXKHH@Z ", ctypes.stdcall_abi, ctypes.void_t, ctypes.uint32_t, ctypes.int32_t, ctypes.int32_t);
wmctrldll.h
#ifdef WMCTRLDLL_EXPORTS #define WMCTRLDLL_API __declspec(dllexport) #else #define WMCTRLDLL_API __declspec(dllimport) #endif WMCTRLDLL_API void wmctrl_window_focus (unsigned long wid); WMCTRLDLL_API void wmctrl_window_move (unsigned long wid, int x, int y); WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title);
wmctrldll.cpp
#include "stdafx.h" #include "wmctrldll.h" typedef struct { HWND hWnd; char title[255]; } myWinSpec; BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) { char String[255]; myWinSpec* to_find = (myWinSpec*) lParam;