summaryrefslogtreecommitdiff
path: root/openbox/mainloop.c
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/mainloop.c
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/mainloop.c')
-rw-r--r--openbox/mainloop.c53
1 files changed, 46 insertions, 7 deletions
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;
}