add (optional) support for showing a busy cursor via startup notification
authorDana Jansens <danakj@orodu.net>
Sun, 18 May 2003 02:10:26 +0000 (02:10 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 18 May 2003 02:10:26 +0000 (02:10 +0000)
configure.ac
openbox/Makefile.am
openbox/event.c
openbox/openbox.c
openbox/openbox.h
openbox/screen.c

index 16f54e2..c8174de 100644 (file)
@@ -51,10 +51,17 @@ PKG_CHECK_MODULES([GMODULE], [gmodule-2.0])
 AC_SUBST(GMODULE_CFLAGS)
 AC_SUBST(GMODULE_LIBS)
 
-PKG_CHECK_MODULES(XFT, xft)
+PKG_CHECK_MODULES(XFT, [xft])
 AC_SUBST(XFT_CFLAGS)
 AC_SUBST(XFT_LIBS)
 
+PKG_CHECK_MODULES(LIBSN, [libstartup-notification-1.0])
+AC_SUBST(LIBSN_CFLAGS)
+AC_SUBST(LIBSN_LIBS)
+if test "$LIBSN_LIBS"; then
+   AC_DEFINE(USE_LIBSN)
+fi
+
 # Check for X11 extensions
 X11_EXT_XKB
 X11_EXT_XRANDR
index 795b26a..ac277c0 100644 (file)
@@ -6,7 +6,7 @@ binary=openbox3
 url=http://icculus.org/openbox
 
 CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
-          @CPPFLAGS@ \
+         $(LIBSN_CFLAGS) @CPPFLAGS@ \
          -DLOCALEDIR=\"$(localedir)\" \
          -DRCDIR=\"$(rcdir)\" \
          -DPLUGINDIR=\"$(plugindir)\" \
@@ -15,8 +15,8 @@ CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
 
 INCLUDES=-I..
 LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(XKB_LIBS) $(XRANDR_LIBS) \
-       $(VIDMODE_LIBS) $(XSHAPE_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) @LIBS@ \
-       @LIBINTL@
+       $(VIDMODE_LIBS) $(XSHAPE_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) \
+       $(LIBSN_LIBS) @LIBS@ @LIBINTL@
 
 bin_PROGRAMS=$(binary)
 
index 900567c..a2604bc 100644 (file)
 #include <X11/Xatom.h>
 #include <glib.h>
 
+#ifdef USE_LIBSN
+#  include <libsn/sn.h>
+#endif
+
 #ifdef HAVE_SYS_SELECT_H
 #  include <sys/select.h>
 #endif
@@ -129,6 +133,10 @@ void event_loop()
        }
        XNextEvent(ob_display, &e);
 
+#ifdef USE_LIBSN
+        sn_display_process_event(ob_sn_display, &e);
+#endif
+
        event_process(&e);
         had_event = TRUE;
     }
index 93e91a5..3b2a999 100644 (file)
@@ -118,7 +118,11 @@ int main(int argc, char **argv)
        g_critical("Failed to set display as close-on-exec.");
        exit(1);
     }
-         
+
+#ifdef USE_LIBSN
+    ob_sn_display = sn_display_new(ob_display, NULL, NULL);
+#endif
+
     ob_screen = DefaultScreen(ob_display);
     ob_root = RootWindow(ob_display, ob_screen);
 
@@ -140,6 +144,7 @@ int main(int argc, char **argv)
     putenv(g_strdup_printf("DISPLAY=%s", DisplayString(ob_display)));
 
     ob_cursors.ptr = XCreateFontCursor(ob_display, XC_left_ptr);
+    ob_cursors.busy = XCreateFontCursor(ob_display, XC_watch);
     ob_cursors.move = XCreateFontCursor(ob_display, XC_fleur);
     ob_cursors.tl = XCreateFontCursor(ob_display, XC_top_left_corner);
     ob_cursors.tr = XCreateFontCursor(ob_display, XC_top_right_corner);
index d747b3f..51f6207 100644 (file)
@@ -1,11 +1,21 @@
 #ifndef __openbox_h
 #define __openbox_h
 
+#ifdef USE_LIBSN
+#  define SN_API_NOT_YET_FROZEN
+#  include <libsn/sn.h>
+#endif
+
 #include <glib.h>
 #include <X11/Xlib.h>
 
 /*! The X display */
 extern Display *ob_display; 
+
+#ifdef USE_LIBSN
+SnDisplay *ob_sn_display;
+#endif
+
 /*! The number of the screen on which we're running */
 extern int      ob_screen;
 /*! The root window */
