From efa0ae83737dd33a9bee4eed0c5f2e45fc860c92 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 27 Feb 2002 02:05:39 +0000 Subject: [PATCH] Screw around with Anders's ping patch so he'll get plenty of CVS 2002-02-26 Havoc Pennington Screw around with Anders's ping patch so he'll get plenty of CVS conflicts. ;-) * src/display.c (meta_display_ping_window): spew warnings if we try to call this with CurrentTime (meta_display_ping_timeout): remove ping from the pending pings after it times out. * src/util.h: added PING debug category * src/display.c (remove_pending_pings_for_window): don't remove "tmp" just before "tmp->next", don't break out of loop after finding the first match (meta_display_open): no trailing comma in array init (event_callback): move the processing of ping replies into a separate function * src/screen.c (set_supported_hint): add _NET_WM_PING to supported list * src/display.h: change gpointer to void* 2002-02-26 Anders Carlsson * src/display.c: (ping_data_free), (remove_pending_pings_for_window), (meta_display_open), (event_callback), (meta_display_unregister_x_window), (meta_display_ping_timeout), (meta_display_ping_window), (meta_display_window_has_pending_pings): Implement meta_display_ping_window, and filter out scroll wheel events. * src/display.h: Add MetaWindowPingFunc, meta_display_ping_window and meta_display_window_has_pending_pings. --- ChangeLog | 38 +++++++++ src/display.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++- src/display.h | 21 +++++ src/screen.c | 3 +- src/util.h | 3 +- 5 files changed, 275 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e92b365dc..37b218b79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2002-02-26 Havoc Pennington + + Screw around with Anders's ping patch so he'll get plenty of CVS + conflicts. ;-) + + * src/display.c (meta_display_ping_window): spew warnings + if we try to call this with CurrentTime + (meta_display_ping_timeout): remove ping from the pending pings + after it times out. + + * src/util.h: added PING debug category + + * src/display.c (remove_pending_pings_for_window): don't remove + "tmp" just before "tmp->next", don't break out of loop after + finding the first match + (meta_display_open): no trailing comma in array init + (event_callback): move the processing of ping replies into a + separate function + + * src/screen.c (set_supported_hint): add _NET_WM_PING to supported + list + + * src/display.h: change gpointer to void* + +2002-02-26 Anders Carlsson + + * src/display.c: (ping_data_free), + (remove_pending_pings_for_window), (meta_display_open), + (event_callback), (meta_display_unregister_x_window), + (meta_display_ping_timeout), (meta_display_ping_window), + (meta_display_window_has_pending_pings): + Implement meta_display_ping_window, and filter out scroll wheel + events. + + * src/display.h: + Add MetaWindowPingFunc, meta_display_ping_window and + meta_display_window_has_pending_pings. + 2002-02-24 Havoc Pennington * src/display.c (xcursor_for_op): switch on the op passed in, not diff --git a/src/display.c b/src/display.c index aa12c6c5e..4f226263b 100644 --- a/src/display.c +++ b/src/display.c @@ -36,7 +36,18 @@ #define USE_GDK_DISPLAY +typedef struct { + MetaDisplay *display; + Window xwindow; + Time timestamp; + MetaWindowPingFunc ping_reply_func; + MetaWindowPingFunc ping_timeout_func; + void *user_data; + guint ping_timeout_id; +} MetaPingData; + static GSList *all_displays = NULL; + static void meta_spew_event (MetaDisplay *display, XEvent *event); static void event_queue_callback (XEvent *event, @@ -47,7 +58,8 @@ static Window event_get_modified_window (MetaDisplay *display, XEvent *event); static guint32 event_get_time (MetaDisplay *display, XEvent *event); - +static void process_pong_message (MetaDisplay *display, + XEvent *event); static gint @@ -84,6 +96,46 @@ set_utf8_string_hint (MetaDisplay *display, return meta_error_trap_pop (display); } +static void +ping_data_free (MetaPingData *ping_data) +{ + /* Remove the timeout */ + if (ping_data->ping_timeout_id != 0) + g_source_remove (ping_data->ping_timeout_id); + + g_free (ping_data); +} + +static void +remove_pending_pings_for_window (MetaDisplay *display, Window xwindow) +{ + GSList *tmp; + GSList *dead; + + /* could obviously be more efficient, don't care */ + + /* build list to be removed */ + dead = NULL; + for (tmp = display->pending_pings; tmp; tmp = tmp->next) + { + MetaPingData *ping_data = tmp->data; + + if (ping_data->xwindow == xwindow) + dead = g_slist_prepend (dead, ping_data); + } + + /* remove what we found */ + for (tmp = dead; tmp; tmp = tmp->next) + { + MetaPingData *ping_data = tmp->data; + + display->pending_pings = g_slist_remove (display->pending_pings, ping_data); + ping_data_free (ping_data); + } + + g_slist_free (dead); +} + gboolean meta_display_open (const char *name) { @@ -148,6 +200,9 @@ meta_display_open (const char *name) "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", "_NET_WM_STATE_FULLSCREEN" + "_NET_WM_PING", + "_NET_WM_PID", + "WM_CLIENT_MACHINE" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -182,6 +237,7 @@ meta_display_open (const char *name) display->server_grab_count = 0; display->workspaces = NULL; + display->pending_pings = NULL; display->focus_window = NULL; display->prev_focus_window = NULL; @@ -250,7 +306,10 @@ meta_display_open (const char *name) display->atom_net_wm_window_type_utility = atoms[50]; display->atom_net_wm_window_type_splashscreen = atoms[51]; display->atom_net_wm_state_fullscreen = atoms[52]; - + display->atom_net_wm_ping = atoms[53]; + display->atom_net_wm_pid = atoms[54]; + display->atom_wm_client_machine = atoms[55]; + /* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK, * created in screen_new */ @@ -670,17 +729,24 @@ event_callback (XEvent *event, MetaDisplay *display; Window modified; gboolean frame_was_receiver; + gboolean filter_out_event; display = data; if (dump_events) meta_spew_event (display, event); + filter_out_event = FALSE; display->current_time = event_get_time (display, event); - /* mark double click events, kind of a hack, oh well. */ if (event->type == ButtonPress) { + /* filter out scrollwheel */ + if (event->xbutton.button == 4 || + event->xbutton.button == 5) + return FALSE; + + /* mark double click events, kind of a hack, oh well. */ if (((int)event->xbutton.button) == display->last_button_num && event->xbutton.window == display->last_button_xwindow && event->xbutton.time < (display->last_button_time + display->double_click_time)) @@ -1132,6 +1198,22 @@ event_callback (XEvent *event, (int) event->xclient.data.l[0]); meta_set_keybindings_disabled (!event->xclient.data.l[0]); } + else if (event->xclient.message_type == + display->atom_wm_protocols) + { + meta_verbose ("Received WM_PROTOCOLS message\n"); + + if ((Atom)event->xclient.data.l[0] == display->atom_net_wm_ping) + { + process_pong_message (display, event); + + /* We don't want ping reply events going into + * the GTK+ event loop because gtk+ will treat + * them as ping requests and send more replies. + */ + filter_out_event = TRUE; + } + } } } break; @@ -1142,7 +1224,7 @@ event_callback (XEvent *event, } display->current_time = CurrentTime; - return FALSE; + return filter_out_event; } /* Return the window this has to do with, if any, rather @@ -1596,6 +1678,9 @@ meta_display_unregister_x_window (MetaDisplay *display, g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL); g_hash_table_remove (display->window_ids, &xwindow); + + /* Remove any pending pings */ + remove_pending_pings_for_window (display, xwindow); } MetaWorkspace* @@ -2163,3 +2248,126 @@ meta_set_syncing (gboolean setting) } } } + +#define PING_TIMEOUT_DELAY 3000 + +static gboolean +meta_display_ping_timeout (gpointer data) +{ + MetaPingData *ping_data; + + ping_data = data; + + ping_data->ping_timeout_id = 0; + + meta_topic (META_DEBUG_PING, + "Ping %lu on window %lx timed out\n", + ping_data->timestamp, ping_data->xwindow); + + (* ping_data->ping_timeout_func) (ping_data->display, ping_data->xwindow, + ping_data->user_data); + + ping_data->display->pending_pings = + g_slist_remove (ping_data->display->pending_pings, + ping_data); + ping_data_free (ping_data); + + return FALSE; +} + +void +meta_display_ping_window (MetaDisplay *display, + MetaWindow *window, + Time timestamp, + MetaWindowPingFunc ping_reply_func, + MetaWindowPingFunc ping_timeout_func, + gpointer user_data) +{ + MetaPingData *ping_data; + + if (timestamp == CurrentTime) + { + meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n"); + return; + } + + ping_data = g_new (MetaPingData, 1); + ping_data->display = display; + ping_data->xwindow = window->xwindow; + ping_data->timestamp = timestamp; + ping_data->ping_reply_func = ping_reply_func; + ping_data->ping_timeout_func = ping_timeout_func; + ping_data->user_data = user_data; + ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, + meta_display_ping_timeout, + ping_data); + + display->pending_pings = g_slist_prepend (display->pending_pings, ping_data); + + meta_topic (META_DEBUG_PING, + "Sending ping with timestamp %lu to window %s\n", + timestamp, window->desc); + meta_window_send_icccm_message (window, + display->atom_net_wm_ping, + timestamp); +} + +/* process the pong from our ping */ +static void +process_pong_message (MetaDisplay *display, + XEvent *event) +{ + GSList *tmp; + + meta_topic (META_DEBUG_PING, "Received a pong with timestamp %lu\n", + (Time) event->xclient.data.l[1]); + + for (tmp = display->pending_pings; tmp; tmp = tmp->next) + { + MetaPingData *ping_data = tmp->data; + + if ((Time)event->xclient.data.l[1] == ping_data->timestamp) + { + meta_topic (META_DEBUG_PING, + "Matching ping found for pong %lu\n", + ping_data->timestamp); + + /* Remove the ping data from the list */ + display->pending_pings = g_slist_remove (display->pending_pings, + ping_data); + + /* Remove the timeout */ + if (ping_data->ping_timeout_id != 0) + { + g_source_remove (ping_data->ping_timeout_id); + ping_data->ping_timeout_id = 0; + } + + /* Call callback */ + (* ping_data->ping_reply_func) (display, ping_data->xwindow, + ping_data->user_data); + + ping_data_free (ping_data); + + break; + } + } +} + +gboolean +meta_display_window_has_pending_pings (MetaDisplay *display, + MetaWindow *window) +{ + GSList *tmp; + + for (tmp = display->pending_pings; tmp; tmp = tmp->next) + { + MetaPingData *ping_data = tmp->data; + + if (ping_data->xwindow == window->xwindow) + return TRUE; + } + + return FALSE; +} + diff --git a/src/display.h b/src/display.h index 4ab5750f7..669bfb1e7 100644 --- a/src/display.h +++ b/src/display.h @@ -48,6 +48,11 @@ typedef struct _MetaUISlave MetaUISlave; typedef struct _MetaWindow MetaWindow; typedef struct _MetaWorkspace MetaWorkspace; +typedef void (* MetaWindowPingFunc) (MetaDisplay *display, + Window xwindow, + gpointer user_data); + + #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ #define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ @@ -111,6 +116,9 @@ struct _MetaDisplay Atom atom_net_wm_state_hidden; Atom atom_net_wm_window_type_utility; Atom atom_net_wm_window_type_splashscreen; + Atom atom_net_wm_ping; + Atom atom_net_wm_pid; + Atom atom_wm_client_machine; Atom atom_net_wm_state_fullscreen; /* This is the actual window from focus events, @@ -150,6 +158,9 @@ struct _MetaDisplay unsigned long last_ignored_unmap_serial; guint32 current_time; + + /* Pings which we're waiting for a reply from */ + GSList *pending_pings; /* current window operation */ MetaGrabOp grab_op; @@ -238,4 +249,14 @@ const char* meta_focus_detail_to_string (int d); void meta_display_queue_retheme_all_windows (MetaDisplay *display); void meta_display_retheme_all (void); +void meta_display_ping_window (MetaDisplay *display, + MetaWindow *window, + Time timestamp, + MetaWindowPingFunc ping_reply_func, + MetaWindowPingFunc ping_timeout_func, + void *user_data); +gboolean meta_display_window_has_pending_pings (MetaDisplay *display, + MetaWindow *window); + + #endif diff --git a/src/screen.c b/src/screen.c index 010413dd2..f2e7e4d6e 100644 --- a/src/screen.c +++ b/src/screen.c @@ -78,7 +78,7 @@ set_wm_check_hint (MetaScreen *screen) static int set_supported_hint (MetaScreen *screen) { -#define N_SUPPORTED 27 +#define N_SUPPORTED 28 #define N_WIN_SUPPORTED 1 Atom atoms[N_SUPPORTED]; @@ -109,6 +109,7 @@ set_supported_hint (MetaScreen *screen) atoms[24] = screen->display->atom_net_wm_window_type_utility; atoms[25] = screen->display->atom_net_wm_window_type_splashscreen; atoms[26] = screen->display->atom_net_wm_state_fullscreen; + atoms[27] = screen->display->atom_net_wm_ping; XChangeProperty (screen->display->xdisplay, screen->xroot, screen->display->atom_net_supported, diff --git a/src/util.h b/src/util.h index afd9bdc8b..7f5c08a2c 100644 --- a/src/util.h +++ b/src/util.h @@ -54,7 +54,8 @@ typedef enum META_DEBUG_WINDOW_STATE = 1 << 6, META_DEBUG_WINDOW_OPS = 1 << 7, META_DEBUG_GEOMETRY = 1 << 8, - META_DEBUG_PLACEMENT = 1 << 9 + META_DEBUG_PLACEMENT = 1 << 9, + META_DEBUG_PING = 1 << 10 } MetaDebugTopic;