Adding startup-notification support.
git-svn-id: http://tint2.googlecode.com/svn/trunk@650 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
parent
13b0d7612a
commit
cfa4bc89e1
5 changed files with 146 additions and 7 deletions
|
@ -10,6 +10,7 @@ pkg_check_modules( CAIRO REQUIRED cairo )
|
||||||
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
||||||
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
||||||
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
||||||
|
pkg_check_modules( SN libstartup-notification-1.0>=0.12 )
|
||||||
find_library( RT_LIBRARY rt )
|
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 )
|
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}
|
${CAIRO_INCLUDE_DIRS}
|
||||||
${GLIB2_INCLUDE_DIRS}
|
${GLIB2_INCLUDE_DIRS}
|
||||||
${GOBJECT2_INCLUDE_DIRS}
|
${GOBJECT2_INCLUDE_DIRS}
|
||||||
${IMLIB2_INCLUDE_DIRS} )
|
${IMLIB2_INCLUDE_DIRS}
|
||||||
|
${SN_INCLUDE_DIRS} )
|
||||||
|
|
||||||
set( SOURCES src/config.c
|
set( SOURCES src/config.c
|
||||||
src/panel.c
|
src/panel.c
|
||||||
|
@ -61,6 +63,12 @@ set( SOURCES src/config.c
|
||||||
option( ENABLE_BATTERY "Enable battery status plugin" ON )
|
option( ENABLE_BATTERY "Enable battery status plugin" ON )
|
||||||
option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme switcher for tint2" 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_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 )
|
if( ENABLE_BATTERY )
|
||||||
set( SOURCES ${SOURCES} src/battery/battery.c )
|
set( SOURCES ${SOURCES} src/battery/battery.c )
|
||||||
|
@ -86,7 +94,8 @@ link_directories( ${X11_LIBRARY_DIRS}
|
||||||
${CAIRO_LIBRARY_DIRS}
|
${CAIRO_LIBRARY_DIRS}
|
||||||
${GLIB2_LIBRARY_DIRS}
|
${GLIB2_LIBRARY_DIRS}
|
||||||
${GOBJECT2_LIBRARY_DIRS}
|
${GOBJECT2_LIBRARY_DIRS}
|
||||||
${IMLIB2_LIBRARY_DIRS} )
|
${IMLIB2_LIBRARY_DIRS}
|
||||||
|
${SN_LIBRARY_DIRS} )
|
||||||
add_executable(tint2 ${SOURCES})
|
add_executable(tint2 ${SOURCES})
|
||||||
target_link_libraries( tint2 ${X11_LIBRARIES}
|
target_link_libraries( tint2 ${X11_LIBRARIES}
|
||||||
${PANGOCAIRO_LIBRARIES}
|
${PANGOCAIRO_LIBRARIES}
|
||||||
|
@ -94,7 +103,8 @@ target_link_libraries( tint2 ${X11_LIBRARIES}
|
||||||
${CAIRO_LIBRARIES}
|
${CAIRO_LIBRARIES}
|
||||||
${GLIB2_LIBRARIES}
|
${GLIB2_LIBRARIES}
|
||||||
${GOBJECT2_LIBRARIES}
|
${GOBJECT2_LIBRARIES}
|
||||||
${IMLIB2_LIBRARIES} )
|
${IMLIB2_LIBRARIES}
|
||||||
|
${SN_LIBRARIES} )
|
||||||
if( RT_LIBRARY )
|
if( RT_LIBRARY )
|
||||||
target_link_libraries( tint2 ${RT_LIBRARY} )
|
target_link_libraries( tint2 ${RT_LIBRARY} )
|
||||||
endif( RT_LIBRARY )
|
endif( RT_LIBRARY )
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SN
|
||||||
|
#include <libsn/sn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "area.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);
|
char *cmd = malloc(strlen(icon->cmd) + 10);
|
||||||
sprintf(cmd, "(%s&)", icon->cmd);
|
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);
|
free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ void draw_launcher (void *obj, cairo_t *c);
|
||||||
void launcher_load_themes(Launcher *launcher);
|
void launcher_load_themes(Launcher *launcher);
|
||||||
// Populates the list_icons list
|
// Populates the list_icons list
|
||||||
void launcher_load_icons(Launcher *launcher);
|
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_desktop_file();
|
||||||
void test_launcher_read_theme_file();
|
void test_launcher_read_theme_file();
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SN
|
||||||
|
#include <libsn/sn.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct Global_atom
|
typedef struct Global_atom
|
||||||
{
|
{
|
||||||
|
@ -118,6 +123,10 @@ typedef struct
|
||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
Colormap colormap32;
|
Colormap colormap32;
|
||||||
Global_atom atom;
|
Global_atom atom;
|
||||||
|
#ifdef HAVE_SN
|
||||||
|
SnDisplay *sn_dsp;
|
||||||
|
GTree *pids;
|
||||||
|
#endif // HAVE_SN
|
||||||
} Server_global;
|
} Server_global;
|
||||||
|
|
||||||
|
|
||||||
|
|
75
src/tint.c
75
src/tint.c
|
@ -31,6 +31,11 @@
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SN
|
||||||
|
#include <libsn/sn.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
@ -120,6 +125,58 @@ void init (int argc, char *argv[])
|
||||||
// sigprocmask(SIG_BLOCK, &block_mask, 0);
|
// 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()
|
void init_X11()
|
||||||
{
|
{
|
||||||
server.dsp = XOpenDisplay (NULL);
|
server.dsp = XOpenDisplay (NULL);
|
||||||
|
@ -134,6 +191,19 @@ void init_X11()
|
||||||
server_init_visual();
|
server_init_visual();
|
||||||
XSetErrorHandler ((XErrorHandler) server_catch_error);
|
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_display (server.dsp);
|
||||||
imlib_context_set_visual (server.visual);
|
imlib_context_set_visual (server.visual);
|
||||||
imlib_context_set_colormap (server.colormap);
|
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)) {
|
if ( click_launcher(panel, e->xbutton.x, e->xbutton.y)) {
|
||||||
LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
|
LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
|
||||||
if (icon) {
|
if (icon) {
|
||||||
launcher_action(icon);
|
launcher_action(icon, e);
|
||||||
}
|
}
|
||||||
task_drag = 0;
|
task_drag = 0;
|
||||||
return;
|
return;
|
||||||
|
@ -1035,6 +1105,9 @@ start:
|
||||||
if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
|
if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
|
||||||
while (XPending (server.dsp)) {
|
while (XPending (server.dsp)) {
|
||||||
XNextEvent(server.dsp, &e);
|
XNextEvent(server.dsp, &e);
|
||||||
|
#if HAVE_SN
|
||||||
|
sn_display_process_event (server.sn_dsp, &e);
|
||||||
|
#endif // HAVE_SN
|
||||||
|
|
||||||
panel = get_panel(e.xany.window);
|
panel = get_panel(e.xany.window);
|
||||||
if (panel && panel_autohide) {
|
if (panel && panel_autohide) {
|
||||||
|
|
Loading…
Reference in a new issue