all repos — openbox @ 299687110d478a4928932f72031c345b27a01840

openbox fork - make it a bit more like ryudo

use hash tables in ping.[ch] instead of a list. we're pinging every window, not just windows youre trying to close, so don't use datastructures that suck with lots of windows..
Dana Jansens danakj@orodu.net
commit

299687110d478a4928932f72031c345b27a01840

parent

2ee4251092a70af6a7c1826aaef01506dfcbf556

4 files changed, 70 insertions(+), 57 deletions(-)

jump to
M openbox/event.copenbox/event.c

@@ -769,7 +769,7 @@ ob_restart();

else if (e->xclient.data.l[0] == 3) ob_exit(0); } else if (msgtype == prop_atoms.wm_protocols) { - if (e->xclient.data.l[0] == prop_atoms.net_wm_ping) + if ((Atom)e->xclient.data.l[0] == prop_atoms.net_wm_ping) ping_got_pong(e->xclient.data.l[1]); } break;
M openbox/openbox.copenbox/openbox.c

@@ -43,6 +43,7 @@ #include "menuframe.h"

#include "grab.h" #include "group.h" #include "config.h" +#include "ping.h" #include "mainloop.h" #include "gettext.h" #include "parser/parse.h"

@@ -301,6 +302,7 @@ focus_cycle_popup_startup(reconfigure);

screen_startup(reconfigure); grab_startup(reconfigure); group_startup(reconfigure); + ping_startup(reconfigure); client_startup(reconfigure); dock_startup(reconfigure); moveresize_startup(reconfigure);

@@ -360,6 +362,7 @@ keyboard_shutdown(reconfigure);

moveresize_shutdown(reconfigure); dock_shutdown(reconfigure); client_shutdown(reconfigure); + ping_shutdown(reconfigure); group_shutdown(reconfigure); grab_shutdown(reconfigure); screen_shutdown(reconfigure);
M openbox/ping.copenbox/ping.c

@@ -33,46 +33,59 @@ guint32 id;

gint waiting; } ObPingTarget; -static GSList *ping_targets = NULL; -static gboolean active = FALSE; -static guint32 ping_next_id = 1; +static GHashTable *ping_targets = NULL; +static GHashTable *ping_ids = NULL; +static guint32 ping_next_id = 1; #define PING_TIMEOUT (G_USEC_PER_SEC * 3) /*! Warn the user after this many PING_TIMEOUT intervals */ #define PING_TIMEOUT_WARN 3 -static void ping_send(ObPingTarget *t); -static void ping_end(ObClient *client, gpointer data); +static void ping_send(ObPingTarget *t); +static void ping_end(ObClient *client, gpointer data); static gboolean ping_timeout(gpointer data); +void ping_startup(gboolean reconfigure) +{ + if (reconfigure) return; + + ping_targets = g_hash_table_new(g_direct_hash, g_int_equal); + ping_ids = g_hash_table_new(g_direct_hash, g_int_equal); + + /* listen for clients to disappear */ + client_add_destroy_notify(ping_end, NULL); +} + +void ping_shutdown(gboolean reconfigure) +{ + if (reconfigure) return; + + g_hash_table_unref(ping_targets); + g_hash_table_unref(ping_ids); + + client_remove_destroy_notify(ping_end); +} + void ping_start(struct _ObClient *client, ObPingEventHandler h) { - GSList *it; ObPingTarget *t; g_assert(client->ping == TRUE); /* make sure we're not already pinging it */ - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->client == client) return; - } + g_assert(g_hash_table_lookup(ping_targets, &client) == NULL); - t = g_new(ObPingTarget, 1); + t = g_new0(ObPingTarget, 1); t->client = client; t->h = h; - t->waiting = 1; /* first wait for a reply */ + + g_hash_table_insert(ping_targets, &t->client, t); - ping_send(t); - ping_targets = g_slist_prepend(ping_targets, t); ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, t, g_direct_equal, NULL); - - if (!active) { - active = TRUE; - /* listen for the client to disappear */ - client_add_destroy_notify(ping_end, NULL); - } + /* act like we just timed out immediately, to start the pinging process + now instead of after the first delay */ + ping_timeout(t); } void ping_stop(struct _ObClient *c)

@@ -82,31 +95,35 @@ }

void ping_got_pong(guint32 id) { - GSList *it; ObPingTarget *t; - /* make sure we're not already pinging it */ - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->id == id) { - /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ - if (t->waiting > PING_TIMEOUT_WARN) { - /* we had notified that they weren't responding, so now we - need to notify that they are again */ - t->h(t->client, FALSE); - } - t->waiting = 0; /* not waiting for a reply anymore */ - break; + if ((t = g_hash_table_lookup(ping_ids, &id))) { + /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ + if (t->waiting > PING_TIMEOUT_WARN) { + /* we had notified that they weren't responding, so now we + need to notify that they are again */ + t->h(t->client, FALSE); } + t->waiting = 0; /* not waiting for a reply anymore */ } - - if (it == NULL) + else ob_debug("Got PONG with id %u but not waiting for one\n", id); } static void ping_send(ObPingTarget *t) { - t->id = ping_next_id++; + /* t->id is 0 when it hasn't been assigned an id ever yet. + we can reuse ids when t->waiting == 0, because we won't be getting a + pong for that id in the future again. that way for apps that aren't + timing out we don't need to remove/add them from/to the hash table */ + if (t->id == 0 || t->waiting > 0) { + /* pick an id, and reinsert in the hash table with the new id */ + if (t->id) g_hash_table_remove(ping_ids, &t->id); + t->id = ping_next_id; + if (++ping_next_id == 0) ++ping_next_id; /* skip 0 on wraparound */ + g_hash_table_insert(ping_ids, &t->id, t); + } + /*g_print("+PING: '%s' (id %u)\n", t->client->title, t->id);*/ PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->id, t->client->window, 0, 0,

@@ -117,11 +134,9 @@ static gboolean ping_timeout(gpointer data)

{ ObPingTarget *t = data; - if (t->waiting == 0) { /* got a reply already */ - /* send another ping to make sure it's still alive */ - ping_send(t); - } + ping_send(t); + /* if the client hasn't been responding then do something about it */ if (t->waiting == PING_TIMEOUT_WARN) t->h(t->client, TRUE); /* notify that the client isn't responding */

@@ -132,23 +147,15 @@ }

static void ping_end(ObClient *client, gpointer data) { - GSList *it; ObPingTarget *t; - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->client == client) { - ping_targets = g_slist_remove_link(ping_targets, it); - ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, - FALSE); - g_free(t); - break; - } - } + t = g_hash_table_lookup(ping_targets, &client); + g_assert(t); + + g_hash_table_remove(ping_targets, &t->client); + g_hash_table_remove(ping_ids, &t->id); + + ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE); - /* stop listening if we're not waiting for any more pings */ - if (!ping_targets) { - active = FALSE; - client_remove_destroy_notify(ping_end); - } + g_free(t); }
M openbox/ping.hopenbox/ping.h

@@ -33,6 +33,9 @@ again

*/ typedef void (*ObPingEventHandler) (struct _ObClient *c, gboolean dead); +void ping_startup(gboolean reconfigure); +void ping_shutdown(gboolean reconfigure); + void ping_start(struct _ObClient *c, ObPingEventHandler h); void ping_stop(struct _ObClient *c);