From: Dana Jansens Date: Tue, 8 Jun 2010 21:50:23 +0000 (-0400) Subject: Use GMainLoop instead of ObtMainLoop X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=fd77a0a7b3f892925f203287b8b46c6ec9be94ea;p=chaz%2Fopenbox Use GMainLoop instead of ObtMainLoop --- diff --git a/Makefile.am b/Makefile.am index 4c670bc0..246abede 100644 --- a/Makefile.am +++ b/Makefile.am @@ -134,8 +134,6 @@ obt_libobt_la_SOURCES = \ obt/internal.h \ obt/keyboard.h \ obt/keyboard.c \ - obt/mainloop.h \ - obt/mainloop.c \ obt/xml.h \ obt/xml.c \ obt/ddparse.h \ @@ -147,8 +145,6 @@ obt_libobt_la_SOURCES = \ obt/prop.h \ obt/prop.c \ obt/util.h \ - obt/xevent.h \ - obt/xevent.c \ obt/xqueue.h \ obt/xqueue.c @@ -437,13 +433,11 @@ obtpubinclude_HEADERS = \ obt/link.h \ obt/display.h \ obt/keyboard.h \ - obt/mainloop.h \ obt/xml.h \ obt/paths.h \ obt/prop.h \ obt/util.h \ obt/version.h \ - obt/xevent.h \ obt/xqueue.h nodist_pkgconfig_DATA = \ diff --git a/obt/mainloop.c b/obt/mainloop.c deleted file mode 100644 index 75366256..00000000 --- a/obt/mainloop.c +++ /dev/null @@ -1,698 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - obt/mainloop.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "obt/mainloop.h" -#include "obt/display.h" -#include "obt/xqueue.h" -#include "obt/util.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_SIGNAL_H -#include -#endif - -typedef struct _ObtMainLoopTimer ObtMainLoopTimer; -typedef struct _ObtMainLoopSignal ObtMainLoopSignal; -typedef struct _ObtMainLoopSignalHandlerType ObtMainLoopSignalHandlerType; -typedef struct _ObtMainLoopXHandlerType ObtMainLoopXHandlerType; -typedef struct _ObtMainLoopFdHandlerType ObtMainLoopFdHandlerType; - -/* this should be more than the number of possible signals on any - architecture... */ -#define NUM_SIGNALS 99 - -/* all created ObtMainLoops. Used by the signal handler to pass along - signals */ -static GSList *all_loops; - -/* signals are global to all loops */ -static struct { - guint installed; /* a ref count */ - struct sigaction oldact; -} all_signals[NUM_SIGNALS]; - -/* a set of all possible signals */ -static sigset_t all_signals_set; - -/* signals which cause a core dump, these can't be used for callbacks */ -static gint core_signals[] = -{ - SIGABRT, - SIGSEGV, - SIGFPE, - SIGILL, - SIGQUIT, - SIGTRAP, - SIGSYS, - SIGBUS, - SIGXCPU, - SIGXFSZ -}; -#define NUM_CORE_SIGNALS (sizeof(core_signals) / sizeof(core_signals[0])) - -static void sighandler(gint sig); -static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait); -static void fd_handler_destroy(gpointer data); -static void calc_max_fd(ObtMainLoop *loop); - -struct _ObtMainLoop -{ - gint ref; - Display *display; - - gboolean run; /* do keep running */ - gboolean running; /* is still running */ - - GSList *x_handlers; - - gint fd_x; /* The X fd is a special case! */ - gint fd_max; - GHashTable *fd_handlers; - fd_set fd_set; - - GSList *timers; - GTimeVal now; - GTimeVal ret_wait; - - gboolean signal_fired; - guint signals_fired[NUM_SIGNALS]; - GSList *signal_handlers[NUM_SIGNALS]; -}; - -struct _ObtMainLoopTimer -{ - gulong delay; - GSourceFunc func; - gpointer data; - GEqualFunc equal; - GDestroyNotify destroy; - - /* The timer needs to be freed */ - gboolean del_me; - /* The time the last fire should've been at */ - GTimeVal last; - /* When this timer will next trigger */ - GTimeVal timeout; - - /* Only allow a timer's function to fire once per run through the list, - so that it doesn't get locked in there forever */ - gboolean fired; -}; - -struct _ObtMainLoopSignalHandlerType -{ - ObtMainLoop *loop; - gint signal; - gpointer data; - ObtMainLoopSignalHandler func; - GDestroyNotify destroy; -}; - -struct _ObtMainLoopXHandlerType -{ - ObtMainLoop *loop; - gpointer data; - ObtMainLoopXHandler func; - GDestroyNotify destroy; -}; - -struct _ObtMainLoopFdHandlerType -{ - ObtMainLoop *loop; - gint fd; - gpointer data; - ObtMainLoopFdHandler func; - GDestroyNotify destroy; -}; - -ObtMainLoop *obt_main_loop_new(void) -{ - ObtMainLoop *loop; - - loop = g_slice_new0(ObtMainLoop); - loop->ref = 1; - FD_ZERO(&loop->fd_set); - loop->fd_x = -1; - loop->fd_max = -1; - - loop->fd_handlers = g_hash_table_new_full(g_int_hash, g_int_equal, - NULL, fd_handler_destroy); - - g_get_current_time(&loop->now); - - /* only do this if we're the first loop created */ - if (!all_loops) { - guint i; - struct sigaction action; - sigset_t sigset; - - /* initialize the all_signals_set */ - sigfillset(&all_signals_set); - - sigemptyset(&sigset); - action.sa_handler = sighandler; - action.sa_mask = sigset; - action.sa_flags = SA_NOCLDSTOP; - - /* grab all the signals that cause core dumps */ - for (i = 0; i < NUM_CORE_SIGNALS; ++i) { - /* SIGABRT is curiously not grabbed here!! that's because when we - get one of the core_signals, we use abort() to dump the core. - And having the abort() only go back to our signal handler again - is less than optimal */ - if (core_signals[i] != SIGABRT) { - sigaction(core_signals[i], &action, - &all_signals[core_signals[i]].oldact); - all_signals[core_signals[i]].installed++; - } - } - } - - all_loops = g_slist_prepend(all_loops, loop); - - return loop; -} - -void obt_main_loop_ref(ObtMainLoop *loop) -{ - ++loop->ref; -} - -void obt_main_loop_unref(ObtMainLoop *loop) -{ - guint i; - GSList *it, *next; - - if (loop && --loop->ref == 0) { - g_assert(loop->running == FALSE); - - for (it = loop->x_handlers; it; it = next) { - ObtMainLoopXHandlerType *h = it->data; - next = g_slist_next(it); - obt_main_loop_x_remove(loop, h->func); - } - - g_hash_table_destroy(loop->fd_handlers); - - for (it = loop->timers; it; it = g_slist_next(it)) { - ObtMainLoopTimer *t = it->data; - if (t->destroy) t->destroy(t->data); - g_slice_free(ObtMainLoopTimer, t); - } - g_slist_free(loop->timers); - loop->timers = NULL; - - for (i = 0; i < NUM_SIGNALS; ++i) - for (it = loop->signal_handlers[i]; it; it = next) { - ObtMainLoopSignalHandlerType *h = it->data; - next = g_slist_next(it); - obt_main_loop_signal_remove(loop, h->func); - } - - all_loops = g_slist_remove(all_loops, loop); - - /* only do this if we're the last loop destroyed */ - if (!all_loops) { - /* grab all the signals that cause core dumps */ - for (i = 0; i < NUM_CORE_SIGNALS; ++i) { - if (all_signals[core_signals[i]].installed) { - sigaction(core_signals[i], - &all_signals[core_signals[i]].oldact, NULL); - all_signals[core_signals[i]].installed--; - } - } - } - - g_slice_free(ObtMainLoop, loop); - } -} - -static void fd_handle_foreach(gpointer key, - gpointer value, - gpointer data) -{ - ObtMainLoopFdHandlerType *h = value; - fd_set *set = data; - - if (FD_ISSET(h->fd, set)) - h->func(h->fd, h->data); -} - -void obt_main_loop_run(ObtMainLoop *loop) -{ - XEvent e; - struct timeval *wait; - fd_set selset; - GSList *it; - - loop->run = TRUE; - loop->running = TRUE; - - while (loop->run) { - if (loop->signal_fired) { - guint i; - sigset_t oldset; - - /* block signals so that we can do this without the data changing - on us */ - sigprocmask(SIG_SETMASK, &all_signals_set, &oldset); - - for (i = 0; i < NUM_SIGNALS; ++i) { - while (loop->signals_fired[i]) { - for (it = loop->signal_handlers[i]; - it; it = g_slist_next(it)) { - ObtMainLoopSignalHandlerType *h = it->data; - h->func(i, h->data); - } - loop->signals_fired[i]--; - } - } - loop->signal_fired = FALSE; - - sigprocmask(SIG_SETMASK, &oldset, NULL); - } else if (loop->display && xqueue_pending_local()) { - while (xqueue_next_local(&e) && loop->run) { - if (e.type == MappingNotify) - XRefreshKeyboardMapping(&e.xmapping); - - for (it = loop->x_handlers; it; it = g_slist_next(it)) { - ObtMainLoopXHandlerType *h = it->data; - h->func(&e, h->data); - } - } - } else { - /* this only runs if there were no x events received */ - 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 - the signal until 'wait' expires. possible solutions include - using GStaticMutex, and having the signal handler set 'wait' - to 0 */ - if (!loop->signal_fired) - select(loop->fd_max + 1, &selset, NULL, NULL, wait); - - /* handle the X events with highest prioirity */ - if (FD_ISSET(loop->fd_x, &selset)) - continue; - - g_hash_table_foreach(loop->fd_handlers, - fd_handle_foreach, &selset); - } - } - - loop->running = FALSE; -} - -void obt_main_loop_exit(ObtMainLoop *loop) -{ - loop->run = FALSE; -} - -/*** XEVENT WATCHERS ***/ - -void obt_main_loop_x_add(ObtMainLoop *loop, - ObtMainLoopXHandler handler, - gpointer data, - GDestroyNotify notify) -{ - ObtMainLoopXHandlerType *h; - - h = g_slice_new(ObtMainLoopXHandlerType); - h->loop = loop; - h->func = handler; - h->data = data; - h->destroy = notify; - - if (!loop->x_handlers) { - g_assert(obt_display); /* is the display open? */ - - loop->display = obt_display; - loop->fd_x = ConnectionNumber(loop->display); - FD_SET(loop->fd_x, &loop->fd_set); - calc_max_fd(loop); - } - - loop->x_handlers = g_slist_prepend(loop->x_handlers, h); -} - -void obt_main_loop_x_remove(ObtMainLoop *loop, - ObtMainLoopXHandler handler) -{ - GSList *it, *next; - - for (it = loop->x_handlers; it; it = next) { - ObtMainLoopXHandlerType *h = it->data; - next = g_slist_next(it); - if (h->func == handler) { - loop->x_handlers = g_slist_delete_link(loop->x_handlers, it); - if (h->destroy) h->destroy(h->data); - g_slice_free(ObtMainLoopXHandlerType, h); - } - } - - if (!loop->x_handlers) { - FD_CLR(loop->fd_x, &loop->fd_set); - calc_max_fd(loop); - } -} - -/*** SIGNAL WATCHERS ***/ - -static void sighandler(gint sig) -{ - GSList *it; - guint i; - - g_return_if_fail(sig < NUM_SIGNALS); - - for (i = 0; i < NUM_CORE_SIGNALS; ++i) - if (sig == core_signals[i]) { - /* XXX special case for signals that default to core dump. - but throw some helpful output here... */ - - fprintf(stderr, "How are you gentlemen? All your base are" - " belong to us. (Openbox received signal %d)\n", sig); - - /* die with a core dump */ - abort(); - } - - for (it = all_loops; it; it = g_slist_next(it)) { - ObtMainLoop *loop = it->data; - loop->signal_fired = TRUE; - loop->signals_fired[sig]++; - } -} - -void obt_main_loop_signal_add(ObtMainLoop *loop, - gint signal, - ObtMainLoopSignalHandler handler, - gpointer data, - GDestroyNotify notify) -{ - ObtMainLoopSignalHandlerType *h; - - g_return_if_fail(signal < NUM_SIGNALS); - - h = g_slice_new(ObtMainLoopSignalHandlerType); - h->loop = loop; - h->signal = signal; - h->func = handler; - h->data = data; - h->destroy = notify; - loop->signal_handlers[h->signal] = - g_slist_prepend(loop->signal_handlers[h->signal], h); - - if (!all_signals[signal].installed) { - struct sigaction action; - sigset_t sigset; - - sigemptyset(&sigset); - action.sa_handler = sighandler; - action.sa_mask = sigset; - action.sa_flags = SA_NOCLDSTOP; - - sigaction(signal, &action, &all_signals[signal].oldact); - } - - all_signals[signal].installed++; -} - -void obt_main_loop_signal_remove(ObtMainLoop *loop, - ObtMainLoopSignalHandler handler) -{ - guint i; - GSList *it, *next; - - for (i = 0; i < NUM_SIGNALS; ++i) { - for (it = loop->signal_handlers[i]; it; it = next) { - ObtMainLoopSignalHandlerType *h = it->data; - - next = g_slist_next(it); - - if (h->func == handler) { - g_assert(all_signals[h->signal].installed > 0); - - all_signals[h->signal].installed--; - if (!all_signals[h->signal].installed) { - sigaction(h->signal, &all_signals[h->signal].oldact, NULL); - } - - loop->signal_handlers[i] = - g_slist_delete_link(loop->signal_handlers[i], it); - if (h->destroy) h->destroy(h->data); - - g_slice_free(ObtMainLoopSignalHandlerType, h); - } - } - } - -} - -/*** FILE DESCRIPTOR WATCHERS ***/ - -static void max_fd_func(gpointer key, gpointer value, gpointer data) -{ - ObtMainLoop *loop = data; - - /* key is the fd */ - loop->fd_max = MAX(loop->fd_max, *(gint*)key); -} - -static void calc_max_fd(ObtMainLoop *loop) -{ - loop->fd_max = loop->fd_x; - - g_hash_table_foreach(loop->fd_handlers, max_fd_func, loop); -} - -void obt_main_loop_fd_add(ObtMainLoop *loop, - gint fd, - ObtMainLoopFdHandler handler, - gpointer data, - GDestroyNotify notify) -{ - ObtMainLoopFdHandlerType *h; - - h = g_slice_new(ObtMainLoopFdHandlerType); - h->loop = loop; - h->fd = fd; - h->func = handler; - h->data = data; - h->destroy = notify; - - g_hash_table_replace(loop->fd_handlers, &h->fd, h); - FD_SET(h->fd, &loop->fd_set); - calc_max_fd(loop); -} - -static void fd_handler_destroy(gpointer data) -{ - ObtMainLoopFdHandlerType *h = data; - - FD_CLR(h->fd, &h->loop->fd_set); - - if (h->destroy) - h->destroy(h->data); - g_slice_free(ObtMainLoopFdHandlerType, h); -} - -void obt_main_loop_fd_remove(ObtMainLoop *loop, - gint fd) -{ - g_hash_table_remove(loop->fd_handlers, &fd); - calc_max_fd(loop); -} - -/*** TIMEOUTS ***/ - -#define NEAREST_TIMEOUT(loop) \ - (((ObtMainLoopTimer*)(loop)->timers->data)->timeout) - -static glong timecompare(GTimeVal *a, GTimeVal *b) -{ - glong r; - if ((r = a->tv_sec - b->tv_sec)) return r; - return a->tv_usec - b->tv_usec; -} - -static void insert_timer(ObtMainLoop *loop, ObtMainLoopTimer *ins) -{ - GSList *it; - for (it = loop->timers; it; it = g_slist_next(it)) { - ObtMainLoopTimer *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); -} - -void obt_main_loop_timeout_add(ObtMainLoop *loop, - gulong microseconds, - GSourceFunc handler, - gpointer data, - GEqualFunc cmp, - GDestroyNotify notify) -{ - ObtMainLoopTimer *t = g_slice_new(ObtMainLoopTimer); - - g_assert(microseconds > 0); /* if it's 0 it'll cause an infinite loop */ - - t->delay = microseconds; - t->func = handler; - t->data = data; - t->equal = cmp; - t->destroy = notify; - t->del_me = FALSE; - g_get_current_time(&loop->now); - t->last = t->timeout = loop->now; - g_time_val_add(&t->timeout, t->delay); - - insert_timer(loop, t); -} - -void obt_main_loop_timeout_remove(ObtMainLoop *loop, - GSourceFunc handler) -{ - GSList *it; - - for (it = loop->timers; it; it = g_slist_next(it)) { - ObtMainLoopTimer *t = it->data; - if (t->func == handler) - t->del_me = TRUE; - } -} - -void obt_main_loop_timeout_remove_data(ObtMainLoop *loop, GSourceFunc handler, - gpointer data, gboolean cancel_dest) -{ - GSList *it; - - for (it = loop->timers; it; it = g_slist_next(it)) { - ObtMainLoopTimer *t = it->data; - if (t->func == handler && t->equal(t->data, data)) { - t->del_me = TRUE; - if (cancel_dest) - t->destroy = NULL; - } - } -} - -/* find the time to wait for the nearest timeout */ -static gboolean nearest_timeout_wait(ObtMainLoop *loop, GTimeVal *tm) -{ - if (loop->timers == NULL) - return FALSE; - - tm->tv_sec = NEAREST_TIMEOUT(loop).tv_sec - loop->now.tv_sec; - tm->tv_usec = NEAREST_TIMEOUT(loop).tv_usec - loop->now.tv_usec; - - while (tm->tv_usec < 0) { - tm->tv_usec += G_USEC_PER_SEC; - tm->tv_sec--; - } - tm->tv_sec += tm->tv_usec / G_USEC_PER_SEC; - tm->tv_usec %= G_USEC_PER_SEC; - if (tm->tv_sec < 0) - tm->tv_sec = 0; - - return TRUE; -} - -static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait) -{ - GSList *it, *next; - - gboolean fired = FALSE; - - g_get_current_time(&loop->now); - - for (it = loop->timers; it; it = next) { - ObtMainLoopTimer *curr; - - next = g_slist_next(it); - - 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) { - /* delete the top */ - loop->timers = g_slist_delete_link(loop->timers, it); - if (curr->destroy) - curr->destroy(curr->data); - g_slice_free(ObtMainLoopTimer, 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)) { - g_time_val_add(&curr->timeout, curr->delay); - insert_timer(loop, curr); - } else { - if (curr->destroy) - curr->destroy(curr->data); - g_slice_free(ObtMainLoopTimer, curr); - } - - /* the timer queue has been shuffled, start from the beginning - (which is the next one to fire) */ - next = loop->timers; - - fired = TRUE; - } - - 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; - } else if (nearest_timeout_wait(loop, &loop->ret_wait)) - *wait = &loop->ret_wait; - else - *wait = NULL; -} diff --git a/obt/mainloop.h b/obt/mainloop.h deleted file mode 100644 index f455d629..00000000 --- a/obt/mainloop.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - obt/mainloop.h for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __obt_mainloop_h -#define __obt_mainloop_h - -#include -#include - -G_BEGIN_DECLS - -typedef struct _ObtMainLoop ObtMainLoop; - -ObtMainLoop *obt_main_loop_new(void); -void obt_main_loop_ref(ObtMainLoop *loop); -void obt_main_loop_unref(ObtMainLoop *loop); - -typedef void (*ObtMainLoopXHandler) (const XEvent *e, gpointer data); - -void obt_main_loop_x_add(ObtMainLoop *loop, - ObtMainLoopXHandler handler, - gpointer data, - GDestroyNotify notify); -void obt_main_loop_x_remove(ObtMainLoop *loop, - ObtMainLoopXHandler handler); - -typedef void (*ObtMainLoopFdHandler) (gint fd, gpointer data); - -void obt_main_loop_fd_add(ObtMainLoop *loop, - gint fd, - ObtMainLoopFdHandler handler, - gpointer data, - GDestroyNotify notify); -void obt_main_loop_fd_remove(ObtMainLoop *loop, - gint fd); - -typedef void (*ObtMainLoopSignalHandler) (gint signal, gpointer data); - -void obt_main_loop_signal_add(ObtMainLoop *loop, - gint signal, - ObtMainLoopSignalHandler handler, - gpointer data, - GDestroyNotify notify); -void obt_main_loop_signal_remove(ObtMainLoop *loop, - ObtMainLoopSignalHandler handler); - -void obt_main_loop_timeout_add(ObtMainLoop *loop, - gulong microseconds, - GSourceFunc handler, - gpointer data, - GEqualFunc cmp, - GDestroyNotify notify); -void obt_main_loop_timeout_remove(ObtMainLoop *loop, - GSourceFunc handler); -void obt_main_loop_timeout_remove_data(ObtMainLoop *loop, - GSourceFunc handler, - gpointer data, - gboolean cancel_dest); - -void obt_main_loop_run(ObtMainLoop *loop); -void obt_main_loop_exit(ObtMainLoop *loop); - -G_END_DECLS - -#endif diff --git a/obt/xevent.c b/obt/xevent.c deleted file mode 100644 index 10771657..00000000 --- a/obt/xevent.c +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - obt/xevent.c for the Openbox window manager - Copyright (c) 2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "obt/xevent.h" -#include "obt/mainloop.h" -#include "obt/util.h" - -typedef struct _ObtXEventBinding ObtXEventBinding; - -struct _ObtXEventHandler -{ - gint ref; - ObtMainLoop *loop; - - /* An array of hash tables where the key is the window, and the value is - the ObtXEventBinding */ - GHashTable **bindings; - gint num_event_types; /* the length of the bindings array */ -}; - -struct _ObtXEventBinding -{ - Window win; - ObtXEventCallback func; - gpointer data; -}; - -static void xevent_handler(const XEvent *e, gpointer data); -static guint window_hash(Window *w) { return *w; } -static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } -static void binding_free(gpointer b); - -ObtXEventHandler* xevent_new(void) -{ - ObtXEventHandler *h; - - h = g_slice_new0(ObtXEventHandler); - h->ref = 1; - - return h; -} - -void xevent_ref(ObtXEventHandler *h) -{ - ++h->ref; -} - -void xevent_unref(ObtXEventHandler *h) -{ - if (h && --h->ref == 0) { - gint i; - - if (h->loop) - obt_main_loop_x_remove(h->loop, xevent_handler); - for (i = 0; i < h->num_event_types; ++i) - g_hash_table_destroy(h->bindings[i]); - g_free(h->bindings); - - g_slice_free(ObtXEventHandler, h); - } -} - -void xevent_register(ObtXEventHandler *h, ObtMainLoop *loop) -{ - h->loop = loop; - obt_main_loop_x_add(loop, xevent_handler, h, NULL); -} - -void xevent_set_handler(ObtXEventHandler *h, gint type, Window win, - ObtXEventCallback func, gpointer data) -{ - ObtXEventBinding *b; - - g_assert(func); - - /* make sure we have a spot for the event */ - if (type + 1 < h->num_event_types) { - gint i; - h->bindings = g_renew(GHashTable*, h->bindings, type + 1); - for (i = h->num_event_types; i < type + 1; ++i) - h->bindings[i] = g_hash_table_new_full((GHashFunc)window_hash, - (GEqualFunc)window_comp, - NULL, binding_free); - h->num_event_types = type + 1; - } - - b = g_slice_new(ObtXEventBinding); - b->win = win; - b->func = func; - b->data = data; - g_hash_table_replace(h->bindings[type], &b->win, b); -} - -static void binding_free(gpointer b) -{ - g_slice_free(ObtXEventBinding, b); -} - -void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win) -{ - g_assert(type < h->num_event_types); - g_assert(win); - - g_hash_table_remove(h->bindings[type], &win); -} - -static void xevent_handler(const XEvent *e, gpointer data) -{ - ObtXEventHandler *h; - ObtXEventBinding *b; - - h = data; - - if (e->type < h->num_event_types) { - const gint all = OBT_XEVENT_ALL_WINDOWS; - /* run the all_windows handler first */ - b = g_hash_table_lookup(h->bindings[e->xany.type], &all); - if (b) b->func(e, b->data); - /* then run the per-window handler */ - b = g_hash_table_lookup(h->bindings[e->xany.type], &e->xany.window); - if (b) b->func(e, b->data); - } - else - g_message("Unhandled X Event type %d", e->xany.type); -} diff --git a/obt/xevent.h b/obt/xevent.h deleted file mode 100644 index ec0b66e5..00000000 --- a/obt/xevent.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - obt/xevent.h for the Openbox window manager - Copyright (c) 2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __obt_xevent_h -#define __obt_xevent_h - -#include -#include - -G_BEGIN_DECLS - -struct _ObtMainLoop; - -typedef struct _ObtXEventHandler ObtXEventHandler; - -typedef void (*ObtXEventCallback) (const XEvent *e, gpointer data); - -ObtXEventHandler* xevent_new(void); -void xevent_ref(ObtXEventHandler *h); -void xevent_unref(ObtXEventHandler *h); - -void xevent_register(ObtXEventHandler *h, - struct _ObtMainLoop *loop); - -#define OBT_XEVENT_ALL_WINDOWS None - -void xevent_set_handler(ObtXEventHandler *h, gint type, Window win, - ObtXEventCallback func, gpointer data); -void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win); - -G_END_DECLS - -#endif /*__obt_xevent_h*/ diff --git a/obt/xqueue.c b/obt/xqueue.c index e5d2da31..22a3de23 100644 --- a/obt/xqueue.c +++ b/obt/xqueue.c @@ -318,3 +318,69 @@ gboolean xqueue_pending_local(void) if (!qnum) read_events(FALSE); return qnum != 0; } + +typedef struct _ObtXQueueCB { + ObtXQueueFunc func; + gpointer data; +} ObtXQueueCB; + +static ObtXQueueCB *callbacks = NULL; +static guint n_callbacks = 0; + +static gboolean event_read(GIOChannel *s, GIOCondition cond, gpointer data) +{ + XEvent ev; + + while (xqueue_next_local(&ev)) { + guint i; + for (i = 0; i < n_callbacks; ++i) + callbacks[i].func(&ev, callbacks[i].data); + } + + return TRUE; /* repeat */ +} + +void xqueue_listen(void) +{ + GIOChannel *ch; + + g_assert(obt_display != NULL); + + ch = g_io_channel_unix_new(ConnectionNumber(obt_display)); + g_io_add_watch(ch, G_IO_IN, event_read, NULL); + g_io_channel_unref(ch); +} + +void xqueue_add_callback(ObtXQueueFunc f, gpointer data) +{ + guint i; + + g_return_if_fail(f != NULL); + + for (i = 0; i < n_callbacks; ++i) + if (callbacks[i].func == f && callbacks[i].data == data) + return; + + callbacks = g_renew(ObtXQueueCB, callbacks, n_callbacks + 1); + callbacks[n_callbacks].func = f; + callbacks[n_callbacks].data = data; + ++n_callbacks; +} + +void xqueue_remove_callback(ObtXQueueFunc f, gpointer data) +{ + guint i; + + g_return_if_fail(f != NULL); + + for (i = 0; i < n_callbacks; ++i) { + if (callbacks[i].func == f && callbacks[i].data == data) { + /* remove it */ + for (; i < n_callbacks - 1; ++i) + callbacks[i] = callbacks[i+1]; + callbacks = g_renew(ObtXQueueCB, callbacks, n_callbacks - 1); + --n_callbacks; + break; + } + } +} diff --git a/obt/xqueue.h b/obt/xqueue.h index 8b312785..11cd2bc0 100644 --- a/obt/xqueue.h +++ b/obt/xqueue.h @@ -87,6 +87,15 @@ gboolean xqueue_exists_local(xqueue_match_func match, gpointer data); gboolean xqueue_remove_local(XEvent *event_return, xqueue_match_func match, gpointer data); +typedef void (*ObtXQueueFunc)(const XEvent *ev, gpointer data); + +/*! Begin listening for X events in the default GMainContext, and feed them + to the registered callback functions, added with xqueue_add_callback(). */ +void xqueue_listen(void); + +void xqueue_add_callback(ObtXQueueFunc f, gpointer data); +void xqueue_remove_callback(ObtXQueueFunc f, gpointer data); + G_END_DECLS #endif diff --git a/openbox/dock.c b/openbox/dock.c index 3a58344e..fa088c6b 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -33,6 +33,8 @@ ButtonMotionMask) static ObDock *dock; +static guint show_timeout_id; +static guint hide_timeout_id; StrutPartial dock_strut; @@ -628,15 +630,19 @@ static gboolean hide_timeout(gpointer data) dock->hidden = TRUE; dock_configure(); + hide_timeout_id = 0; + return FALSE; /* don't repeat */ } static gboolean show_timeout(gpointer data) { - /* hide */ + /* show */ dock->hidden = FALSE; dock_configure(); + show_timeout_id = 0; + return FALSE; /* don't repeat */ } @@ -644,21 +650,21 @@ void dock_hide(gboolean hide) { if (!hide) { if (dock->hidden && config_dock_hide) { - obt_main_loop_timeout_add(ob_main_loop, - config_dock_show_delay * 1000, - show_timeout, NULL, - g_direct_equal, NULL); - } else if (!dock->hidden && config_dock_hide) { - obt_main_loop_timeout_remove(ob_main_loop, hide_timeout); + show_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, + config_dock_show_delay, + show_timeout, NULL, NULL); + } else if (!dock->hidden && config_dock_hide && hide_timeout_id) { + if (hide_timeout_id) g_source_remove(hide_timeout_id); + hide_timeout_id = 0; } } else { if (!dock->hidden && config_dock_hide) { - obt_main_loop_timeout_add(ob_main_loop, - config_dock_hide_delay * 1000, - hide_timeout, NULL, - g_direct_equal, NULL); - } else if (dock->hidden && config_dock_hide) { - obt_main_loop_timeout_remove(ob_main_loop, show_timeout); + hide_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, + config_dock_show_delay, + hide_timeout, NULL, NULL); + } else if (dock->hidden && config_dock_hide && show_timeout_id) { + if (show_timeout_id) g_source_remove(show_timeout_id); + show_timeout_id = 0; } } } diff --git a/openbox/event.c b/openbox/event.c index d3ffae12..9701ad62 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -93,7 +93,7 @@ static gboolean is_enter_focus_event_ignored(gulong serial); static void event_ignore_enter_range(gulong start, gulong end); static void focus_delay_dest(gpointer data); -static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2); +static void unfocus_delay_dest(gpointer data); static gboolean focus_delay_func(gpointer data); static gboolean unfocus_delay_func(gpointer data); static void focus_delay_client_dest(ObClient *client, gpointer data); @@ -112,25 +112,34 @@ static gboolean focus_left_screen = FALSE; static gboolean waiting_for_focusin = FALSE; /*! A list of ObSerialRanges which are to be ignored for mouse enter events */ static GSList *ignore_serials = NULL; +static guint focus_delay_timeout_id = 0; +static ObClient *focus_delay_timeout_client = NULL; +static guint unfocus_delay_timeout_id = 0; +static ObClient *unfocus_delay_timeout_client = NULL; #ifdef USE_SM -static void ice_handler(gint fd, gpointer conn) +static gboolean ice_handler(GIOChannel *source, GIOCondition cond, + gpointer conn) { Bool b; IceProcessMessages(conn, NULL, &b); + return TRUE; /* don't remove the event source */ } static void ice_watch(IceConn conn, IcePointer data, Bool opening, IcePointer *watch_data) { - static gint fd = -1; + static guint id = 0; if (opening) { - fd = IceConnectionNumber(conn); - obt_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL); - } else { - obt_main_loop_fd_remove(ob_main_loop, fd); - fd = -1; + GIOChannel *ch; + + ch = g_io_channel_unix_new(IceConnectionNumber(conn)); + id = g_io_add_watch(ch, G_IO_IN, ice_handler, conn); + g_io_channel_unref(ch); + } else if (id) { + g_source_remove(id); + id = 0; } } #endif @@ -139,7 +148,7 @@ void event_startup(gboolean reconfig) { if (reconfig) return; - obt_main_loop_x_add(ob_main_loop, event_process, NULL, NULL); + xqueue_add_callback(event_process, NULL); #ifdef USE_SM IceAddConnectionWatch(ice_watch, NULL); @@ -806,17 +815,20 @@ void event_enter_client(ObClient *client) if (config_focus_delay) { ObFocusDelayData *data; - obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func); + if (focus_delay_timeout_id) + g_source_remove(focus_delay_timeout_id); data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_time(); data->serial = event_curserial; - obt_main_loop_timeout_add(ob_main_loop, - config_focus_delay * 1000, - focus_delay_func, - data, focus_delay_cmp, focus_delay_dest); + focus_delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, + config_focus_delay, + focus_delay_func, + data, + focus_delay_dest); + focus_delay_timeout_client = client; } else { ObFocusDelayData data; data.client = client; @@ -841,17 +853,20 @@ void event_leave_client(ObClient *client) if (config_focus_delay) { ObFocusDelayData *data; - obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); + if (unfocus_delay_timeout_id) + g_source_remove(unfocus_delay_timeout_id); data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_time(); data->serial = event_curserial; - obt_main_loop_timeout_add(ob_main_loop, - config_focus_delay * 1000, - unfocus_delay_func, - data, focus_delay_cmp, focus_delay_dest); + unfocus_delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, + config_focus_delay, + unfocus_delay_func, + data, + unfocus_delay_dest); + unfocus_delay_timeout_client = client; } else { ObFocusDelayData data; data.client = client; @@ -1060,10 +1075,8 @@ static void event_handle_client(ObClient *client, XEvent *e) delay is up */ e->xcrossing.detail != NotifyInferior) { - if (config_focus_delay) - obt_main_loop_timeout_remove_data(ob_main_loop, - focus_delay_func, - client, FALSE); + if (config_focus_delay && focus_delay_timeout_id) + g_source_remove(focus_delay_timeout_id); if (config_unfocus_leave) event_leave_client(client); } @@ -1113,10 +1126,8 @@ static void event_handle_client(ObClient *client, XEvent *e) e->xcrossing.serial, (client?client->window:0)); if (config_focus_follow) { - if (config_focus_delay) - obt_main_loop_timeout_remove_data(ob_main_loop, - unfocus_delay_func, - client, FALSE); + if (config_focus_delay && unfocus_delay_timeout_id) + g_source_remove(unfocus_delay_timeout_id); event_enter_client(client); } } @@ -2047,12 +2058,15 @@ static gboolean event_handle_user_input(ObClient *client, XEvent *e) static void focus_delay_dest(gpointer data) { g_slice_free(ObFocusDelayData, data); + focus_delay_timeout_id = 0; + focus_delay_timeout_client = NULL; } -static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2) +static void unfocus_delay_dest(gpointer data) { - const ObFocusDelayData *f1 = d1; - return f1->client == d2; + g_slice_free(ObFocusDelayData, data); + unfocus_delay_timeout_id = 0; + unfocus_delay_timeout_client = NULL; } static gboolean focus_delay_func(gpointer data) @@ -2082,18 +2096,18 @@ static gboolean unfocus_delay_func(gpointer data) static void focus_delay_client_dest(ObClient *client, gpointer data) { - obt_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, - client, FALSE); - obt_main_loop_timeout_remove_data(ob_main_loop, unfocus_delay_func, - client, FALSE); + if (focus_delay_timeout_client == client && focus_delay_timeout_id) + g_source_remove(focus_delay_timeout_id); + if (unfocus_delay_timeout_client == client && unfocus_delay_timeout_id) + g_source_remove(unfocus_delay_timeout_id); } void event_halt_focus_delay(void) { /* ignore all enter events up till the event which caused this to occur */ if (event_curserial) event_ignore_enter_range(1, event_curserial); - obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func); - obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); + if (focus_delay_timeout_id) g_source_remove(focus_delay_timeout_id); + if (unfocus_delay_timeout_id) g_source_remove(unfocus_delay_timeout_id); } gulong event_start_ignore_all_enters(void) diff --git a/openbox/frame.c b/openbox/frame.c index 4f262554..c6a47b08 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -41,7 +41,7 @@ EnterWindowMask | LeaveWindowMask) #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */ -#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */ +#define FRAME_ANIMATE_ICONIFY_STEP_TIME (1000 / 60) /* 60 Hz */ #define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b) @@ -1060,8 +1060,8 @@ static gboolean find_reparent(XEvent *e, gpointer data) void frame_release_client(ObFrame *self) { /* if there was any animation going on, kill it */ - obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify, - self, FALSE); + if (self->iconify_animation_timer) + g_source_remove(self->iconify_animation_timer); /* check if the app has already reparented its window away */ if (!xqueue_exists_local(find_reparent, self)) { @@ -1118,7 +1118,7 @@ void frame_release_client(ObFrame *self) window_remove(self->rgriptop); window_remove(self->rgripbottom); - obt_main_loop_timeout_remove_data(ob_main_loop, flash_timeout, self, TRUE); + if (self->flash_timer) g_source_remove(self->flash_timer); } /* is there anything present between us and the label? */ @@ -1674,12 +1674,9 @@ void frame_flash_start(ObFrame *self) self->flash_on = self->focused; if (!self->flashing) - obt_main_loop_timeout_add(ob_main_loop, - G_USEC_PER_SEC * 0.6, - flash_timeout, - self, - g_direct_equal, - flash_done); + self->flash_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, + 600, flash_timeout, self, + flash_done); g_get_current_time(&self->flash_end); g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5); @@ -1837,12 +1834,13 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying) } if (new_anim) { - obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify, - self, FALSE); - obt_main_loop_timeout_add(ob_main_loop, - FRAME_ANIMATE_ICONIFY_STEP_TIME, - frame_animate_iconify, self, - g_direct_equal, NULL); + if (self->iconify_animation_timer) + g_source_remove(self->iconify_animation_timer); + self->iconify_animation_timer = + g_timeout_add_full(G_PRIORITY_DEFAULT, + FRAME_ANIMATE_ICONIFY_STEP_TIME, + frame_animate_iconify, self, NULL); + /* do the first step */ frame_animate_iconify(self); diff --git a/openbox/frame.h b/openbox/frame.h index 8f1ed91b..b0d99690 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -190,12 +190,14 @@ struct _ObFrame gboolean flashing; gboolean flash_on; GTimeVal flash_end; + guint flash_timer; /*! Is the frame currently in an animation for iconify or restore. 0 means that it is not animating. > 0 means it is animating an iconify. < 0 means it is animating a restore. */ gint iconify_animation_going; + guint iconify_animation_timer; GTimeVal iconify_animation_end; }; diff --git a/openbox/keyboard.c b/openbox/keyboard.c index ad4e4f3c..5b8016dd 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -40,6 +40,7 @@ KeyBindingTree *keyboard_firstnode = NULL; static ObPopup *popup = NULL; static KeyBindingTree *curpos; +static guint chain_timer = 0; static void grab_keys(gboolean grab) { @@ -68,6 +69,11 @@ static gboolean chain_timeout(gpointer data) return FALSE; /* don't repeat */ } +static void chain_done(gpointer data) +{ + chain_timer = 0; +} + static void set_curpos(KeyBindingTree *newpos) { if (curpos == newpos) return; @@ -93,7 +99,7 @@ static void set_curpos(KeyBindingTree *newpos) a = screen_physical_area_primary(FALSE); popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10); /* 1 second delay for the popup to show */ - popup_delay_show(popup, G_USEC_PER_SEC, text); + popup_delay_show(popup, 1000, text); g_free(text); } else { popup_hide(popup); @@ -226,7 +232,7 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) if (e->xkey.keycode == config_keyboard_reset_keycode && mods == config_keyboard_reset_state) { - obt_main_loop_timeout_remove(ob_main_loop, chain_timeout); + if (chain_timer) g_source_remove(chain_timer); keyboard_reset_chains(-1); return TRUE; } @@ -243,11 +249,12 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) menu_frame_hide_all(); if (p->first_child != NULL) { /* part of a chain */ - obt_main_loop_timeout_remove(ob_main_loop, chain_timeout); + if (chain_timer) g_source_remove(chain_timer); /* 3 second timeout for chains */ - obt_main_loop_timeout_add(ob_main_loop, 3 * G_USEC_PER_SEC, - chain_timeout, NULL, - g_direct_equal, NULL); + chain_timer = + g_timeout_add_full(G_PRIORITY_DEFAULT, + 3000, chain_timeout, NULL, + chain_done); set_curpos(p); } else if (p->chroot) /* an empty chroot */ set_curpos(p); @@ -322,7 +329,7 @@ void keyboard_startup(gboolean reconfig) void keyboard_shutdown(gboolean reconfig) { - obt_main_loop_timeout_remove(ob_main_loop, chain_timeout); + if (chain_timer) g_source_remove(chain_timer); keyboard_unbind_all(); set_curpos(NULL); diff --git a/openbox/menu.c b/openbox/menu.c index 1f9874ac..374aeec1 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -486,10 +486,10 @@ void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client) menu_can_hide = TRUE; else { menu_can_hide = FALSE; - obt_main_loop_timeout_add(ob_main_loop, - config_menu_hide_delay * 1000, - menu_hide_delay_func, - NULL, g_direct_equal, NULL); + g_timeout_add_full(G_PRIORITY_DEFAULT, + config_menu_hide_delay, + menu_hide_delay_func, + NULL, NULL); } } } diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 91e7c53e..5708cdf8 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -44,6 +44,8 @@ GList *menu_frame_visible; GHashTable *menu_frame_map; static RrAppearance *a_sep; +static guint submenu_show_timer = 0; +static guint submenu_hide_timer = 0; static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry, ObMenuFrame *frame); @@ -1009,8 +1011,8 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y, */ static void remove_submenu_hide_timeout(ObMenuFrame *child) { - obt_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout, - child, FALSE); + if (submenu_hide_timer) g_source_remove(submenu_hide_timer); + submenu_hide_timer = 0; } gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, @@ -1107,7 +1109,8 @@ void menu_frame_hide_all(void) if (config_submenu_show_delay) { /* remove any submenu open requests */ - obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout); + if (submenu_show_timer) g_source_remove(submenu_show_timer); + submenu_show_timer = 0; } if ((it = g_list_last(menu_frame_visible))) menu_frame_hide(it->data); @@ -1188,7 +1191,8 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, if (config_submenu_show_delay) { /* remove any submenu open requests */ - obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout); + if (submenu_show_timer) g_source_remove(submenu_show_timer); + submenu_show_timer = 0; } self->selected = entry; @@ -1208,12 +1212,13 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, submenu */ if (immediate || config_submenu_hide_delay == 0) menu_frame_hide(oldchild); - else if (config_submenu_hide_delay > 0) - obt_main_loop_timeout_add(ob_main_loop, - config_submenu_hide_delay * 1000, - submenu_hide_timeout, - oldchild, g_direct_equal, - NULL); + else if (config_submenu_hide_delay > 0) { + if (submenu_hide_timer) g_source_remove(submenu_hide_timer); + submenu_hide_timer = + g_timeout_add_full(G_PRIORITY_DEFAULT, + config_submenu_hide_delay, + submenu_hide_timeout, oldchild, NULL); + } } } @@ -1225,12 +1230,15 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, if (oldchild_entry != self->selected) { if (immediate || config_submenu_hide_delay == 0) menu_entry_frame_show_submenu(self->selected); - else if (config_submenu_hide_delay > 0) - obt_main_loop_timeout_add(ob_main_loop, - config_submenu_show_delay * 1000, - submenu_show_timeout, - self->selected, g_direct_equal, - NULL); + else if (config_submenu_hide_delay > 0) { + if (submenu_show_timer) + g_source_remove(submenu_show_timer); + submenu_show_timer = + g_timeout_add_full(G_PRIORITY_DEFAULT, + config_submenu_show_delay, + submenu_show_timeout, + self->selected, NULL); + } } /* hide the grandchildren of this menu. and move the cursor to the current menu */ diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 96cd6239..2f68395a 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -61,9 +61,11 @@ static guint button; static guint32 corner; static ObDirection edge_warp_dir = -1; static gboolean edge_warp_odd = FALSE; +static guint edge_warp_timer = 0; static ObDirection key_resize_edge = -1; #ifdef SYNC static guint waiting_for_sync; +static guint sync_timer = 0; #endif static ObPopup *popup = NULL; @@ -319,7 +321,8 @@ void moveresize_end(gboolean cancel) moveresize_alarm = None; } - obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func); + if (sync_timer) g_source_remove(sync_timer); + sync_timer = 0; #endif } @@ -433,10 +436,8 @@ static void do_resize(void) waiting_for_sync = 1; - obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func); - obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2, - sync_timeout_func, - NULL, NULL, NULL); + if (sync_timer) g_source_remove(sync_timer); + sync_timer = g_timeout_add(2000, sync_timeout_func, NULL); } #endif @@ -461,8 +462,10 @@ static gboolean sync_timeout_func(gpointer data) ++waiting_for_sync; /* we timed out waiting for our sync... */ do_resize(); /* ...so let any pending resizes through */ - if (waiting_for_sync > SYNC_TIMEOUTS) + if (waiting_for_sync > SYNC_TIMEOUTS) { + sync_timer = 0; return FALSE; /* don't repeat */ + } else return TRUE; /* keep waiting */ } @@ -649,10 +652,8 @@ static void do_edge_warp(gint x, gint y) cancel_edge_warp(); if (dir != (ObDirection)-1) { edge_warp_odd = TRUE; /* switch on the first timeout */ - obt_main_loop_timeout_add(ob_main_loop, - config_mouse_screenedgetime * 1000, - edge_warp_delay_func, - NULL, NULL, NULL); + edge_warp_timer = g_timeout_add(config_mouse_screenedgetime, + edge_warp_delay_func, NULL); } edge_warp_dir = dir; } @@ -660,7 +661,8 @@ static void do_edge_warp(gint x, gint y) static void cancel_edge_warp(void) { - obt_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func); + if (edge_warp_timer) g_source_remove(edge_warp_timer); + edge_warp_timer = 0; } static void move_with_keys(KeySym sym, guint state) diff --git a/openbox/openbox.c b/openbox/openbox.c index fb43b978..b2cdc8ef 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -46,6 +46,7 @@ #include "obrender/render.h" #include "obrender/theme.h" #include "obt/display.h" +#include "obt/xqueue.h" #include "obt/prop.h" #include "obt/keyboard.h" #include "obt/xml.h" @@ -83,7 +84,7 @@ RrInstance *ob_rr_inst; RrImageCache *ob_rr_icons; RrTheme *ob_rr_theme; -ObtMainLoop *ob_main_loop; +GMainLoop *ob_main_loop; gint ob_screen; gboolean ob_replace_wm = FALSE; gboolean ob_sm_use = TRUE; @@ -157,18 +158,18 @@ gint main(gint argc, gchar **argv) exit(EXIT_SUCCESS); } - ob_main_loop = obt_main_loop_new(); + ob_main_loop = g_main_loop_new(NULL, FALSE); /* set up signal handler */ - obt_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGTTIN, signal_handler, NULL,NULL); - obt_main_loop_signal_add(ob_main_loop, SIGTTOU, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGTTIN, signal_handler, NULL,NULL); +// obt_main_loop_signal_add(ob_main_loop, SIGTTOU, signal_handler, NULL,NULL); ob_screen = DefaultScreen(obt_display); @@ -316,6 +317,10 @@ gint main(gint argc, gchar **argv) menu_startup(reconfigure); prompt_startup(reconfigure); + /* do this after everything is started so no events will get + missed */ + xqueue_listen(); + if (!reconfigure) { guint32 xid; ObWindow *w; @@ -367,7 +372,7 @@ gint main(gint argc, gchar **argv) } } - obt_main_loop_run(ob_main_loop); + g_main_loop_run(ob_main_loop); ob_set_state(reconfigure ? OB_STATE_RECONFIGURING : OB_STATE_EXITING); @@ -741,14 +746,14 @@ void ob_reconfigure(void) void ob_exit(gint code) { exitcode = code; - obt_main_loop_exit(ob_main_loop); + g_main_loop_quit(ob_main_loop); } void ob_exit_replace(void) { exitcode = 0; being_replaced = TRUE; - obt_main_loop_exit(ob_main_loop); + g_main_loop_quit(ob_main_loop); } Cursor ob_cursor(ObCursor cursor) diff --git a/openbox/openbox.h b/openbox/openbox.h index 229c584d..94f49105 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -23,7 +23,6 @@ #include "obrender/render.h" #include "obrender/theme.h" -#include "obt/mainloop.h" #include "obt/display.h" #include @@ -32,7 +31,7 @@ extern RrInstance *ob_rr_inst; extern RrImageCache *ob_rr_icons; extern RrTheme *ob_rr_theme; -extern ObtMainLoop *ob_main_loop; +extern GMainLoop *ob_main_loop; /*! The number of the screen on which we're running */ extern gint ob_screen; diff --git a/openbox/ping.c b/openbox/ping.c index bf39a30a..7cb47669 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -22,7 +22,6 @@ #include "event.h" #include "debug.h" #include "openbox.h" -#include "obt/mainloop.h" #include "obt/prop.h" typedef struct _ObPingTarget @@ -30,13 +29,14 @@ typedef struct _ObPingTarget ObClient *client; ObPingEventHandler h; guint32 id; + guint loopid; gint waiting; } ObPingTarget; static GHashTable *ping_ids = NULL; static guint32 ping_next_id = 1; -#define PING_TIMEOUT (G_USEC_PER_SEC * 3) +#define PING_TIMEOUT 3000 /* in MS */ /*! Warn the user after this many PING_TIMEOUT intervals */ #define PING_TIMEOUT_WARN 2 @@ -79,8 +79,8 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) t->client = client; t->h = h; - obt_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, - t, g_direct_equal, NULL); + t->loopid = g_timeout_add_full(G_PRIORITY_DEFAULT, PING_TIMEOUT, + ping_timeout, t, NULL); /* act like we just timed out immediately, to start the pinging process now instead of after the first delay. this makes sure the client ends up in the ping_ids hash table now. */ @@ -158,8 +158,7 @@ static void ping_end(ObClient *client, gpointer data) if ((t = g_hash_table_find(ping_ids, find_client, client))) { g_hash_table_remove(ping_ids, &t->id); - obt_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, - t, FALSE); + g_source_remove(t->loopid); g_slice_free(ObPingTarget, t); } diff --git a/openbox/popup.c b/openbox/popup.c index 7d59d912..e6e1ec5a 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -146,11 +146,12 @@ static gboolean popup_show_timeout(gpointer data) stacking_raise(INTERNAL_AS_WINDOW(self)); self->mapped = TRUE; self->delay_mapped = FALSE; + self->delay_timer = 0; return FALSE; /* don't repeat */ } -void popup_delay_show(ObPopup *self, gulong usec, gchar *text) +void popup_delay_show(ObPopup *self, gulong msec, gchar *text) { gint l, t, r, b; gint x, y, w, h; @@ -292,12 +293,11 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text) /* do the actual showing */ if (!self->mapped) { - if (usec) { + if (msec) { /* don't kill previous show timers */ if (!self->delay_mapped) { - obt_main_loop_timeout_add(ob_main_loop, usec, - popup_show_timeout, self, - g_direct_equal, NULL); + self->delay_timer = + g_timeout_add(msec, popup_show_timeout, self); self->delay_mapped = TRUE; } } else { @@ -319,7 +319,8 @@ void popup_hide(ObPopup *self) event_end_ignore_all_enters(ignore_start); } else if (self->delay_mapped) { - obt_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE); + g_source_remove(self->delay_timer); + self->delay_timer = 0; self->delay_mapped = FALSE; } } @@ -365,7 +366,7 @@ void icon_popup_free(ObIconPopup *self) } } -void icon_popup_delay_show(ObIconPopup *self, gulong usec, +void icon_popup_delay_show(ObIconPopup *self, gulong msec, gchar *text, RrImage *icon) { if (icon) { @@ -378,7 +379,7 @@ void icon_popup_delay_show(ObIconPopup *self, gulong usec, self->a_icon->texture[0].type = RR_TEXTURE_NONE; } - popup_delay_show(self->popup, usec, text); + popup_delay_show(self->popup, msec, text); } void icon_popup_icon_size_multiplier(ObIconPopup *self, guint wm, guint hm) @@ -528,7 +529,7 @@ void pager_popup_free(ObPagerPopup *self) } } -void pager_popup_delay_show(ObPagerPopup *self, gulong usec, +void pager_popup_delay_show(ObPagerPopup *self, gulong msec, gchar *text, guint desk) { guint i; @@ -557,7 +558,7 @@ void pager_popup_delay_show(ObPagerPopup *self, gulong usec, self->desks = screen_num_desktops; self->curdesk = desk; - popup_delay_show(self->popup, usec, text); + popup_delay_show(self->popup, msec, text); } void pager_popup_icon_size_multiplier(ObPagerPopup *self, guint wm, guint hm) diff --git a/openbox/popup.h b/openbox/popup.h index f876e3ce..6de9d184 100644 --- a/openbox/popup.h +++ b/openbox/popup.h @@ -53,6 +53,7 @@ struct _ObPopup guint iconhm; /* icon height multiplier. multipled by the normal height */ gboolean mapped; gboolean delay_mapped; + guint delay_timer; void (*draw_icon)(gint x, gint y, gint w, gint h, gpointer data); gpointer draw_icon_data; @@ -99,7 +100,7 @@ void popup_text_width_to_strings(ObPopup *self, gchar **strings, gint num); void popup_set_text_align(ObPopup *self, RrJustify align); #define popup_show(s, t) popup_delay_show((s),0,(t)) -void popup_delay_show(ObPopup *self, gulong usec, gchar *text); +void popup_delay_show(ObPopup *self, gulong msec, gchar *text); void popup_hide(ObPopup *self); RrAppearance *popup_icon_appearance(ObPopup *self); @@ -109,7 +110,7 @@ ObIconPopup *icon_popup_new(void); void icon_popup_free(ObIconPopup *self); #define icon_popup_show(s, t, i) icon_popup_delay_show((s),0,(t),(i)) -void icon_popup_delay_show(ObIconPopup *self, gulong usec, +void icon_popup_delay_show(ObIconPopup *self, gulong msec, gchar *text, RrImage *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)) @@ -128,7 +129,7 @@ ObPagerPopup *pager_popup_new(void); void pager_popup_free(ObPagerPopup *self); #define pager_popup_show(s, t, d) pager_popup_delay_show((s),0,(t),(d)) -void pager_popup_delay_show(ObPagerPopup *self, gulong usec, +void pager_popup_delay_show(ObPagerPopup *self, gulong msec, gchar *text, guint desk); #define pager_popup_hide(p) popup_hide((p)->popup) #define pager_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y)) diff --git a/openbox/screen.c b/openbox/screen.c index 47ecc183..353d2de0 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -38,7 +38,6 @@ #include "obt/display.h" #include "obt/xqueue.h" #include "obt/prop.h" -#include "obt/mainloop.h" #include #ifdef HAVE_UNISTD_H @@ -71,6 +70,7 @@ Time screen_desktop_user_time = CurrentTime; static Size screen_physical_size; static guint screen_old_desktop; static gboolean screen_desktop_timeout = TRUE; +static guint screen_desktop_timer = 0; /*! An array of desktops, holding an array of areas per monitor */ static Rect *monitor_area = NULL; /*! An array of desktops, holding an array of struts */ @@ -80,11 +80,12 @@ static GSList *struts_right = NULL; static GSList *struts_bottom = NULL; static ObPagerPopup *desktop_popup; +static guint desktop_popup_timer = 0; static gboolean desktop_popup_perm; /*! The number of microseconds that you need to be on a desktop before it will replace the remembered "last desktop" */ -#define REMEMBER_LAST_DESKTOP_TIME 750000 +#define REMEMBER_LAST_DESKTOP_TIME 750 static gboolean replace_wm(void) { @@ -601,7 +602,8 @@ static void screen_fallback_focus(void) static gboolean last_desktop_func(gpointer data) { screen_desktop_timeout = TRUE; - return FALSE; + screen_desktop_timer = 0; + return FALSE; /* don't repeat */ } void screen_set_desktop(guint num, gboolean dofocus) @@ -683,9 +685,9 @@ void screen_set_desktop(guint num, gboolean dofocus) } } screen_desktop_timeout = FALSE; - obt_main_loop_timeout_remove(ob_main_loop, last_desktop_func); - obt_main_loop_timeout_add(ob_main_loop, REMEMBER_LAST_DESKTOP_TIME, - last_desktop_func, NULL, NULL, NULL); + if (screen_desktop_timer) g_source_remove(screen_desktop_timer); + screen_desktop_timer = g_timeout_add(REMEMBER_LAST_DESKTOP_TIME, + last_desktop_func, NULL); ob_debug("Moving to desktop %d", num+1); @@ -937,6 +939,7 @@ static guint translate_row_col(guint r, guint c) static gboolean hide_desktop_popup_func(gpointer data) { pager_popup_hide(desktop_popup); + desktop_popup_timer = 0; return FALSE; /* don't repeat */ } @@ -959,21 +962,21 @@ void screen_show_desktop_popup(guint d, gboolean perm) MAX(a->width/3, POPUP_WIDTH)); pager_popup_show(desktop_popup, screen_desktop_names[d], d); - obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func); + if (desktop_popup_timer) g_source_remove(desktop_popup_timer); + desktop_popup_timer = 0; if (!perm && !desktop_popup_perm) /* only hide if its not already being show permanently */ - obt_main_loop_timeout_add(ob_main_loop, - config_desktop_popup_time * 1000, - hide_desktop_popup_func, desktop_popup, - g_direct_equal, NULL); + desktop_popup_timer = g_timeout_add(config_desktop_popup_time, + hide_desktop_popup_func, + desktop_popup); if (perm) desktop_popup_perm = TRUE; } void screen_hide_desktop_popup(void) { - obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func, - desktop_popup, FALSE); + if (desktop_popup_timer) g_source_remove(desktop_popup_timer); + desktop_popup_timer = 0; pager_popup_hide(desktop_popup); desktop_popup_perm = FALSE; } diff --git a/openbox/startupnotify.c b/openbox/startupnotify.c index c300d57d..16654cfd 100644 --- a/openbox/startupnotify.c +++ b/openbox/startupnotify.c @@ -20,6 +20,7 @@ #include "startupnotify.h" #include "gettext.h" #include "event.h" +#include "obt/xqueue.h" #ifdef HAVE_STDLIB_H # include @@ -67,7 +68,7 @@ void sn_startup(gboolean reconfig) sn_event_func, NULL, NULL); sn_launcher = sn_launcher_context_new(sn_display, ob_screen); - obt_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL); + xqueue_add_callback(sn_handler, NULL); } void sn_shutdown(gboolean reconfig) @@ -76,7 +77,7 @@ void sn_shutdown(gboolean reconfig) if (reconfig) return; - obt_main_loop_x_remove(ob_main_loop, sn_handler); + xqueue_remove_callback(sn_handler, NULL); for (it = sn_waits; it; it = g_slist_next(it)) sn_startup_sequence_unref((SnStartupSequence*)it->data); @@ -139,10 +140,9 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data) sn_waits = g_slist_prepend(sn_waits, seq); /* 20 second timeout for apps to start if the launcher doesn't have a timeout */ - obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC, - sn_wait_timeout, seq, - g_direct_equal, - (GDestroyNotify)sn_startup_sequence_unref); + g_timeout_add_full(G_PRIORITY_DEFAULT, + 20 * 1000, sn_wait_timeout, seq, + (GDestroyNotify)sn_startup_sequence_unref); change = TRUE; break; case SN_MONITOR_EVENT_CHANGED: @@ -153,8 +153,7 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data) case SN_MONITOR_EVENT_CANCELED: if ((seq = sequence_find(sn_startup_sequence_get_id(seq)))) { sn_waits = g_slist_remove(sn_waits, seq); - obt_main_loop_timeout_remove_data(ob_main_loop, sn_wait_timeout, - seq, FALSE); + g_source_remove_by_user_data(seq); change = TRUE; } break; @@ -260,10 +259,9 @@ void sn_setup_spawn_environment(const gchar *program, const gchar *name, /* 20 second timeout for apps to start */ sn_launcher_context_ref(sn_launcher); - obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC, - sn_launch_wait_timeout, sn_launcher, - g_direct_equal, - (GDestroyNotify)sn_launcher_context_unref); + g_timeout_add_full(G_PRIORITY_DEFAULT, + 20 * 1000, sn_launch_wait_timeout, sn_launcher, + (GDestroyNotify)sn_launcher_context_unref); setenv("DESKTOP_STARTUP_ID", id, TRUE);