]> Dogcows Code - chaz/openbox/commitdiff
add startup notification in its own .c/.h files
authorDana Jansens <danakj@orodu.net>
Wed, 3 Sep 2003 20:35:22 +0000 (20:35 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 3 Sep 2003 20:35:22 +0000 (20:35 +0000)
openbox/startupnotify.c [new file with mode: 0644]
openbox/startupnotify.h [new file with mode: 0644]

diff --git a/openbox/startupnotify.c b/openbox/startupnotify.c
new file mode 100644 (file)
index 0000000..6d1ba5a
--- /dev/null
@@ -0,0 +1,198 @@
+#include "startupnotify.h"
+
+#ifndef USE_LIBSN
+
+void sn_startup(gboolean reconfig) {}
+void sn_shutdown(gboolean reconfig) {}
+gboolean sn_app_starting() { return FALSE; }
+void sn_app_started(gchar *wmclass, guint *desktop) {}
+
+#else
+
+#include "openbox.h"
+#include "mainloop.h"
+#include "screen.h"
+
+#define SN_API_NOT_YET_FROZEN
+#include <libsn/sn.h>
+
+typedef struct {
+    SnStartupSequence *seq;
+    gboolean feedback;
+} ObWaitData;
+
+static SnDisplay *sn_display;
+static SnMonitorContext *sn_context;
+static GSList *sn_waits; /* list of ObWaitDatas */
+
+static ObWaitData* wait_data_new(SnStartupSequence *seq);
+static void wait_data_free(ObWaitData *d);
+static ObWaitData* wait_find(const gchar *id);
+
+static void sn_handler(const XEvent *e, gpointer data);
+static void sn_event_func(SnMonitorEvent *event, gpointer data);
+
+void sn_startup(gboolean reconfig)
+{
+    if (reconfig) return;
+
+    sn_display = sn_display_new(ob_display, NULL, NULL);
+    sn_context = sn_monitor_context_new(sn_display, ob_screen,
+                                        sn_event_func, NULL, NULL);
+
+    ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
+}
+
+void sn_shutdown(gboolean reconfig)
+{
+    GSList *it;
+
+    if (reconfig) return;
+
+    for (it = sn_waits; it; it = g_slist_next(it))
+        wait_data_free(it->data);
+    g_slist_free(sn_waits);
+    sn_waits = NULL;
+
+    screen_set_root_cursor();
+
+    sn_monitor_context_unref(sn_context);
+    sn_display_unref(sn_display);
+}
+
+static ObWaitData* wait_data_new(SnStartupSequence *seq)
+{
+    ObWaitData *d = g_new(ObWaitData, 1);
+    d->seq = seq;
+    d->feedback = TRUE;
+
+    sn_startup_sequence_ref(d->seq);
+
+    return d;
+}
+
+static void wait_data_free(ObWaitData *d)
+{
+    if (d) {
+        sn_startup_sequence_unref(d->seq);
+
+        g_free(d);
+    }
+}
+
+static ObWaitData* wait_find(const gchar *id)
+{
+    ObWaitData *ret = NULL;
+    GSList *it;
+
+    for (it = sn_waits; it; it = g_slist_next(it)) {
+        ObWaitData *d = it->data;
+        if (!strcmp(id, sn_startup_sequence_get_id(d->seq))) {
+            ret = d;
+            break;
+        }
+    }
+    return ret;
+}
+
+gboolean sn_app_starting()
+{
+    GSList *it;
+
+    for (it = sn_waits; it; it = g_slist_next(it)) {
+        ObWaitData *d = it->data;
+        if (d->feedback)
+            return TRUE;
+    }
+    return FALSE;
+}
+
+static gboolean sn_wait_timeout(gpointer data)
+{
+    ObWaitData *d = data;
+    d->feedback = FALSE;
+    screen_set_root_cursor();
+    return FALSE; /* don't repeat */
+}
+
+static void sn_wait_destroy(gpointer data)
+{
+    ObWaitData *d = data;
+    sn_waits = g_slist_remove(sn_waits, d);
+    wait_data_free(d);
+}
+
+static void sn_handler(const XEvent *e, gpointer data)
+{
+    XEvent ec;
+    ec = *e;
+    sn_display_process_event(sn_display, &ec);
+}
+
+static void sn_event_func(SnMonitorEvent *ev, gpointer data)
+{
+    SnStartupSequence *seq;
+    gboolean change = FALSE;
+    ObWaitData *d;
+
+    if (!(seq = sn_monitor_event_get_startup_sequence(ev)))
+        return;
+
+    switch (sn_monitor_event_get_type(ev)) {
+    case SN_MONITOR_EVENT_INITIATED:
+        g_message("starting");
+        d = wait_data_new(seq);
+        sn_waits = g_slist_prepend(sn_waits, d);
+        /* 30 second timeout for apps to start */
+        ob_main_loop_timeout_add(ob_main_loop, 30 * G_USEC_PER_SEC,
+                                 sn_wait_timeout, d, sn_wait_destroy);
+        change = TRUE;
+        break;
+    case SN_MONITOR_EVENT_CHANGED:
+        /* XXX feedback changed? */
+        change = TRUE;
+        break;
+    case SN_MONITOR_EVENT_COMPLETED:
+    case SN_MONITOR_EVENT_CANCELED:
+        if ((d = wait_find(sn_startup_sequence_get_id(seq)))) {
+            d->feedback = FALSE;
+            ob_main_loop_timeout_remove_data(ob_main_loop, sn_wait_timeout, d);
+            change = TRUE;
+        }
+        break;
+    };
+
+    if (change)
+        screen_set_root_cursor();
+}
+
+void sn_app_started(gchar *wmclass)
+{
+    GSList *it;
+
+    for (it = sn_waits; it; it = g_slist_next(it)) {
+        ObWaitData *d = it->data;
+        if (sn_startup_sequence_get_wmclass(d->seq) &&
+            !strcmp(sn_startup_sequence_get_wmclass(d->seq), wmclass))
+        {
+            sn_startup_sequence_complete(d->seq);
+            break;
+        }
+    }
+}
+
+gboolean sn_get_desktop(gchar *id, guint *desktop)
+{
+    ObWaitData *d;
+
+    if (id && (d = wait_find(id))) {
+        gint desk = sn_startup_sequence_get_workspace(d->seq);
+        if (desk != -1) {
+            *desktop = desk;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+#endif
diff --git a/openbox/startupnotify.h b/openbox/startupnotify.h
new file mode 100644 (file)
index 0000000..6cc9451
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef ob__startupnotify_h
+#define ob__startupnotify_h
+
+#include <glib.h>
+
+void sn_startup(gboolean reconfig);
+void sn_shutdown(gboolean reconfig);
+
+gboolean sn_app_starting();
+
+/*! Notify that an app has started */
+void sn_app_started(gchar *wmclass);
+
+/*! Get the desktop requested via the startup-notiication protocol if one
+  was requested */
+gboolean sn_get_desktop(gchar *id, guint *desktop);
+
+#endif
This page took 0.02716 seconds and 4 git commands to generate.