我正在我的 firefox 插件中寻找一个解决方案来检测用户工作区何时被锁定/释放。在 google chrome 中有一个简单的 API chrome.idle.onStateChanged.addListener
,firefox 中是否有类似的东西或者是否有可能做到这一点,独立于平台?
对了,我用的是addon sdk。
我已经尝试过空闲服务:
Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService)
但我只是让我在进入休眠状态时访问一些空闲超时或系统,而不仅仅是锁定工作区。
编辑:“工作区锁定”是指用户使用 ctrl + alt + delete 锁定工作区。我不知道这在 OSX 或 Linux 上究竟是如何工作的。
Edit2:我目前在 Windows 8.1 中工作,但我猜 chrome.idle
处理程序可以跨平台工作。
Edit3:我目前从当前答案中得到的是
1. chrome 和 firefox 都没有跨平台解决方案。
chrome.idle.onStateChanged
似乎在 windows、linux 和 osx 上工作不同。只有 Windows 可以按预期处理该“锁定”行为。我无法测试 OSX,在 ubuntu 14 上它对我不起作用。
2. 对于 firefox,有一些深入的代码可以尝试使其正常工作 - 请参阅本主题中 Noitidart 的以下回答。
Edit4:Noitidart 找到了适用于 Windows 的解决方案 - github link .
最佳答案
我不知道如何检测屏幕锁定,但有这些观察者通知:
https://developer.mozilla.org/en-US/docs/Observer_Notifications#Idle_Service
还有计算机 sleep 唤醒通知。我会四处询问锁定屏幕,这很有趣。
关于这个主题的一些有用的聊天,看看谷歌浏览器是如何做到的:
[12:33] ok guys question about actual work. anyone know how to detect if screen was locked? apparently google chrome has a method: https://developer.chrome.com/extensions/idle#event-onStateChanged
[12:45] anyone know of a MXR or DXR for google chromes codebase?
[12:46] mxr.mozilla.org/chromium
[12:52] Ms2ger: can you help me find how they test screen lock. im looking here: http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_api_unittest.cc#84
[12:56] oh yuck it looks like they poll: http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.h#118
也许他们没有投票。
检查一下:
http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.cc#246
244 void IdleManager::UpdateIdleStateCallback(int idle_time) {
245 DCHECK(thread_checker_.CalledOnValidThread());
246 bool locked = idle_time_provider_->CheckIdleStateIsLocked();
247 int listener_count = 0;
导致:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#52
52 bool CheckIdleStateIsLocked() {
53 return ui::IsWorkstationLocked() || IsScreensaverRunning();
54 }
因此这导致我们测试屏幕保护程序是否正在运行或工作站是否已锁定
导致:
http://mxr.mozilla.org/chromium/search?string=IsWorkstationLocked
我们只看到一个实现(这很好奇,因为没有 linux 支持,但在 chrome 文档页面上没有这样说,所以我可能找不到它)
window
http://mxr.mozilla.org/chromium/source/src/ui/base/win/lock_state.cc#11
11 bool IsWorkstationLocked() { 12 bool is_locked = true; 13 HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ); 14 if (input_desk) { 15 wchar_t name[256] = {0}; 16 DWORD needed = 0; 17 if (::GetUserObjectInformation( 18 input_desk, UOI_NAME, name, sizeof(name), &needed)) { 19 is_locked = lstrcmpi(name, L"default") != 0; 20 } 21 ::CloseDesktop(input_desk); 22 } 23 return is_locked; 24 }
- 麦克
- 请参阅下面的屏幕保护程序部分,屏幕锁定也是通过那里处理的
http://mxr.mozilla.org/chromium/search?string=IsScreensaverRunning&find=&findi=&filter= ^%5B^\0%5D*%24&hitlimit=&tree= Chrome
我们在这个搜索结果中看到 2 个实现,mac 和 windows 它看起来不支持 linux,这很好奇,因为 chrome.idle 页面没有在文档上提到这个,也许我只是找不到它
windows 实现:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#39
39 bool IsScreensaverRunning() { 40 DWORD result = 0; 41 if (::SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &result, 0)) 42 return result != FALSE; 43 return false; 44 } 45
mac 实现:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_mac.mm#28
28 - (id)init { 29 if ((self = [super init])) { 30 NSDistributedNotificationCenter* distCenter = 31 [NSDistributedNotificationCenter defaultCenter]; 32 [distCenter addObserver:self 33 selector:@selector(onScreenSaverStarted:) 34 name:@"com.apple.screensaver.didstart" 35 object:nil]; 36 [distCenter addObserver:self 37 selector:@selector(onScreenSaverStopped:) 38 name:@"com.apple.screensaver.didstop" 39 object:nil]; 40 [distCenter addObserver:self 41 selector:@selector(onScreenLocked:) 42 name:@"com.apple.screenIsLocked" 43 object:nil]; 44 [distCenter addObserver:self 45 selector:@selector(onScreenUnlocked:) 46 name:@"com.apple.screenIsUnlocked" 47 object:nil]; 48 } 49 return self; 50 }
总结一下:
[13:32] for windows its peice of cake winapi has call to test if screen is locked or scrensaver running
[13:32] for mac they dont have screen lock test. they just have screensaver test, but its an observer method
[13:32] for linux they dont have screen lock nor screen saver test. real odd. ill ask the guy if he knows which os's they support chrome.idle in
编辑:实际上我找到了 linux 实现。从以下搜索结果返回:CheckIdleStateLocked
:http://mxr.mozilla.org/chromium/search?string=CheckIdleStateIsLocked
http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_linux.cc#24
24 bool CheckIdleStateIsLocked() { 25 // Usually the screensaver is used to lock the screen, so we do not need to 26 // check if the workstation is locked. 27 #if defined(OS_CHROMEOS) 28 return false; 29 #elif defined(USE_OZONE) 30 return false; 31 #else 32 return ScreensaverWindowFinder::ScreensaverWindowExists(); 33 #endif 34 }
导致问
ScreensaverWindowExists
我们怎么找到这个:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc15 bool ScreensaverWindowFinder::ScreensaverWindowExists() { 16 gfx::X11ErrorTracker err_tracker; 17 ScreensaverWindowFinder finder; 18 ui::EnumerateTopLevelWindows(&finder); 19 return finder.exists_ && !err_tracker.FoundNewError(); 20 }
导致什么是
EnumerateTopLevelWindows
http://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#1059 :1059 void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) { 1060 std::vector<XID> stack; 1061 if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) { 1062 // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back 1063 // to old school enumeration of all X windows. Some WMs parent 'top-level' 1064 // windows in unnamed actual top-level windows (ion WM), so extend the 1065 // search depth to all children of top-level windows. 1066 const int kMaxSearchDepth = 1; 1067 ui::EnumerateAllWindows(delegate, kMaxSearchDepth); 1068 return; 1069 } 1070 XMenuList::GetInstance()->InsertMenuWindowXIDs(&stack); 1071 1072 std::vector<XID>::iterator iter; 1073 for (iter = stack.begin(); iter != stack.end(); iter++) { 1074 if (delegate->ShouldStopIterating(*iter)) 1075 return; 1076 } 1077 } 1078
我们说他们调用了
delegate->ShouldStopIterating
,它与ScreensaverWindowExists
在同一文件中看到:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc22 bool ScreensaverWindowFinder::ShouldStopIterating(XID window) { 23 if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window)) 24 return false; 25 exists_ = true; 26 return true; 27 }
导问什么是
IsWindowVisible
和IsScreensaverWindow
*IsScreensaverWindow
,在 ScreensaverWindowExists
的同一文件中:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
29 bool ScreensaverWindowFinder::IsScreensaverWindow(XID window) const {
30 // It should occupy the full screen.
31 if (!ui::IsX11WindowFullScreen(window))
32 return false;
33
34 // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
35 if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
36 return true;
37
38 // For all others, like gnome-screensaver, the window's WM_CLASS property
39 // should contain "screensaver".
40 std::string value;
41 if (!ui::GetStringProperty(window, "WM_CLASS", &value))
42 return false;
43
44 return value.find("screensaver") != std::string::npos;
45 }
IsWindowVisible
:http://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#546546 bool IsWindowVisible(XID window) { 547 TRACE_EVENT0("ui", "IsWindowVisible"); 548 549 XWindowAttributes win_attributes; 550 if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes)) 551 return false; 552 if (win_attributes.map_state != IsViewable) 553 return false; 554 555 // Minimized windows are not visible. 556 std::vector<XAtom> wm_states; 557 if (GetAtomArrayProperty(window, "_NET_WM_STATE", &wm_states)) { 558 XAtom hidden_atom = GetAtom("_NET_WM_STATE_HIDDEN"); 559 if (std::find(wm_states.begin(), wm_states.end(), hidden_atom) != 560 wm_states.end()) { 561 return false; 562 } 563 }
关于Firefox 扩展/插件 - 检测工作区已锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27377686/