summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-09-28 06:31:00 +0000
committerDana Jansens <danakj@orodu.net>2003-09-28 06:31:00 +0000
commitf6ba1f27b9790f56bda1e5831069e2dd7e2c96a2 (patch)
treeeab63d53f7acd59f0e835b359468d2475aacd5a4 /openbox
parent518f819cdb18ea68b5d1bf93cd3d44737ef27915 (diff)
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.
Diffstat (limited to 'openbox')
-rw-r--r--openbox/client.c128
-rw-r--r--openbox/client.h8
-rw-r--r--openbox/client_list_menu.c2
-rw-r--r--openbox/event.c10
-rw-r--r--openbox/focus.c8
-rw-r--r--openbox/framerender.c6
-rw-r--r--openbox/keyboard.c7
-rw-r--r--openbox/mainloop.c53
-rw-r--r--openbox/menu.c4
-rw-r--r--openbox/moveresize.c4
-rw-r--r--openbox/popup.c2
-rw-r--r--openbox/popup.h2
12 files changed, 159 insertions, 75 deletions
diff --git a/openbox/client.c b/openbox/client.c
index bc3c6f0d..375e18aa 100644
--- a/openbox/client.c
+++ b/openbox/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 @@ void client_unmanage(ObClient *self)
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 @@ void client_unmanage(ObClient *self)
/* 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 @@ void client_update_icons(ObClient *self)
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 @@ void client_update_icons(ObClient *self)
(((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 @@ void client_update_icons(ObClient *self)
}
}
- 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 @@ gboolean client_focused(ObClient *self)
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)) {
@@ -2682,6 +2713,21 @@ ObClientIcon *client_icon(ObClient *self, int w, int h)
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 */
ObClient *client_find_directional(ObClient *c, ObDirection dir)
{
diff --git a/openbox/client.h b/openbox/client.h
index ed664c32..078de272 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -272,8 +272,10 @@ extern GList *client_list;
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 @@ void client_setup_decor_and_functions(ObClient *self);
/*! 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.
diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c
index 3a3e5a10..4d4555f8 100644
--- a/openbox/client_list_menu.c
+++ b/openbox/client_list_menu.c
@@ -53,7 +53,7 @@ static void desk_menu_update(ObMenuFrame *frame, gpointer data)
GSList *acts;
ObAction* act;
ObMenuEntry *e;
- ObClientIcon *icon;
+ const ObClientIcon *icon;
empty = FALSE;
diff --git a/openbox/event.c b/openbox/event.c
index 2df720b0..6c3d61bb 100644
--- a/openbox/event.c
+++ b/openbox/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 @@ void event_startup(gboolean reconfig)
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 @@ static gboolean focus_delay_func(gpointer data)
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()
diff --git a/openbox/focus.c b/openbox/focus.c
index d13df1dd..3376d50a 100644
--- a/openbox/focus.c
+++ b/openbox/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 @@ void focus_startup(gboolean reconfig)
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 @@ void focus_shutdown(gboolean reconfig)
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]);
diff --git a/openbox/framerender.c b/openbox/framerender.c
index 093260fb..a05ef6cf 100644
--- a/openbox/framerender.c
+++ b/openbox/framerender.c
@@ -238,9 +238,9 @@ static void framerender_icon(ObFrame *self, RrAppearance *a)
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;
diff --git a/openbox/keyboard.c b/openbox/keyboard.c
index b1d1d223..11b3a985 100644
--- a/openbox/keyboard.c
+++ b/openbox/keyboard.c
@@ -197,17 +197,16 @@ void keyboard_interactive_end(ObInteractiveState *s,
}
}
-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 @@ void keyboard_startup(gboolean reconfig)
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)
diff --git a/openbox/mainloop.c b/openbox/mainloop.c
index dea9e8c1..2e7c190b 100644
--- a/openbox/mainloop.c
+++ b/openbox/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 @@ struct _ObMainLoop
guint signals_fired[NUM_SIGNALS];
GSList *signal_handlers[NUM_SIGNALS];
- GQueue *action_queue;
+ GSList *action_queue;
};
struct _ObMainLoopTimer
@@ -178,7 +179,7 @@ ObMainLoop *ob_main_loop_new(Display *display)
all_loops = g_slist_prepend(all_loops, loop);
- loop->action_queue = g_queue_new();
+ loop->action_queue = NULL;
return loop;
}
@@ -230,7 +231,9 @@ void ob_main_loop_destroy(ObMainLoop *loop)
}
}
- 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 @@ static void fd_handle_foreach(gpointer key,
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)
@@ -263,6 +279,8 @@ void ob_main_loop_run(ObMainLoop *loop)
loop->run = TRUE;
loop->running = TRUE;
+ client_add_destructor(ob_main_loop_client_destroy, loop);
+
while (loop->run) {
if (loop->signal_fired) {
guint i;
@@ -294,12 +312,31 @@ void ob_main_loop_run(ObMainLoop *loop)
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 */
@@ -323,6 +360,8 @@ void ob_main_loop_run(ObMainLoop *loop)
}
}
+ client_remove_destructor(ob_main_loop_client_destroy);
+
loop->running = FALSE;
}
diff --git a/openbox/menu.c b/openbox/menu.c
index 2bd382cb..69256f5f 100644
--- a/openbox/menu.c
+++ b/openbox/menu.c
@@ -51,7 +51,7 @@ static void parse_menu_separator(ObParseInst *i,
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 @@ void menu_startup(gboolean reconfig)
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)
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index 74419175..41bb2d2a 100644
--- a/openbox/moveresize.c
+++ b/openbox/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 @@ void moveresize_startup(gboolean reconfig)
popup = popup_new(FALSE);
if (!reconfig)
- client_add_destructor(client_dest);
+ client_add_destructor(client_dest, NULL);
}
void moveresize_shutdown(gboolean reconfig)
diff --git a/openbox/popup.c b/openbox/popup.c
index 3844089c..3df451b5 100644
--- a/openbox/popup.c
+++ b/openbox/popup.c
@@ -248,7 +248,7 @@ void icon_popup_free(ObIconPopup *self)
}
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;
diff --git a/openbox/popup.h b/openbox/popup.h
index 82f45c96..847f264f 100644
--- a/openbox/popup.h
+++ b/openbox/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))