Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Xfce #311

Open
fohrloop opened this issue May 26, 2024 · 2 comments
Open

Add support for Xfce #311

fohrloop opened this issue May 26, 2024 · 2 comments
Labels
Type: Feature New feature or request

Comments

@fohrloop
Copy link
Owner

fohrloop commented May 26, 2024

Different methods on xfce:

org.Xfce.Session.Manager.Inhibit

  • Introduced in xfce-session/#22 (in particular, the commit 895a580d). Merged into xfce-session in commit aa586e05 (April 13th, 2023). It is not part of the xfce-4.18 branch, but it is part of the xfce-session-4.19.0 tag.
  • Since Xfce releases every odd number (..., 4.14, 4.16, 4.18, 4.20, ...) as binary releases (changelog here), the org.Xfce.Session.Manager.Inhibit will only be part of the 4.19 "development" (source) release, and then finally in the Xfce 4.20, which is probably out in late 2024 or early 2025 (ref). See also: Schedule for and Status of the Xfce 4.20 Development Cycle.
  • D-Bus path: /org/xfce/SessionManager
  • D-Bus interface: org.xfce.Session.Manager
  • Method: Inhibit, with parameters app_id (str), toplevel_xid (int), reason (str), flags (int) and return value inhibit_cookie (int)

org.freedesktop.PowerManagement.Inhibit

  • Obsolete spec, but still used: https://wakepy.readthedocs.io/stable/methods-reference.html#org-freedesktop-powermanagement
  • There's a bug in XFCE. org.freedesktop.PowerManagement.Inhibit inhibits also screensaver: https://gitlab.xfce.org/xfce/xfce4-power-manager/-/issues/65
  • This is present on Xfce 4.18 session bus. Tested and this prevents idle; it implements keep.presenting mode.
  • D-Bus name org.freedesktop.PowerManagement (on Session bus)
  • D-Bus path: /org/freedesktop/PowerManagement/Inhibit
  • D-Bus interface: org.freedesktop.PowerManagement.Inhibit
  • Method: Inhibit, with parameters application_name (str) and reason (str) and return value inhibit_cookie (int). Note that since this does not have input parameter "flags", you may not control what this inhibits, and there are two kinds of behaviors found in the wild (keep.running (=the correct one?) and keep.presenting).

org.freedesktop.login1.Manager.Inhibit

  • This is present on Xfce 4.18 system bus
  • D-Bus name: org.freedesktop.login1
  • D-Bus path:/org/freedesktop/login1
  • D-Bus interface: org.freedesktop.login1.Manager
  • Method: Inhibit, with parameters what (str) who (str) why (str) mode (str) and return value file_descriptor (File Descriptor).

org.xfce.PowerManager

  • Mentioned on xfce4-power-manager roadmap for Xfce 4.10
  • Likely to just be a proxy or alias for org.freedesktop.PowerManagement.Inhibit
  • This is present on Xfce 4.18 session bus. Tested and this prevents idle; it implements keep.presenting mode.
  • D-Bus name: org.xfce.PowerManager
  • D-Bus path: /org/freedesktop/PowerManagement/Inhibit
  • D-Bus interface: org.freedesktop.PowerManagement.Inhibit
  • Method: Inhibit, with parameters application_name (str) and reason (str) and return value inhibit_cookie (int).

Notes

@fohrloop fohrloop added the Type: Feature New feature or request label May 30, 2024
@fohrloop fohrloop self-assigned this Sep 22, 2024
@fohrloop
Copy link
Owner Author

fohrloop commented Sep 23, 2024

I've done some testing and here are results.

org.Xfce.Session.Manager.Inhibit

  • Does not exists yet in Xfce 4.18. Should probably be the chosen method on Xfce 4.20 and above (in the future).

org.freedesktop.PowerManagement.Inhibit

  • Has only one possible "mode": keep.presenting, which prevents the idle action and keeps also the screen awake. This cannot be modified in any way, so implementing keep.presenting mode is not possible. In my understanding, the spec says that this should only prevent suspending (allow automatic screenlock+screen saver), so using this method would mean that wakepy would rely on a bug existing on Xfce. See also xfce4-power-manager/#65 and org.freedesktop.PowerManagement docs. This bug has been fixed in KDE 5.12.90.

org.xfce.PowerManager

  • Seems to be just a proxy / alias for org.freedesktop.PowerManagement.Inhibit

org.freedesktop.login1.Manager.Inhibit

  • Should be able to prevent suspend/sleep or the idle action. Checking if this is possible without root.
