all repos — openbox @ f6ba1f27b9790f56bda1e5831069e2dd7e2c96a2

openbox fork - make it a bit more like ryudo

halfway through client changes but...
should fix crashes irt actions in the action queue for clients that have been destroyed. now those actions are skipped or performed without a client as possible.
Dana Jansens danakj@orodu.net
commit

f6ba1f27b9790f56bda1e5831069e2dd7e2c96a2

parent

518f819cdb18ea68b5d1bf93cd3d44737ef27915

M openbox/client.copenbox/client.c

@@ -50,6 +50,12 @@

#define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \ ButtonMotionMask) +typedef struct +{ + ObClientDestructor func; + gpointer data; +} Destructor; + GList *client_list = NULL; GSList *client_destructors = NULL;

@@ -81,14 +87,26 @@ void client_shutdown(gboolean reconfig)

{ } -void client_add_destructor(GDestroyNotify func) +void client_add_destructor(ObClientDestructor func, gpointer data) { - client_destructors = g_slist_prepend(client_destructors, (gpointer)func); + Destructor *d = g_new(Destructor, 1); + d->func = func; + d->data = data; + client_destructors = g_slist_prepend(client_destructors, d); } -void client_remove_destructor(GDestroyNotify func) +void client_remove_destructor(ObClientDestructor func) { - client_destructors = g_slist_remove(client_destructors, (gpointer)func); + GSList *it; + + for (it = client_destructors; it; it = g_slist_next(it)) { + Destructor *d = it->data; + if (d->func == func) { + g_free(d); + client_destructors = g_slist_delete_link(client_destructors, it); + break; + } + } } void client_set_list()

@@ -402,8 +420,8 @@ influence */

screen_update_areas(); for (it = client_destructors; it; it = g_slist_next(it)) { - GDestroyNotify func = (GDestroyNotify) it->data; - func(self); + Destructor *d = it->data; + d->func(self, d->data); } if (focus_client == self) {

@@ -473,9 +491,9 @@

/* free all data allocated in the client struct */ g_slist_free(self->transients); for (j = 0; j < self->nicons; ++j) - g_free(self->icons[j].data); + g_free(self->icons[j].data); if (self->nicons > 0) - g_free(self->icons); + g_free(self->icons); g_free(self->title); g_free(self->icon_title); g_free(self->name);

@@ -1498,35 +1516,35 @@ guint32 *data;

guint w, h, i, j; for (i = 0; i < self->nicons; ++i) - g_free(self->icons[i].data); + g_free(self->icons[i].data); if (self->nicons > 0) - g_free(self->icons); + g_free(self->icons); self->nicons = 0; if (PROP_GETA32(self->window, net_wm_icon, cardinal, &data, &num)) { - /* figure out how many valid icons are in here */ - i = 0; - while (num - i > 2) { - w = data[i++]; - h = data[i++]; - i += w * h; - if (i > num || w*h == 0) break; - ++self->nicons; - } + /* figure out how many valid icons are in here */ + i = 0; + while (num - i > 2) { + w = data[i++]; + h = data[i++]; + i += w * h; + if (i > num || w*h == 0) break; + ++self->nicons; + } - self->icons = g_new(ObClientIcon, self->nicons); + self->icons = g_new(ObClientIcon, self->nicons); - /* store the icons */ - i = 0; - for (j = 0; j < self->nicons; ++j) { + /* store the icons */ + i = 0; + for (j = 0; j < self->nicons; ++j) { guint x, y, t; - w = self->icons[j].width = data[i++]; - h = self->icons[j].height = data[i++]; + w = self->icons[j].width = data[i++]; + h = self->icons[j].height = data[i++]; if (w*h == 0) continue; - self->icons[j].data = g_new(RrPixel32, w * h); + self->icons[j].data = g_new(RrPixel32, w * h); for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) { if (x >= w) { x = 0;

@@ -1538,10 +1556,10 @@ (((data[i] >> 16) & 0xff) << RrDefaultRedOffset) +

(((data[i] >> 8) & 0xff) << RrDefaultGreenOffset) + (((data[i] >> 0) & 0xff) << RrDefaultBlueOffset); } - g_assert(i <= num); - } + g_assert(i <= num); + } - g_free(data); + g_free(data); } else if (PROP_GETA32(self->window, kwm_win_icon, kwm_win_icon, &data, &num)) { if (num == 2) {

@@ -1583,18 +1601,8 @@ XFree(hints);

} } - if (!self->nicons) { - self->nicons++; - self->icons = g_new(ObClientIcon, self->nicons); - self->icons[self->nicons-1].width = 48; - self->icons[self->nicons-1].height = 48; - self->icons[self->nicons-1].data = g_memdup(ob_rr_theme->def_win_icon, - sizeof(RrPixel32) - * 48 * 48); - } - if (self->frame) - frame_adjust_icon(self->frame); + frame_adjust_icon(self->frame); } static void client_change_state(ObClient *self)

