diff options
author | Havoc Pennington <hp@redhat.com> | 2002-10-21 02:47:15 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2002-10-21 02:47:15 +0000 |
commit | ccaabe6206adab552c6daa70e892d0f66f9a4448 (patch) | |
tree | 781be3d608770e291b1632a2dec5d48bcadddf07 | |
parent | 3fda9848b002bcfb5fc376bbf5d36bb0f7851c9c (diff) | |
download | startup-notification-ccaabe6206adab552c6daa70e892d0f66f9a4448.tar.gz |
port to new setup, add multihead support
port to new setup, and blow away all monitoring stuff, just use
sn-monitor.h
make it all multihead-safe
port to new setup and strip the other stuff out
s/DESKTOP_LAUNCH_ID/DESKTOP_STARTUP_ID/ for env variable, add
_NET_STARTUP_ID window manager hint.
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | doc/startup-notification.txt | 13 | ||||
-rw-r--r-- | libsn/sn-common.c | 3 | ||||
-rw-r--r-- | libsn/sn-internals.h | 8 | ||||
-rw-r--r-- | libsn/sn-launchee.c | 157 | ||||
-rw-r--r-- | libsn/sn-launchee.h | 12 | ||||
-rw-r--r-- | libsn/sn-launcher.c | 856 | ||||
-rw-r--r-- | libsn/sn-launcher.h | 63 | ||||
-rw-r--r-- | libsn/sn-monitor.c | 696 | ||||
-rw-r--r-- | libsn/sn-monitor.h | 59 | ||||
-rw-r--r-- | libsn/sn-util.c | 18 | ||||
-rw-r--r-- | libsn/sn-xmessages.c | 64 | ||||
-rw-r--r-- | libsn/sn-xmessages.h | 4 | ||||
-rw-r--r-- | test/test-launchee.c | 17 | ||||
-rw-r--r-- | test/test-launcher.c | 35 | ||||
-rw-r--r-- | test/test-monitor.c | 93 | ||||
-rw-r--r-- | test/test-send-xmessage.c | 2 | ||||
-rw-r--r-- | test/test-watch-xmessages.c | 3 |
18 files changed, 398 insertions, 1725 deletions
@@ -1,5 +1,25 @@ 2002-10-20 Havoc Pennington <hp@pobox.com> + * libsn/sn-monitor.c: port to new setup, add multihead support + + * libsn/sn-launcher.c: port to new setup, and blow away + all monitoring stuff, just use sn-monitor.h + + * libsn/sn-xmessages.c: make it all multihead-safe + + * libsn/sn-launchee.c: port to new setup and strip the other stuff + out + + * doc/startup-notification.txt: + s/DESKTOP_LAUNCH_ID/DESKTOP_STARTUP_ID/ for env variable, + add _NET_STARTUP_ID window manager hint. + +2002-10-20 Havoc Pennington <hp@pobox.com> + + * doc/startup-notification.txt: new docs, new proposed spec + +2002-10-20 Havoc Pennington <hp@pobox.com> + * Massively rename everything from liblf to libsn, and reimport to CVS. diff --git a/doc/startup-notification.txt b/doc/startup-notification.txt index 1406b1e..1939c19 100644 --- a/doc/startup-notification.txt +++ b/doc/startup-notification.txt @@ -262,7 +262,7 @@ To communicate the startup sequence information from a launcher process to a launchee process, when possible an environment variable should be used: - DESKTOP_LAUNCH_ID + DESKTOP_STARTUP_ID value of the "ID" field in the "new" message Mechanisms other than the environment variable may be used as well, as @@ -271,7 +271,7 @@ the launchee code is in a process started by the launcher code; if they are in the same process the environment variable may not be relevant. -Desktop entry extensions +Desktop entry spec extensions === StartupNotify=BOOLEAN @@ -285,6 +285,15 @@ StartupWMClass=STRING If true, it is KNOWN that the application will map at least one window with the given string as its WM class or WM name hint. +EWMH spec extensions +=== + +_NET_STARTUP_ID, UTF8_STRING + + The ID used for the startup sequence for the window. If set + on a group leader window, applies to all application windows + in that group that do not set their own _NET_STARTUP_ID. + A. Sample code to send X message === diff --git a/libsn/sn-common.c b/libsn/sn-common.c index b6c449e..33f6237 100644 --- a/libsn/sn-common.c +++ b/libsn/sn-common.c @@ -168,9 +168,6 @@ sn_display_process_event (SnDisplay *display, retval = FALSE; - if (sn_internal_launcher_process_event (display, xevent)) - retval = TRUE; - if (sn_internal_monitor_process_event (display, xevent)) retval = TRUE; diff --git a/libsn/sn-internals.h b/libsn/sn-internals.h index d4e2953..5f73c6d 100644 --- a/libsn/sn-internals.h +++ b/libsn/sn-internals.h @@ -49,10 +49,6 @@ SN_BEGIN_DECLS #define NULL ((void*) 0) #endif -/* --- From sn-launcher.c --- */ -sn_bool_t sn_internal_launcher_process_event (SnDisplay *display, - XEvent *xevent); - /* --- From sn-monitor.c --- */ sn_bool_t sn_internal_monitor_process_event (SnDisplay *display, XEvent *xevent); @@ -67,6 +63,10 @@ void sn_internal_strfreev (char **strings); unsigned long sn_internal_string_to_ulong (const char* str); +void sn_internal_append_to_string (char **append_to, + int *current_len, + const char *append); + /* --- From sn-xmessages.c --- */ sn_bool_t sn_internal_xmessage_process_event (SnDisplay *display, XEvent *xevent); diff --git a/libsn/sn-launchee.c b/libsn/sn-launchee.c index bade52c..bdf9ab3 100644 --- a/libsn/sn-launchee.c +++ b/libsn/sn-launchee.c @@ -23,31 +23,32 @@ */ #include "sn-launchee.h" #include "sn-internals.h" +#include "sn-xmessages.h" #include <errno.h> struct SnLauncheeContext { int refcount; SnDisplay *display; - char *launch_id; - Window launch_window; + int screen; + char *startup_id; }; /** * sn_launchee_context_new: * @display: an #SnDisplay - * @launch_id: launch ID as in DESKTOP_LAUNCH_ID - * @launch_window: launch window as in DESKTOP_LAUNCH_WINDOW + * @screen: an X screen number + * @startup_id: launch ID as in DESKTOP_STARTUP_ID env variable * - * Creates a new launchee-side context for the launch feedback + * Creates a new launchee-side context for the startup notification * protocol. * * Return value: a new launchee context **/ SnLauncheeContext* sn_launchee_context_new (SnDisplay *display, - const char *launch_id, - Window launch_window) + int screen, + const char *startup_id) { SnLauncheeContext *context; @@ -57,11 +58,9 @@ sn_launchee_context_new (SnDisplay *display, context->display = display; sn_display_ref (context->display); - - context->launch_id = sn_malloc (strlen (launch_id) + 1); - strcpy (context->launch_id, launch_id); - - context->launch_window = launch_window; + context->screen = screen; + + context->startup_id = sn_internal_strdup (startup_id); return context; } @@ -69,33 +68,27 @@ sn_launchee_context_new (SnDisplay *display, /** * sn_launchee_context_new_from_environment: * @display: an #SnDisplay + * @screen: an X screen number * - * Tries to create an #SnLauncheeContext given information in - * the program's environment (DESKTOP_LAUNCH_ID and DESKTOP_LAUNCH_WINDOW - * environment variables). Returns %NULL if the env variables are not - * available or can't be parsed. + * Tries to create an #SnLauncheeContext given information in the + * program's environment (DESKTOP_STARTUP_ID environment + * variable). Returns %NULL if the env variables are not available or + * can't be parsed. * * Return value: a new #SnLauncheeContext or %NULL **/ SnLauncheeContext* -sn_launchee_context_new_from_environment (SnDisplay *display) +sn_launchee_context_new_from_environment (SnDisplay *display, + int screen) { const char *id_str; - const char *window_str; - unsigned long window; - - id_str = getenv ("DESKTOP_LAUNCH_ID"); - window_str = getenv ("DESKTOP_LAUNCH_WINDOW"); - if (id_str == NULL || window_str == NULL) - return NULL; - - window = sn_internal_string_to_ulong (window_str); + id_str = getenv ("DESKTOP_STARTUP_ID"); - if (window == None) + if (id_str == NULL) return NULL; - return sn_launchee_context_new (display, id_str, window); + return sn_launchee_context_new (display, screen, id_str); } void @@ -110,92 +103,57 @@ sn_launchee_context_unref (SnLauncheeContext *context) context->refcount -= 1; if (context->refcount == 0) { - sn_free (context->launch_id); + sn_free (context->startup_id); sn_free (context); } } -Window -sn_launchee_context_get_launch_window (SnLauncheeContext *context) -{ - return context->launch_window; -} - -const char* -sn_launchee_context_get_launch_id (SnLauncheeContext *context) -{ - return context->launch_id; -} - /** - * sn_launchee_context_pulse: + * sn_launchee_context_get_startup_id: * @context: an #SnLauncheeContext - * - * Notifies the launcher that progress is being made. Should be - * called regularly during a long launch operation. * - **/ -void -sn_launchee_context_pulse (SnLauncheeContext *context) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = sn_display_get_x_display (context->display); - xev.xclient.window = context->launch_window; - xev.xclient.message_type = sn_internal_atom_get (context->display, - "_NET_LAUNCH_PULSE"); - xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - - sn_display_error_trap_push (context->display); - XSendEvent (sn_display_get_x_display (context->display), - context->launch_window, - False, - PropertyChangeMask, - &xev); - XFlush (sn_display_get_x_display (context->display)); - sn_display_error_trap_pop (context->display); -} - -/** - * sn_launchee_context_cancel: - * @context: an #SnLauncheeContext - * - * Called by the launchee application to cancel a launch (will - * probably cause the launcher to kill the launchee). + * Get the startup ID for the context. * + * Return value: the startup ID for the context. **/ -void -sn_launchee_context_cancel (SnLauncheeContext *context) +const char* +sn_launchee_context_get_startup_id (SnLauncheeContext *context) { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_CANCELED", - 0); + return context->startup_id; } + /** * sn_launchee_context_complete: * @context: an #SnLauncheeContext * - * Called by the launchee application when it is fully started up - * and launch feedback should end. + * Called by the launchee when it is fully started up and the startup + * sequence should end. * **/ void sn_launchee_context_complete (SnLauncheeContext *context) { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_COMPLETE", - 0); + char *keys[2]; + char *vals[2]; + char *message; + + keys[0] = "ID"; + keys[1] = NULL; + vals[0] = context->startup_id; + vals[1] = NULL; + + message = sn_internal_serialize_message ("remove", + (const char**) keys, + (const char **) vals); + + sn_internal_broadcast_xmessage (context->display, + context->screen, + "_NET_STARTUP_INFO", + message); + + sn_free (message); } /** @@ -203,12 +161,11 @@ sn_launchee_context_complete (SnLauncheeContext *context) * @context: a #SnLauncheeContext * @xwindow: window to be set up * - * Sets up @xwindow, marking it as launched by the launch sequence - * represented by @context. For example sets the _NET_LAUNCH_ID - * property. Only the group leader windows of an application - * MUST be set up with this function, though if - * any other windows come from a separate launch sequence, - * they can be setup up separately. + * Sets up @xwindow, marking it as launched by the startup sequence + * represented by @context. For example sets the _NET_STARTUP_ID + * property. Only the group leader windows of an application MUST be + * set up with this function, though if any other windows come from a + * separate startup sequence, they can be set up separately. * **/ void @@ -217,6 +174,6 @@ sn_launchee_context_setup_window (SnLauncheeContext *context, { sn_internal_set_string (context->display, xwindow, - "_NET_LAUNCH_ID", - context->launch_id); + "_NET_STARTUP_ID", + context->startup_id); } diff --git a/libsn/sn-launchee.h b/libsn/sn-launchee.h index ee9f189..bdd6081 100644 --- a/libsn/sn-launchee.h +++ b/libsn/sn-launchee.h @@ -34,15 +34,13 @@ SN_BEGIN_DECLS typedef struct SnLauncheeContext SnLauncheeContext; SnLauncheeContext* sn_launchee_context_new (SnDisplay *display, - const char *launch_id, - Window launch_window); -SnLauncheeContext* sn_launchee_context_new_from_environment (SnDisplay *display); + int screen, + const char *startup_id); +SnLauncheeContext* sn_launchee_context_new_from_environment (SnDisplay *display, + int screen); void sn_launchee_context_ref (SnLauncheeContext *context); void sn_launchee_context_unref (SnLauncheeContext *context); -Window sn_launchee_context_get_launch_window (SnLauncheeContext *context); -const char* sn_launchee_context_get_launch_id (SnLauncheeContext *context); -void sn_launchee_context_pulse (SnLauncheeContext *context); -void sn_launchee_context_cancel (SnLauncheeContext *context); +const char* sn_launchee_context_get_startup_id (SnLauncheeContext *context); void sn_launchee_context_complete (SnLauncheeContext *context); void sn_launchee_context_setup_window (SnLauncheeContext *context, Window xwindow); diff --git a/libsn/sn-launcher.c b/libsn/sn-launcher.c index 520a342..3e27d35 100644 --- a/libsn/sn-launcher.c +++ b/libsn/sn-launcher.c @@ -23,9 +23,11 @@ */ #include "sn-launcher.h" #include "sn-internals.h" +#include "sn-xmessages.h" #include <sys/types.h> #include <unistd.h> +#include <assert.h> static SnList* context_list = NULL; @@ -33,38 +35,28 @@ struct SnLauncherContext { int refcount; SnDisplay *display; - SnLauncherEventFunc event_func; - void *event_func_data; - SnFreeFunc free_data_func; - char *launch_id; - Window launch_window; - SnLaunchType type; - Window geometry_window; + int screen; + char *startup_id; char *name; char *description; int workspace; - char *resource_class; - char *resource_name; - char *window_title; + char *wmclass; char *binary_name; - int pid; char *icon_name; - int x, y, width, height; - unsigned int supports_cancel : 1; unsigned int completed : 1; unsigned int canceled : 1; - unsigned int geometry_set : 1; }; /** * sn_launcher_context_new: * @display: an #SnDisplay + * @screen: X screen number * @event_func: function to be called when a notable event occurs * @event_func_data: data to pass to @event_func * @free_data_func: function to be called on @event_func_data when freeing the context * * Creates a new launcher context, to be used by the program that is - * starting a launch sequence. For example a file manager might + * starting a startup sequence. For example a file manager might * create a launcher context when the user double-clicks on * an application icon. * @@ -72,9 +64,7 @@ struct SnLauncherContext **/ SnLauncherContext* sn_launcher_context_new (SnDisplay *display, - SnLauncherEventFunc event_func, - void *event_func_data, - SnFreeFunc free_data_func) + int screen) { SnLauncherContext *context; @@ -86,13 +76,8 @@ sn_launcher_context_new (SnDisplay *display, context->refcount = 1; context->display = display; sn_display_ref (context->display); - context->event_func = event_func; - context->event_func_data = event_func_data; - context->free_data_func = free_data_func; context->workspace = -1; - context->pid = -1; - context->type = SN_LAUNCH_TYPE_OTHER; sn_list_prepend (context_list, context); @@ -127,26 +112,14 @@ sn_launcher_context_unref (SnLauncherContext *context) { sn_list_remove (context_list, context); - if (context->free_data_func) - (* context->free_data_func) (context->event_func_data); - - sn_free (context->launch_id); - - if (context->launch_window != None) - { - sn_display_error_trap_push (context->display); - - XDestroyWindow (sn_display_get_x_display (context->display), - context->launch_window); - - sn_display_error_trap_pop (context->display); - } + sn_free (context->startup_id); sn_display_unref (context->display); sn_free (context); } } + static char* strip_slashes (const char *src) { @@ -173,7 +146,7 @@ strip_slashes (const char *src) * @launchee_name: name of the launchee app, suitable for debug output * @timestamp: X timestamp of event causing the launch * - * Initiates a launch sequence. All the properties of the launch (such + * Initiates a startup sequence. All the properties of the launch (such * as type, geometry, description) should be set up prior to * initiating the sequence. **/ @@ -188,12 +161,16 @@ sn_launcher_context_initiate (SnLauncherContext *context, static char hostbuf[257]; char *s; int len; - Display *xdisplay; char *canonicalized_launcher; char *canonicalized_launchee; - Atom atoms[1]; + int i; +#define MAX_PROPS 12 + char *names[MAX_PROPS]; + char *values[MAX_PROPS]; + char *message; + char workspacebuf[257]; - if (context->launch_id != NULL) + if (context->startup_id != NULL) { fprintf (stderr, "%s called twice for the same SnLaunchContext\n", __FUNCTION__); @@ -220,302 +197,89 @@ sn_launcher_context_initiate (SnLauncherContext *context, canonicalized_launcher, canonicalized_launchee, (unsigned long) timestamp, (int) getpid (), (int) sequence_number, hostbuf); ++sequence_number; - + sn_free (canonicalized_launcher); sn_free (canonicalized_launchee); - context->launch_id = s; - - xdisplay = sn_display_get_x_display (context->display); - - { - XSetWindowAttributes attrs; - - attrs.override_redirect = True; - attrs.event_mask = PropertyChangeMask | StructureNotifyMask; - - context->launch_window = - XCreateWindow (xdisplay, - RootWindow (xdisplay, 0), - -100, -100, 1, 1, - 0, - CopyFromParent, - CopyFromParent, - CopyFromParent, - CWOverrideRedirect | CWEventMask, - &attrs); - } - - /* push outer error to allow avoiding XSync after every - * property set - */ - sn_display_error_trap_push (context->display); + context->startup_id = s; - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_ID", - context->launch_id); - - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_HOSTNAME", - hostbuf); - - switch (context->type) - { - case SN_LAUNCH_TYPE_OTHER: - atoms[0] = sn_internal_atom_get (context->display, - "_NET_LAUNCH_TYPE_OTHER"); - break; - case SN_LAUNCH_TYPE_DOCK_ICON: - atoms[0] = sn_internal_atom_get (context->display, - "_NET_LAUNCH_TYPE_DOCK_ICON"); - break; - case SN_LAUNCH_TYPE_DESKTOP_ICON: - atoms[0] = sn_internal_atom_get (context->display, - "_NET_LAUNCH_TYPE_DESKTOP_ICON"); - break; - case SN_LAUNCH_TYPE_MENU: - atoms[0] = sn_internal_atom_get (context->display, - "_NET_LAUNCH_TYPE_MENU"); - break; - case SN_LAUNCH_TYPE_KEY_SHORTCUT: - atoms[0] = sn_internal_atom_get (context->display, - "_NET_LAUNCH_TYPE_KEY_SHORTCUT"); - break; - } - - sn_internal_set_atom_list (context->display, - context->launch_window, - "_NET_LAUNCH_TYPE", - atoms, 1); + i = 0; - if (context->geometry_set) - { - int cardinals[4]; - - cardinals[0] = context->x; - cardinals[1] = context->y; - cardinals[2] = context->width; - cardinals[3] = context->height; - - sn_internal_set_cardinal_list (context->display, - context->launch_window, - "_NET_LAUNCH_GEOMETRY", - cardinals, 4); - } - - if (context->geometry_window != None) - { - sn_internal_set_window (context->display, - context->launch_window, - "_NET_LAUNCH_GEOMETRY_WINDOW", - context->geometry_window); - } - - if (context->supports_cancel) - { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_SUPPORTS_CANCEL", - context->supports_cancel); - } + names[i] = "ID"; + values[i] = context->startup_id; + ++i; - if (context->name) + if (context->name != NULL) { - sn_internal_set_utf8_string (context->display, - context->launch_window, - "_NET_LAUNCH_NAME", - context->name); + names[i] = "NAME"; + values[i] = context->name; + ++i; } - if (context->description) + if (context->description != NULL) { - sn_internal_set_utf8_string (context->display, - context->launch_window, - "_NET_LAUNCH_DESCRIPTION", - context->description); + names[i] = "DESCRIPTION"; + values[i] = context->description; + ++i; } if (context->workspace >= 0) { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_DESKTOP", - context->workspace); + names[i] = "DESCRIPTION"; + sprintf (workspacebuf, "%d", context->workspace); + values[i] = workspacebuf; + ++i; } - if (context->pid >= 0) + if (context->wmclass != NULL) { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_PID", - context->pid); - } - - if (context->binary_name) - { - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_BINARY_NAME", - context->binary_name); - } - - if (context->icon_name) - { - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_ICON_NAME", - context->icon_name); + names[i] = "WMCLASS"; + values[i] = context->wmclass; + ++i; } - if (context->resource_class) + if (context->binary_name != NULL) { - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_LEGACY_RESOURCE_CLASS", - context->resource_class); + names[i] = "BIN"; + values[i] = context->binary_name; + ++i; } - if (context->resource_name) + if (context->icon_name != NULL) { - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_LEGACY_RESOURCE_NAME", - context->resource_name); + names[i] = "ICON"; + values[i] = context->icon_name; + ++i; } - if (context->window_title) - { - sn_internal_set_string (context->display, - context->launch_window, - "_NET_LAUNCH_LEGACY_NAME", - context->window_title); - } + assert (i < MAX_PROPS); - sn_display_error_trap_pop (context->display); + names[i] = NULL; + values[i] = NULL; - /* Sync to server (so the launch window ID exists for example) */ - XFlush (xdisplay); - - /* Initiation message to all screens */ - { - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = xdisplay; - xev.xclient.window = context->launch_window; - xev.xclient.message_type = sn_internal_atom_get (context->display, - "_NET_LAUNCH_INITIATE"); - xev.xclient.format = 32; - xev.xclient.data.l[0] = timestamp; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - - sn_internal_send_event_all_screens (context->display, - PropertyChangeMask, - &xev); - } -} + message = sn_internal_serialize_message ("new", + (const char**) names, + (const char**) values); -Window -sn_launcher_context_get_launch_window (SnLauncherContext *context) -{ - return context->launch_window; + sn_internal_broadcast_xmessage (context->display, + context->screen, + "_NET_STARTUP_INFO", + message); + + sn_free (message); } const char* -sn_launcher_context_get_launch_id (SnLauncherContext *context) +sn_launcher_context_get_startup_id (SnLauncherContext *context) { - return context->launch_id; + return context->startup_id; } sn_bool_t sn_launcher_context_get_initiated (SnLauncherContext *context) { - return context->launch_id != NULL; -} - -sn_bool_t -sn_launcher_context_get_canceled (SnLauncherContext *context) -{ - return context->canceled; -} - -/** - * sn_launcher_context_get_completed: - * @context: an #SnLauncherContext - * - * Returns %TRUE if _NET_LAUNCH_COMPLETE has been set or the - * launch sequence window has been destroyed. - * - * Return value: %TRUE if the launch sequence has been completed - **/ -sn_bool_t -sn_launcher_context_get_completed (SnLauncherContext *context) -{ - return context->completed; -} - -/** - * sn_launcher_context_cancel: - * @context: an #SnLauncherContext - * - * Marks the launch canceled by setting the _NET_LAUNCH_CANCELED - * property on the launch window. May not be called if the launch has - * not been initiated. An #SN_LAUNCHER_EVENT_CANCELED event should be - * received in response to the cancellation, under normal - * circumstances. - * - * sn_launcher_context_cancel() should be called to request a - * cancellation. Normally the launcher process is the process that - * performs the cancellation as well, in response to an - * #SN_LAUNCHER_EVENT_CANCELED event. - * - **/ -void -sn_launcher_context_cancel (SnLauncherContext *context) -{ - if (context->launch_id == NULL) - { - fprintf (stderr, "%s called for an SnLauncherContext that hasn't been initiated\n", - __FUNCTION__); - return; - } - - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_CANCELED", - 0); -} - -/** - * sn_launcher_context_complete: - * @context: an #SnLauncherContext - * - * Marks @context as completed. Normally the launchee process marks a - * launch sequence completed, however the launcher has to do it - * if the launch is canceled. - * - **/ -void -sn_launcher_context_complete (SnLauncherContext *context) -{ - if (context->launch_id == NULL) - { - fprintf (stderr, "%s called for an SnLauncherContext that hasn't been initiated\n", - __FUNCTION__); - return; - } - - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_COMPLETE", - 0); + return context->startup_id != NULL; } /** @@ -524,7 +288,7 @@ sn_launcher_context_complete (SnLauncherContext *context) * * This function should be called after forking, but before exec(), in * the child process being launched. It sets up the environment variables - * telling the child process about the launch ID and launch window. + * telling the child process about the launch ID. * This function will leak the strings passed to putenv() so should * only be used prior to an exec(). * @@ -532,11 +296,9 @@ sn_launcher_context_complete (SnLauncherContext *context) void sn_launcher_context_setup_child_process (SnLauncherContext *context) { - char *launch_id; - char *s; - char *launch_window; + char *startup_id; - if (context->launch_id == NULL) + if (context->startup_id == NULL) { fprintf (stderr, "%s called for an SnLauncherContext that hasn't been initiated\n", __FUNCTION__); @@ -545,61 +307,25 @@ sn_launcher_context_setup_child_process (SnLauncherContext *context) /* Man we need glib here */ - launch_id = sn_malloc (strlen (context->launch_id) + strlen ("DESKTOP_LAUNCH_ID") + 3); - strcpy (launch_id, "DESKTOP_LAUNCH_ID="); - strcat (launch_id, context->launch_id); - - putenv (launch_id); - - launch_window = sn_malloc (strlen ("DESKTOP_LAUNCH_WINDOW") + 128); - strcpy (launch_window, "DESKTOP_LAUNCH_WINDOW="); - s = launch_window; - while (*s) - ++s; - - snprintf (s, 100, "0x%lx", context->launch_window); + startup_id = sn_malloc (strlen (context->startup_id) + strlen ("DESKTOP_STARTUP_ID") + 3); + strcpy (startup_id, "DESKTOP_STARTUP_ID="); + strcat (startup_id, context->startup_id); - putenv (launch_window); + putenv (startup_id); /* Can't free strings passed to putenv */ } -#define WARN_ALREADY_INITIATED(context) do { if ((context)->launch_id != NULL) { \ +/* FIXME use something pluggable, not fprintf */ +#define WARN_ALREADY_INITIATED(context) do { if ((context)->startup_id != NULL) { \ fprintf (stderr, "%s called for an SnLauncherContext that has already been initiated\n", \ __FUNCTION__); \ return; \ } } while (0) void -sn_launcher_context_set_launch_type (SnLauncherContext *context, - SnLaunchType type) -{ - WARN_ALREADY_INITIATED (context); - - context->type = type; -} - -void -sn_launcher_context_set_geometry_window (SnLauncherContext *context, - Window xwindow) -{ - WARN_ALREADY_INITIATED (context); - - context->geometry_window = xwindow; -} - -void -sn_launcher_context_set_supports_cancel (SnLauncherContext *context, - sn_bool_t supports_cancel) -{ - WARN_ALREADY_INITIATED (context); - - context->supports_cancel = supports_cancel; -} - -void -sn_launcher_context_set_launch_name (SnLauncherContext *context, - const char *name) +sn_launcher_context_set_name (SnLauncherContext *context, + const char *name) { WARN_ALREADY_INITIATED (context); @@ -608,8 +334,8 @@ sn_launcher_context_set_launch_name (SnLauncherContext *context, } void -sn_launcher_context_set_launch_description (SnLauncherContext *context, - const char *description) +sn_launcher_context_set_description (SnLauncherContext *context, + const char *description) { WARN_ALREADY_INITIATED (context); @@ -618,8 +344,8 @@ sn_launcher_context_set_launch_description (SnLauncherContext *context, } void -sn_launcher_context_set_launch_workspace (SnLauncherContext *context, - int workspace) +sn_launcher_context_set_workspace (SnLauncherContext *context, + int workspace) { WARN_ALREADY_INITIATED (context); @@ -627,33 +353,13 @@ sn_launcher_context_set_launch_workspace (SnLauncherContext *context, } void -sn_launcher_context_set_legacy_resource_class (SnLauncherContext *context, - const char *klass) +sn_launcher_context_set_wmclass (SnLauncherContext *context, + const char *klass) { WARN_ALREADY_INITIATED (context); - sn_free (context->resource_class); - context->resource_class = sn_internal_strdup (klass); -} - -void -sn_launcher_context_set_legacy_resource_name (SnLauncherContext *context, - const char *name) -{ - WARN_ALREADY_INITIATED (context); - - sn_free (context->resource_name); - context->resource_name = sn_internal_strdup (name); -} - -void -sn_launcher_context_set_legacy_window_title (SnLauncherContext *context, - const char *title) -{ - WARN_ALREADY_INITIATED (context); - - sn_free (context->window_title); - context->window_title = sn_internal_strdup (title); + sn_free (context->wmclass); + context->wmclass = sn_internal_strdup (klass); } void @@ -667,22 +373,6 @@ sn_launcher_context_set_binary_name (SnLauncherContext *context, } void -sn_launcher_context_set_pid (SnLauncherContext *context, - int pid) -{ - context->pid = pid; - - /* set the X property if launch window already exists */ - if (context->launch_id != NULL) - { - sn_internal_set_cardinal (context->display, - context->launch_window, - "_NET_LAUNCH_PID", - context->pid); - } -} - -void sn_launcher_context_set_icon_name (SnLauncherContext *context, const char *name) { @@ -691,385 +381,3 @@ sn_launcher_context_set_icon_name (SnLauncherContext *context, sn_free (context->icon_name); context->icon_name = sn_internal_strdup (name); } - -struct SnLauncherEvent -{ - int refcount; - SnLauncherEventType type; - Time timestamp; - SnLauncherContext *context; -}; - -/** - * sn_launcher_event_copy: - * @event: event to copy - * - * Creates a copy of @event, the copy has a reference count of one. - * - * Return value: a new #SnLauncherEvent that's a copy of @event - **/ -SnLauncherEvent* -sn_launcher_event_copy (SnLauncherEvent *event) -{ - SnLauncherEvent *copy; - - copy = sn_new (SnLauncherEvent, 1); - - copy->refcount = 1; - copy->type = event->type; - copy->timestamp = event->timestamp; - copy->context = event->context; - if (copy->context) - sn_launcher_context_ref (copy->context); - - return copy; -} - -/** - * sn_launcher_event_ref: - * @event: a #SnLauncherEvent - * - * Increments @event's reference count. - **/ -void -sn_launcher_event_ref (SnLauncherEvent *event) -{ - event->refcount += 1; -} - -/** - * sn_launcher_event_unref: - * @event: a #SnLauncherEvent - * - * Decrements @event's reference count and frees @event - * if the count reaches zero. - **/ -void -sn_launcher_event_unref (SnLauncherEvent *event) -{ - event->refcount -= 1; - - if (event->refcount == 0) - { - if (event->context) - sn_launcher_context_unref (event->context); - sn_free (event); - } -} - -/** - * sn_launcher_event_get_type: - * @event: a #SnLauncherEvent - * - * Gets the type of the launcher event. - * - * Return value: the type of event - **/ -SnLauncherEventType -sn_launcher_event_get_type (SnLauncherEvent *event) -{ - return event->type; -} - -/** - * sn_launcher_event_get_context: - * @event: a #SnLauncherEvent - * - * Gets the context associated with @event. The - * returned context is owned by the event, i.e. - * the caller of sn_launcher_event_get_context() should - * not unref the context. - * - * Return value: the context for this event - **/ -SnLauncherContext* -sn_launcher_event_get_context (SnLauncherEvent *event) -{ - return event->context; -} - -/** - * sn_launcher_event_get_time: - * @event: a #SnLauncherEvent - * - * Gets the X Window System timestamp associated with this launcher - * event. - * - * Return value: timestamp for the event, or CurrentTime if none available - **/ -Time -sn_launcher_event_get_time (SnLauncherEvent *event) -{ - return event->timestamp; -} - -static sn_bool_t -check_cardinal_exists (SnDisplay *display, - Window xwindow, - const char *property) -{ - int val; - - return sn_internal_get_cardinal (display, xwindow, property, - &val); -} - -typedef struct -{ - SnDisplay *display; - Window launch_window; - sn_bool_t result; -} HaveContextsData; - -static sn_bool_t -have_active_contexts_foreach (void *value, - void *data) -{ - SnLauncherContext *context = value; - HaveContextsData *hcd = data; - - if (!context->completed && - context->launch_window == hcd->launch_window && - sn_display_get_x_display (context->display) == - sn_display_get_x_display (hcd->display)) - { - hcd->result = TRUE; - return FALSE; - } - - return TRUE; -} - -typedef struct -{ - SnDisplay *display; - Window launch_window; - SnList *contexts; -} FindContextsData; - -static sn_bool_t -find_active_contexts_foreach (void *value, - void *data) -{ - SnLauncherContext *context = value; - FindContextsData *fcd = data; - - if (!context->completed && - context->launch_window == fcd->launch_window && - sn_display_get_x_display (context->display) == - sn_display_get_x_display (fcd->display)) - sn_list_prepend (fcd->contexts, context); - - return TRUE; -} - -typedef struct -{ - SnLauncherEvent *base_event; - SnList *events; -} CreateEventsData; - -static sn_bool_t -create_events_foreach (void *value, - void *data) -{ - SnLauncherContext *context = value; - CreateEventsData *ced = data; - SnLauncherEvent *event; - - event = sn_launcher_event_copy (ced->base_event); - event->context = context; - sn_launcher_context_ref (context); - - sn_list_prepend (ced->events, event); - - return TRUE; -} - -static sn_bool_t -dispatch_events_foreach (void *value, - void *data) -{ - SnLauncherEvent *event = value; - - /* Filter out duplicate events and update flags */ - switch (event->type) - { - case SN_LAUNCHER_EVENT_CANCELED: - if (event->context->canceled) - { - sn_launcher_event_unref (event); - event = NULL; - } - else - { - event->context->canceled = TRUE; - } - break; - case SN_LAUNCHER_EVENT_COMPLETED: - if (event->context->completed) - { - sn_launcher_event_unref (event); - event = NULL; - } - else - { - event->context->completed = TRUE; - } - break; - - default: - break; - } - - if (event) - { - if (event->context->event_func) - (* event->context->event_func) (event, - event->context->event_func_data); - sn_launcher_event_unref (event); - } - - return TRUE; -} - -static void -dispatch_event (SnDisplay *display, - Window launch_window, - SnLauncherEvent *event) -{ - /* Find all applicable contexts, create an event for each, and send - * the events out. - */ - FindContextsData fcd; - CreateEventsData ced; - - fcd.display = display; - fcd.launch_window = launch_window; - fcd.contexts = sn_list_new (); - - if (context_list != NULL) - sn_list_foreach (context_list, find_active_contexts_foreach, &fcd); - - ced.base_event = event; - ced.events = sn_list_new (); - sn_list_foreach (fcd.contexts, create_events_foreach, &ced); - - /* This unref's each event as it's dispatched */ - sn_list_foreach (ced.events, dispatch_events_foreach, NULL); - - sn_list_free (fcd.contexts); - sn_list_free (ced.events); -} - -sn_bool_t -sn_internal_launcher_process_event (SnDisplay *display, - XEvent *xevent) -{ - sn_bool_t retval; - SnLauncherEvent *event; - Window event_xwindow; - - if (context_list == NULL || - sn_list_empty (context_list)) - return FALSE; /* no one cares */ - - event_xwindow = None; - event = NULL; - retval = FALSE; - - switch (xevent->xany.type) - { - case PropertyNotify: - if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_CANCELED")) - { - event_xwindow = xevent->xproperty.window; - - if (check_cardinal_exists (display, event_xwindow, - "_NET_LAUNCH_CANCELED")) - { - event = sn_new (SnLauncherEvent, 1); - - event->refcount = 1; - event->type = SN_LAUNCHER_EVENT_CANCELED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - } - - retval = TRUE; - } - else if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_COMPLETE")) - { - event_xwindow = xevent->xproperty.window; - - if (check_cardinal_exists (display, event_xwindow, - "_NET_LAUNCH_COMPLETE")) - { - event = sn_new (SnLauncherEvent, 1); - - event->refcount = 1; - event->type = SN_LAUNCHER_EVENT_COMPLETED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - } - - retval = TRUE; - } - break; - - case ClientMessage: - if (xevent->xclient.message_type == - sn_internal_atom_get (display, - "_NET_LAUNCH_PULSE")) - { - event_xwindow = xevent->xclient.window; - - event = sn_new (SnLauncherEvent, 1); - - event->refcount = 1; - event->type = SN_LAUNCHER_EVENT_PULSE; - event->timestamp = CurrentTime; - event->context = NULL; - - retval = TRUE; - } - break; - - case DestroyNotify: - { - HaveContextsData hcd; - hcd.display = display; - hcd.launch_window = xevent->xdestroywindow.window; - hcd.result = FALSE; - if (context_list) - sn_list_foreach (context_list, have_active_contexts_foreach, &hcd); - if (hcd.result) - { - event_xwindow = hcd.launch_window; - - event = sn_new (SnLauncherEvent, 1); - - event->refcount = 1; - event->type = SN_LAUNCHER_EVENT_COMPLETED; - event->timestamp = CurrentTime; - event->context = NULL; - } - } - break; - - default: - break; - } - - if (event != NULL) - { - dispatch_event (display, event_xwindow, event); - - sn_launcher_event_unref (event); - } - - return retval; -} - diff --git a/libsn/sn-launcher.h b/libsn/sn-launcher.h index bafeef1..07ad7c6 100644 --- a/libsn/sn-launcher.h +++ b/libsn/sn-launcher.h @@ -32,22 +32,9 @@ SN_BEGIN_DECLS typedef struct SnLauncherContext SnLauncherContext; -typedef struct SnLauncherEvent SnLauncherEvent; - -typedef void (* SnLauncherEventFunc) (SnLauncherEvent *event, - void *user_data); - -typedef enum -{ - SN_LAUNCHER_EVENT_CANCELED, - SN_LAUNCHER_EVENT_COMPLETED, - SN_LAUNCHER_EVENT_PULSE -} SnLauncherEventType; SnLauncherContext* sn_launcher_context_new (SnDisplay *display, - SnLauncherEventFunc event_func, - void *event_func_data, - SnFreeFunc free_data_func); + int screen); void sn_launcher_context_ref (SnLauncherContext *context); void sn_launcher_context_unref (SnLauncherContext *context); @@ -56,47 +43,23 @@ void sn_launcher_context_initiate (SnLauncherContext *context, const char *launcher_name, const char *launchee_name, Time timestamp); -Window sn_launcher_context_get_launch_window (SnLauncherContext *context); const char* sn_launcher_context_get_launch_id (SnLauncherContext *context); sn_bool_t sn_launcher_context_get_initiated (SnLauncherContext *context); -sn_bool_t sn_launcher_context_get_canceled (SnLauncherContext *context); -sn_bool_t sn_launcher_context_get_completed (SnLauncherContext *context); -void sn_launcher_context_cancel (SnLauncherContext *context); -void sn_launcher_context_complete (SnLauncherContext *context); void sn_launcher_context_setup_child_process (SnLauncherContext *context); -void sn_launcher_context_set_launch_type (SnLauncherContext *context, - SnLaunchType type); -void sn_launcher_context_set_geometry_window (SnLauncherContext *context, - Window xwindow); -void sn_launcher_context_set_supports_cancel (SnLauncherContext *context, - sn_bool_t supports_cancel); -void sn_launcher_context_set_launch_name (SnLauncherContext *context, - const char *name); -void sn_launcher_context_set_launch_description (SnLauncherContext *context, - const char *description); -void sn_launcher_context_set_launch_workspace (SnLauncherContext *context, - int workspace); -void sn_launcher_context_set_legacy_resource_class (SnLauncherContext *context, - const char *klass); -void sn_launcher_context_set_legacy_resource_name (SnLauncherContext *context, - const char *name); -void sn_launcher_context_set_legacy_window_title (SnLauncherContext *context, - const char *title); -void sn_launcher_context_set_binary_name (SnLauncherContext *context, - const char *name); -void sn_launcher_context_set_pid (SnLauncherContext *context, - int pid); -void sn_launcher_context_set_icon_name (SnLauncherContext *context, - const char *name); - -SnLauncherEvent* sn_launcher_event_copy (SnLauncherEvent *event); -void sn_launcher_event_ref (SnLauncherEvent *event); -void sn_launcher_event_unref (SnLauncherEvent *event); -SnLauncherEventType sn_launcher_event_get_type (SnLauncherEvent *event); -SnLauncherContext* sn_launcher_event_get_context (SnLauncherEvent *event); -Time sn_launcher_event_get_time (SnLauncherEvent *event); +void sn_launcher_context_set_name (SnLauncherContext *context, + const char *name); +void sn_launcher_context_set_description (SnLauncherContext *context, + const char *description); +void sn_launcher_context_set_workspace (SnLauncherContext *context, + int workspace); +void sn_launcher_context_set_wmclass (SnLauncherContext *context, + const char *klass); +void sn_launcher_context_set_binary_name (SnLauncherContext *context, + const char *name); +void sn_launcher_context_set_icon_name (SnLauncherContext *context, + const char *name); SN_END_DECLS diff --git a/libsn/sn-monitor.c b/libsn/sn-monitor.c index c657114..c3f3f1a 100644 --- a/libsn/sn-monitor.c +++ b/libsn/sn-monitor.c @@ -25,12 +25,11 @@ #include "sn-internals.h" #include "sn-xmessages.h" -#define KDE_STARTUP_INFO_ATOM "_KDE_STARTUP_INFO" - struct SnMonitorContext { int refcount; SnDisplay *display; + int screen; SnMonitorEventFunc event_func; void *event_func_data; SnFreeFunc free_data_func; @@ -45,42 +44,31 @@ struct SnMonitorEvent int refcount; SnMonitorEventType type; SnMonitorContext *context; - SnLaunchSequence *sequence; - Time timestamp; + SnStartupSequence *sequence; + Window xwindow; /* where event occurred */ }; -struct SnLaunchSequence +struct SnStartupSequence { int refcount; - - char *id; + SnDisplay *display; + int screen; - /* launch_window is NULL for Xmessage-based launches */ - Window launch_window; - + char *id; + char *name; char *description; - char *resource_class; - char *resource_name; - char *window_title; + char *wmclass; int workspace; char *binary_name; - char *hostname; - char *icon_name; - int pid; - - /* geometry */ - Window geometry_window; - int x, y, width, height; + char *icon_name; - unsigned int geometry_set : 1; - unsigned int canceled : 1; unsigned int completed : 1; - unsigned int supports_cancel : 1; + unsigned int canceled : 1; int creation_serial; }; @@ -91,23 +79,25 @@ static int next_sequence_serial = 0; static void xmessage_func (SnDisplay *display, const char *message_type, + Window xwindow, const char *message, void *user_data); /** * sn_monitor_context_new: * @display: an #SnDisplay + * @screen: an X screen number * @event_func: function to call when an event is received * @event_func_data: extra data to pass to @event_func * @free_data_func: function to free @event_func_data when the context is freed * - * Creates a new context for monitoring launch sequences. Normally + * Creates a new context for monitoring startup sequences. Normally * only launch feedback indicator applications such as the window * manager or task manager would use #SnMonitorContext. * #SnLauncherContext and #SnLauncheeContext are more often used by * applications. * - * To detect launch sequence initiations, PropertyChangeMask must be + * To detect startup sequence initiations, PropertyChangeMask must be * selected on all root windows for a display. libsn does not do this * for you because it's pretty likely to mess something up. So you * have to do it yourself in programs that use #SnMonitorContext. @@ -116,6 +106,7 @@ static void xmessage_func (SnDisplay *display, **/ SnMonitorContext* sn_monitor_context_new (SnDisplay *display, + int screen, SnMonitorEventFunc event_func, void *event_func_data, SnFreeFunc free_data_func) @@ -131,13 +122,15 @@ sn_monitor_context_new (SnDisplay *display, context->display = display; sn_display_ref (context->display); - + context->screen = screen; + if (context_list == NULL) context_list = sn_list_new (); if (sn_list_empty (context_list)) sn_internal_add_xmessage_func (display, - KDE_STARTUP_INFO_ATOM, + screen, + "_NET_STARTUP_INFO", xmessage_func, NULL, NULL); @@ -180,7 +173,8 @@ sn_monitor_context_unref (SnMonitorContext *context) if (sn_list_empty (context_list)) sn_internal_remove_xmessage_func (context->display, - KDE_STARTUP_INFO_ATOM, + context->screen, + "_NET_STARTUP_INFO", xmessage_func, NULL); @@ -208,7 +202,7 @@ sn_monitor_event_unref (SnMonitorEvent *event) if (event->context) sn_monitor_context_unref (event->context); if (event->sequence) - sn_launch_sequence_unref (event->sequence); + sn_startup_sequence_unref (event->sequence); sn_free (event); } } @@ -228,10 +222,9 @@ sn_monitor_event_copy (SnMonitorEvent *event) sn_monitor_context_ref (copy->context); copy->sequence = event->sequence; if (copy->sequence) - sn_launch_sequence_ref (copy->sequence); - - copy->timestamp = event->timestamp; - + sn_startup_sequence_ref (copy->sequence); + copy->xwindow = event->xwindow; + return copy; } @@ -241,8 +234,8 @@ sn_monitor_event_get_type (SnMonitorEvent *event) return event->type; } -SnLaunchSequence* -sn_monitor_event_get_launch_sequence (SnMonitorEvent *event) +SnStartupSequence* +sn_monitor_event_get_startup_sequence (SnMonitorEvent *event) { return event->sequence; } @@ -253,163 +246,14 @@ sn_monitor_event_get_context (SnMonitorEvent *event) return event->context; } -Time -sn_monitor_event_get_time (SnMonitorEvent *event) -{ - return event->timestamp; -} - -static void -update_geometry (SnLaunchSequence *sequence) -{ - int *vals; - int n_vals; - - sequence->geometry_set = FALSE; - - vals = NULL; - n_vals = 0; - if (sn_internal_get_cardinal_list (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_GEOMETRY", - &vals, &n_vals) && - n_vals == 4) - { - sequence->x = vals[0]; - sequence->y = vals[1]; - sequence->width = vals[2]; - sequence->height = vals[3]; - } - - sn_free (vals); -} - -static void -update_pid (SnLaunchSequence *sequence) -{ - int val; - - sequence->pid = -1; - - val = -1; - if (sn_internal_get_cardinal (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_PID", - &val)) - sequence->pid = val; -} - -static SnLaunchSequence* -sn_launch_sequence_new (SnDisplay *display, - Window launch_window) -{ - SnLaunchSequence *sequence; - char *id; - int val; - - /* Select input, then get _NET_LAUNCH_ID, - * because we want to be sure we detect a BadWindow - * if it happens prior to selecting input, and - * getting _NET_LAUNCH_ID will bomb on BadWindow - */ - if (launch_window != None) /* launch_window may be NULL for xmessage sequence */ - { - sn_display_error_trap_push (display); - XSelectInput (sn_display_get_x_display (display), - launch_window, - PropertyChangeMask | StructureNotifyMask); - sn_display_error_trap_pop (display); - - id = NULL; - if (!sn_internal_get_string (display, launch_window, - "_NET_LAUNCH_ID", &id)) - { - return NULL; - } - } - - sequence = sn_new0 (SnLaunchSequence, 1); - - sequence->refcount = 1; - - sequence->creation_serial = next_sequence_serial; - ++next_sequence_serial; - - sequence->id = id; - sequence->launch_window = launch_window; - sequence->display = display; - sn_display_ref (display); - - sequence->workspace = -1; /* not set */ - sequence->pid = -1; - - /* Update stuff that can change over time */ - update_geometry (sequence); - update_pid (sequence); - - if (sequence->launch_window != None) - { - /* Grab all the stuff that can't be changed later */ - sn_internal_get_utf8_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_NAME", - &sequence->name); - sn_internal_get_utf8_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_DESCRIPTION", - &sequence->description); - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_LEGACY_RESOURCE_CLASS", - &sequence->resource_class); - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_LEGACY_RESOURCE_NAME", - &sequence->resource_name); - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_LEGACY_NAME", - &sequence->window_title); - if (sn_internal_get_cardinal (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_DESKTOP", - &val)) - sequence->workspace = val; - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_BINARY_NAME", - &sequence->binary_name); - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_HOSTNAME", - &sequence->hostname); - sn_internal_get_string (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_ICON_NAME", - &sequence->icon_name); - sn_internal_get_window (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_GEOMETRY_WINDOW", - &sequence->geometry_window); - - if (sn_internal_get_cardinal (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_SUPPORTS_CANCEL", - &val)) - sequence->supports_cancel = val != 0; - } - - return sequence; -} - void -sn_launch_sequence_ref (SnLaunchSequence *sequence) +sn_startup_sequence_ref (SnStartupSequence *sequence) { sequence->refcount += 1; } void -sn_launch_sequence_unref (SnLaunchSequence *sequence) +sn_startup_sequence_unref (SnStartupSequence *sequence) { sequence->refcount -= 1; @@ -419,12 +263,9 @@ sn_launch_sequence_unref (SnLaunchSequence *sequence) sn_free (sequence->name); sn_free (sequence->description); - sn_free (sequence->resource_class); - sn_free (sequence->resource_name); - sn_free (sequence->window_title); + sn_free (sequence->wmclass); sn_free (sequence->binary_name); sn_free (sequence->icon_name); - sn_free (sequence->hostname); sn_display_unref (sequence->display); sn_free (sequence); @@ -432,145 +273,73 @@ sn_launch_sequence_unref (SnLaunchSequence *sequence) } const char* -sn_launch_sequence_get_id (SnLaunchSequence *sequence) +sn_startup_sequence_get_id (SnStartupSequence *sequence) { return sequence->id; } -Window -sn_launch_sequence_get_window (SnLaunchSequence *sequence) -{ - return sequence->launch_window; -} - -sn_bool_t -sn_launch_sequence_get_geometry (SnLaunchSequence *sequence, - int *x, - int *y, - int *width, - int *height) -{ - if (sequence->geometry_set) - { - *x = sequence->x; - *y = sequence->y; - *width = sequence->width; - *height = sequence->height; - return TRUE; - } - else - { - *x = 0; - *y = 0; - *width = 0; - *height = 0; - return FALSE; - } -} - -Window -sn_launch_sequence_get_geometry_window (SnLaunchSequence *sequence) -{ - return sequence->geometry_window; -} - sn_bool_t -sn_launch_sequence_get_completed (SnLaunchSequence *sequence) +sn_startup_sequence_get_completed (SnStartupSequence *sequence) { return sequence->completed; } -sn_bool_t -sn_launch_sequence_get_canceled (SnLaunchSequence *sequence) -{ - return sequence->canceled; -} - const char* -sn_launch_sequence_get_name (SnLaunchSequence *sequence) +sn_startup_sequence_get_name (SnStartupSequence *sequence) { return sequence->name; } const char* -sn_launch_sequence_get_description (SnLaunchSequence *sequence) +sn_startup_sequence_get_description (SnStartupSequence *sequence) { return sequence->description; } int -sn_launch_sequence_get_workspace (SnLaunchSequence *sequence) +sn_startup_sequence_get_workspace (SnStartupSequence *sequence) { return sequence->workspace; } const char* -sn_launch_sequence_get_legacy_resource_class (SnLaunchSequence *sequence) -{ - return sequence->resource_class; -} - -const char* -sn_launch_sequence_get_legacy_resource_name (SnLaunchSequence *sequence) +sn_startup_sequence_get_wmclass (SnStartupSequence *sequence) { - return sequence->resource_name; + return sequence->wmclass; } const char* -sn_launch_sequence_get_legacy_window_title (SnLaunchSequence *sequence) -{ - return sequence->window_title; -} - -sn_bool_t -sn_launch_sequence_get_supports_cancel (SnLaunchSequence *sequence) -{ - return sequence->supports_cancel; -} - -int -sn_launch_sequence_get_pid (SnLaunchSequence *sequence) -{ - return sequence->pid; -} - -const char* -sn_launch_sequence_get_binary_name (SnLaunchSequence *sequence) +sn_startup_sequence_get_binary_name (SnStartupSequence *sequence) { return sequence->binary_name; } const char* -sn_launch_sequence_get_hostname (SnLaunchSequence *sequence) -{ - return sequence->hostname; -} - -const char* -sn_launch_sequence_get_icon_name (SnLaunchSequence *sequence) +sn_startup_sequence_get_icon_name (SnStartupSequence *sequence) { return sequence->icon_name; } -void -sn_launch_sequence_cancel (SnLaunchSequence *sequence) -{ - if (sequence->supports_cancel) - sn_internal_set_cardinal (sequence->display, - sequence->launch_window, - "_NET_LAUNCH_CANCELED", - 0); -} -static sn_bool_t -check_cardinal_exists (SnDisplay *display, - Window xwindow, - const char *property) +static SnStartupSequence* +sn_startup_sequence_new (SnDisplay *display) { - int val; + SnStartupSequence *sequence; + + sequence = sn_new0 (SnStartupSequence, 1); + + sequence->refcount = 1; - return sn_internal_get_cardinal (display, xwindow, property, - &val); + sequence->creation_serial = next_sequence_serial; + ++next_sequence_serial; + + sequence->id = NULL; + sequence->display = display; + sn_display_ref (display); + + sequence->workspace = -1; /* not set */ + + return sequence; } typedef struct @@ -589,7 +358,7 @@ create_context_events_foreach (void *value, SnMonitorContext *context = value; CreateContextEventsData *ced = data; - /* Don't send events for launch sequences initiated before the + /* Don't send events for startup sequences initiated before the * context was created */ if (ced->base_event->sequence->creation_serial >= @@ -662,61 +431,17 @@ filter_event (SnMonitorEvent *event) return retval; } -typedef struct -{ - SnDisplay *display; - Window launch_window; - SnLaunchSequence *found; -} FindSequenceData; - -static sn_bool_t -find_sequence_foreach (void *value, - void *data) -{ - SnLaunchSequence *sequence = value; - FindSequenceData *fsd = data; - - if (sequence->launch_window == fsd->launch_window && - sn_display_get_x_display (sequence->display) == - sn_display_get_x_display (fsd->display)) - { - fsd->found = sequence; - return FALSE; - } - - return TRUE; -} - -static SnLaunchSequence* -find_sequence_for_window (SnDisplay *display, - Window event_window) -{ - FindSequenceData fsd; - - if (sequence_list == NULL) - return NULL; - - fsd.display = display; - fsd.launch_window = event_window; - fsd.found = NULL; - - sn_list_foreach (sequence_list, find_sequence_foreach, &fsd); - - return fsd.found; -} - -static SnLaunchSequence* -add_sequence (SnDisplay *display, - Window event_xwindow) +static SnStartupSequence* +add_sequence (SnDisplay *display) { - SnLaunchSequence *sequence; + SnStartupSequence *sequence; sequence = - sn_launch_sequence_new (display, event_xwindow); + sn_startup_sequence_new (display); if (sequence) { - sn_launch_sequence_ref (sequence); /* ref held by sequence list */ + sn_startup_sequence_ref (sequence); /* ref held by sequence list */ if (sequence_list == NULL) sequence_list = sn_list_new (); sn_list_prepend (sequence_list, sequence); @@ -726,46 +451,21 @@ add_sequence (SnDisplay *display, } static void -remove_sequence (SnLaunchSequence *sequence) +remove_sequence (SnStartupSequence *sequence) { sn_list_remove (sequence_list, sequence); - sn_launch_sequence_unref (sequence); + sn_startup_sequence_unref (sequence); } static void dispatch_monitor_event (SnDisplay *display, - SnMonitorEvent *event, - Window event_xwindow) + SnMonitorEvent *event) { if (event->type == SN_MONITOR_EVENT_INITIATED) { if (event->sequence == NULL) - event->sequence = add_sequence (display, event_xwindow); + event->sequence = add_sequence (display); } - else if (event->sequence == NULL) - { - event->sequence = find_sequence_for_window (display, - event_xwindow); - if (event->sequence) - sn_launch_sequence_ref (event->sequence); /* ref held by event */ - } - - if (event->sequence != NULL) - { - switch (event->type) - { - case SN_MONITOR_EVENT_GEOMETRY_CHANGED: - update_geometry (event->sequence); - break; - - case SN_MONITOR_EVENT_PID_CHANGED: - update_pid (event->sequence); - break; - - default: - break; - } - } if (event->sequence != NULL && !filter_event (event)) @@ -794,170 +494,13 @@ sn_internal_monitor_process_event (SnDisplay *display, XEvent *xevent) { sn_bool_t retval; - SnMonitorEvent *event; - Window event_xwindow; if (context_list == NULL || sn_list_empty (context_list)) return FALSE; /* no one cares */ - - event_xwindow = None; - event = NULL; - retval = FALSE; - - switch (xevent->xany.type) - { - case PropertyNotify: - if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_CANCELED")) - { - event_xwindow = xevent->xproperty.window; - - if (check_cardinal_exists (display, event_xwindow, - "_NET_LAUNCH_CANCELED")) - { - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_CANCELED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - event->sequence = NULL; - - retval = TRUE; - } - } - else if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_COMPLETE")) - { - event_xwindow = xevent->xproperty.window; - - if (check_cardinal_exists (display, event_xwindow, - "_NET_LAUNCH_COMPLETE")) - { - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_COMPLETED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - event->sequence = NULL; - - retval = TRUE; - } - } - else if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_GEOMETRY")) - { - event_xwindow = xevent->xproperty.window; - - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_GEOMETRY_CHANGED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - event->sequence = NULL; - - retval = TRUE; - } - else if (xevent->xproperty.atom == - sn_internal_atom_get (display, "_NET_LAUNCH_PID")) - { - event_xwindow = xevent->xproperty.window; - - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_PID_CHANGED; - event->timestamp = xevent->xproperty.time; - event->context = NULL; - event->sequence = NULL; - - retval = TRUE; - } - break; - - case ClientMessage: - if (xevent->xclient.message_type == - sn_internal_atom_get (display, - "_NET_LAUNCH_PULSE")) - { - event_xwindow = xevent->xclient.window; - - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_PULSE; - event->timestamp = CurrentTime; - event->context = NULL; - event->sequence = NULL; - - retval = TRUE; - } - else if (xevent->xclient.message_type == - sn_internal_atom_get (display, - "_NET_LAUNCH_INITIATE")) - { - SnLaunchSequence *sequence; - - /* Don't be fooled by duplicate initiate messages - - * check that the sequence doesn't exist yet - */ - sequence = find_sequence_for_window (display, - xevent->xclient.window); - - if (sequence == NULL) - { - event_xwindow = xevent->xclient.window; - - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_INITIATED; - event->timestamp = xevent->xclient.data.l[0]; - event->context = NULL; - event->sequence = NULL; - } - - retval = TRUE; - } - break; - - case DestroyNotify: - { - SnLaunchSequence *sequence; - - sequence = find_sequence_for_window (display, - xevent->xdestroywindow.window); - - if (sequence != NULL) - { - event_xwindow = xevent->xdestroywindow.window; - - event = sn_new (SnMonitorEvent, 1); - - event->refcount = 1; - event->type = SN_MONITOR_EVENT_COMPLETED; - event->timestamp = CurrentTime; - event->context = NULL; - event->sequence = sequence; - sn_launch_sequence_ref (sequence); - } - } - break; - - default: - break; - } - - if (event != NULL) - { - dispatch_monitor_event (display, event, event_xwindow); - - sn_monitor_event_unref (event); - } + retval = FALSE; + return retval; } @@ -965,14 +508,14 @@ typedef struct { SnDisplay *display; const char *id; - SnLaunchSequence *found; + SnStartupSequence *found; } FindSequenceByIdData; static sn_bool_t find_sequence_by_id_foreach (void *value, void *data) { - SnLaunchSequence *sequence = value; + SnStartupSequence *sequence = value; FindSequenceByIdData *fsd = data; if (strcmp (sequence->id, fsd->id) == 0 && @@ -986,7 +529,7 @@ find_sequence_by_id_foreach (void *value, return TRUE; } -static SnLaunchSequence* +static SnStartupSequence* find_sequence_for_id (SnDisplay *display, const char *id) { @@ -1011,7 +554,7 @@ do_xmessage_event_foreach (void *value, SnMonitorEvent *event = value; SnDisplay *display = data; - dispatch_monitor_event (display, event, None); + dispatch_monitor_event (display, event); return TRUE; } @@ -1027,6 +570,7 @@ unref_event_foreach (void *value, static void xmessage_func (SnDisplay *display, const char *message_type, + Window xwindow, const char *message, void *user_data) { @@ -1036,7 +580,7 @@ xmessage_func (SnDisplay *display, char **values; int i; const char *launch_id; - SnLaunchSequence *sequence; + SnStartupSequence *sequence; SnList *events; prefix = NULL; @@ -1070,7 +614,7 @@ xmessage_func (SnDisplay *display, { SnMonitorEvent *event; - sequence = add_sequence (display, None); + sequence = add_sequence (display); if (sequence == NULL) goto out; @@ -1080,10 +624,10 @@ xmessage_func (SnDisplay *display, event->refcount = 1; event->type = SN_MONITOR_EVENT_INITIATED; - event->timestamp = CurrentTime; event->context = NULL; event->sequence = sequence; /* ref from add_sequence goes here */ - + event->xwindow = xwindow; + sn_list_append (events, event); } } @@ -1094,9 +638,7 @@ xmessage_func (SnDisplay *display, if (strcmp (prefix, "change") == 0 || strcmp (prefix, "new") == 0) { - sn_bool_t random_stuff_changed = FALSE; - sn_bool_t pid_changed = FALSE; - sn_bool_t workspace_changed = FALSE; + sn_bool_t changed = FALSE; i = 0; while (names[i]) @@ -1106,7 +648,7 @@ xmessage_func (SnDisplay *display, if (sequence->binary_name == NULL) { sequence->binary_name = sn_internal_strdup (values[i]); - random_stuff_changed = TRUE; + changed = TRUE; } } else if (strcmp (names[i], "NAME") == 0) @@ -1114,15 +656,23 @@ xmessage_func (SnDisplay *display, if (sequence->name == NULL) { sequence->name = sn_internal_strdup (values[i]); - random_stuff_changed = TRUE; + changed = TRUE; } } + else if (strcmp (names[i], "DESCRIPTION") == 0) + { + if (sequence->description == NULL) + { + sequence->description = sn_internal_strdup (values[i]); + changed = TRUE; + } + } else if (strcmp (names[i], "ICON") == 0) { if (sequence->icon_name == NULL) { sequence->icon_name = sn_internal_strdup (values[i]); - random_stuff_changed = TRUE; + changed = TRUE; } } else if (strcmp (names[i], "DESKTOP") == 0) @@ -1132,77 +682,35 @@ xmessage_func (SnDisplay *display, workspace = sn_internal_string_to_ulong (values[i]); sequence->workspace = workspace; - workspace_changed = TRUE; + changed = TRUE; } else if (strcmp (names[i], "WMCLASS") == 0) { - if (sequence->resource_class == NULL) + if (sequence->wmclass == NULL) { - sequence->resource_class = sn_internal_strdup (values[i]); - random_stuff_changed = TRUE; - } - } - else if (strcmp (names[i], "PID") == 0) - { - int pid; - - pid = sn_internal_string_to_ulong (values[i]); - - if (pid > 0) - { - sequence->pid = pid; - - pid_changed = TRUE; - } - } - else if (strcmp (names[i], "HOSTNAME") == 0) - { - if (sequence->hostname == NULL) - { - sequence->hostname = sn_internal_strdup (values[i]); - random_stuff_changed = TRUE; + sequence->wmclass = sn_internal_strdup (values[i]); + changed = TRUE; } } ++i; } - - if (pid_changed) + + if (changed) { SnMonitorEvent *event; event = sn_new (SnMonitorEvent, 1); event->refcount = 1; - event->type = SN_MONITOR_EVENT_PID_CHANGED; - event->timestamp = CurrentTime; + event->type = SN_MONITOR_EVENT_CHANGED; event->context = NULL; event->sequence = sequence; - sn_launch_sequence_ref (sequence); - - sn_list_append (events, event); - } - - if (workspace_changed) - { - SnMonitorEvent *event; - - event = sn_new (SnMonitorEvent, 1); + sn_startup_sequence_ref (sequence); + event->xwindow = xwindow; - event->refcount = 1; - event->type = SN_MONITOR_EVENT_WORKSPACE_CHANGED; - event->timestamp = CurrentTime; - event->context = NULL; - event->sequence = sequence; - sn_launch_sequence_ref (sequence); - sn_list_append (events, event); } - - if (random_stuff_changed) - { - /* FIXME */ - } } else if (strcmp (prefix, "remove") == 0) { @@ -1212,11 +720,11 @@ xmessage_func (SnDisplay *display, event->refcount = 1; event->type = SN_MONITOR_EVENT_COMPLETED; - event->timestamp = CurrentTime; event->context = NULL; event->sequence = sequence; - sn_launch_sequence_ref (sequence); - + sn_startup_sequence_ref (sequence); + event->xwindow = xwindow; + sn_list_append (events, event); } diff --git a/libsn/sn-monitor.h b/libsn/sn-monitor.h index 9f799c5..508bb94 100644 --- a/libsn/sn-monitor.h +++ b/libsn/sn-monitor.h @@ -33,7 +33,7 @@ SN_BEGIN_DECLS typedef struct SnMonitorContext SnMonitorContext; typedef struct SnMonitorEvent SnMonitorEvent; -typedef struct SnLaunchSequence SnLaunchSequence; +typedef struct SnStartupSequence SnStartupSequence; typedef void (* SnMonitorEventFunc) (SnMonitorEvent *event, void *user_data); @@ -42,55 +42,36 @@ typedef enum { SN_MONITOR_EVENT_INITIATED, SN_MONITOR_EVENT_COMPLETED, - SN_MONITOR_EVENT_CANCELED, - SN_MONITOR_EVENT_PULSE, - SN_MONITOR_EVENT_GEOMETRY_CHANGED, - SN_MONITOR_EVENT_PID_CHANGED, - /* only allowed with xmessages protocol */ - SN_MONITOR_EVENT_WORKSPACE_CHANGED + SN_MONITOR_EVENT_CHANGED, + SN_MONITOR_EVENT_CANCELED /* not used for now */ } SnMonitorEventType; SnMonitorContext* sn_monitor_context_new (SnDisplay *display, + int screen, SnMonitorEventFunc event_func, void *event_func_data, SnFreeFunc free_data_func); void sn_monitor_context_ref (SnMonitorContext *context); void sn_monitor_context_unref (SnMonitorContext *context); +void sn_monitor_event_ref (SnMonitorEvent *event); +void sn_monitor_event_unref (SnMonitorEvent *event); +SnMonitorEvent* sn_monitor_event_copy (SnMonitorEvent *event); +SnMonitorEventType sn_monitor_event_get_type (SnMonitorEvent *event); +SnStartupSequence* sn_monitor_event_get_startup_sequence (SnMonitorEvent *event); +SnMonitorContext* sn_monitor_event_get_context (SnMonitorEvent *event); -void sn_monitor_event_ref (SnMonitorEvent *event); -void sn_monitor_event_unref (SnMonitorEvent *event); -SnMonitorEvent* sn_monitor_event_copy (SnMonitorEvent *event); -SnMonitorEventType sn_monitor_event_get_type (SnMonitorEvent *event); -SnLaunchSequence* sn_monitor_event_get_launch_sequence (SnMonitorEvent *event); -SnMonitorContext* sn_monitor_event_get_context (SnMonitorEvent *event); -Time sn_monitor_event_get_time (SnMonitorEvent *event); -void sn_launch_sequence_ref (SnLaunchSequence *sequence); -void sn_launch_sequence_unref (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_id (SnLaunchSequence *sequence); -Window sn_launch_sequence_get_window (SnLaunchSequence *sequence); -sn_bool_t sn_launch_sequence_get_geometry (SnLaunchSequence *sequence, - int *x, - int *y, - int *width, - int *height); -Window sn_launch_sequence_get_geometry_window (SnLaunchSequence *sequence); -sn_bool_t sn_launch_sequence_get_completed (SnLaunchSequence *sequence); -sn_bool_t sn_launch_sequence_get_canceled (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_name (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_description (SnLaunchSequence *sequence); -int sn_launch_sequence_get_workspace (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_legacy_resource_class (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_legacy_resource_name (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_legacy_window_title (SnLaunchSequence *sequence); -sn_bool_t sn_launch_sequence_get_supports_cancel (SnLaunchSequence *sequence); -int sn_launch_sequence_get_pid (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_binary_name (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_hostname (SnLaunchSequence *sequence); -const char* sn_launch_sequence_get_icon_name (SnLaunchSequence *sequence); - -void sn_launch_sequence_cancel (SnLaunchSequence *sequence); +void sn_startup_sequence_ref (SnStartupSequence *sequence); +void sn_startup_sequence_unref (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_id (SnStartupSequence *sequence); +sn_bool_t sn_startup_sequence_get_completed (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_name (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_description (SnStartupSequence *sequence); +int sn_startup_sequence_get_workspace (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_wmclass (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_binary_name (SnStartupSequence *sequence); +const char* sn_startup_sequence_get_icon_name (SnStartupSequence *sequence); SN_END_DECLS diff --git a/libsn/sn-util.c b/libsn/sn-util.c index 89ef913..775df13 100644 --- a/libsn/sn-util.c +++ b/libsn/sn-util.c @@ -308,3 +308,21 @@ sn_internal_string_to_ulong (const char* str) return retval; } + + +void +sn_internal_append_to_string (char **append_to, + int *current_len, + const char *append) +{ + int len; + char *end; + + len = strlen (append); + + *append_to = sn_realloc (*append_to, *current_len + len + 1); + + end = *append_to + *current_len; + strcpy (end, append); + *current_len = *current_len + len; +} diff --git a/libsn/sn-xmessages.c b/libsn/sn-xmessages.c index 61577e8..e1e3652 100644 --- a/libsn/sn-xmessages.c +++ b/libsn/sn-xmessages.c @@ -29,6 +29,7 @@ typedef struct { Display *xdisplay; + Window root; Atom type_atom; char *message_type; SnXmessageFunc func; @@ -49,6 +50,7 @@ static SnList *pending_messages = NULL; void sn_internal_add_xmessage_func (SnDisplay *display, + int screen, const char *message_type, SnXmessageFunc func, void *func_data, @@ -62,6 +64,7 @@ sn_internal_add_xmessage_func (SnDisplay *display, handler = sn_new0 (SnXmessageHandler, 1); handler->xdisplay = sn_display_get_x_display (display); + handler->root = RootWindow (handler->xdisplay, screen); handler->type_atom = sn_internal_atom_get (display, message_type); handler->message_type = sn_internal_strdup (message_type); handler->func= func; @@ -76,6 +79,7 @@ typedef struct const char *message_type; SnXmessageFunc func; void *func_data; + Window root; SnXmessageHandler *handler; } FindHandlerData; @@ -88,6 +92,7 @@ find_handler_foreach (void *value, if (handler->func == fhd->func && handler->func_data == fhd->func_data && + handler->root == fhd->root && strcmp (fhd->message_type, handler->message_type) == 0) { fhd->handler = handler; @@ -99,6 +104,7 @@ find_handler_foreach (void *value, void sn_internal_remove_xmessage_func (SnDisplay *display, + int screen, const char *message_type, SnXmessageFunc func, void *func_data) @@ -108,7 +114,8 @@ sn_internal_remove_xmessage_func (SnDisplay *display, fhd.func = func; fhd.func_data = func_data; fhd.handler = NULL; - + fhd.root = RootWindow (sn_display_get_x_display (display), screen); + if (xmessage_funcs != NULL) sn_list_foreach (xmessage_funcs, find_handler_foreach, &fhd); @@ -127,6 +134,7 @@ sn_internal_remove_xmessage_func (SnDisplay *display, void sn_internal_broadcast_xmessage (SnDisplay *display, + int screen, const char *message_type, const char *message) { @@ -201,7 +209,7 @@ sn_internal_broadcast_xmessage (SnDisplay *display, } XSendEvent (xdisplay, - target_xwindow, + RootWindow (xdisplay, screen), False, PropertyChangeMask, &xevent); @@ -216,6 +224,7 @@ typedef struct { Display *xdisplay; Atom atom; + Window xwindow; sn_bool_t found_handler; } HandlerForAtomData; @@ -227,7 +236,8 @@ handler_for_atom_foreach (void *value, HandlerForAtomData *hfad = data; if (handler->xdisplay == hfad->xdisplay && - handler->type_atom == hfad->atom) + handler->type_atom == hfad->atom && + handler->root == hfad->xwindow) { hfad->found_handler = TRUE; return FALSE; @@ -244,6 +254,7 @@ some_handler_handles_event (SnDisplay *display, hfad.atom = xevent->xclient.message_type; hfad.xdisplay = sn_display_get_x_display (display); + hfad.xwindow = xevent->xclient.window; hfad.found_handler = FALSE; if (xmessage_funcs) @@ -380,6 +391,7 @@ dispatch_message_foreach (void *value, (* handler->func) (mdd->display, handler->message_type, + mdd->message->xwindow, mdd->message->message, handler->func_data); @@ -430,6 +442,11 @@ sn_internal_xmessage_process_event (SnDisplay *display, dispatch_message_foreach, &mdd); } + else + { + /* FIXME don't use fprintf, use something pluggable */ + fprintf (stderr, "Bad UTF-8 in startup notification message\n"); + } sn_free (message->message); sn_free (message); @@ -439,26 +456,9 @@ sn_internal_xmessage_process_event (SnDisplay *display, } static void -append_to_string (char **append_to, - int *current_len, - const char *append) -{ - int len; - char *end; - - len = strlen (append); - - *append_to = sn_realloc (*append_to, *current_len + len + 1); - - end = *append_to + *current_len; - strcpy (end, append); - *current_len = *current_len + len; -} - -static void -append_to_string_escaped (char **append_to, - int *current_len, - const char *append) +sn_internal_append_to_string_escaped (char **append_to, + int *current_len, + const char *append) { char *escaped; int len; @@ -477,16 +477,16 @@ append_to_string_escaped (char **append_to, if (*p == '\\' || *p == '"' || *p == ' ') { buf[0] = '\\'; - append_to_string (&escaped, &len, buf); + sn_internal_append_to_string (&escaped, &len, buf); } buf[0] = *p; - append_to_string (&escaped, &len, buf); + sn_internal_append_to_string (&escaped, &len, buf); ++p; } - append_to_string (append_to, current_len, escaped); - + sn_internal_append_to_string (append_to, current_len, escaped); + sn_free (escaped); } @@ -503,15 +503,15 @@ sn_internal_serialize_message (const char *prefix, len = 0; retval = NULL; - append_to_string (&retval, &len, prefix); - append_to_string (&retval, &len, ": "); + sn_internal_append_to_string (&retval, &len, prefix); + sn_internal_append_to_string (&retval, &len, ": "); i = 0; while (property_names[i]) { - append_to_string (&retval, &len, property_names[i]); - append_to_string (&retval, &len, "="); - append_to_string_escaped (&retval, &len, property_values[i]); + sn_internal_append_to_string (&retval, &len, property_names[i]); + sn_internal_append_to_string (&retval, &len, "="); + sn_internal_append_to_string_escaped (&retval, &len, property_values[i]); ++i; } diff --git a/libsn/sn-xmessages.h b/libsn/sn-xmessages.h index 8f03b77..57b933b 100644 --- a/libsn/sn-xmessages.h +++ b/libsn/sn-xmessages.h @@ -31,19 +31,23 @@ SN_BEGIN_DECLS typedef void (* SnXmessageFunc) (SnDisplay *display, const char *message_type, + Window message_window, const char *message, void *user_data); void sn_internal_add_xmessage_func (SnDisplay *display, + int screen, const char *message_type, SnXmessageFunc func, void *func_data, SnFreeFunc free_data_func); void sn_internal_remove_xmessage_func (SnDisplay *display, + int screen, const char *message_type, SnXmessageFunc func, void *func_data); void sn_internal_broadcast_xmessage (SnDisplay *display, + int screen, const char *message_type, const char *message); diff --git a/test/test-launchee.c b/test/test-launchee.c index 7751cbd..14a7fd9 100644 --- a/test/test-launchee.c +++ b/test/test-launchee.c @@ -33,7 +33,6 @@ main (int argc, char **argv) Display *xdisplay; SnDisplay *display; SnLauncheeContext *context; - int i; xdisplay = XOpenDisplay (NULL); if (xdisplay == NULL) @@ -51,7 +50,8 @@ main (int argc, char **argv) error_trap_push, error_trap_pop); - context = sn_launchee_context_new_from_environment (display); + context = sn_launchee_context_new_from_environment (display, + DefaultScreen (xdisplay)); if (context == NULL) { @@ -59,18 +59,11 @@ main (int argc, char **argv) exit (1); } - printf ("Launchee started with window 0x%lx ID \"%s\"\n", - sn_launchee_context_get_launch_window (context), - sn_launchee_context_get_launch_id (context)); + printf ("Launchee started with window ID \"%s\"\n", + sn_launchee_context_get_startup_id (context)); /* simulate startup time */ - i = 0; - while (i < 4) - { - sleep (1); - sn_launchee_context_pulse (context); - ++i; - } + sleep (4); printf ("Launchee startup complete\n"); sn_launchee_context_complete (context); diff --git a/test/test-launcher.c b/test/test-launcher.c index 2005026..053e84b 100644 --- a/test/test-launcher.c +++ b/test/test-launcher.c @@ -29,30 +29,6 @@ static pid_t child_pid = 0; -static void -launcher_event_func (SnLauncherEvent *event, - void *user_data) -{ - SnLauncherContext *context; - - context = sn_launcher_event_get_context (event); - - switch (sn_launcher_event_get_type (event)) - { - case SN_LAUNCHER_EVENT_COMPLETED: - printf ("Completed!\n"); - break; - case SN_LAUNCHER_EVENT_CANCELED: - printf ("Canceled!\n"); - kill (child_pid, SIGTERM); - sn_launcher_context_complete (context); - break; - case SN_LAUNCHER_EVENT_PULSE: - printf (" pulse.\n"); - break; - } -} - int main (int argc, char **argv) { @@ -82,13 +58,10 @@ main (int argc, char **argv) error_trap_push, error_trap_pop); - context = sn_launcher_context_new (display, - launcher_event_func, - NULL, NULL); + context = sn_launcher_context_new (display, DefaultScreen (xdisplay)); - sn_launcher_context_set_launch_name (context, "Test Launch"); - sn_launcher_context_set_launch_description (context, "Launching a test program for libsn"); - sn_launcher_context_set_supports_cancel (context, TRUE); + sn_launcher_context_set_name (context, "Test Launch"); + sn_launcher_context_set_description (context, "Launching a test program for libsn"); sn_launcher_context_set_binary_name (context, argv[1]); sn_launcher_context_initiate (context, @@ -108,8 +81,6 @@ main (int argc, char **argv) _exit (1); break; } - - sn_launcher_context_set_pid (context, child_pid); while (TRUE) { diff --git a/test/test-monitor.c b/test/test-monitor.c index 6f031fd..b6e40d2 100644 --- a/test/test-monitor.c +++ b/test/test-monitor.c @@ -32,106 +32,51 @@ monitor_event_func (SnMonitorEvent *event, void *user_data) { SnMonitorContext *context; - SnLaunchSequence *sequence; + SnStartupSequence *sequence; context = sn_monitor_event_get_context (event); - sequence = sn_monitor_event_get_launch_sequence (event); + sequence = sn_monitor_event_get_startup_sequence (event); switch (sn_monitor_event_get_type (event)) { case SN_MONITOR_EVENT_INITIATED: + printf ("Initiated sequence %s\n", + sn_startup_sequence_get_id (sequence)); + /* FALL THRU */ + case SN_MONITOR_EVENT_CHANGED: { - int x, y, w, h; const char *s; - - printf ("Initiated sequence %s\n", - sn_launch_sequence_get_id (sequence)); - printf (" launch window 0x%lx\n", - sn_launch_sequence_get_window (sequence)); - s = sn_launch_sequence_get_name (sequence); + s = sn_startup_sequence_get_id (sequence); + printf (" id %s\n", s ? s : "(unset)"); + + s = sn_startup_sequence_get_name (sequence); printf (" name %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_description (sequence); + s = sn_startup_sequence_get_description (sequence); printf (" description %s\n", s ? s : "(unset)"); printf (" workspace %d\n", - sn_launch_sequence_get_workspace (sequence)); - - printf (" %s cancel\n", - sn_launch_sequence_get_supports_cancel (sequence) ? - "supports" : "does not support"); - - if (sn_launch_sequence_get_geometry (sequence, - &x, &y, &w, &h)) - printf (" geometry %d,%d %d x %d window 0x%lx\n", - x, y, w, h, - sn_launch_sequence_get_geometry_window (sequence)); - else - printf (" no geometry set\n"); - - printf (" pid %d\n", - sn_launch_sequence_get_pid (sequence)); + sn_startup_sequence_get_workspace (sequence)); - s = sn_launch_sequence_get_binary_name (sequence); + s = sn_startup_sequence_get_binary_name (sequence); printf (" binary name %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_icon_name (sequence); + s = sn_startup_sequence_get_icon_name (sequence); printf (" icon name %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_hostname (sequence); - printf (" hostname %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_legacy_resource_class (sequence); - printf (" legacy class %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_legacy_resource_name (sequence); - printf (" legacy name %s\n", s ? s : "(unset)"); - s = sn_launch_sequence_get_legacy_window_title (sequence); - printf (" legacy title %s\n", s ? s : "(unset)"); + s = sn_startup_sequence_get_wmclass (sequence); + printf (" wm class %s\n", s ? s : "(unset)"); } break; case SN_MONITOR_EVENT_COMPLETED: printf ("Completed sequence %s\n", - sn_launch_sequence_get_id (sequence)); + sn_startup_sequence_get_id (sequence)); break; case SN_MONITOR_EVENT_CANCELED: printf ("Canceled sequence %s\n", - sn_launch_sequence_get_id (sequence)); - break; - - case SN_MONITOR_EVENT_PULSE: - printf ("Pulse for sequence %s\n", - sn_launch_sequence_get_id (sequence)); - break; - - case SN_MONITOR_EVENT_GEOMETRY_CHANGED: - { - int x, y, w, h; - - printf ("Geometry changed for sequence %s\n", - sn_launch_sequence_get_id (sequence)); - if (sn_launch_sequence_get_geometry (sequence, - &x, &y, &w, &h)) - printf (" geometry %d,%d %d x %d window 0x%lx\n", - x, y, w, h, - sn_launch_sequence_get_geometry_window (sequence)); - else - printf (" no geometry set\n"); - } - break; - case SN_MONITOR_EVENT_PID_CHANGED: - { - printf ("PID for sequence %s is now %d\n", - sn_launch_sequence_get_id (sequence), - sn_launch_sequence_get_pid (sequence)); - } - break; - case SN_MONITOR_EVENT_WORKSPACE_CHANGED: - { - printf ("Workspace for sequence %s is now %d\n", - sn_launch_sequence_get_id (sequence), - sn_launch_sequence_get_workspace (sequence)); - } + sn_startup_sequence_get_id (sequence)); break; } } @@ -166,7 +111,7 @@ main (int argc, char **argv) error_trap_push, error_trap_pop); - context = sn_monitor_context_new (display, + context = sn_monitor_context_new (display, DefaultScreen (xdisplay), monitor_event_func, NULL, NULL); diff --git a/test/test-send-xmessage.c b/test/test-send-xmessage.c index 00ae71a..d1c0a6f 100644 --- a/test/test-send-xmessage.c +++ b/test/test-send-xmessage.c @@ -56,7 +56,7 @@ main (int argc, char **argv) error_trap_push, error_trap_pop); - sn_internal_broadcast_xmessage (display, + sn_internal_broadcast_xmessage (display, DefaultScreen (xdisplay), argv[1], argv[2]); diff --git a/test/test-watch-xmessages.c b/test/test-watch-xmessages.c index 85728a5..3374f0e 100644 --- a/test/test-watch-xmessages.c +++ b/test/test-watch-xmessages.c @@ -32,6 +32,7 @@ static void message_func (SnDisplay *display, const char *message_type, + Window xwindow, const char *message, void *user_data) { @@ -100,7 +101,7 @@ main (int argc, char **argv) error_trap_push, error_trap_pop); - sn_internal_add_xmessage_func (display, + sn_internal_add_xmessage_func (display, DefaultScreen (xdisplay), argv[1], message_func, NULL, NULL); |