是否有可能使我的firefox扩展获得关注其他程序?

时间:2012-11-20 17:21:38

标签: javascript firefox window focus

我正在开发一个firefox扩展,我需要关注其他程序。 window.focus()仅适用于其他firefox窗口。这可能吗?

1 个答案:

答案 0 :(得分:0)

这与我在这里回答的另一个问题类似:xul:panel position on multiple monitors

在js-ctypes加载/使用的外部DLL的帮助下,我能够实现你想要的。为了操纵OS级别的窗口焦点,您需要能够做两件事:

  • 找到有问题的Firefox窗口(下面是find_window javascript函数),
  • 关注窗口(下面的window_focus功能)。

我发现找到窗口句柄的最简单方法是将窗口标题更改为可预测的不会与其他窗口标题冲突的内容(比如MD5总和为"your-app"+(new Date())),然后枚举所有操作系统 - 级别窗口查找具有该标题的窗口(find_window)。

一旦有了窗口句柄,就可以调用window_focus(在下面定义)来聚焦操作系统级窗口。


Win32示例:

以下是将外部DLL绑定到JavaScript的基础知识。此示例仅涵盖Win32,但每个都适用相同的过程。

共有3个部分:

  • 加载/绑定特定于平台(即:Win32)API的特权JavaScript代码
  • 外部DLL的CPP头文件
  • 外部DLL的CPP源文件

我在VS2010中构建了一个简单的GUI DLL项目,后面有两个文件&编译wmctrl.dll,具体取决于msvcr100.dll,并使用Dependency Walker查找DLL导出的“plain C”符号,供js-ctypes使用。

在特权JavaScript代码中(例如:在您的插件代码中):

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

我也为Linux(X11)和Mac OS X做了这个,没有太多困难。