@@ -2659,13 +2667,36 @@ {

return self == focus_client; } -ObClientIcon *client_icon(ObClient *self, int w, int h) +static ObClientIcon* client_icon_recursive(ObClient *self, int w, int h) { guint i; /* si is the smallest image >= req */ /* li is the largest image < req */ unsigned long size, smallest = 0xffffffff, largest = 0, si = 0, li = 0; + g_message("icons %d", self->nicons); + + if (!self->nicons) { + ObClientIcon *parent = NULL; + + if (self->transient_for) { + if (self->transient_for != OB_TRAN_GROUP) + parent = client_icon_recursive(self->transient_for, w, h); + else { + GSList *it; + for (it = self->group->members; it; it = g_slist_next(it)) { + ObClient *c = it->data; + if (c != self && !c->transient_for) { + if ((parent = client_icon_recursive(c, w, h))) + break; + } + } + } + } + + return parent; + } + for (i = 0; i < self->nicons; ++i) { size = self->icons[i].width * self->icons[i].height; if (size < smallest && size >= (unsigned)(w * h)) {

@@ -2680,6 +2711,21 @@ }

if (largest == 0) /* didnt find one smaller than the requested size */ return &self->icons[si]; return &self->icons[li]; +} + +const ObClientIcon* client_icon(ObClient *self, int w, int h) +{ + ObClientIcon *ret; + static ObClientIcon deficon; + + g_message("going for broke"); + if (!(ret = client_icon_recursive(self, w, h))) { + g_message("using default"); + deficon.width = deficon.height = 48; + deficon.data = ob_rr_theme->def_win_icon; + ret = &deficon; + } + return ret; } /* this be mostly ripped from fvwm */
M openbox/client.hopenbox/client.h

@@ -272,8 +272,10 @@

void client_startup(gboolean reconfig); void client_shutdown(gboolean reconfig); -void client_add_destructor(GDestroyNotify func); -void client_remove_destructor(GDestroyNotify func); +typedef void (*ObClientDestructor)(ObClient *client, gpointer data); + +void client_add_destructor(ObClientDestructor func, gpointer data); +void client_remove_destructor(ObClientDestructor func); /*! Manages all existing windows */ void client_manage_all();

@@ -503,7 +505,7 @@

/*! Retrieves the window's type and sets ObClient->type */ void client_get_type(ObClient *self); -ObClientIcon *client_icon(ObClient *self, int w, int h); +const ObClientIcon *client_icon(ObClient *self, int w, int h); /*! Searches a client's direct parents for a focused window. The function does not check for the passed client, only for *ONE LEVEL* of its parents.
M openbox/client_list_menu.copenbox/client_list_menu.c

@@ -53,7 +53,7 @@ if (client_normal(c)) {

GSList *acts; ObAction* act; ObMenuEntry *e; - ObClientIcon *icon; + const ObClientIcon *icon; empty = FALSE;
M openbox/event.copenbox/event.c

@@ -69,7 +69,7 @@ static void event_handle_client(ObClient *c, XEvent *e);

static void event_handle_group(ObGroup *g, XEvent *e); static gboolean focus_delay_func(gpointer data); -static void focus_delay_client_dest(gpointer data); +static void focus_delay_client_dest(ObClient *client, gpointer data); static gboolean menu_hide_delay_func(gpointer data);

@@ -157,7 +157,7 @@ #ifdef USE_SM

IceAddConnectionWatch(ice_watch, NULL); #endif - client_add_destructor(focus_delay_client_dest); + client_add_destructor(focus_delay_client_dest, NULL); } void event_shutdown(gboolean reconfig)

@@ -1252,11 +1252,9 @@ client_raise(c);

return FALSE; /* no repeat */ } -static void focus_delay_client_dest(gpointer data) +static void focus_delay_client_dest(ObClient *client, gpointer data) { - ObClient *c = data; - - ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, c); + ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, client); } void event_ignore_queued_enters()
M openbox/focus.copenbox/focus.c

