the phrygian cap


luisbg

@luisbg

luis@debethencourt.com



Ohloh profile for Luis de Bethencourt
Blogalia




<Abril 2014
Lu Ma Mi Ju Vi Sa Do
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        

Creative Commons License


planet gnome
planet ubuntu
alberto ruiz
andy wingo
jeff fortin
slomo's blog
jan schmidt
vincent's random waffle



"all religions, arts and sciences are branches of the same tree. all these aspirations are directed toward ennobling man's life, lifting it from the sphere of mere physical existence and leading the individual towards freedom." albert einstein

HOWTO: Disable the Gnome screensaver from your application



A broad group of applications have some sort of display running without user feedback, an obvious example are multimedia applications. For instance the user of a video editor is viewing his work in-progress, in such use cases it would be frustrating if the screensaver kicked in, blocking the video. So how do we disable the screensaver temporarily from our application?

Recently there have been some changes around GNOME's screensaver and which component handles the requests to disable it. It used to be gnome-screensaver directly but now it is managed by gnome-session. What you need to do is simply send the DBus message "Inhibit" to org.gnome.SessionManager, and later send "Uninhibit" to reactivate it.

Sebastian Dröge implemented this in snappy, basing his code heavily in that of totem. We have the following function that depending on the second argument, disables or enables the screensaver:

static void
screensaver_inhibit_dbus (ScreenSaver * screensaver, gboolean inhibit)
{
  if (!screensaver->gs_proxy)
    return;

  if (inhibit) {
    guint xid;

    xid = screensaver->window;

    g_dbus_proxy_call (screensaver->gs_proxy,
        "Inhibit",
        g_variant_new ("(susu)",
            g_get_application_name (),
            xid,
            REASON,
            GS_NO_IDLE_FLAG),
        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, on_inhibit_cb, screensaver);
  } else {
    if (screensaver->cookie > 0) {
      g_dbus_proxy_call (screensaver->gs_proxy,
          "Uninhibit",
          g_variant_new ("(u)", screensaver->cookie),
          G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, on_uninhibit_cb,
          screensaver);
    }
  }
}


When the "Inhibit" request is satisfied asynchronously, the on_inhibit_cb () callback is called. This checks if the operation happened succesfully, and saves the cookie that we see used above when uninhibiting. gnome-session uses this cookie to track the disabling and enabling of the screensaver by multiple applications. If two applications request a screensaver disable and later only one has enabled it, it will still wait for the second one before doing so.

static void
on_inhibit_cb (GObject * source_object, GAsyncResult * res, gpointer user_data)
{
  GDBusProxy *proxy = G_DBUS_PROXY (source_object);
  ScreenSaver *screensaver = (ScreenSaver *) user_data;
  GVariant *value;
  GError *error = NULL;

  value = g_dbus_proxy_call_finish (proxy, res, &error);
  if (!value) {
    g_warning ("Problem inhibiting the screensaver: %s", error->message);
    g_error_free (error);
    return;
  }

  /* save the cookie */
  if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
    g_variant_get (value, "(u)", &screensaver->cookie);
  else
    screensaver->cookie = 0;

  g_variant_unref (value);
}


on_uninhibit_cb () does the reverse, checks if operation finished succesfully and it clears the cookie.

For those who want the whole picture... getting the GDBusProxy (screensaver->gs_proxy) which needs to be set before running the proxy call in screensaver_inhibit_dbus () above, is set by:

static void
screensaver_init_dbus (ScreenSaver * screensaver)
{
  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
      G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
      NULL,
      GS_SERVICE,
      GS_PATH, GS_INTERFACE, NULL, screensaver_dbus_proxy_new_cb, screensaver);
}


The screensaver_dbus_proxy_new_cb callback checks the operation and then runs:
screensaver->gs_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL);

Here is the full code if you want to take a look at it.


pd: Soon part II, the XTst variant of screensaver disabling for x11.

4 Comentarios


Referencias (TrackBacks)

URL de trackback de esta historia http://luisbg.blogalia.com//trackbacks/69989

Comentarios

1
De: Aaron Seigo Fecha: 2011-07-12 09:56

This also works with the screen saver in a KDE session using the org.freedesktop.ScreenSaver service which is under object /ScreenSaver. We harmonized this DBus interface a few years back, and hopefully the GNOME implementation advertises with the same service+object address on the session bus.



2
De: Anon Fecha: 2011-07-12 10:39

Is this change really recent? - https://bugzilla.gnome.org/show_bug.cgi?id=472812



3
De: luisbg Fecha: 2011-07-12 10:55

Aaron: cool! good to know. I should add that to snappy soon.

Anon: there have been multiple changes AFAIK.



4
De: Anon Fecha: 2011-07-12 15:25

PS: Aaron has raised a familiar political point which boils down to "there is no way to use one command to control the screensaver of KDE and GNOME (outside something like xdg-screensaver).



Nombre
Correo-e
URL
Dirección IP: 107.20.30.170 (3e5c9d4c6f)
Comentario

©2007-2013 luis de bethencourt guimera
powered by Blogalia