Bug 1587360 - Add support for idle-inhibit Wayland protocol r=stransky

The idle-inhibit protocol allows idle wake locks on Wayland
without any of the supported D-Bus interfaces running.

Differential Revision: https://phabricator.services.mozilla.com/D49095

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Greg V 2020-01-06 16:11:19 +00:00
parent 179fa09dcb
commit 97c5686fd7
8 changed files with 392 additions and 3 deletions

View File

@ -16,6 +16,12 @@
# include "prlink.h"
# endif
# if defined(MOZ_WAYLAND)
# include "mozilla/widget/nsWaylandDisplay.h"
# include "nsWindow.h"
# include "mozilla/dom/power/PowerManagerService.h"
# endif
# define FREEDESKTOP_SCREENSAVER_TARGET "org.freedesktop.ScreenSaver"
# define FREEDESKTOP_SCREENSAVER_OBJECT "/ScreenSaver"
# define FREEDESKTOP_SCREENSAVER_INTERFACE "org.freedesktop.ScreenSaver"
@ -37,6 +43,9 @@ enum DesktopEnvironment {
GNOME,
# if defined(MOZ_X11)
XScreenSaver,
# endif
# if defined(MOZ_WAYLAND)
WaylandIdleInhibit,
# endif
Unsupported,
};
@ -44,12 +53,17 @@ enum DesktopEnvironment {
class WakeLockTopic {
public:
WakeLockTopic(const nsAString& aTopic, DBusConnection* aConnection)
: mTopic(NS_ConvertUTF16toUTF8(aTopic)),
:
# if defined(MOZ_WAYLAND)
mWaylandInhibitor(nullptr),
# endif
mTopic(NS_ConvertUTF16toUTF8(aTopic)),
mConnection(aConnection),
mDesktopEnvironment(FreeDesktop),
mInhibitRequest(0),
mShouldInhibit(false),
mWaitingForReply(false) {}
mWaitingForReply(false) {
}
nsresult InhibitScreensaver(void);
nsresult UninhibitScreensaver(void);
@ -67,6 +81,13 @@ class WakeLockTopic {
static bool InhibitXScreenSaver(bool inhibit);
# endif
# if defined(MOZ_WAYLAND)
zwp_idle_inhibitor_v1* mWaylandInhibitor;
static bool CheckWaylandIdleInhibitSupport();
bool InhibitWaylandIdle();
bool UninhibitWaylandIdle();
# endif
static void ReceiveInhibitReply(DBusPendingCall* aPending, void* aUserData);
void InhibitFailed();
void InhibitSucceeded(uint32_t aInhibitRequest);
@ -197,6 +218,49 @@ bool WakeLockTopic::InhibitXScreenSaver(bool inhibit) {
# endif
# if defined(MOZ_WAYLAND)
/* static */
bool WakeLockTopic::CheckWaylandIdleInhibitSupport() {
GdkDisplay* gDisplay = gdk_display_get_default();
if (GDK_IS_X11_DISPLAY(gDisplay)) return false;
widget::nsWaylandDisplay* waylandDisplay =
widget::WaylandDisplayGet(gDisplay);
if (!waylandDisplay->GetIdleInhibitManager()) return false;
return true;
}
bool WakeLockTopic::InhibitWaylandIdle() {
GdkDisplay* gDisplay = gdk_display_get_default();
widget::nsWaylandDisplay* waylandDisplay =
widget::WaylandDisplayGet(gDisplay);
nsWindow* focusedWindow = nsWindow::GetFocusedWindow();
if (!focusedWindow) return false;
UninhibitWaylandIdle();
mWaylandInhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(
waylandDisplay->GetIdleInhibitManager(),
focusedWindow->GetWaylandSurface());
return true;
}
bool WakeLockTopic::UninhibitWaylandIdle() {
if (mWaylandInhibitor == nullptr) return false;
zwp_idle_inhibitor_v1_destroy(mWaylandInhibitor);
mWaylandInhibitor = nullptr;
return true;
}
# endif
bool WakeLockTopic::SendInhibit() {
bool sendOk = false;
@ -210,6 +274,10 @@ bool WakeLockTopic::SendInhibit() {
# if defined(MOZ_X11)
case XScreenSaver:
return InhibitXScreenSaver(true);
# endif
# if defined(MOZ_WAYLAND)
case WaylandIdleInhibit:
return InhibitWaylandIdle();
# endif
case Unsupported:
return false;
@ -239,6 +307,11 @@ bool WakeLockTopic::SendUninhibit() {
return InhibitXScreenSaver(false);
}
# endif
# if defined(MOZ_WAYLAND)
else if (mDesktopEnvironment == WaylandIdleInhibit) {
return UninhibitWaylandIdle();
}
# endif
if (!message) {
return false;
@ -299,6 +372,10 @@ void WakeLockTopic::InhibitFailed() {
# if defined(MOZ_X11)
} else if (mDesktopEnvironment == GNOME && CheckXScreenSaverSupport()) {
mDesktopEnvironment = XScreenSaver;
# endif
# if defined(MOZ_WAYLAND)
} else if (mDesktopEnvironment == GNOME && CheckWaylandIdleInhibitSupport()) {
mDesktopEnvironment = WaylandIdleInhibit;
# endif
} else {
mDesktopEnvironment = Unsupported;

View File

@ -147,6 +147,11 @@ void nsWaylandDisplay::SetPrimarySelectionDeviceManager(
mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager;
}
void nsWaylandDisplay::SetIdleInhibitManager(
zwp_idle_inhibit_manager_v1* aIdleInhibitManager) {
mIdleInhibitManager = aIdleInhibitManager;
}
void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf) {
mDmabuf = aDmabuf;
}
@ -238,6 +243,13 @@ static void global_registry_handler(void* data, wl_registry* registry,
wl_proxy_set_queue((struct wl_proxy*)primary_selection_device_manager,
display->GetEventQueue());
display->SetPrimarySelectionDeviceManager(primary_selection_device_manager);
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
auto idle_inhibit_manager =
static_cast<zwp_idle_inhibit_manager_v1*>(wl_registry_bind(
registry, id, &zwp_idle_inhibit_manager_v1_interface, 1));
wl_proxy_set_queue((struct wl_proxy*)idle_inhibit_manager,
display->GetEventQueue());
display->SetIdleInhibitManager(idle_inhibit_manager);
} else if (strcmp(interface, "wl_compositor") == 0) {
// Requested wl_compositor version 4 as we need wl_surface_damage_buffer().
auto compositor = static_cast<wl_compositor*>(
@ -388,6 +400,7 @@ nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
mShm(nullptr),
mSyncCallback(nullptr),
mPrimarySelectionDeviceManager(nullptr),
mIdleInhibitManager(nullptr),
mRegistry(nullptr),
mDmabuf(nullptr),
mGbmDevice(nullptr),

View File

@ -10,6 +10,7 @@
#include "mozilla/widget/mozwayland.h"
#include "mozilla/widget/gtk-primary-selection-client-protocol.h"
#include "mozilla/widget/idle-inhibit-unstable-v1-client-protocol.h"
#include "base/message_loop.h" // for MessageLoop
#include "base/task.h" // for NewRunnableMethod, etc
@ -59,6 +60,9 @@ class nsWaylandDisplay {
gtk_primary_selection_device_manager* GetPrimarySelectionDeviceManager(void) {
return mPrimarySelectionDeviceManager;
};
zwp_idle_inhibit_manager_v1* GetIdleInhibitManager(void) {
return mIdleInhibitManager;
}
void SetShm(wl_shm* aShm);
void SetCompositor(wl_compositor* aCompositor);
@ -67,6 +71,7 @@ class nsWaylandDisplay {
void SetSeat(wl_seat* aSeat);
void SetPrimarySelectionDeviceManager(
gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager);
void SetIdleInhibitManager(zwp_idle_inhibit_manager_v1* aIdleInhibitManager);
void Shutdown();
@ -101,6 +106,7 @@ class nsWaylandDisplay {
wl_shm* mShm;
wl_callback* mSyncCallback;
gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager;
zwp_idle_inhibit_manager_v1* mIdleInhibitManager;
wl_registry* mRegistry;
zwp_linux_dmabuf_v1* mDmabuf;
gbm_device* mGbmDevice;

View File

@ -7736,4 +7736,6 @@ void nsWindow::SetEGLNativeWindowSize(
aEGLWindowSize.height);
}
}
nsWindow* nsWindow::GetFocusedWindow() { return gFocusWindow; }
#endif

View File

@ -230,6 +230,7 @@ class nsWindow final : public nsBaseWidget {
#ifdef MOZ_WAYLAND
void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
static nsWindow* GetFocusedWindow();
#endif
RefPtr<mozilla::gfx::VsyncSource> GetVsyncSource() override;

View File

@ -0,0 +1,228 @@
/* Generated by wayland-scanner 1.16.0 */
#ifndef IDLE_INHIBIT_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define IDLE_INHIBIT_UNSTABLE_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_idle_inhibit_unstable_v1 The idle_inhibit_unstable_v1 protocol
* @section page_ifaces_idle_inhibit_unstable_v1 Interfaces
* - @subpage page_iface_zwp_idle_inhibit_manager_v1 - control behavior when
* display idles
* - @subpage page_iface_zwp_idle_inhibitor_v1 - context object for inhibiting
* idle behavior
* @section page_copyright_idle_inhibit_unstable_v1 Copyright
* <pre>
*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* </pre>
*/
struct wl_surface;
struct zwp_idle_inhibit_manager_v1;
struct zwp_idle_inhibitor_v1;
/**
* @page page_iface_zwp_idle_inhibit_manager_v1 zwp_idle_inhibit_manager_v1
* @section page_iface_zwp_idle_inhibit_manager_v1_desc Description
*
* This interface permits inhibiting the idle behavior such as screen
* blanking, locking, and screensaving. The client binds the idle manager
* globally, then creates idle-inhibitor objects for each surface.
*
* Warning! The protocol described in this file is experimental and
* backward incompatible changes may be made. Backward compatible changes
* may be added together with the corresponding interface version bump.
* Backward incompatible changes are done by bumping the version number in
* the protocol and interface names and resetting the interface version.
* Once the protocol is to be declared stable, the 'z' prefix and the
* version number in the protocol and interface names are removed and the
* interface version number is reset.
* @section page_iface_zwp_idle_inhibit_manager_v1_api API
* See @ref iface_zwp_idle_inhibit_manager_v1.
*/
/**
* @defgroup iface_zwp_idle_inhibit_manager_v1 The zwp_idle_inhibit_manager_v1
* interface
*
* This interface permits inhibiting the idle behavior such as screen
* blanking, locking, and screensaving. The client binds the idle manager
* globally, then creates idle-inhibitor objects for each surface.
*
* Warning! The protocol described in this file is experimental and
* backward incompatible changes may be made. Backward compatible changes
* may be added together with the corresponding interface version bump.
* Backward incompatible changes are done by bumping the version number in
* the protocol and interface names and resetting the interface version.
* Once the protocol is to be declared stable, the 'z' prefix and the
* version number in the protocol and interface names are removed and the
* interface version number is reset.
*/
extern const struct wl_interface zwp_idle_inhibit_manager_v1_interface;
/**
* @page page_iface_zwp_idle_inhibitor_v1 zwp_idle_inhibitor_v1
* @section page_iface_zwp_idle_inhibitor_v1_desc Description
*
* An idle inhibitor prevents the output that the associated surface is
* visible on from being set to a state where it is not visually usable due
* to lack of user interaction (e.g. blanked, dimmed, locked, set to power
* save, etc.) Any screensaver processes are also blocked from displaying.
*
* If the surface is destroyed, unmapped, becomes occluded, loses
* visibility, or otherwise becomes not visually relevant for the user, the
* idle inhibitor will not be honored by the compositor; if the surface
* subsequently regains visibility the inhibitor takes effect once again.
* Likewise, the inhibitor isn't honored if the system was already idled at
* the time the inhibitor was established, although if the system later
* de-idles and re-idles the inhibitor will take effect.
* @section page_iface_zwp_idle_inhibitor_v1_api API
* See @ref iface_zwp_idle_inhibitor_v1.
*/
/**
* @defgroup iface_zwp_idle_inhibitor_v1 The zwp_idle_inhibitor_v1 interface
*
* An idle inhibitor prevents the output that the associated surface is
* visible on from being set to a state where it is not visually usable due
* to lack of user interaction (e.g. blanked, dimmed, locked, set to power
* save, etc.) Any screensaver processes are also blocked from displaying.
*
* If the surface is destroyed, unmapped, becomes occluded, loses
* visibility, or otherwise becomes not visually relevant for the user, the
* idle inhibitor will not be honored by the compositor; if the surface
* subsequently regains visibility the inhibitor takes effect once again.
* Likewise, the inhibitor isn't honored if the system was already idled at
* the time the inhibitor was established, although if the system later
* de-idles and re-idles the inhibitor will take effect.
*/
extern const struct wl_interface zwp_idle_inhibitor_v1_interface;
#define ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY 0
#define ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR 1
/**
* @ingroup iface_zwp_idle_inhibit_manager_v1
*/
#define ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zwp_idle_inhibit_manager_v1
*/
#define ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR_SINCE_VERSION 1
/** @ingroup iface_zwp_idle_inhibit_manager_v1 */
static inline void zwp_idle_inhibit_manager_v1_set_user_data(
struct zwp_idle_inhibit_manager_v1* zwp_idle_inhibit_manager_v1,
void* user_data) {
wl_proxy_set_user_data((struct wl_proxy*)zwp_idle_inhibit_manager_v1,
user_data);
}
/** @ingroup iface_zwp_idle_inhibit_manager_v1 */
static inline void* zwp_idle_inhibit_manager_v1_get_user_data(
struct zwp_idle_inhibit_manager_v1* zwp_idle_inhibit_manager_v1) {
return wl_proxy_get_user_data((struct wl_proxy*)zwp_idle_inhibit_manager_v1);
}
static inline uint32_t zwp_idle_inhibit_manager_v1_get_version(
struct zwp_idle_inhibit_manager_v1* zwp_idle_inhibit_manager_v1) {
return wl_proxy_get_version((struct wl_proxy*)zwp_idle_inhibit_manager_v1);
}
/**
* @ingroup iface_zwp_idle_inhibit_manager_v1
*
* Destroy the inhibit manager.
*/
static inline void zwp_idle_inhibit_manager_v1_destroy(
struct zwp_idle_inhibit_manager_v1* zwp_idle_inhibit_manager_v1) {
wl_proxy_marshal((struct wl_proxy*)zwp_idle_inhibit_manager_v1,
ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY);
wl_proxy_destroy((struct wl_proxy*)zwp_idle_inhibit_manager_v1);
}
/**
* @ingroup iface_zwp_idle_inhibit_manager_v1
*
* Create a new inhibitor object associated with the given surface.
*/
static inline struct zwp_idle_inhibitor_v1*
zwp_idle_inhibit_manager_v1_create_inhibitor(
struct zwp_idle_inhibit_manager_v1* zwp_idle_inhibit_manager_v1,
struct wl_surface* surface) {
struct wl_proxy* id;
id = wl_proxy_marshal_constructor(
(struct wl_proxy*)zwp_idle_inhibit_manager_v1,
ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR,
&zwp_idle_inhibitor_v1_interface, NULL, surface);
return (struct zwp_idle_inhibitor_v1*)id;
}
#define ZWP_IDLE_INHIBITOR_V1_DESTROY 0
/**
* @ingroup iface_zwp_idle_inhibitor_v1
*/
#define ZWP_IDLE_INHIBITOR_V1_DESTROY_SINCE_VERSION 1
/** @ingroup iface_zwp_idle_inhibitor_v1 */
static inline void zwp_idle_inhibitor_v1_set_user_data(
struct zwp_idle_inhibitor_v1* zwp_idle_inhibitor_v1, void* user_data) {
wl_proxy_set_user_data((struct wl_proxy*)zwp_idle_inhibitor_v1, user_data);
}
/** @ingroup iface_zwp_idle_inhibitor_v1 */
static inline void* zwp_idle_inhibitor_v1_get_user_data(
struct zwp_idle_inhibitor_v1* zwp_idle_inhibitor_v1) {
return wl_proxy_get_user_data((struct wl_proxy*)zwp_idle_inhibitor_v1);
}
static inline uint32_t zwp_idle_inhibitor_v1_get_version(
struct zwp_idle_inhibitor_v1* zwp_idle_inhibitor_v1) {
return wl_proxy_get_version((struct wl_proxy*)zwp_idle_inhibitor_v1);
}
/**
* @ingroup iface_zwp_idle_inhibitor_v1
*
* Remove the inhibitor effect from the associated wl_surface.
*/
static inline void zwp_idle_inhibitor_v1_destroy(
struct zwp_idle_inhibitor_v1* zwp_idle_inhibitor_v1) {
wl_proxy_marshal((struct wl_proxy*)zwp_idle_inhibitor_v1,
ZWP_IDLE_INHIBITOR_V1_DESTROY);
wl_proxy_destroy((struct wl_proxy*)zwp_idle_inhibitor_v1);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,60 @@
/* Generated by wayland-scanner 1.16.0 */
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
#endif
#pragma GCC visibility push(default)
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface zwp_idle_inhibitor_v1_interface;
#pragma GCC visibility pop
static const struct wl_interface* types[] = {
&zwp_idle_inhibitor_v1_interface,
&wl_surface_interface,
};
static const struct wl_message zwp_idle_inhibit_manager_v1_requests[] = {
{"destroy", "", types + 0},
{"create_inhibitor", "no", types + 0},
};
const struct wl_interface zwp_idle_inhibit_manager_v1_interface = {
"zwp_idle_inhibit_manager_v1", 1, 2,
zwp_idle_inhibit_manager_v1_requests, 0, NULL,
};
static const struct wl_message zwp_idle_inhibitor_v1_requests[] = {
{"destroy", "", types + 0},
};
const struct wl_interface zwp_idle_inhibitor_v1_interface = {
"zwp_idle_inhibitor_v1", 1, 1, zwp_idle_inhibitor_v1_requests, 0, NULL,
};

View File

@ -9,13 +9,15 @@ with Files("**"):
SOURCES += [
'gtk-primary-selection-protocol.c',
'idle-inhibit-unstable-v1-protocol.c',
'linux-dmabuf-unstable-v1-protocol.c'
]
EXPORTS.mozilla.widget += [
'gbm.h',
'gtk-primary-selection-client-protocol.h',
'linux-dmabuf-unstable-v1-client-protocol.h',
'idle-inhibit-unstable-v1-client-protocol.h',
'linux-dmabuf-unstable-v1-client-protocol.h'
]
include('/ipc/chromium/chromium-config.mozbuild')