]> Dogcows Code - chaz/openbox/blobdiff - openbox/mainloop.c
define DEBUG, NDEBUG, and G_DISABLE_ASSERTS
[chaz/openbox] / openbox / mainloop.c
index b8b7e698001d4982a3889275c57147e8519d9113..eef794034b3b266cb846b93e39cab00f76b1152f 100644 (file)
@@ -17,6 +17,8 @@
 */
 
 #include "mainloop.h"
+#include "action.h"
+#include "client.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -86,6 +88,8 @@ struct _ObMainLoop
     gboolean signal_fired;
     guint signals_fired[NUM_SIGNALS];
     GSList *signal_handlers[NUM_SIGNALS];
+
+    GSList *action_queue;
 };
 
 struct _ObMainLoopTimer
@@ -117,6 +121,7 @@ struct _ObMainLoopXHandlerType
     ObMainLoop *loop;
     gpointer data;
     ObMainLoopXHandler func;
+    ObMainLoopXDoneHandler done_func;
     GDestroyNotify destroy;
 };
 
@@ -175,6 +180,8 @@ ObMainLoop *ob_main_loop_new(Display *display)
 
     all_loops = g_slist_prepend(all_loops, loop);
 
+    loop->action_queue = NULL;
+
     return loop;
 }
 
@@ -225,6 +232,10 @@ void ob_main_loop_destroy(ObMainLoop *loop)
             }
         }
 
+        for (it = loop->action_queue; it; it = g_slist_next(it))
+            action_unref(it->data);
+        g_slist_free(loop->action_queue);
+
         g_free(loop);
     }
 }
@@ -240,16 +251,37 @@ static void fd_handle_foreach(gpointer key,
         h->func(h->fd, h->data);
 }
 
+void ob_main_loop_queue_action(ObMainLoop *loop, ObAction *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)
 {
     XEvent e;
     struct timeval *wait;
     fd_set selset;
     GSList *it;
+    ObAction *act;
 
     loop->run = TRUE;
     loop->running = TRUE;
 
+    client_add_destructor(ob_main_loop_client_destroy, loop);
+
     while (loop->run) {
         if (loop->signal_fired) {
             guint i;
@@ -281,10 +313,42 @@ void ob_main_loop_run(ObMainLoop *loop)
                     h->func(&e, h->data);
                 }
             } while (XPending(loop->display));
+        } 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 :) */
+
+            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 */
 
+            for (it = loop->x_handlers; it; it = g_slist_next(it)) {
+                ObMainLoopXHandlerType *h = it->data;
+                if (h->done_func)
+                    h->done_func(h->data);
+            }            
+
             timer_dispatch(loop, (GTimeVal**)&wait);
+
             selset = loop->fd_set;
             /* there is a small race condition here. if a signal occurs
                between this if() and the select() then we will not process
@@ -303,6 +367,8 @@ void ob_main_loop_run(ObMainLoop *loop)
         }
     }
 
+    client_remove_destructor(ob_main_loop_client_destroy);
+
     loop->running = FALSE;
 }
 
@@ -315,6 +381,7 @@ void ob_main_loop_exit(ObMainLoop *loop)
 
 void ob_main_loop_x_add(ObMainLoop *loop,
                         ObMainLoopXHandler handler,
+                        ObMainLoopXDoneHandler done_handler,
                         gpointer data,
                         GDestroyNotify notify)
 {
@@ -323,6 +390,7 @@ void ob_main_loop_x_add(ObMainLoop *loop,
     h = g_new(ObMainLoopXHandlerType, 1);
     h->loop = loop;
     h->func = handler;
+    h->done_func = done_handler;
     h->data = data;
     h->destroy = notify;
     loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
@@ -507,14 +575,14 @@ static void insert_timer(ObMainLoop *loop, ObMainLoopTimer *ins)
 {
     GSList *it;
     for (it = loop->timers; it; it = g_slist_next(it)) {
-       ObMainLoopTimer *t = it->data;
-        if (timecompare(&ins->timeout, &t->timeout) <= 0) {
-           loop->timers = g_slist_insert_before(loop->timers, it, ins);
-           break;
-       }
+        ObMainLoopTimer *t = it->data;
+        if (timecompare(&ins->timeout, &t->timeout) >= 0) {
+            loop->timers = g_slist_insert_before(loop->timers, it, ins);
+            break;
+        }
     }
     if (it == NULL) /* didnt fit anywhere in the list */
-       loop->timers = g_slist_append(loop->timers, ins);
+        loop->timers = g_slist_append(loop->timers, ins);
 }
 
 void ob_main_loop_timeout_add(ObMainLoop *loop,
@@ -591,34 +659,34 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
     g_get_current_time(&loop->now);
 
     for (it = loop->timers; it; it = next) {
-       ObMainLoopTimer *curr;
+        ObMainLoopTimer *curr;
         
         next = g_slist_next(it);
 
-       curr = it->data;
+        curr = it->data;
 
-       /* since timer_stop doesn't actually free the timer, we have to do our
-          real freeing in here.
-       */
-       if (curr->del_me) {
+        /* since timer_stop doesn't actually free the timer, we have to do our
+           real freeing in here.
+        */
+        if (curr->del_me) {
             /* delete the top */
-           loop->timers = g_slist_delete_link(loop->timers, it); 
-           g_free(curr);
-           continue;
-       }
+            loop->timers = g_slist_delete_link(loop->timers, it); 
+            g_free(curr);
+            continue;
+        }
        
-       /* the queue is sorted, so if this timer shouldn't fire, none are 
-          ready */
-        if (timecompare(&NEAREST_TIMEOUT(loop), &loop->now) <= 0)
-           break;
-
-       /* we set the last fired time to delay msec after the previous firing,
-          then re-insert.  timers maintain their order and may trigger more
-          than once if they've waited more than one delay's worth of time.
-       */
-       loop->timers = g_slist_delete_link(loop->timers, it);
-       g_time_val_add(&curr->last, curr->delay);
-       if (curr->func(curr->data)) {
+        /* the queue is sorted, so if this timer shouldn't fire, none are 
+           ready */
+        if (timecompare(&NEAREST_TIMEOUT(loop), &loop->now) < 0)
+            break;
+
+        /* we set the last fired time to delay msec after the previous firing,
+           then re-insert.  timers maintain their order and may trigger more
+           than once if they've waited more than one delay's worth of time.
+        */
+        loop->timers = g_slist_delete_link(loop->timers, it);
+        g_time_val_add(&curr->last, curr->delay);
+        if (curr->func(curr->data)) {
             g_time_val_add(&curr->timeout, curr->delay);
             insert_timer(loop, curr);
         } else {
@@ -631,13 +699,13 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
     }
 
     if (fired) {
-       /* if at least one timer fires, then don't wait on X events, as there
-          may already be some in the queue from the timer callbacks.
-       */
-       loop->ret_wait.tv_sec = loop->ret_wait.tv_usec = 0;
-       *wait = &loop->ret_wait;
+        /* if at least one timer fires, then don't wait on X events, as there
+           may already be some in the queue from the timer callbacks.
+        */
+        loop->ret_wait.tv_sec = loop->ret_wait.tv_usec = 0;
+        *wait = &loop->ret_wait;
     } else if (nearest_timeout_wait(loop, &loop->ret_wait))
-       *wait = &loop->ret_wait;
+        *wait = &loop->ret_wait;
     else
-       *wait = NULL;
+        *wait = NULL;
 }
This page took 0.026997 seconds and 4 git commands to generate.