I'm searching for a solution in my firefox addon to detect when the user workspace has locked/released. In google chrome there is an easy API chrome.idle.onStateChanged.addListener
for it, is there something similar in firefox or any possibility to do that, platform independent?
By the way, I use the addon sdk.
I've already tried the idle service:
Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService)
but I just gives me access to some idle timeout or system when go to sleep and not to just workspace locked.
Edit: With "workspace locked" I mean the user lock the workspace with ctrl + alt + delete. I don't know how this exactly work on OSX or linux.
Edit2: I working in Windows 8.1 currently, but I guess the chrome.idle
handler works cross platform.
Edit3: What i currently get out of current answers is
1. That there not exist a cross-platform solution, neither in chrome nor in firefox.
chrome.idle.onStateChanged
seems to work different on windows, linux and osx. Only windows can handle that "locked" behaviour as expected. I can't test OSX, on ubuntu 14 it doesn't work for me.
2. For firefox there some in-depth code things to try to make it working - see answer bellow from Noitidart in this topic.
Edit4: Noitidart have found a solution for windows - github link.
I don't know how to detect screen lock but there are these observer notifications:
https://developer.mozilla.org/en-US/docs/Observer_Notifications#Idle_Service
Also the computer sleep wake notifications. ill ask around for lock screen thats an interesting one.
Some useful chat about the subject, looking at how google chrome does it:
[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
maybe they arent polling.
check this out:
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;
leads to: http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#52
52 bool CheckIdleStateIsLocked() {
53 return ui::IsWorkstationLocked() || IsScreensaverRunning();
54 }
so this leads us to test if screensaver running or workstation locked
leads to:
http://mxr.mozilla.org/chromium/search?string=IsWorkstationLocked
we see just one implementation (its curious because there is no linux support but it doesnt say so on the chrome docs page, so maybe i couldnt find it)
Windows
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=chromium
we see in this search results 2 implementations, mac and windows it looks like no support for linux, which is curious because the chrome.idle page doesnt mention this on docs, maybe i just couldnt find it
windows implementation: 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 implementation: 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 }
so to sum this all up:
[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
edit: actually i found the linux implementation. back from the search results of: 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 }
Leads to ask how is ScreensaverWindowExists
we find this: http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
15 bool ScreensaverWindowFinder::ScreensaverWindowExists() {
16 gfx::X11ErrorTracker err_tracker;
17 ScreensaverWindowFinder finder;
18 ui::EnumerateTopLevelWindows(&finder);
19 return finder.exists_ && !err_tracker.FoundNewError();
20 }
Leads to what is 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
We say they call delegate->ShouldStopIterating
which was seen in same file as ScreensaverWindowExists
: http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
22 bool ScreensaverWindowFinder::ShouldStopIterating(XID window) {
23 if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
24 return false;
25 exists_ = true;
26 return true;
27 }
Leads to ask what is IsWindowVisible
and IsScreensaverWindow
*IsScreensaverWindow
, in same file of 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#546
546 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 }