@@ -36,6 +46,7 @@ extern gboolean ob_sync;
 
 typedef struct Cursors {
     Cursor ptr;
+    Cursor busy;
     Cursor move;
     Cursor bl;
     Cursor br;
index fd62446..044098f 100644 (file)
@@ -2,6 +2,7 @@
 #include "dock.h"
 #include "prop.h"
 #include "startup.h"
+#include "timer.h"
 #include "config.h"
 #include "screen.h"
 #include "client.h"
 #include "extensions.h"
 #include "../render/render.h"
 
+#ifdef USE_LIBSN
+#  define SN_API_NOT_YET_FROZEN
+#  include <libsn/sn.h>
+#endif
+
 #include <X11/Xlib.h>
 #ifdef HAVE_UNISTD_H
 #  include <sys/types.h>
@@ -34,7 +40,16 @@ static Rect  *area = NULL;
 static Strut *strut = NULL;
 static Window support_window = None;
 
+#ifdef USE_LIBSN
+static SnMonitorContext *sn_context;
+static int sn_busy_cnt;
+static Timer *sn_timer = NULL;
+
+static void sn_event_func(SnMonitorEvent *event, void *data);
+#endif
+
 static void screen_update_area();
+static void set_root_cursor();
 
 static gboolean running;
 static int another_running(Display *d, XErrorEvent *e)
@@ -63,8 +78,7 @@ gboolean screen_annex()
 
     g_message("Managing screen %d", ob_screen);
 
-    /* set the mouse cursor for the root window (the default cursor) */
-    XDefineCursor(ob_display, ob_root, ob_cursors.ptr);
+    set_root_cursor();
 
     /* set the OPENBOX_PID hint */
     pid = getpid();
@@ -187,6 +201,12 @@ void screen_startup()
     PROP_SET32(ob_root, net_showing_desktop, cardinal, screen_showing_desktop);
 
     screen_update_layout();
+
+#ifdef USE_LIBSN
+    sn_context = sn_monitor_context_new(ob_sn_display, ob_screen,
+                                        sn_event_func, NULL, NULL);
+    sn_busy_cnt = 0;
+#endif
 }
 
 void screen_shutdown()
@@ -599,3 +619,68 @@ Strut *screen_strut(guint desktop)
     }
     return &strut[desktop];
 }
+
+static void set_root_cursor()
+{
+#ifdef USE_LIBSN
+        if (sn_busy_cnt)
+            XDefineCursor(ob_display, ob_root, ob_cursors.busy);
+        else
+#endif
+            XDefineCursor(ob_display, ob_root, ob_cursors.ptr);
+}
+
+#ifdef USE_LIBSN
+static void sn_timeout(void *data)
+{
+    timer_stop(sn_timer);
+    sn_timer = NULL;
+    sn_busy_cnt = 0;
+
+    set_root_cursor();
+}
+
+static void sn_event_func(SnMonitorEvent *ev, void *data)
+{
+    SnStartupSequence *seq;
+    const char *seq_id, *bin_name;
+    int cnt = sn_busy_cnt;
+
+    if (!(seq = sn_monitor_event_get_startup_sequence(ev)))
+        return;
+
+    seq_id = sn_startup_sequence_get_id(seq);
+    bin_name = sn_startup_sequence_get_binary_name(seq);
+    
+    if (!(seq_id && bin_name))
+        return;
+
+    switch (sn_monitor_event_get_type(ev)) {
+    case SN_MONITOR_EVENT_INITIATED:
+        ++sn_busy_cnt;
+        if (sn_timer)
+            timer_stop(sn_timer);
+        /* 30 second timeout for apps to start */
+        sn_timer = timer_start(30 * 1000000, sn_timeout, NULL);
+        break;
+    case SN_MONITOR_EVENT_CHANGED:
+        break;
+    case SN_MONITOR_EVENT_COMPLETED:
+        if (sn_busy_cnt) --sn_busy_cnt;
+        if (sn_timer) {
+            timer_stop(sn_timer);
+            sn_timer = NULL;
+        }
+        break;
+    case SN_MONITOR_EVENT_CANCELED:
+        if (sn_busy_cnt) --sn_busy_cnt;
+        if (sn_timer) {
+            timer_stop(sn_timer);
+            sn_timer = NULL;
+        }
+    };
+
+    if (sn_busy_cnt != cnt)
+        set_root_cursor();
+}
+#endif