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

Method using gtk_application_inhibit() #407

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

fohrloop
Copy link
Owner

@fohrloop fohrloop commented Sep 25, 2024

Aims to close: #404

Add support for unix systems with GTK

  • The solution supports both, GTK3 and GTK4, and adds keep.running and keep.presenting modes to all platforms with the GTK graphical toolkit. Many desktop environments are based on GTK. A few examples are GNOME, Xfce, Cinnamon, LXDE, MATE, Unity, Budgie and Pantheon.
  • The requirements for this method to work are (1) GTK installed on the system (this a bit vague, but if you're running a DE which is based on GTK, that's most likely enough) 2) The python bindings for it; the PyGObject (gi) python library installed either on the current python environment or the system python site packages.

Details

  • Use the Gtk.Application.inhibit() from the GObject Instrospection python package (import name: gi, package name: PyGObject) for inhibiting sleep/idle. This is the PyGObject interface to the gtk_application_inhibit() function.
  • Add new server script which can be started with any python interpreter. The idea is that this is called with the system interpreter since that is expected to have the gi module for accessing GTK functions from python. User is not required to have installed the in their current (virtual) environment. It's just faster to use (300ms vs 5ms) if gi is available in the current python environment. Most people probably won't care if their long running script takes a 300ms more, and not having to install PyGObject is a nice thing as the installation will require compilation step(s), so it's a bit trickier and slower to install than a pure python package.
  • New concept: Inhibit module. This is a python module (a .py file), which should contain one class with the name Inhibitor, which should comply with the new Inhibitor protocol: There must be a start(self, *args) and stop(self) methods. The *args are positional arguments given to the server and passed to the inhibitor.

TODO

  • Add logic to get the system python interpreter path
  • Add logic for creating a random socket
  • Create wakepy.Method for this
  • Pass down the IDLE vs SUSPEND argument from the Method
  • Add tests
  • Update documentation
  • Check that the solution is not considerably slower than the other altenatives (like: D-Bus based methods)

@fohrloop
Copy link
Owner Author

fohrloop commented Sep 26, 2024

I have now a working implementation which still requires some refactoring + tests, but here are some timings. It can run in two modes:

  • If gi (PyGObject) is installed to the current python environment, that is used.
  • If gi is not installed to current python environment, but is available to system python, that is used.

Timings

Here are some timings for doing one inhibit -> uninhibit cycle:

Code used for benchmarking
import time 
import logging 
logging.basicConfig(level=logging.DEBUG)

from wakepy import keep

t0 = time.time()
with keep.presenting(methods=['gtk_application_inhibit']) as m:
    ...
t1 = time.time()
print(t1-t0)
  • Using local gi module: 198ms first run, 3.8ms second run. (for reference: org.gnome.SessionManager method took around 5ms)
  • Using the subprocess + system python: 200-300ms each run
  • out of this, about 150 ms is used for importing Gtk; this line:
    from gi.repository import Gio, Gtk.
  • Therefore, inhibiting with the system python in a subprocess adds about 100-150ms

Using local gi module:

# first run
DEBUG:wakepy.core.mode:'WAKEPY_FAKE_SUCCESS' not set.
DEBUG:wakepy.pyinhibitor.inhibitors:Inhibitor module 'wakepy.methods.gtk.inhibitor' loaded to local python environment
DEBUG:wakepy.methods.gtk.inhibitor:Registering Gtk.Application with id  io.readthedocs.wakepy.inhibitor1
DEBUG:wakepy.methods.gtk.inhibitor:Registered Gtk.Application with id  io.readthedocs.wakepy.inhibitor1
0.1985936164855957

# second run
DEBUG:wakepy.core.mode:'WAKEPY_FAKE_SUCCESS' not set.
DEBUG:wakepy.pyinhibitor.inhibitors:Inhibitor module 'wakepy.methods.gtk.inhibitor' loaded to local python environment
DEBUG:wakepy.methods.gtk.inhibitor:Registering Gtk.Application with id  io.readthedocs.wakepy.inhibitor2
DEBUG:wakepy.methods.gtk.inhibitor:Registered Gtk.Application with id  io.readthedocs.wakepy.inhibitor2
0.0038368701934814453

Using the subprocess:

DEBUG:wakepy.core.mode:'WAKEPY_FAKE_SUCCESS' not set.
DEBUG:wakepy.pyinhibitor.inhibitors:Inhibitor module "wakepy.methods.gtk.inhibitor" not found in the current python environment. Trying to use "/usr/bin/python" instead.
DEBUG:wakepy.pyinhibitor.inhibitors:Response from pyinhibit server: INHIBIT_OK
Received request: QUIT
DEBUG:wakepy.pyinhibitor.inhibitors:Response from pyinhibit server: UNINHIBIT_OK
0.22979283332824707

@fohrloop fohrloop force-pushed the issue-404-using-gtk_application_inhibit branch from 5ce3042 to 8c264f2 Compare September 27, 2024 07:43
@fohrloop
Copy link
Owner Author

I'm leaving this one open. I'm working on other projects and I don't have this top of my priority list. Coming back to this later, whenever I have spare time for a new release :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Method using gtk_application_inhibit()?
1 participant