@@ -42,10 +42,10 @@ ObClient *focus_cycle_target;

static ObIconPopup *focus_cycle_popup; -static void focus_cycle_destructor(ObClient *c) +static void focus_cycle_destructor(ObClient *client, gpointer data) { /* end cycling if the target disappears */ - if (focus_cycle_target == c) + if (focus_cycle_target == client) focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE); }

@@ -54,7 +54,7 @@ {

focus_cycle_popup = icon_popup_new(TRUE); if (!reconfig) { - client_add_destructor((GDestroyNotify) focus_cycle_destructor); + client_add_destructor(focus_cycle_destructor, NULL); /* start with nothing focused */ focus_set_client(NULL);

@@ -68,7 +68,7 @@

icon_popup_free(focus_cycle_popup); if (!reconfig) { - client_remove_destructor((GDestroyNotify) focus_cycle_destructor); + client_remove_destructor(focus_cycle_destructor); for (i = 0; i < screen_num_desktops; ++i) g_list_free(focus_order[i]);
M openbox/framerender.copenbox/framerender.c

@@ -238,9 +238,9 @@ {

if (self->icon_x < 0) return; if (self->client->nicons) { - ObClientIcon *icon = client_icon(self->client, - ob_rr_theme->button_size + 2, - ob_rr_theme->button_size + 2); + const ObClientIcon *icon = client_icon(self->client, + ob_rr_theme->button_size + 2, + ob_rr_theme->button_size + 2); a->texture[0].type = RR_TEXTURE_RGBA; a->texture[0].data.rgba.width = icon->width; a->texture[0].data.rgba.height = icon->height;
M openbox/keyboard.copenbox/keyboard.c

@@ -197,17 +197,16 @@ keyboard_reset_chains();

} } -void keyboard_interactive_end_client(gpointer data) +void keyboard_interactive_end_client(ObClient *client, gpointer data) { GSList *it, *next; - ObClient *c = data; for (it = interactive_states; it; it = next) { ObInteractiveState *s = it->data; next = g_slist_next(it); - if (s->client == c) + if (s->client == client) s->client = NULL; } }

@@ -291,7 +290,7 @@ {

grab_keys(TRUE); if (!reconfig) - client_add_destructor(keyboard_interactive_end_client); + client_add_destructor(keyboard_interactive_end_client, NULL); } void keyboard_shutdown(gboolean reconfig)
M openbox/mainloop.copenbox/mainloop.c

@@ -18,6 +18,7 @@ */

#include "mainloop.h" #include "action.h" +#include "client.h" #include <stdio.h> #include <stdlib.h>

@@ -88,7 +89,7 @@ gboolean signal_fired;

guint signals_fired[NUM_SIGNALS]; GSList *signal_handlers[NUM_SIGNALS]; - GQueue *action_queue; + GSList *action_queue; }; struct _ObMainLoopTimer

@@ -178,7 +179,7 @@ }

all_loops = g_slist_prepend(all_loops, loop); - loop->action_queue = g_queue_new(); + loop->action_queue = NULL; return loop; }

@@ -230,7 +231,9 @@ }

} } - g_queue_free(loop->action_queue); + for (it = loop->action_queue; it; it = g_slist_next(it)) + action_unref(it->data); + g_slist_free(loop->action_queue); g_free(loop); }

