]> Dogcows Code - chaz/tint2/commitdiff
Adding startup-notification support.
authorUnknown <xico.atelo@gmail.com>
Mon, 2 Jul 2012 16:50:30 +0000 (16:50 +0000)
committerUnknown <xico.atelo@gmail.com>
Mon, 2 Jul 2012 16:50:30 +0000 (16:50 +0000)
CMakeLists.txt
src/launcher/launcher.c
src/launcher/launcher.h
src/server.h
src/tint.c

index c687ab3687d63209fc945e9d3a8d0ac4f4cd0de2..3b5a0f30ce92d620ebb1620e823b6c78420a6b42 100644 (file)
@@ -10,6 +10,7 @@ pkg_check_modules( CAIRO REQUIRED cairo )
 pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
 pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
 pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
+pkg_check_modules( SN libstartup-notification-1.0>=0.12 )
 find_library( RT_LIBRARY rt )
 
 if( NOT X11_FOUND OR NOT PANGOCAIRO_FOUND OR NOT PANGO_FOUND OR NOT CAIRO_FOUND OR NOT GLIB2_FOUND OR NOT GOBJECT2_FOUND OR NOT IMLIB2_FOUND )
@@ -38,7 +39,8 @@ include_directories( ${PROJECT_BINARY_DIR}
                      ${CAIRO_INCLUDE_DIRS}
                      ${GLIB2_INCLUDE_DIRS}
                      ${GOBJECT2_INCLUDE_DIRS}
-                     ${IMLIB2_INCLUDE_DIRS} )
+                     ${IMLIB2_INCLUDE_DIRS}
+                    ${SN_INCLUDE_DIRS} )
 
 set( SOURCES src/config.c
              src/panel.c
@@ -61,6 +63,12 @@ set( SOURCES src/config.c
 option( ENABLE_BATTERY "Enable battery status plugin" ON )
 option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme switcher for tint2" ON )
 option( ENABLE_EXAMPLES "Install additional tin2rc examples" OFF )
+option( ENABLE_SN "Startup notification support" ON )
+if( ENABLE_SN )
+  if( SN_FOUND )
+    add_definitions( -DHAVE_SN -DSN_API_NOT_YET_FROZEN )
+  endif( SN_FOUND )
+endif( ENABLE_SN)
 
 if( ENABLE_BATTERY )
   set( SOURCES ${SOURCES} src/battery/battery.c )
@@ -86,7 +94,8 @@ link_directories( ${X11_LIBRARY_DIRS}
                   ${CAIRO_LIBRARY_DIRS}
                   ${GLIB2_LIBRARY_DIRS}
                   ${GOBJECT2_LIBRARY_DIRS}
-                  ${IMLIB2_LIBRARY_DIRS} )
+                  ${IMLIB2_LIBRARY_DIRS}
+                 ${SN_LIBRARY_DIRS} )
 add_executable(tint2 ${SOURCES})
 target_link_libraries( tint2 ${X11_LIBRARIES}
                              ${PANGOCAIRO_LIBRARIES}
@@ -94,7 +103,8 @@ target_link_libraries( tint2 ${X11_LIBRARIES}
                              ${CAIRO_LIBRARIES}
                              ${GLIB2_LIBRARIES}
                              ${GOBJECT2_LIBRARIES}
-                             ${IMLIB2_LIBRARIES} )
+                             ${IMLIB2_LIBRARIES}
+                            ${SN_LIBRARIES} )
 if( RT_LIBRARY )
   target_link_libraries( tint2 ${RT_LIBRARY} )
 endif( RT_LIBRARY )
index 2d1f8e84f1d3703902b71eb0adb2539675cc5dfe..69c31fb4c1f5a26b3193af071ff6e9477e98fefc 100644 (file)
 #include <stdlib.h>
 #include <glib/gi18n.h>
 
+#ifdef HAVE_SN
+#include <libsn/sn.h>
+#endif
+
 #include "window.h"
 #include "server.h"
 #include "area.h"
@@ -332,11 +336,54 @@ void free_icon(Imlib_Image icon)
        }
 }
 
-void launcher_action(LauncherIcon *icon)
+void launcher_action(LauncherIcon *icon, XEvent* evt)
 {
        char *cmd = malloc(strlen(icon->cmd) + 10);
        sprintf(cmd, "(%s&)", icon->cmd);
-       tint_exec(cmd);
+#if HAVE_SN
+               SnLauncherContext* ctx;
+               Time time;
+
+               ctx = sn_launcher_context_new(server.sn_dsp, server.screen);
+               sn_launcher_context_set_name(ctx, icon->icon_tooltip);
+               sn_launcher_context_set_description(ctx, "Application launched from tint2");
+               sn_launcher_context_set_binary_name (ctx, icon->cmd);
+               // Get a timestamp from the X event
+               if (evt->type == ButtonPress || evt->type == ButtonRelease) {
+                   time = evt->xbutton.time;
+               }
+               else {
+                       fprintf(stderr, "Unknown X event: %d\n", evt->type);
+                       free(cmd);
+                       return;
+               }
+               sn_launcher_context_initiate(ctx, "tint2", icon->cmd, time);
+#endif /* HAVE_SN */
+       pid_t pid;
+       pid = fork();
+       if (pid < 0) {
+               fprintf(stderr, "Could not fork\n");
+       }
+       else if (pid == 0) {
+#if HAVE_SN
+               sn_launcher_context_setup_child_process (ctx);
+#endif // HAVE_SN
+               // Allow children to exist after parent destruction
+               setsid ();
+               // Run the command
+               execl("/bin/sh", "/bin/sh", "-c", icon->cmd, NULL);
+
+               fprintf(stderr, "Failed to execlp %s\n", icon->cmd);
+#if HAVE_SN
+               sn_launcher_context_unref (ctx);
+#endif // HAVE_SN
+               _exit(1);
+       }
+#if HAVE_SN
+       else {
+               g_tree_insert (server.pids, GINT_TO_POINTER (pid), ctx);
+       }
+#endif // HAVE_SN
        free(cmd);
 }
 
