user1256960
user1256960

Reputation: 303

xul:panel position on multiple monitors

I have a xul:panel on my firefox extension. I give the position to display acording to screen.width and screen.height. My problem appears when I have multiple monitors and I start the browser on the first monitor, it appears on the second one and the xul:panel is drawn according to the first screen's resolution on the second one. Is there a solution to draw according to the second screen's resolution?

Upvotes: 2

Views: 410

Answers (1)

David-SkyMesh
David-SkyMesh

Reputation: 5171

Background:

When I was developing a mutli-monitor application based on XULRunner for work, I found that you just couldn't predict where the window manager would place windows launched after the initial launch of your main application/browser window.

XULRunner did correctly give me:

  • geometry (width, height) for the full multi-monitor display
  • window position for the given window on the multi-monitor display
  • window state (MAXIMIZED, MINIMIZED, neither) for the given window
  • the ability to (un-)maximize a window

It did not correctly respect multi-monitor geometry when I specified a set of window coordinates that would have placed the window on a specific monitor (rather the window manager placed the new window wherever it pleased).

That left me with the task of somehow doing the following:

  • Positioning the window with respect to the multi-monitor display, and
    (because moving the window would sometimes lose window focus)
  • Focusing the window.

I was able to achieve both with the help of an external DLL loaded/used by js-ctypes.


Example for Win32:

Here's are the basics for binding the external DLL to JavaScript. This example only covers Win32, but I also did this for Linux and for MacOSX (which were easier & harder respectively compared to Win32).

There are 3 parts:

  1. The privileged JavaScript code to load/bind the Win32 APIs
  2. The CPP header file for our external DLL
  3. The CPP source file for our external DLL

I build a simple GUI DLL project with the later two files & compiled wmctrl.dll, depending on msvcr100.dll, and used Dependency Walker to find the "plain C" symbols exported by the DLL for use by js-ctypes.

I also built a JavaScript library around the APIs which allowed to manipulate, track & persist window state/geometry for multiple windows over multiple runs of the application, but that's not really relevant to 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;

  // 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;
}

WMCTRLDLL_API void wmctrl_window_move(unsigned long wid, int x, int y) {
  UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE;

  SetForegroundWindow((HWND) wid);
  SetWindowPos((HWND) wid, HWND_NOTOPMOST, x, y, NULL, NULL, flags);
}

Upvotes: 2

Related Questions