@@ -249,7 +252,20 @@ }

void ob_main_loop_queue_action(ObMainLoop *loop, ObAction *act) { - g_queue_push_tail(loop->action_queue, action_copy(act)); + loop->action_queue = g_slist_append(loop->action_queue, action_copy(act)); +} + +static void ob_main_loop_client_destroy(ObClient *client, gpointer data) +{ + ObMainLoop *loop = data; + GSList *it; + + for (it = loop->action_queue; it; it = g_slist_next(it)) { + ObAction *act = it->data; + + if (act->data.any.c == client) + act->data.any.c = NULL; + } } void ob_main_loop_run(ObMainLoop *loop)

@@ -262,6 +278,8 @@ ObAction *act;

loop->run = TRUE; loop->running = TRUE; + + client_add_destructor(ob_main_loop_client_destroy, loop); while (loop->run) { if (loop->signal_fired) {

@@ -294,12 +312,31 @@ ObMainLoopXHandlerType *h = it->data;

h->func(&e, h->data); } } while (XPending(loop->display)); - } else if ((act = g_queue_pop_head(loop->action_queue))) { + } else if (loop->action_queue) { /* only fire off one action at a time, then go back for more X events, since the action might cause some X events (like FocusIn :) */ - act->func(&act->data); - action_unref(act); + + do { + act = loop->action_queue->data; + if (act->data.any.client_action == OB_CLIENT_ACTION_ALWAYS && + !act->data.any.c) + { + loop->action_queue = + g_slist_delete_link(loop->action_queue, + loop->action_queue); + action_unref(act); + act = NULL; + } + } while (!act && loop->action_queue); + + if (act) { + act->func(&act->data); + loop->action_queue = + g_slist_delete_link(loop->action_queue, + loop->action_queue); + action_unref(act); + } } else { /* this only runs if there were no x events received */

@@ -322,6 +359,8 @@ g_hash_table_foreach(loop->fd_handlers,

fd_handle_foreach, &selset); } } + + client_remove_destructor(ob_main_loop_client_destroy); loop->running = FALSE; }
M openbox/menu.copenbox/menu.c

@@ -51,7 +51,7 @@ gpointer data);

static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, gpointer data); -static void client_dest(gpointer client) +static void client_dest(ObClient *client, gpointer data) { /* menus can be associated with a client, so close any that are since we are disappearing now */

@@ -98,7 +98,7 @@

g_assert(menu_parse_state.parent == NULL); if (!reconfig) - client_add_destructor(client_dest); + client_add_destructor(client_dest, NULL); } void menu_shutdown(gboolean reconfig)
M openbox/moveresize.copenbox/moveresize.c

@@ -46,7 +46,7 @@ static ObCorner lockcorner;

static ObPopup *popup = NULL; -static void client_dest(gpointer client) +static void client_dest(ObClient *client, gpointer data) { if (moveresize_client == client) moveresize_end(TRUE);

@@ -57,7 +57,7 @@ {

popup = popup_new(FALSE); if (!reconfig) - client_add_destructor(client_dest); + client_add_destructor(client_dest, NULL); } void moveresize_shutdown(gboolean reconfig)
M openbox/popup.copenbox/popup.c

@@ -248,7 +248,7 @@ }

} void icon_popup_show(ObIconPopup *self, - gchar *text, struct _ObClientIcon *icon) + gchar *text, const ObClientIcon *icon) { if (icon) { self->a_icon->texture[0].type = RR_TEXTURE_RGBA;
M openbox/popup.hopenbox/popup.h

@@ -98,7 +98,7 @@ ObIconPopup *icon_popup_new();

void icon_popup_free(ObIconPopup *self); void icon_popup_show(ObIconPopup *self, - gchar *text, struct _ObClientIcon *icon); + gchar *text, const struct _ObClientIcon *icon); #define icon_popup_hide(p) popup_hide((p)->popup) #define icon_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y)) #define icon_popup_size(p, w, h) popup_size((p)->popup,(w),(h))