index dc853a7c2804e4f0f788263e4c8ac435a9f1baa1..f60aceee8e207c4d8d6e1ac5614338ca34bd6fa9 100644 (file)
@@ -83,7 +83,7 @@ void draw_launcher (void *obj, cairo_t *c);
 void launcher_load_themes(Launcher *launcher);
 // Populates the list_icons list
 void launcher_load_icons(Launcher *launcher);
-void launcher_action(LauncherIcon *icon);
+void launcher_action(LauncherIcon *icon, XEvent* e);
 
 void test_launcher_read_desktop_file();
 void test_launcher_read_theme_file();
index 7a725a865c8bdfe8fa2b5f13b35bfd84aa3e398c..07876c6a2d08d592f7eb58844fb18c1fcd1d3fd6 100644 (file)
 #include <X11/Xatom.h>
 #include <X11/extensions/Xinerama.h>
 
+#ifdef HAVE_SN
+#include <libsn/sn.h>
+#include <glib.h>
+#endif
+
 
 typedef struct Global_atom
 {
@@ -118,6 +123,10 @@ typedef struct
        Colormap colormap;
        Colormap colormap32;
        Global_atom atom;
+#ifdef HAVE_SN
+       SnDisplay *sn_dsp;
+       GTree *pids;
+#endif // HAVE_SN
 } Server_global;
 
 
index cfd24bb86f39b1775881dcb4ec52b37d0c0ac152..7b6e637594b65db025e2e6c9dc9398d5a6bffe6e 100644 (file)
 #include <Imlib2.h>
 #include <signal.h>
 
+#ifdef HAVE_SN
+#include <libsn/sn.h>
+#include <sys/wait.h>
+#endif
+
 #include <version.h>
 #include "server.h"
 #include "window.h"
@@ -120,6 +125,58 @@ void init (int argc, char *argv[])
 //     sigprocmask(SIG_BLOCK, &block_mask, 0);
 }
 
+#ifdef HAVE_SN
+static int error_trap_depth = 0;
+
+static void
+error_trap_push (SnDisplay *display,
+                Display   *xdisplay)
+{
+       ++error_trap_depth;
+}
+
+static void
+error_trap_pop (SnDisplay *display,
+               Display   *xdisplay)
+{
+       if (error_trap_depth == 0)
+       {
+               fprintf(stderr, "Error trap underflow!\n");
+               return;
+       }
+
+       XSync(xdisplay, False); /* get all errors out of the queue */
+       --error_trap_depth;
+}
+
+static void sigchld_handler(int sig) {
+        // Wait for all dead processes
+        pid_t pid;
+        while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
+               SnLauncherContext *ctx;
+               ctx = (SnLauncherContext *) g_tree_lookup (server.pids, GINT_TO_POINTER (pid));
+               if (ctx == NULL) {
+                       fprintf(stderr, "Unknown child %d terminated!\n", pid);
+               }
+               else {
+                       g_tree_remove (server.pids, GINT_TO_POINTER (pid));
+                       sn_launcher_context_complete (ctx);
+                       sn_launcher_context_unref (ctx);
+               }
+       }
+}
+
+static gint cmp_ptr(gconstpointer a, gconstpointer b) {
+        if (a < b)
+         return -1;
+       else if (a == b)
+         return 0;
+       else
+         return 1;
+}
+
+#endif // HAVE_SN
+
 void init_X11()
 {
        server.dsp = XOpenDisplay (NULL);
@@ -134,6 +191,19 @@ void init_X11()
        server_init_visual();
        XSetErrorHandler ((XErrorHandler) server_catch_error);
 
+#ifdef HAVE_SN
+       // Initialize startup-notification
+       server.sn_dsp = sn_display_new (server.dsp, error_trap_push, error_trap_pop);
+       server.pids = g_tree_new (cmp_ptr);
+       // Setup a handler for child termination
+       struct sigaction act;
+       memset (&act, 0, sizeof (struct sigaction));
+       act.sa_handler = sigchld_handler;
+       if (sigaction(SIGCHLD, &act, 0)) {
+               perror("sigaction");
+       }
+#endif // HAVE_SN
+
        imlib_context_set_display (server.dsp);
        imlib_context_set_visual (server.visual);
        imlib_context_set_colormap (server.colormap);
@@ -446,7 +516,7 @@ void event_button_release (XEvent *e)
        if ( click_launcher(panel, e->xbutton.x, e->xbutton.y)) {
                LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
                if (icon) {
-                       launcher_action(icon);
+                       launcher_action(icon, e);
                }
                task_drag = 0;
                return;
@@ -1035,6 +1105,9 @@ start:
                if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
                        while (XPending (server.dsp)) {
                                XNextEvent(server.dsp, &e);
+#if HAVE_SN
+                               sn_display_process_event (server.sn_dsp, &e);
+#endif // HAVE_SN
 
                                panel = get_panel(e.xany.window);
                                if (panel && panel_autohide) {
This page took 0.030269 seconds and 4 git commands to generate.