Test 1
  • Trying to inhibit "sleep" with org.freedesktop.login1.Manager.Inhibit. (no sudo used)
  • Result: This does not work.
Test 1 details
from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg


addr = DBusAddress(
    object_path='/org/freedesktop/login1',
    bus_name='org.freedesktop.login1',
    interface='org.freedesktop.login1.Manager',
)

msg = new_method_call(
    addr,
    method='Inhibit',
    signature='ssss',
    body=('sleep', 'wakepy', 'wakelock active', 'block'),
)

connection = open_dbus_connection(bus="SYSTEM", enable_fds=True)
reply = connection.send_and_get_reply(msg, timeout=2)
resp = unwrap_msg(reply)

fd = resp[0]

Running this with -i flag to keep the file descriptor object open.

(venv) fohrloop@fedora:~/code/wakepy$ python -i foo.py 
>>> fd
<FileDescriptor (5)>

But this did not prevent automatic suspend

Test 2
  • Trying to inhibit "sleep" with org.freedesktop.login1.Manager.Inhibit with sudo.
  • This time the suspend was prevented. After logging back in (from screensaver/screenlock), I was greeted with this:

image

Code

Some pieces of code for possible use in the future

org.freedesktop.login1

class FreedesktopLogin1Inhibit(Method):
    """Method using org.freedesktop.login1.Manager.Inhibit D-Bus API

    References:
    [1]: https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html
    [2]: https://systemd.io/INHIBITOR_LOCKS/

    """
    name = "org.freedesktop.login1"
    mode_name = ModeName.KEEP_RUNNING

    login1_manager = DBusAddress(
        bus=BusType.SYSTEM,
        service="org.freedesktop.login1",
        path="/org/freedesktop/login1",
        interface="org.freedesktop.login1.Manager",
    )

    # Note: There is no "UnInhibit" method.  The method returns a file
    # descriptor. The lock is released the moment this file descriptor and all
    # its duplicates are closed.
    method_inhibit = DBusMethod(
        name="Inhibit",
        signature="ssss",
        params=("what", "who", "why", "mode"),
        output_signature="h",
        output_params=("fd",),
    ).of(login1_manager)


    supported_platforms = (PlatformType.UNIX_LIKE_FOSS,)

    def enter_mode(self) -> None:

        # The method arguments are:
        # what (str):
        #   Colon-separated list of lock types: shutdown, sleep, idle,
        #   handle-power-key, handle-suspend-key, handle-hibernate-key
        #   and handle-lid-switch. The ones interesting for wakepy are "sleep"
        #   and "idle".
        # who (str)
        #   The name of the application requesting the lock.
        # why (str):
        #   The reason for requesting the lock.
        # mode (str):
        #   The lock mode. Either "block" or "delay".
        call = DBusMethodCall(
            method=self.method_inhibit,
            args=dict(
                what="sleep",
                who="wakepy",
                why="wakelock active",
                mode="block",
            ),
        )

        retval = self.process_dbus_call(call)
        if retval is None:
            raise RuntimeError(
                "Could not get file handle from org.freedesktop.login1"
            )
        self.inhibit_cookie = retval[0]

lower-level alternative:

from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg


addr = DBusAddress(
    object_path='/org/freedesktop/login1',
    bus_name='org.freedesktop.login1',
    interface='org.freedesktop.login1.Manager',
)

msg = new_method_call(
    addr,
    method='Inhibit',
    signature='ssss',
    body=('sleep', 'wakepy', 'wakelock active', 'block'),
)

connection = open_dbus_connection(bus="SYSTEM", enable_fds=True)
reply = connection.send_and_get_reply(msg, timeout=2)
resp = unwrap_msg(reply)

fd = resp[0]

org.xfce.PowerManager

class XfcePowerManagerInhibit(FreedesktopInhibitorWithCookieMethod):

    name = "org.xfce.PowerManager"
    mode_name = ModeName.KEEP_RUNNING

    service_dbus_address = DBusAddress(
        bus=BusType.SESSION,
        service="org.xfce.PowerManager",
        path="/org/freedesktop/PowerManagement/Inhibit",
        interface="org.freedesktop.PowerManagement.Inhibit",
    )

@fohrloop
Copy link
Owner Author

As none of the above methods are suitable for just the keep.running method (without sudo), I'm not sure what to do. I asked on the xfce forums some advice. Perhaps there's still some other way to prevent automatic suspending on Xcfe < 4.19.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant