wakepy icon indicating copy to clipboard operation
wakepy copied to clipboard

Method using gtk_application_inhibit()?

Open fohrloop opened this issue 1 year ago • 4 comments

See: https://docs.gtk.org/gtk3/method.Application.inhibit.html

If I'm not mistaken, this requires PyGObject (which has import name gi) . It could be used as an alternative "no dbus" option?

This is a particularly interesting option since so many Desktop Environments are based on the GTK graphical toolkit (GNOME, Xfce, Cinnamon, LXDE, MATE, Unity, Budgie, Pantheon), and because it offers a non-dbus alternative.

Alternatives

  1. Make PyGObject (gi) a requirement for wakepy. This has the downside that (1) It's an additional dependency and (2) the PyGObject is not pure python package so it requires compiling tools to be available.

  2. ~Do site-packages search for system python folder and add the gi package into the sys.path~ Use system python in separate process. I'm assuming that gi python package is available in all the desktop environments which use GTK. No additional dependencies would be needed for wakepy. In other words, the gi python package would be treated as any non-python dependency; you search, and if you find, you can use.

  3. Interfacing gtk_application_inhibit() directly without gi somehow. Does not require dependency but probably requires a lot of extra work. I assume that if a system has GTK, it has also gi python package available so this kind extension module is not required.

Tasks

  • [x] Try out gtk_application_inhibit() with gi. Is it possible to prevent sleep and/or idle with it (to support both: keep.running and keep.presenting modes)? yes, it is.
  • [ ] Find a way to get the system site-packages location reliably

fohrloop avatar Sep 22 '24 17:09 fohrloop

About availability of gtk_application_inhibit()

  • It has been available since Gtk 3.4 (mentioned in the docs). It's also available in gtk4.

fohrloop avatar Sep 24 '24 08:09 fohrloop

Minimal working example

Here is a minimal working example which uses the gtk_application_inhibit(), made available through the method inhibit of the Gtk.Application:

import time

import gi

gi.require_version("Gtk", "3.0")

from gi.repository import Gio, Gtk

app = Gtk.Application(
    application_id="io.readthedocs.wakepy",
    flags=Gio.ApplicationFlags.IS_SERVICE | Gio.ApplicationFlags.NON_UNIQUE,
)
app.register()
app.inhibit(
    None,
    Gtk.ApplicationInhibitFlags(8),  # prevent idle
    "wakelock requested (wakepy)",
)
app.hold()

time.sleep(30)

app.release()

unsolved

  • ~A proper way to stop the wakelock?~ done.
  • ~Can gi.require_version("Gtk", "3.0") be called? What if the app running wakepy uses different version of gtk?~ done.
  • ~Should this be ran in a separate python process?~ yes
  • Finding the system level site-packages gi library inside venv

fohrloop avatar Sep 24 '24 09:09 fohrloop

Running this in a separate process

One difficulty in using this within a virtual environment where gi is not installed is that the sys.path and sys.modules are shared between threads. Since wakepy should not do any kind of alterations to the sys.path or sys.modules, it should run in a separate process. It also requires some communication mechanism between the wakelock process and the main process.

fohrloop avatar Sep 24 '24 12:09 fohrloop

Update: I have some sort of implementation which successfully inhibits idle (#407). It has two parts (1) server, which is intended to be started with the system python interpreter, like /usr/bin/python, and (2) client, which is intended to be used within a wakepy.Method. There's still quite a lot of work before this can be part of a wakepy release.

fohrloop avatar Sep 25 '24 13:09 fohrloop