diff --git a/widget/gtk/WakeLockListener.cpp b/widget/gtk/WakeLockListener.cpp index d93ca51718da..6d468cf72844 100644 --- a/widget/gtk/WakeLockListener.cpp +++ b/widget/gtk/WakeLockListener.cpp @@ -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; diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp index ccd68ddff478..fad5cff5184a 100644 --- a/widget/gtk/nsWaylandDisplay.cpp +++ b/widget/gtk/nsWaylandDisplay.cpp @@ -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(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( @@ -388,6 +400,7 @@ nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay) mShm(nullptr), mSyncCallback(nullptr), mPrimarySelectionDeviceManager(nullptr), + mIdleInhibitManager(nullptr), mRegistry(nullptr), mDmabuf(nullptr), mGbmDevice(nullptr), diff --git a/widget/gtk/nsWaylandDisplay.h b/widget/gtk/nsWaylandDisplay.h index 936d26444fff..bdab12f4dba5 100644 --- a/widget/gtk/nsWaylandDisplay.h +++ b/widget/gtk/nsWaylandDisplay.h @@ -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; diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 89748404988c..2fb1b6f7ed3e 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -7736,4 +7736,6 @@ void nsWindow::SetEGLNativeWindowSize( aEGLWindowSize.height); } } + +nsWindow* nsWindow::GetFocusedWindow() { return gFocusWindow; } #endif diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 3c70cb46f853..01ea534e7e24 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -230,6 +230,7 @@ class nsWindow final : public nsBaseWidget { #ifdef MOZ_WAYLAND void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize); + static nsWindow* GetFocusedWindow(); #endif RefPtr GetVsyncSource() override; diff --git a/widget/gtk/wayland/idle-inhibit-unstable-v1-client-protocol.h b/widget/gtk/wayland/idle-inhibit-unstable-v1-client-protocol.h new file mode 100644 index 000000000000..3ae2303b3cb3 --- /dev/null +++ b/widget/gtk/wayland/idle-inhibit-unstable-v1-client-protocol.h @@ -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 +#include +#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 + *
+ *
+ * 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.
+ * 
+ */ +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 diff --git a/widget/gtk/wayland/idle-inhibit-unstable-v1-protocol.c b/widget/gtk/wayland/idle-inhibit-unstable-v1-protocol.c new file mode 100644 index 000000000000..579095e003f5 --- /dev/null +++ b/widget/gtk/wayland/idle-inhibit-unstable-v1-protocol.c @@ -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 +#include +#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, +}; diff --git a/widget/gtk/wayland/moz.build b/widget/gtk/wayland/moz.build index 2168eae1c673..7e175da0332e 100644 --- a/widget/gtk/wayland/moz.build +++ b/widget/gtk/wayland/moz.build @@ -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')