all repos — openbox @ 2cd1644e1040684d5f646541f65a36b01b011db2

openbox fork - make it a bit more like ryudo

add startup notification in its own .c/.h files
Dana Jansens danakj@orodu.net
commit

2cd1644e1040684d5f646541f65a36b01b011db2

parent

ed9dc5dc788e3d0e79fa5010265ba9ce57ea6859

2 files changed, 216 insertions(+), 0 deletions(-)

jump to
A openbox/startupnotify.c

@@ -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
A openbox/startupnotify.h

@@ -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