【问题标题】:xul:panel position on multiple monitorsxul:多台显示器上的面板位置
【发布时间】:2012-04-09 07:56:08
【问题描述】:

我的 Firefox 扩展上有一个 xul:panel。我根据screen.width和screen.height给出显示的位置。当我有多个显示器并且我在第一台显示器上启动浏览器时出现我的问题,它出现在第二台显示器上,并且 xul:panel 是根据第二台显示器上的第一个屏幕的分辨率绘制的。有没有办法根据第二屏的分辨率画图?

【问题讨论】:

  • 实际上是一团糟!我不得不暂停基于 XULRunner 的应用程序的开发来处理窗口管理。我最终直接从js-ctypes 使用了 Win32 或 X11 api(取决于平台)。基本上,我会快速更改窗口的标题以通过窗口枚举从 C++ 代码中识别它,然后将其设置回原始标题并保留对已识别窗口的引用,以供以后从我通过@987654322 向 JavaScript 公开的 API 中使用@.
  • 不确定 XULJet 是否有任何改进,或者这是否适用于 Firefox 扩展。
  • 我会写一个答案,但也许有人可以使用纯 JavaScript 解决方案:-)
  • 好的,这是相当多的代码和解释:-/ 希望能帮助您入门,或者有人找到更简单的独立于平台的方法。

标签: javascript firefox xul


【解决方案1】:

背景:

当我为工作开发基于 XULRunner 的多监视器应用程序时,我发现您无法预测窗口管理器会将在您的主应用程序/浏览器窗口初始启动后启动的窗口放置在哪里。

XULRunner 确实正确地给了我:

  • 完整的多显示器显示的几何形状(宽度、高度)
  • 多显示器上给定窗口的窗口位置
  • 给定窗口的窗口状态(MAXIMIZED、MINIMIZED,两者都不是)
  • 能够(不)最大化窗口

当我指定一组窗口坐标以将窗口放置在特定监视器上时(而是窗口管理器将新窗口放置在任何它喜欢的位置)时,它没有正确遵守多监视器几何形状。

这让我不得不以某种方式完成以下任务:

  • 相对于多显示器显示定位窗口,以及
    (因为移动窗口有时会失去窗口焦点)
  • 聚焦窗口。

借助 js-ctypes 加载/使用的外部 DLL,我能够实现这两个目标。


Win32 示例:

以下是将外部 DLL 绑定到 JavaScript 的基础知识。此示例仅涵盖 Win32,但我也针对 Linux 和 MacOSX 进行了此操作(与 Win32 相比,它们分别更容易和更难)。

有3个部分:

  1. 加载/绑定 Win32 API 的特权 JavaScript 代码
  2. 外部 DLL 的 CPP 头文件
  3. 我们的外部 DLL 的 CPP 源文件

我用后面的两个文件构建了一个简单的GUI DLL项目并编译了wmctrl.dll,依赖于msvcr100.dll,并使用Dependency Walker找到了DLL导出的“纯C”符号供js-ctypes使用.

我还围绕 API 构建了一个 JavaScript 库,它允许在应用程序的多次运行中为多个窗口操作、跟踪和持久化窗口状态/几何,但这与这个简单的示例并不真正相关。

在特权 JavaScript 代码中:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多