commit b6582225b9c8b9ae1446f2f3e0556322f6aac41c
parent 77f736a623f12eb22e6c92e595deff767ec626b1
Author: Martin Stransky <stransky@redhat.com>
Date: Thu, 23 Oct 2025 12:10:04 +0000
Bug 1665986 [Linux] Inhibit suspend when audio is playing on background r=alwu
Differential Revision: https://phabricator.services.mozilla.com/D268854
Diffstat:
2 files changed, 102 insertions(+), 49 deletions(-)
diff --git a/widget/gtk/WakeLockListener.cpp b/widget/gtk/WakeLockListener.cpp
@@ -36,6 +36,7 @@
# define FREEDESKTOP_PORTAL_DESKTOP_TARGET "org.freedesktop.portal.Desktop"
# define FREEDESKTOP_PORTAL_DESKTOP_OBJECT "/org/freedesktop/portal/desktop"
# define FREEDESKTOP_PORTAL_DESKTOP_INTERFACE "org.freedesktop.portal.Inhibit"
+# define FREEDESKTOP_PORTAL_DESKTOP_INHIBIT_SUSPEND_FLAG 4
# define FREEDESKTOP_PORTAL_DESKTOP_INHIBIT_IDLE_FLAG 8
# define FREEDESKTOP_SCREENSAVER_TARGET "org.freedesktop.ScreenSaver"
@@ -49,6 +50,8 @@
# define SESSION_MANAGER_TARGET "org.gnome.SessionManager"
# define SESSION_MANAGER_OBJECT "/org/gnome/SessionManager"
# define SESSION_MANAGER_INTERFACE "org.gnome.SessionManager"
+# define SESSION_MANAGER_INHIBIT_SUSPEND_FLAG 4
+# define SESSION_MANAGER_INHIBIT_IDLE_FLAG 8
# define DBUS_TIMEOUT (-1)
#endif
@@ -156,9 +159,11 @@ class WakeLockTopic {
public:
NS_INLINE_DECL_REFCOUNTING(WakeLockTopic)
- explicit WakeLockTopic(const nsAString& aTopic) {
+ WakeLockTopic(const nsAString& aTopic, bool aLockOnBackground)
+ : mLockOnBackground(aLockOnBackground) {
CopyUTF16toUTF8(aTopic, mTopic);
- WAKE_LOCK_LOG("WakeLockTopic::WakeLockTopic() created %s", mTopic.get());
+ WAKE_LOCK_LOG("WakeLockTopic::WakeLockTopic() created %s on background %d",
+ mTopic.get(), mLockOnBackground);
if (mTopic.Equals("video-playing")) {
nsCString videoPlayingString = []() -> nsCString {
auto string = GetLocalizedWakeLockString("WakeLockVideoPlaying");
@@ -178,7 +183,7 @@ class WakeLockTopic {
}();
mNiceTopic = audioPlayingString;
}
- if (sWakeLockType == Initial) {
+ if (GetWakeLockType() == Initial) {
InitializeWakeLockType();
}
}
@@ -279,10 +284,26 @@ class WakeLockTopic {
#endif
std::queue<WakeLockState> mStateQueue;
- static int sWakeLockType;
+
+ int GetWakeLockType() {
+ return mLockOnBackground ? sBackgroundWakeLockType
+ : sForegroundWakeLockType;
+ }
+ void SetWakeLockType(int aWakeLockType) {
+ if (mLockOnBackground) {
+ sBackgroundWakeLockType = aWakeLockType;
+ } else {
+ sForegroundWakeLockType = aWakeLockType;
+ }
+ }
+
+ const bool mLockOnBackground = false;
+ static int sForegroundWakeLockType;
+ static int sBackgroundWakeLockType;
};
-int WakeLockTopic::sWakeLockType = Initial;
+int WakeLockTopic::sForegroundWakeLockType = Initial;
+int WakeLockTopic::sBackgroundWakeLockType = Initial;
#ifdef MOZ_ENABLE_DBUS
void WakeLockTopic::DBusInhibitSucceeded(uint32_t aInhibitRequestID) {
@@ -329,7 +350,7 @@ void WakeLockTopic::DBusUninhibitFailed() {
// We're in inhibited state and we can't switch back.
// Let's try again but there isn't much to do.
if (--mUninhibitAttempts == 0) {
- sWakeLockType = Unsupported;
+ SetWakeLockType(Unsupported);
}
}
@@ -472,7 +493,8 @@ void WakeLockTopic::DBusUninhibitScreensaver(const char* aName,
}
void WakeLockTopic::InhibitFreeDesktopPortal() {
- WAKE_LOCK_LOG("WakeLockTopic::InhibitFreeDesktopPortal()");
+ WAKE_LOCK_LOG("WakeLockTopic::InhibitFreeDesktopPortal() background %d",
+ mLockOnBackground);
MOZ_DIAGNOSTIC_ASSERT(!mCancellable);
MOZ_DIAGNOSTIC_ASSERT(mState == WaitingToInhibit);
@@ -493,13 +515,16 @@ void WakeLockTopic::InhibitFreeDesktopPortal() {
g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add(&b, "{sv}", "reason",
g_variant_new_string(self->mNiceTopic.get()));
-
// From
// https://flatpak.github.io/xdg-desktop-portal/docs/#gdbus-org.freedesktop.portal.Inhibit
DBusProxyCall(
aProxy.get(), "Inhibit",
- g_variant_new("(sua{sv})", g_get_prgname(),
- FREEDESKTOP_PORTAL_DESKTOP_INHIBIT_IDLE_FLAG, &b),
+ g_variant_new(
+ "(sua{sv})", g_get_prgname(),
+ mLockOnBackground
+ ? FREEDESKTOP_PORTAL_DESKTOP_INHIBIT_SUSPEND_FLAG
+ : FREEDESKTOP_PORTAL_DESKTOP_INHIBIT_IDLE_FLAG,
+ &b),
G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, mCancellable)
->Then(
GetCurrentSerialEventTarget(), __func__,
@@ -540,6 +565,8 @@ void WakeLockTopic::InhibitFreeDesktopPortal() {
void WakeLockTopic::InhibitFreeDesktopScreensaver() {
WAKE_LOCK_LOG("InhibitFreeDesktopScreensaver()");
+ MOZ_DIAGNOSTIC_ASSERT(!mLockOnBackground,
+ "Background lock is not supported.");
DBusInhibitScreensaver(FREEDESKTOP_SCREENSAVER_TARGET,
FREEDESKTOP_SCREENSAVER_OBJECT,
FREEDESKTOP_SCREENSAVER_INTERFACE, "Inhibit",
@@ -549,6 +576,8 @@ void WakeLockTopic::InhibitFreeDesktopScreensaver() {
void WakeLockTopic::InhibitFreeDesktopPower() {
WAKE_LOCK_LOG("InhibitFreeDesktopPower()");
+ MOZ_DIAGNOSTIC_ASSERT(!mLockOnBackground,
+ "Background lock is not supported.");
DBusInhibitScreensaver(FREEDESKTOP_POWER_TARGET, FREEDESKTOP_POWER_OBJECT,
FREEDESKTOP_POWER_INTERFACE, "Inhibit",
dont_AddRef(g_variant_ref_sink(g_variant_new(
@@ -556,9 +585,11 @@ void WakeLockTopic::InhibitFreeDesktopPower() {
}
void WakeLockTopic::InhibitGNOME() {
- WAKE_LOCK_LOG("InhibitGNOME()");
+ WAKE_LOCK_LOG("InhibitGNOME() background %d", mLockOnBackground);
static const uint32_t xid = 0;
- static const uint32_t flags = (1 << 3); // Inhibit idle
+ static const uint32_t flags = mLockOnBackground
+ ? SESSION_MANAGER_INHIBIT_SUSPEND_FLAG
+ : SESSION_MANAGER_INHIBIT_IDLE_FLAG;
DBusInhibitScreensaver(
SESSION_MANAGER_TARGET, SESSION_MANAGER_OBJECT, SESSION_MANAGER_INTERFACE,
"Inhibit",
@@ -772,9 +803,9 @@ bool WakeLockTopic::UninhibitWaylandIdle() {
bool WakeLockTopic::SendInhibit() {
WAKE_LOCK_LOG("WakeLockTopic::SendInhibit() WakeLockType %s",
- WakeLockTypeNames[sWakeLockType]);
- MOZ_ASSERT(sWakeLockType != Initial);
- switch (sWakeLockType) {
+ WakeLockTypeNames[GetWakeLockType()]);
+ MOZ_ASSERT(GetWakeLockType() != Initial);
+ switch (GetWakeLockType()) {
#if defined(MOZ_ENABLE_DBUS)
case FreeDesktopPortal:
InhibitFreeDesktopPortal();
@@ -805,9 +836,9 @@ bool WakeLockTopic::SendInhibit() {
bool WakeLockTopic::SendUninhibit() {
WAKE_LOCK_LOG("WakeLockTopic::SendUninhibit() WakeLockType %s",
- WakeLockTypeNames[sWakeLockType]);
- MOZ_ASSERT(sWakeLockType != Initial);
- switch (sWakeLockType) {
+ WakeLockTypeNames[GetWakeLockType()]);
+ MOZ_ASSERT(GetWakeLockType() != Initial);
+ switch (GetWakeLockType()) {
#if defined(MOZ_ENABLE_DBUS)
case FreeDesktopPortal:
UninhibitFreeDesktopPortal();
@@ -840,7 +871,7 @@ nsresult WakeLockTopic::InhibitScreensaver() {
WAKE_LOCK_LOG("WakeLockTopic::InhibitScreensaver() state %s",
GetInhibitStateName(mState));
// We're broken, don't even try
- if (sWakeLockType == Unsupported) {
+ if (GetWakeLockType() == Unsupported) {
return NS_ERROR_FAILURE;
}
mStateQueue.push(Inhibited);
@@ -854,7 +885,7 @@ nsresult WakeLockTopic::UninhibitScreensaver() {
WAKE_LOCK_LOG("WakeLockTopic::UnInhibitScreensaver() state %s",
GetInhibitStateName(mState));
// We're broken, don't even try
- if (sWakeLockType == Unsupported) {
+ if (GetWakeLockType() == Unsupported) {
return NS_ERROR_FAILURE;
}
mStateQueue.push(Uninhibited);
@@ -912,14 +943,19 @@ void WakeLockTopic::Shutdown() {
bool WakeLockTopic::IsWakeLockTypeAvailable(int aWakeLockType) {
switch (aWakeLockType) {
#if defined(MOZ_ENABLE_DBUS)
- case FreeDesktopPortal:
case FreeDesktopScreensaver:
case FreeDesktopPower:
+ // Doesn't support background inihibit
+ return !mLockOnBackground;
+ case FreeDesktopPortal:
case GNOME:
return true;
#endif
#if defined(MOZ_X11)
case XScreenSaver:
+ if (mLockOnBackground) {
+ return false;
+ }
if (!GdkIsX11Display()) {
return false;
}
@@ -931,6 +967,9 @@ bool WakeLockTopic::IsWakeLockTypeAvailable(int aWakeLockType) {
#endif
#if defined(MOZ_WAYLAND)
case WaylandIdleInhibit:
+ if (mLockOnBackground) {
+ return false;
+ }
if (!GdkIsWaylandDisplay()) {
return false;
}
@@ -961,17 +1000,19 @@ bool WakeLockTopic::IsNativeWakeLock(int aWakeLockType) {
}
void WakeLockTopic::InitializeWakeLockType() {
- int lock = GetWakeLockTypeFromEnv();
- if (lock != Initial) {
- WAKE_LOCK_LOG("MOZ_WAKE_LOCK_TYPE set: %s", WakeLockTypeNames[lock]);
- if (IsWakeLockTypeAvailable(lock)) {
- sWakeLockType = lock;
- return;
+ if (!mLockOnBackground) {
+ int lock = GetWakeLockTypeFromEnv();
+ if (lock != Initial) {
+ WAKE_LOCK_LOG("MOZ_WAKE_LOCK_TYPE set: %s", WakeLockTypeNames[lock]);
+ if (IsWakeLockTypeAvailable(lock)) {
+ SetWakeLockType(lock);
+ return;
+ }
+ WAKE_LOCK_LOG(
+ "Requested WakeLockType %s not available, falling back to "
+ "auto-detection",
+ WakeLockTypeNames[lock]);
}
- WAKE_LOCK_LOG(
- "Requested WakeLockType %s not available, falling back to "
- "auto-detection",
- WakeLockTypeNames[lock]);
}
// Fall back to automatic detection
SwitchToNextWakeLockType();
@@ -979,32 +1020,34 @@ void WakeLockTopic::InitializeWakeLockType() {
bool WakeLockTopic::SwitchToNextWakeLockType() {
WAKE_LOCK_LOG("WakeLockTopic::SwitchToNextWakeLockType() WakeLockType %s",
- WakeLockTypeNames[sWakeLockType]);
+ WakeLockTypeNames[GetWakeLockType()]);
- if (sWakeLockType == Unsupported) {
+ if (GetWakeLockType() == Unsupported) {
return false;
}
#ifdef MOZ_LOGGING
auto printWakeLocktype = MakeScopeExit([&] {
WAKE_LOCK_LOG(" switched to WakeLockType %s",
- WakeLockTypeNames[sWakeLockType]);
+ WakeLockTypeNames[GetWakeLockType()]);
});
#endif
#if defined(MOZ_ENABLE_DBUS)
- if (IsDBusWakeLock(sWakeLockType)) {
+ if (IsDBusWakeLock(GetWakeLockType())) {
mState = Uninhibited;
mCancellable = nullptr;
ClearDBusInhibitToken();
}
#endif
- while (sWakeLockType != Unsupported) {
- sWakeLockType++;
- if (IsWakeLockTypeAvailable(sWakeLockType)) {
+ while (GetWakeLockType() != Unsupported) {
+ SetWakeLockType(GetWakeLockType() + 1);
+ if (IsWakeLockTypeAvailable(GetWakeLockType())) {
return true;
}
+ WAKE_LOCK_LOG(" WakeLockType %s is not available",
+ WakeLockTypeNames[GetWakeLockType()]);
}
return false;
}
@@ -1012,26 +1055,35 @@ bool WakeLockTopic::SwitchToNextWakeLockType() {
WakeLockListener::WakeLockListener() = default;
WakeLockListener::~WakeLockListener() {
- for (const auto& topic : mTopics.Values()) {
+ for (const auto& topic : mForegroundTopics.Values()) {
+ topic->Shutdown();
+ }
+ for (const auto& topic : mBackgroundTopics.Values()) {
topic->Shutdown();
}
}
nsresult WakeLockListener::Callback(const nsAString& topic,
const nsAString& state) {
+ WAKE_LOCK_LOG("WakeLockListener::Callback() topic %s state %s",
+ NS_ConvertUTF16toUTF8(topic).get(),
+ NS_ConvertUTF16toUTF8(state).get());
if (!topic.Equals(u"screen"_ns) && !topic.Equals(u"video-playing"_ns) &&
- !topic.Equals(u"autoscroll"_ns)) {
+ !topic.Equals(u"autoscroll"_ns) && !topic.Equals(u"audio-playing"_ns)) {
return NS_OK;
}
- RefPtr<WakeLockTopic> topicLock = mTopics.LookupOrInsertWith(
- topic, [&] { return MakeRefPtr<WakeLockTopic>(topic); });
-
- // Treat "locked-background" the same as "unlocked" on desktop linux.
- bool shouldLock = state.EqualsLiteral("locked-foreground");
- WAKE_LOCK_LOG("WakeLockListener topic %s state %s request lock %d",
- NS_ConvertUTF16toUTF8(topic).get(),
- NS_ConvertUTF16toUTF8(state).get(), shouldLock);
+ bool backgroundLock = !(topic.Equals(u"video-playing"_ns) &&
+ state.EqualsLiteral("locked-foreground"));
+ bool shouldLock = state.EqualsLiteral("locked-background") ||
+ state.EqualsLiteral("locked-foreground");
+
+ nsRefPtrHashtable<nsStringHashKey, WakeLockTopic>* topicTable =
+ backgroundLock ? &mBackgroundTopics : &mForegroundTopics;
+ RefPtr<WakeLockTopic> topicLock = topicTable->LookupOrInsertWith(
+ topic, [&] { return MakeRefPtr<WakeLockTopic>(topic, backgroundLock); });
+ WAKE_LOCK_LOG("Adding WakeLockListener lock %d background %d", shouldLock,
+ backgroundLock);
return shouldLock ? topicLock->InhibitScreensaver()
: topicLock->UninhibitScreensaver();
diff --git a/widget/gtk/WakeLockListener.h b/widget/gtk/WakeLockListener.h
@@ -32,7 +32,8 @@ class WakeLockListener final : public nsIDOMMozWakeLockListener {
// Map of topic names to |WakeLockTopic|s.
// We assume a small, finite-sized set of topics.
- nsRefPtrHashtable<nsStringHashKey, WakeLockTopic> mTopics;
+ nsRefPtrHashtable<nsStringHashKey, WakeLockTopic> mForegroundTopics;
+ nsRefPtrHashtable<nsStringHashKey, WakeLockTopic> mBackgroundTopics;
};
#endif // __WakeLockListener_h__