Closed
Bug 1168090
Opened 10 years ago
Closed 7 years ago
Screensaver inhibition fails
Categories
(Core :: Widget: Gtk, defect, P3)
Tracking
()
RESOLVED
DUPLICATE
of bug 1398539
Tracking | Status | |
---|---|---|
firefox41 | --- | affected |
People
(Reporter: stransky, Unassigned)
References
Details
(Whiteboard: tpi:+)
Attachments
(1 file, 3 obsolete files)
8.34 KB,
patch
|
karlt
:
feedback+
|
Details | Diff | Splinter Review |
Follow up from Bug 811261
Reporter | ||
Comment 1•10 years ago
|
||
Can you please install some dbus inspection utility (d-feet for instance) and check that your desktop provides dbus interfaces "org.freedesktop.ScreenSaver" or "org.gnome.SessionManager"? Because only those two are reflected.
For instance MATE provides only org.mate.ScreenSaver which is not covered by Firefox.
Flags: needinfo?(electrovalent)
Reporter | ||
Updated•10 years ago
|
Severity: enhancement → normal
Reporter | ||
Comment 2•10 years ago
|
||
Note - look at "SessionBus" interface.
Comment 3•10 years ago
|
||
In latest debian testing with xfce i can only see org.xfce.SessionManager dbus interface instead.
Flags: needinfo?(electrovalent)
Reporter | ||
Comment 4•10 years ago
|
||
Well, that's the problem then. Xfce should provide the universal org.freedesktop.ScreenSaver interface (see http://people.freedesktop.org/~hadess/idle-inhibition-spec/re01.html).
Reporter | ||
Comment 5•10 years ago
|
||
FYI you can get the list by this command:
dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep ScreenSaver
would be interested to see which interfaces are provided by other WM like KDE, Cinamon and so on.
Reporter | ||
Comment 6•10 years ago
|
||
I see on Fedora (21,22) those interfaces:
Gtk3/gnome-shell: org.freedesktop.ScreenSaver, org.gnome.ScreenSaver
KDE: org.freedesktop.ScreenSaver
MATE: org.mate.ScreenSaver
Comment 7•10 years ago
|
||
Freedesktop.org provides xdg-utils to handle screensaver. Both xfce and VLC without being the only one, are following this standard. It is the reason why VLC is able to disable both screensaver and power management when enters fullscreen. Is there a reason why Firefox doesn't follow this paradigm? If there is a solution why searching for a new one?
Comment 8•10 years ago
|
||
Firefox could use xdg-screensaver as a fallback when the dbus method is not supported.
Reporter | ||
Updated•10 years ago
|
Assignee: stransky → nobody
Comment 9•9 years ago
|
||
--- Work in progress ---
In this patch I added support for screensaver inhibition for Mate and as fallback I added xdg-screensaver which is invoked periodically every 60 seconds using nsTimer.
I could not think of a way to determine whether xdg-screensaver utility is available on system before creating the timer in XDG SendInhibit() method - maybe check it using system("xdg-screensaver") but that does not feel like a proper solution to me. So right now the xdg-screensaver utility presence is checked in the timer callback.
What do you think, Mike ?
Attachment #8668352 -
Flags: feedback?(mh+mozilla)
Comment 10•9 years ago
|
||
How likely is xdg-screensaver to be on the user system but not in /usr/bin? I'd just hardcode /usr/bin/xdg-screensaver.
Note you should use nsIProcess instead of execlp.
Updated•9 years ago
|
Attachment #8668352 -
Flags: feedback?(mh+mozilla)
Comment 11•9 years ago
|
||
Thanks for the feedback, Mike.
I updated the patch. Before creating a timer it now searches for /usr/bin/xdg-screensaver, if it does not exist, it returns and does not create the timer.
The timer callback now uses nsIProcess run asynchronously instead of execlp.
What do you think ?
Attachment #8668352 -
Attachment is obsolete: true
Attachment #8669606 -
Flags: feedback?(mh+mozilla)
Comment 12•9 years ago
|
||
Comment on attachment 8669606 [details] [diff] [review]
002_screen_saver.patch
Review of attachment 8669606 [details] [diff] [review]:
-----------------------------------------------------------------
At quick glance, that looks reasonable, but that should be reviewed by karlt. Note you have plenty of spurious whitespaces in this patch.
Attachment #8669606 -
Flags: feedback?(mh+mozilla)
Comment 13•9 years ago
|
||
Removed excessive white spaces
Try:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=2e8f59dda765
Attachment #8669606 -
Attachment is obsolete: true
Attachment #8671215 -
Flags: review?(karlt)
Updated•9 years ago
|
Component: Video/Audio Controls → Widget: Gtk
Product: Toolkit → Core
Comment 14•9 years ago
|
||
Comment on attachment 8671215 [details] [diff] [review]
003_screen_saver.patch
Using the "reset" command of xdg-screensaver works around the worst of the
xdg-screensaver shortcomings [1], and hopefully testing for the freedesktop
interface first avoids others such as shared state files.
No new usage of nsIProcess should be added at least until bug 678369 is fixed
(see also [2] [3] [4]), but it is not necessary to use nsIProcess
here. g_spawn_async() is a nice helper that catches errors in launching the
child process. It is not "COM"taminated [5], it doesn't suffer from [4]
AFAICS, and it even handles ECHILD from waitpid() if NSPR steals the child.
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=811261#c83
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=227246
[3] https://bugzilla.mozilla.org/show_bug.cgi?id=933680#c44
[4] https://bugzilla.mozilla.org/show_bug.cgi?id=705543#c13
[5] https://wiki.mozilla.org/Gecko:De_COMtamination
>+ , mTimer(nullptr)
No need for this as nsCOMPtr<> has a default constructor.
> bool mWaitingForReply;
>+
>+ nsCOMPtr<nsITimer> mTimer;
Move mTimer declaration to alongside other pointers (mConnection) for packing.
>+WakeLockTopic::SendMateInhibitMessage()
This looks like the same code as SendGNOMEInhibitMessage(), presumably because
it is the same interface, but with different names.
If so, please use the existing SendGNOMEInhibitMessage() function, and create
the method call with different names according to mDesktopEnvironment.
>+ if (self->GetShouldInhibit()) {
Is this method required?
If the timer is cancelling correctly, then shouldn't it always return true
here?
>+ const char* args[] = {"reset"};
This command parameter seems to do what is necessary, but it is not clear from
the documentation:
reset
Turns the screensaver off immediately. If the screen was locked the
user may be asked to authenticate first.
Please describe the effect this code is depending on here.
>+bool WakeLockTopic::SendXDGInhibitMessage()
>+{
>+ // Check if xdg-screensaver utility is available
>+ nsresult rv;
>+ bool exists;
>+ nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
>+ file->InitWithNativePath(NS_LITERAL_CSTRING(XDG_SCREENSAVER_PATH));
>+ rv = file->Exists(&exists);
>+ if (!exists || NS_FAILED(rv)) {
>+ return false;
>+ }
With g_spawn_async(), there will be no need to test for file existence as the
function will return an error if it does not exist.
>+ if (mTimer) {
>+ return true;
>+ }
>+
>+ if (mTimer) {
>+ mTimer->InitWithFuncCallback(XDGScreenSaverReset,
>+ this,
>+ XDG_SCREEN_SAVER_RESET_INTERVAL,
>+ nsITimer::TYPE_REPEATING_SLACK);
>+ }
>+ else {
>+ return false;
>+ }
>+}
Missing return value on success, but returning true sets mWaitingForReply,
which means UninhibitScreensaver() always returns early.
Perhaps this method doesn't need a return value.
If SendXDGInhibitMessage merely starts a timer, then it could be better named
to indicate that. It could alternatively spawn the first xdg command and set
the timer on success.
>+ if (mTimer) {
>+ mTimer->Cancel();
>+ mTimer = nullptr;
>+ mInhibitRequest = 0;
Is there a need to reset mInhibitRequest here?
InhibitSucceeded() has not been called to set it and it won't be used anyway.
>+ return true;
>+ }
> }
>+
>
> if (!message) {
> return false;
> }
Return true early even when !mTimer for consistency as SendUninhibit() may be
called more than once. (The return value is not used, but if these methods
have return values then they should be sane.)
> case Unsupported:
> return false;
"Unsupported" can't be reached now.
Attachment #8671215 -
Flags: review?(karlt)
Attachment #8671215 -
Flags: review-
Attachment #8671215 -
Flags: feedback+
Comment 15•9 years ago
|
||
Thank you for your feedback, Karl.
I updated the patch, what do you think ?
Attachment #8671215 -
Attachment is obsolete: true
Attachment #8683645 -
Flags: feedback?(karlt)
Comment 16•9 years ago
|
||
Comment on attachment 8683645 [details] [diff] [review]
004_screen_saver.patch
>+#define XDG_SCREENSAVER_RESET "/usr/bin/xdg-screensaver reset"
Now that g_spawn_async() reports errors when exec fails and the file existence
test has been removed, the full path need not be provided.
Use only the executable name without the full path and G_SPAWN_SEARCH_PATH, to allow a user to provide their own version of the command, if required.
>+ bool SendMateInhibitMessage();
No longer defined/required.
>+ }
>+ else {
Gecko uses "} else {" (except in some old code).
>+WakeLockTopic::XDGScreenSaverReset(nsITimer* aTimer, void* aWakeLockTopic)
Please rename aWakeLockTopic to indicate that it is not used.
I don't know for sure, but I expect this will compile:
WakeLockTopic::XDGScreenSaverReset(nsITimer* aTimer, void*)
>+{
>+ gchar** command;
>+ g_shell_parse_argv(XDG_SCREENSAVER_RESET, nullptr, &command, nullptr);
>+ g_spawn_async(nullptr,
>+ command,
>+ nullptr,
>+ G_SPAWN_DEFAULT,
>+ nullptr,
>+ nullptr,
>+ nullptr,
>+ nullptr);
Either free command appropriately or construct command on the stack, so that
the heap allocations are not required and there is no need to free. See, for
example,
https://dxr.mozilla.org/mozilla-central/rev/e790bba372f14241addda469a4bdb7ab00786ab3/dom/ipc/ContentChild.cpp#629
Please place this in a helper function, so that it can be shared with
CreateXDGResetTimer.
>+ if (mTimer) {
>+ mTimer->InitWithFuncCallback(XDGScreenSaverReset,
>+ NULL,
>+ XDG_SCREEN_SAVER_RESET_INTERVAL,
>+ nsITimer::TYPE_REPEATING_SLACK);
>+ return true;
>+ }
>+ else {
>+ return false;
>+ }
>+ }
>+ else {
>+ return false;
>+ }
>+}
No need for the two else and return paths.
Use a single "return false" at the end of the function with no else.
>+ case Mate:
> sendOk = SendGNOMEInhibitMessage();
> break;
>+ case Other:
>+ sendOk = CreateXDGResetTimer();
>+ break;
> }
>
> if (sendOk) {
> mWaitingForReply = true;
> }
CreateXDGResetTimer returning true sets mWaitingForReply,
which means UninhibitScreensaver() always returns early.
Instead always return early in the Other case.
>+ } else if (mDesktopEnvironment == Other) {
>+ // xdg-screensaver does not use dbus
>+ if (mTimer) {
>+ mTimer->Cancel();
>+ mTimer = nullptr;
>+ return true;
>+ }
> }
>+
>
Return early (with true) when (mDesktopEnvironment == Other) even when !mTimer
for consistency as SendUninhibit() may be called more than once. (The return
value is not used, but if these methods have return values then they should be
sane.)
> if (!message) {
>- return false;
>+ return true;
> }
>
> dbus_message_append_args(message,
Leave this returning false, to indicate an error.
Attachment #8683645 -
Flags: feedback?(karlt) → feedback+
Comment 17•8 years ago
|
||
Martin,
Xfce developer here. Just a couple of notes and an idea to fix screensaver inhibition on Xfce and possibly elsewhere.
Firstly we can't support the screensaver DBus interface because our users use multiple lockers / screensavers alongside Xfce which may or may not implement it themselves. This is already a delicate situation for us as we have to do dirty things to figure out which locker is in use, and it would be generally a poor idea to enter a competition with these lockers for an interface we don't even use.
What we do support however is the FreeDesktop Power Management interface (org.freedesktop.powermanagement). I'm not sure if it has been standardised or if someone just forgot to upload an API documentation, but you can see the API here:
http://git.xfce.org/xfce/xfce4-power-manager/tree/src/org.freedesktop.PowerManagement.xml
and
http://git.xfce.org/xfce/xfce4-power-manager/tree/src/org.freedesktop.PowerManagement.Inhibit.xml
Now, using this API also triggers the presentation mode in Xfce, which prevents the screen dimming or going black. We think it's a nicer approach than simply managing lockers, and this is why in Xfce it's the power manager's job to call the locker when the session is inactive for long enough (because most users would have their screen dim before or at the same time as the session locks, rather than after).
Messaging this interface alongside the existing ScreenSaver interface would solve the screensaver inhibition problem as the Xfce power manager would both keep the screen on and prevent the locker from kicking in.
As far as I know this interface is also used by KDE so it could also inhibit screen dimming on KDE.
Would that be an option for Firefox?
Comment 18•8 years ago
|
||
Very basic setup which exhibits this behaviour:
- Up-to-date Arch Linux with Firefox 48, slock-1.3, xss-lock 0.3.0.
- X profile like in <https://github.com/l0b0/tilde/blob/c0e34f86b3893e0815fea4afe3af7f545228d4ee/.xprofile#L59>.
- `xset q` reports "prefer blanking: yes allow exposures: yes" and "timeout: 600 cycle: 600"
Using this setup VLC is able to inhibit the screensaver but Firefox is not.
Updated•8 years ago
|
Priority: -- → P3
Whiteboard: tpi:+
Comment 19•8 years ago
|
||
When implementing a fix for this, please use a single generic solution which will work for any and all desktop environments which use the X server.
Example: the mpv video player (https://mpv.io/) runs on every linux desktop environment AFAIK, and has a single method to disable/enable the screensaver. They don't have to use case statements to check if you're on Gnome or KDE or XFCE or MATE or ...
mpv uses XScreenSaverSuspend (X11/extensions/scrnsaver.h) and DPMSEnable/DPMSDisable (X11/extensions/dpms.h).
Here are details on XScreenSaverSuspend and DPMSEnable/DPMSDisable:
https://www.x.org/archive/current/doc/man/man3/Xss.3.xhtml
https://www.x.org/archive/current/doc/man/man3/DPMSEnable.3.xhtml
https://www.x.org/archive/current/doc/man/man3/DPMSDisable.3.xhtml
Here is a link to the code where mpv implements their screensaver:
https://github.com/mpv-player/mpv/blob/master/video/out/x11_common.c
Here is a code snippet from mpv's x11_common.c:
.....
static int xss_suspend(Display *mDisplay, Bool suspend)
{
#if !HAVE_XSS
return 0;
#else
int event, error, major, minor;
if (XScreenSaverQueryExtension(mDisplay, &event, &error) != True ||
XScreenSaverQueryVersion(mDisplay, &major, &minor) != True)
return 0;
if (major < 1 || (major == 1 && minor < 1))
return 0;
XScreenSaverSuspend(mDisplay, suspend);
return 1;
#endif
}
static void set_screensaver(struct vo_x11_state *x11, bool enabled)
{
Display *mDisplay = x11->display;
if (!mDisplay || x11->screensaver_enabled == enabled)
return;
MP_VERBOSE(x11, "%s screensaver.\n", enabled ? "Enabling" : "Disabling");
x11->screensaver_enabled = enabled;
if (xss_suspend(mDisplay, !enabled))
return;
#if HAVE_XEXT
int nothing;
if (DPMSQueryExtension(mDisplay, ¬hing, ¬hing)) {
BOOL onoff = 0;
CARD16 state;
DPMSInfo(mDisplay, &state, &onoff);
if (!x11->dpms_touched && enabled)
return; // enable DPMS only we we disabled it before
if (enabled != !!onoff) {
MP_VERBOSE(x11, "Setting DMPS: %s.\n", enabled ? "on" : "off");
if (enabled) {
DPMSEnable(mDisplay);
} else {
DPMSDisable(mDisplay);
x11->dpms_touched = true;
}
DPMSInfo(mDisplay, &state, &onoff);
if (enabled != !!onoff)
MP_WARN(x11, "DPMS state could not be set.\n");
}
}
#endif
}
.....
Comment 20•8 years ago
|
||
Hello,
In WakeLockListener.cpp, there is the line:
#define FREEDESKTOP_SCREENSAVER_OBJECT "/ScreenSaver"
Is this line correct?
The specification in https://people.freedesktop.org/~hadess/idle-inhibition-spec/index.html does not specify an object path. However, in all dbus examples dealing with org.freedesktop.ScreenSaver, the path I saw was "/ScreenSaver", not "/ScreenSaver".
Comment 21•8 years ago
|
||
> the path I saw was "/ScreenSaver", not "/ScreenSaver".
... the path I saw was "/org/freedesktop/ScreenSaver", not "/ScreenSaver".
Reporter | ||
Comment 22•8 years ago
|
||
Thanks, I'll look at it.
Comment 25•7 years ago
|
||
Here is Chromium implementation:
https://chromium.googlesource.com/chromium/src/+/master/services/device/wake_lock/power_save_blocker/power_save_blocker_x11.cc
It works fine on XFCE. The API from Comment 17 is used in addition to GNOME's one.
Comment 26•7 years ago
|
||
The chromium implementation also works with my setup (Arch Linux + i3) while the solution that firefox uses does not work. I'd love to switch back from chromium to firefox but this is a blocker for me, so I'd be really happy if this issue saw some attention.
Comment 27•7 years ago
|
||
johannes.loher, could you try Firefox nightly? I recently added XScreenSaver support which may fix the issue with your setup.
Comment 28•7 years ago
|
||
Lee, I have a similar setup as johannes.loher's, with xss-lock running i3locker on Arch Linux. The issue seems to be fixed in Firefox nightly for me. I tested this by playing a YouTube video both fullscreen and not. Do you need any other tests?
Comment 29•7 years ago
|
||
Those tests are enough. It fixed my setup too. Is anyone else still experiencing this issue, or should it be marked as resolved?
Comment 30•7 years ago
|
||
Lee, I tested it with Firefox nightly and the issue indeed seems to be fixed on my system. Thank you very much for working on this!
Comment 31•7 years ago
|
||
I am using Mozilla Firefox 52.5.3 in openSUSE Leap 42.3 and GNOME 3.20.
The problem is not fully fixed. GNOME still needs to disable power management, otherwise the system may go to sleep or hibernate.
Here is a work around for GNOME:
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type nothing
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type nothing
Maybe this problem could be considered as a GNOME problem not correctly implementing Idle Inhibition Service Draft.
Reporter | ||
Comment 32•7 years ago
|
||
(In reply to Stanislav Brabec from comment #31)
> I am using Mozilla Firefox 52.5.3 in openSUSE Leap 42.3 and GNOME 3.20.
>
> The problem is not fully fixed. GNOME still needs to disable power
> management, otherwise the system may go to sleep or hibernate.
>
> Here is a work around for GNOME:
>
> gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type
> nothing
> gsettings set org.gnome.settings-daemon.plugins.power
> sleep-inactive-battery-type nothing
>
> Maybe this problem could be considered as a GNOME problem not correctly
> implementing Idle Inhibition Service Draft.
That's because Bug 1398539 was fixed for Firefox 58.
Flags: needinfo?(jhorak)
Reporter | ||
Updated•7 years ago
|
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → DUPLICATE
You need to log in
before you can comment on or make changes to this bug.
Description
•