using the ObMainLoop, which rulz the planet
This commit is contained in:
parent
952ca24571
commit
de4f92ccc6
14 changed files with 745 additions and 391 deletions
|
@ -146,6 +146,8 @@ openbox_openbox_SOURCES = \
|
|||
openbox/keyboard.h \
|
||||
openbox/keytree.c \
|
||||
openbox/keytree.h \
|
||||
openbox/mainloop.c \
|
||||
openbox/mainloop.h \
|
||||
openbox/menuframe.c \
|
||||
openbox/menuframe.h \
|
||||
openbox/menu.c \
|
||||
|
@ -174,8 +176,6 @@ openbox_openbox_SOURCES = \
|
|||
openbox/stacking.h \
|
||||
openbox/startup.c \
|
||||
openbox/startup.h \
|
||||
openbox/timer.c \
|
||||
openbox/timer.h \
|
||||
openbox/translate.c \
|
||||
openbox/translate.h \
|
||||
openbox/window.c \
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "debug.h"
|
||||
#include "dock.h"
|
||||
#include "mainloop.h"
|
||||
#include "screen.h"
|
||||
#include "prop.h"
|
||||
#include "config.h"
|
||||
|
@ -522,15 +523,13 @@ void dock_app_drag(ObDockApp *app, XMotionEvent *e)
|
|||
dock_configure();
|
||||
}
|
||||
|
||||
static void hide_timeout(void *n)
|
||||
static gboolean hide_timeout(gpointer data)
|
||||
{
|
||||
/* dont repeat */
|
||||
timer_stop(dock->hide_timer);
|
||||
dock->hide_timer = NULL;
|
||||
|
||||
/* hide */
|
||||
dock->hidden = TRUE;
|
||||
dock_configure();
|
||||
|
||||
return FALSE; /* don't repeat */
|
||||
}
|
||||
|
||||
void dock_hide(gboolean hide)
|
||||
|
@ -543,14 +542,9 @@ void dock_hide(gboolean hide)
|
|||
dock_configure();
|
||||
|
||||
/* if was hiding, stop it */
|
||||
if (dock->hide_timer) {
|
||||
timer_stop(dock->hide_timer);
|
||||
dock->hide_timer = NULL;
|
||||
}
|
||||
ob_main_loop_timeout_remove(ob_main_loop, hide_timeout);
|
||||
} else {
|
||||
g_assert(!dock->hide_timer);
|
||||
dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
|
||||
(ObTimeoutHandler)hide_timeout,
|
||||
NULL);
|
||||
ob_main_loop_timeout_add(ob_main_loop, config_dock_hide_timeout * 1000,
|
||||
hide_timeout, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef __dock_h
|
||||
#define __dock_h
|
||||
|
||||
#include "timer.h"
|
||||
#include "window.h"
|
||||
#include "stacking.h"
|
||||
#include "geom.h"
|
||||
|
@ -28,7 +27,6 @@ struct _ObDock
|
|||
gint h;
|
||||
|
||||
gboolean hidden;
|
||||
ObTimer *hide_timer;
|
||||
|
||||
GList *dock_apps;
|
||||
};
|
||||
|
|
148
openbox/event.c
148
openbox/event.c
|
@ -11,12 +11,12 @@
|
|||
#include "menuframe.h"
|
||||
#include "keyboard.h"
|
||||
#include "mouse.h"
|
||||
#include "mainloop.h"
|
||||
#include "framerender.h"
|
||||
#include "focus.h"
|
||||
#include "moveresize.h"
|
||||
#include "stacking.h"
|
||||
#include "extensions.h"
|
||||
#include "timer.h"
|
||||
#include "event.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
@ -39,18 +39,12 @@
|
|||
#include <X11/ICE/ICElib.h>
|
||||
#endif
|
||||
|
||||
static void event_process(XEvent *e);
|
||||
static void event_process(const XEvent *e, gpointer data);
|
||||
static void event_handle_root(XEvent *e);
|
||||
static void event_handle_menu(XEvent *e);
|
||||
static void event_handle_dock(ObDock *s, XEvent *e);
|
||||
static void event_handle_dockapp(ObDockApp *app, XEvent *e);
|
||||
static void event_handle_client(ObClient *c, XEvent *e);
|
||||
static void fd_event_handle();
|
||||
#ifdef USE_SM
|
||||
static void ice_watch(IceConn conn, IcePointer data, Bool opening,
|
||||
IcePointer *watch_data);
|
||||
#endif
|
||||
static void find_max_fd();
|
||||
|
||||
#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
|
||||
(e)->xfocus.detail == NotifyAncestor || \
|
||||
|
@ -75,32 +69,38 @@ static const int mask_table[] = {
|
|||
};
|
||||
static int mask_table_size;
|
||||
|
||||
static fd_set selset, allset;
|
||||
#ifdef USE_SM
|
||||
static IceConn ice_conn;
|
||||
static int ice_fd;
|
||||
#endif
|
||||
static int max_fd, x_fd;
|
||||
static GData *fd_handler_list;
|
||||
static void ice_handler(int fd, gpointer conn)
|
||||
{
|
||||
Bool b;
|
||||
IceProcessMessages(conn, NULL, &b);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_SM
|
||||
static void ice_watch(IceConn conn, IcePointer data, Bool opening,
|
||||
IcePointer *watch_data)
|
||||
{
|
||||
static gint fd = -1;
|
||||
|
||||
if (opening) {
|
||||
g_assert (ice_fd < 0);
|
||||
ice_conn = conn;
|
||||
ice_fd = IceConnectionNumber(conn);
|
||||
FD_SET(ice_fd, &allset);
|
||||
fd = IceConnectionNumber(conn);
|
||||
ob_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
|
||||
} else {
|
||||
FD_CLR(ice_fd, &allset);
|
||||
ice_fd = -1;
|
||||
ob_main_loop_fd_remove(ob_main_loop, fd);
|
||||
fd = -1;
|
||||
}
|
||||
find_max_fd();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBSN
|
||||
static void sn_handler(const XEvent *e, gpointer display)
|
||||
{
|
||||
XEvent ec;
|
||||
ec = *e;
|
||||
sn_display_process_event(display, &ec);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void event_startup()
|
||||
{
|
||||
mask_table_size = sizeof(mask_table) / sizeof(mask_table[0]);
|
||||
|
@ -128,59 +128,20 @@ void event_startup()
|
|||
}
|
||||
}
|
||||
|
||||
FD_ZERO(&allset);
|
||||
max_fd = x_fd = ConnectionNumber(ob_display);
|
||||
FD_SET(x_fd, &allset);
|
||||
ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
|
||||
|
||||
#ifdef USE_SM
|
||||
ice_fd = -1;
|
||||
IceAddConnectionWatch(ice_watch, NULL);
|
||||
#endif
|
||||
|
||||
g_datalist_init(&fd_handler_list);
|
||||
#ifdef USE_LIBSN
|
||||
ob_main_loop_x_add(ob_main_loop, sn_handler, ob_sn_display, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void event_shutdown()
|
||||
{
|
||||
XFreeModifiermap(modmap);
|
||||
g_datalist_clear(&fd_handler_list);
|
||||
}
|
||||
|
||||
void event_loop()
|
||||
{
|
||||
XEvent e;
|
||||
struct timeval *wait;
|
||||
gboolean had_event = FALSE;
|
||||
|
||||
while (XPending(ob_display)) {
|
||||
XNextEvent(ob_display, &e);
|
||||
|
||||
#ifdef USE_LIBSN
|
||||
sn_display_process_event(ob_sn_display, &e);
|
||||
#endif
|
||||
|
||||
event_process(&e);
|
||||
had_event = TRUE;
|
||||
}
|
||||
|
||||
if (!had_event) {
|
||||
timer_dispatch((GTimeVal**)&wait);
|
||||
selset = allset;
|
||||
select(max_fd + 1, &selset, NULL, NULL, wait);
|
||||
|
||||
/* handle the X events as soon as possible? */
|
||||
if (FD_ISSET(x_fd, &selset))
|
||||
return;
|
||||
|
||||
#ifdef USE_SM
|
||||
if (ice_fd >= 0 && FD_ISSET(ice_fd, &selset)) {
|
||||
Bool b;
|
||||
IceProcessMessages(ice_conn, NULL, &b);
|
||||
}
|
||||
#endif
|
||||
|
||||
fd_event_handle();
|
||||
}
|
||||
}
|
||||
|
||||
static Window event_get_window(XEvent *e)
|
||||
|
@ -399,7 +360,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
|
|||
#endif
|
||||
return TRUE;
|
||||
} else {
|
||||
event_process(&fe);
|
||||
event_process(&fe, NULL);
|
||||
#ifdef DEBUG_FOCUS
|
||||
ob_debug("focused window got an Out/In back to "
|
||||
"itself but focus_client was null "
|
||||
|
@ -411,7 +372,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
|
|||
|
||||
/* once all the FocusOut's have been dealt with, if there
|
||||
is a FocusIn still left and it is valid, then use it */
|
||||
event_process(&fe);
|
||||
event_process(&fe, NULL);
|
||||
/* secret magic way of event_process telling us that no
|
||||
client was found for the FocusIn event. ^_^ */
|
||||
if (fe.xfocus.window != None) {
|
||||
|
@ -457,13 +418,18 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void event_process(XEvent *e)
|
||||
static void event_process(const XEvent *ec, gpointer data)
|
||||
{
|
||||
Window window;
|
||||
ObClient *client = NULL;
|
||||
ObDock *dock = NULL;
|
||||
ObDockApp *dockapp = NULL;
|
||||
ObWindow *obwin = NULL;
|
||||
XEvent ee, *e;
|
||||
|
||||
/* make a copy we can mangle */
|
||||
ee = *ec;
|
||||
e = ⅇ
|
||||
|
||||
window = event_get_window(e);
|
||||
if ((obwin = g_hash_table_lookup(window_map, &window))) {
|
||||
|
@ -1063,50 +1029,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
void event_add_fd_handler(event_fd_handler *h) {
|
||||
g_datalist_id_set_data(&fd_handler_list, h->fd, h);
|
||||
FD_SET(h->fd, &allset);
|
||||
max_fd = MAX(max_fd, h->fd);
|
||||
}
|
||||
|
||||
static void find_max_fd_foreach(GQuark n, gpointer data, gpointer max)
|
||||
{
|
||||
*((unsigned int *)max) = MAX(*((unsigned int *)max), n);
|
||||
}
|
||||
|
||||
static void find_max_fd()
|
||||
{
|
||||
int tmpmax = -1;
|
||||
g_datalist_foreach(&fd_handler_list, find_max_fd_foreach,
|
||||
(gpointer)&tmpmax);
|
||||
max_fd = MAX(x_fd, tmpmax);
|
||||
#ifdef USE_SM
|
||||
max_fd = MAX(ice_fd, max_fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void event_remove_fd(gint n)
|
||||
{
|
||||
FD_CLR(n, &allset);
|
||||
g_datalist_id_remove_data(&fd_handler_list, (GQuark)n);
|
||||
find_max_fd();
|
||||
}
|
||||
|
||||
static void fd_event_handle_foreach(GQuark n,
|
||||
gpointer data, gpointer user_data)
|
||||
{
|
||||
if (FD_ISSET( (int)n, &selset)) {
|
||||
event_fd_handler *h = (event_fd_handler *)data;
|
||||
g_assert(h->fd == (int)n);
|
||||
h->handler(h->fd, h->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void fd_event_handle()
|
||||
{
|
||||
g_datalist_foreach(&fd_handler_list, fd_event_handle_foreach, NULL);
|
||||
}
|
||||
|
||||
static void event_handle_dock(ObDock *s, XEvent *e)
|
||||
{
|
||||
switch (e->type) {
|
||||
|
|
|
@ -14,15 +14,4 @@ extern guint ScrollLockMask;
|
|||
void event_startup();
|
||||
void event_shutdown();
|
||||
|
||||
typedef struct event_fd_handler {
|
||||
gint fd;
|
||||
gpointer data;
|
||||
void (*handler)(gint fd, gpointer data);
|
||||
} event_fd_handler;
|
||||
|
||||
void event_add_fd_handler(event_fd_handler *handler);
|
||||
void event_remove_fd(gint n);
|
||||
|
||||
void event_loop();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,9 @@ gboolean grab_keyboard(gboolean grab)
|
|||
XUngrabKeyboard(ob_display, event_lasttime);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
g_message("grabs: %d", kgrabs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "mainloop.h"
|
||||
#include "focus.h"
|
||||
#include "screen.h"
|
||||
#include "frame.h"
|
||||
|
@ -7,7 +8,6 @@
|
|||
#include "client.h"
|
||||
#include "action.h"
|
||||
#include "prop.h"
|
||||
#include "timer.h"
|
||||
#include "config.h"
|
||||
#include "keytree.h"
|
||||
#include "keyboard.h"
|
||||
|
@ -27,7 +27,6 @@ typedef struct {
|
|||
static GSList *interactive_states;
|
||||
|
||||
static KeyBindingTree *curpos;
|
||||
static ObTimer *chain_timer;
|
||||
|
||||
static void grab_for_window(Window win, gboolean grab)
|
||||
{
|
||||
|
@ -62,23 +61,23 @@ static void grab_keys(gboolean grab)
|
|||
grab_for_window(((ObClient*)it->data)->frame->window, grab);
|
||||
}
|
||||
|
||||
static gboolean chain_timeout(gpointer data)
|
||||
{
|
||||
keyboard_reset_chains();
|
||||
|
||||
return FALSE; /* don't repeat */
|
||||
}
|
||||
|
||||
void keyboard_reset_chains()
|
||||
{
|
||||
if (chain_timer) {
|
||||
timer_stop(chain_timer);
|
||||
chain_timer = NULL;
|
||||
}
|
||||
ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
|
||||
|
||||
if (curpos) {
|
||||
curpos = NULL;
|
||||
grab_keys(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void chain_timeout(ObTimer *t, void *data)
|
||||
{
|
||||
keyboard_reset_chains();
|
||||
}
|
||||
|
||||
gboolean keyboard_bind(GList *keylist, ObAction *action)
|
||||
{
|
||||
KeyBindingTree *tree, *t;
|
||||
|
@ -213,10 +212,10 @@ void keyboard_event(ObClient *client, const XEvent *e)
|
|||
if (p->key == e->xkey.keycode &&
|
||||
p->state == e->xkey.state) {
|
||||
if (p->first_child != NULL) { /* part of a chain */
|
||||
if (chain_timer) timer_stop(chain_timer);
|
||||
ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
|
||||
/* 5 second timeout for chains */
|
||||
chain_timer = timer_start(5000*1000, chain_timeout,
|
||||
NULL);
|
||||
ob_main_loop_timeout_add(ob_main_loop, 5 * G_USEC_PER_SEC,
|
||||
chain_timeout, NULL, NULL);
|
||||
curpos = p;
|
||||
grab_keys(TRUE);
|
||||
} else {
|
||||
|
|
601
openbox/mainloop.c
Normal file
601
openbox/mainloop.c
Normal file
|
@ -0,0 +1,601 @@
|
|||
#include "mainloop.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <signal.h>
|
||||
|
||||
typedef struct _ObMainLoopTimer ObMainLoopTimer;
|
||||
typedef struct _ObMainLoopSignal ObMainLoopSignal;
|
||||
typedef struct _ObMainLoopSignalHandlerType ObMainLoopSignalHandlerType;
|
||||
typedef struct _ObMainLoopXHandlerType ObMainLoopXHandlerType;
|
||||
typedef struct _ObMainLoopFdHandlerType ObMainLoopFdHandlerType;
|
||||
|
||||
/* this should be more than the number of possible signals on any
|
||||
architecture... */
|
||||
#define NUM_SIGNALS 99
|
||||
|
||||
/* all created ObMainLoops. Used by the signal handler to pass along signals */
|
||||
static GSList *all_loops;
|
||||
|
||||
/* signals are global to all loops */
|
||||
struct {
|
||||
guint installed; /* a ref count */
|
||||
struct sigaction oldact;
|
||||
} all_signals[NUM_SIGNALS];
|
||||
|
||||
/* a set of all possible signals */
|
||||
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(ObMainLoop *loop, GTimeVal **wait);
|
||||
static void fd_handler_destroy(gpointer data);
|
||||
|
||||
struct _ObMainLoop
|
||||
{
|
||||
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 _ObMainLoopTimer
|
||||
{
|
||||
gulong delay;
|
||||
GSourceFunc func;
|
||||
gpointer data;
|
||||
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;
|
||||
};
|
||||
|
||||
struct _ObMainLoopSignalHandlerType
|
||||
{
|
||||
ObMainLoop *loop;
|
||||
gint signal;
|
||||
gpointer data;
|
||||
ObMainLoopSignalHandler func;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
struct _ObMainLoopXHandlerType
|
||||
{
|
||||
ObMainLoop *loop;
|
||||
gpointer data;
|
||||
ObMainLoopXHandler func;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
struct _ObMainLoopFdHandlerType
|
||||
{
|
||||
ObMainLoop *loop;
|
||||
gint fd;
|
||||
gpointer data;
|
||||
ObMainLoopFdHandler func;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
ObMainLoop *ob_main_loop_new(Display *display)
|
||||
{
|
||||
ObMainLoop *loop;
|
||||
|
||||
loop = g_new0(ObMainLoop, 1);
|
||||
loop->display = display;
|
||||
loop->fd_x = ConnectionNumber(display);
|
||||
FD_ZERO(&loop->fd_set);
|
||||
FD_SET(loop->fd_x, &loop->fd_set);
|
||||
loop->fd_max = loop->fd_x;
|
||||
|
||||
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 ob_main_loop_destroy(ObMainLoop *loop)
|
||||
{
|
||||
guint i;
|
||||
GSList *it, *next;
|
||||
|
||||
if (loop) {
|
||||
g_assert(loop->running == FALSE);
|
||||
|
||||
for (it = loop->x_handlers; it; it = next) {
|
||||
ObMainLoopXHandlerType *h = it->data;
|
||||
next = g_slist_next(it);
|
||||
ob_main_loop_x_remove(loop, h->func);
|
||||
}
|
||||
|
||||
g_hash_table_destroy(loop->fd_handlers);
|
||||
|
||||
for (it = loop->timers; it; it = g_slist_next(it)) {
|
||||
ObMainLoopTimer *t = it->data;
|
||||
if (t->destroy) t->destroy(t->data);
|
||||
g_free(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) {
|
||||
ObMainLoopSignalHandlerType *h = it->data;
|
||||
next = g_slist_next(it);
|
||||
ob_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) {
|
||||
guint i;
|
||||
|
||||
/* 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_free(loop);
|
||||
}
|
||||
}
|
||||
|
||||
static void fd_handle_foreach(gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
ObMainLoopFdHandlerType *h = value;
|
||||
fd_set *set = data;
|
||||
|
||||
if (FD_ISSET(h->fd, set))
|
||||
h->func(h->fd, h->data);
|
||||
}
|
||||
|
||||
void ob_main_loop_run(ObMainLoop *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)) {
|
||||
ObMainLoopSignalHandlerType *h = it->data;
|
||||
h->func(i, h->data);
|
||||
}
|
||||
loop->signals_fired[i]--;
|
||||
}
|
||||
}
|
||||
loop->signal_fired = FALSE;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
} else if (XPending(loop->display)) {
|
||||
do {
|
||||
XNextEvent(loop->display, &e);
|
||||
|
||||
for (it = loop->x_handlers; it; it = g_slist_next(it)) {
|
||||
ObMainLoopXHandlerType *h = it->data;
|
||||
h->func(&e, h->data);
|
||||
}
|
||||
} while (XPending(loop->display));
|
||||
} 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 ob_main_loop_exit(ObMainLoop *loop)
|
||||
{
|
||||
loop->run = FALSE;
|
||||
}
|
||||
|
||||
/*** XEVENT WATCHERS ***/
|
||||
|
||||
void ob_main_loop_x_add(ObMainLoop *loop,
|
||||
ObMainLoopXHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ObMainLoopXHandlerType *h;
|
||||
|
||||
h = g_new(ObMainLoopXHandlerType, 1);
|
||||
h->loop = loop;
|
||||
h->func = handler;
|
||||
h->data = data;
|
||||
h->destroy = notify;
|
||||
loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
|
||||
}
|
||||
|
||||
void ob_main_loop_x_remove(ObMainLoop *loop,
|
||||
ObMainLoopXHandler handler)
|
||||
{
|
||||
GSList *it, *next;
|
||||
|
||||
for (it = loop->x_handlers; it; it = next) {
|
||||
ObMainLoopXHandlerType *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_free(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*** 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, "Fuck ya. Core dump. (Signal=%d)\n", sig);
|
||||
|
||||
/* die with a core dump */
|
||||
abort();
|
||||
}
|
||||
|
||||
for (it = all_loops; it; it = g_slist_next(it)) {
|
||||
ObMainLoop *loop = it->data;
|
||||
loop->signal_fired = TRUE;
|
||||
loop->signals_fired[sig]++;
|
||||
}
|
||||
}
|
||||
|
||||
void ob_main_loop_signal_add(ObMainLoop *loop,
|
||||
gint signal,
|
||||
ObMainLoopSignalHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ObMainLoopSignalHandlerType *h;
|
||||
|
||||
g_return_if_fail(signal < NUM_SIGNALS);
|
||||
|
||||
h = g_new(ObMainLoopSignalHandlerType, 1);
|
||||
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 ob_main_loop_signal_remove(ObMainLoop *loop,
|
||||
ObMainLoopSignalHandler handler)
|
||||
{
|
||||
guint i;
|
||||
GSList *it, *next;
|
||||
|
||||
for (i = 0; i < NUM_SIGNALS; ++i) {
|
||||
for (it = loop->signal_handlers[i]; it; it = next) {
|
||||
ObMainLoopSignalHandlerType *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_free(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*** FILE DESCRIPTOR WATCHERS ***/
|
||||
|
||||
static void max_fd_func(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
ObMainLoop *loop = data;
|
||||
|
||||
/* key is the fd */
|
||||
loop->fd_max = MAX(loop->fd_max, *(gint*)key);
|
||||
}
|
||||
|
||||
static void calc_max_fd(ObMainLoop *loop)
|
||||
{
|
||||
loop->fd_max = loop->fd_x;
|
||||
|
||||
g_hash_table_foreach(loop->fd_handlers, max_fd_func, loop);
|
||||
}
|
||||
|
||||
void ob_main_loop_fd_add(ObMainLoop *loop,
|
||||
gint fd,
|
||||
ObMainLoopFdHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ObMainLoopFdHandlerType *h;
|
||||
|
||||
h = g_new(ObMainLoopFdHandlerType, 1);
|
||||
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)
|
||||
{
|
||||
ObMainLoopFdHandlerType *h = data;
|
||||
|
||||
FD_CLR(h->fd, &h->loop->fd_set);
|
||||
|
||||
if (h->destroy)
|
||||
h->destroy(h->data);
|
||||
}
|
||||
|
||||
void ob_main_loop_fd_remove(ObMainLoop *loop,
|
||||
gint fd)
|
||||
{
|
||||
g_hash_table_remove(loop->fd_handlers, &fd);
|
||||
}
|
||||
|
||||
/*** TIMEOUTS ***/
|
||||
|
||||
#define NEAREST_TIMEOUT(loop) \
|
||||
(((ObMainLoopTimer*)(loop)->timers->data)->timeout)
|
||||
|
||||
static long timecompare(GTimeVal *a, GTimeVal *b)
|
||||
{
|
||||
long r;
|
||||
|
||||
if ((r = b->tv_sec - a->tv_sec)) return r;
|
||||
return b->tv_usec - a->tv_usec;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (it == NULL) /* didnt fit anywhere in the list */
|
||||
loop->timers = g_slist_append(loop->timers, ins);
|
||||
}
|
||||
|
||||
void ob_main_loop_timeout_add(ObMainLoop *loop,
|
||||
gulong microseconds,
|
||||
GSourceFunc handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ObMainLoopTimer *t = g_new(ObMainLoopTimer, 1);
|
||||
t->delay = microseconds;
|
||||
t->func = handler;
|
||||
t->data = data;
|
||||
t->destroy = notify;
|
||||
t->del_me = FALSE;
|
||||
t->last = t->timeout = loop->now;
|
||||
g_time_val_add(&t->timeout, t->delay);
|
||||
|
||||
insert_timer(loop, t);
|
||||
}
|
||||
|
||||
void ob_main_loop_timeout_remove(ObMainLoop *loop,
|
||||
GSourceFunc handler)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
for (it = loop->timers; it; it = g_slist_next(it)) {
|
||||
ObMainLoopTimer *t = it->data;
|
||||
if (t->func == handler) {
|
||||
t->del_me = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* find the time to wait for the nearest timeout */
|
||||
static gboolean nearest_timeout_wait(ObMainLoop *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(ObMainLoop *loop, GTimeVal **wait)
|
||||
{
|
||||
g_get_current_time(&loop->now);
|
||||
|
||||
while (loop->timers != NULL) {
|
||||
ObMainLoopTimer *curr = loop->timers->data; /* get the top element */
|
||||
/* 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, loop->timers);
|
||||
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, loop->timers);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nearest_timeout_wait(loop, &loop->ret_wait))
|
||||
*wait = &loop->ret_wait;
|
||||
else
|
||||
*wait = NULL;
|
||||
}
|
52
openbox/mainloop.h
Normal file
52
openbox/mainloop.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef __ob__mainloop_h
|
||||
#define __ob__mainloop_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct _ObMainLoop ObMainLoop;
|
||||
|
||||
ObMainLoop *ob_main_loop_new(Display *display);
|
||||
void ob_main_loop_destroy(ObMainLoop *loop);
|
||||
|
||||
typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data);
|
||||
|
||||
void ob_main_loop_x_add(ObMainLoop *loop,
|
||||
ObMainLoopXHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void ob_main_loop_x_remove(ObMainLoop *loop,
|
||||
ObMainLoopXHandler handler);
|
||||
|
||||
typedef void (*ObMainLoopFdHandler) (gint fd, gpointer data);
|
||||
|
||||
void ob_main_loop_fd_add(ObMainLoop *loop,
|
||||
gint fd,
|
||||
ObMainLoopFdHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void ob_main_loop_fd_remove(ObMainLoop *loop,
|
||||
gint fd);
|
||||
|
||||
typedef void (*ObMainLoopSignalHandler) (gint signal, gpointer data);
|
||||
|
||||
void ob_main_loop_signal_add(ObMainLoop *loop,
|
||||
gint signal,
|
||||
ObMainLoopSignalHandler handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void ob_main_loop_signal_remove(ObMainLoop *loop,
|
||||
ObMainLoopSignalHandler handler);
|
||||
|
||||
void ob_main_loop_timeout_add(ObMainLoop *loop,
|
||||
gulong microseconds,
|
||||
GSourceFunc handler,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void ob_main_loop_timeout_remove(ObMainLoop *loop,
|
||||
GSourceFunc handler);
|
||||
|
||||
void ob_main_loop_run(ObMainLoop *loop);
|
||||
void ob_main_loop_exit(ObMainLoop *loop);
|
||||
|
||||
#endif
|
|
@ -16,9 +16,9 @@
|
|||
#include "mouse.h"
|
||||
#include "extensions.h"
|
||||
#include "grab.h"
|
||||
#include "timer.h"
|
||||
#include "group.h"
|
||||
#include "config.h"
|
||||
#include "mainloop.h"
|
||||
#include "gettext.h"
|
||||
#include "parser/parse.h"
|
||||
#include "render/render.h"
|
||||
|
@ -49,6 +49,7 @@
|
|||
|
||||
RrInstance *ob_rr_inst;
|
||||
RrTheme *ob_rr_theme;
|
||||
ObMainLoop *ob_main_loop;
|
||||
Display *ob_display;
|
||||
gint ob_screen;
|
||||
gboolean ob_sm_use = TRUE;
|
||||
|
@ -57,20 +58,17 @@ gboolean ob_replace_wm;
|
|||
|
||||
static ObState state;
|
||||
static gboolean xsync;
|
||||
static gboolean shutdown;
|
||||
static gboolean restart;
|
||||
static char *restart_path;
|
||||
static Cursor cursors[OB_NUM_CURSORS];
|
||||
static KeyCode keys[OB_NUM_KEYS];
|
||||
static gchar *sm_save_file;
|
||||
|
||||
static void signal_handler(int signal);
|
||||
static void signal_handler(int signal, gpointer data);
|
||||
static void parse_args(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction action;
|
||||
sigset_t sigset;
|
||||
char *path;
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr node;
|
||||
|
@ -88,19 +86,6 @@ int main(int argc, char **argv)
|
|||
bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
|
||||
textdomain(PACKAGE_NAME);
|
||||
|
||||
/* set up signal handler */
|
||||
sigemptyset(&sigset);
|
||||
action.sa_handler = signal_handler;
|
||||
action.sa_mask = sigset;
|
||||
action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
|
||||
sigaction(SIGUSR1, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGPIPE, &action, (struct sigaction *) NULL);
|
||||
/* sigaction(SIGSEGV, &action, (struct sigaction *) NULL);*/
|
||||
sigaction(SIGFPE, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGTERM, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGINT, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGHUP, &action, (struct sigaction *) NULL);
|
||||
|
||||
/* create the ~/.openbox dir */
|
||||
path = g_build_filename(g_get_home_dir(), ".openbox", NULL);
|
||||
mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP |
|
||||
|
@ -128,6 +113,15 @@ int main(int argc, char **argv)
|
|||
if (fcntl(ConnectionNumber(ob_display), F_SETFD, 1) == -1)
|
||||
ob_exit_with_error("Failed to set display as close-on-exec.");
|
||||
|
||||
ob_main_loop = ob_main_loop_new(ob_display);
|
||||
|
||||
/* set up signal handler */
|
||||
ob_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL, NULL);
|
||||
ob_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL, NULL);
|
||||
ob_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler, NULL, NULL);
|
||||
ob_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler, NULL, NULL);
|
||||
ob_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL, NULL);
|
||||
|
||||
if (sm_save_file)
|
||||
session_load(sm_save_file);
|
||||
session_startup(argc, argv);
|
||||
|
@ -209,9 +203,6 @@ int main(int argc, char **argv)
|
|||
/* startup the parsing so everything can register sections of the rc */
|
||||
i = parse_startup();
|
||||
|
||||
/* anything that is going to read data from the rc file needs to be
|
||||
in this group */
|
||||
timer_startup();
|
||||
event_startup();
|
||||
grab_startup();
|
||||
/* focus_backup is used for stacking, so this needs to come before
|
||||
|
@ -246,8 +237,7 @@ int main(int argc, char **argv)
|
|||
client_manage_all();
|
||||
|
||||
state = OB_STATE_RUNNING;
|
||||
while (!shutdown)
|
||||
event_loop();
|
||||
ob_main_loop_run(ob_main_loop);
|
||||
state = OB_STATE_EXITING;
|
||||
|
||||
dock_remove_all();
|
||||
|
@ -265,7 +255,6 @@ int main(int argc, char **argv)
|
|||
window_shutdown();
|
||||
grab_shutdown();
|
||||
event_shutdown();
|
||||
timer_shutdown();
|
||||
config_shutdown();
|
||||
}
|
||||
|
||||
|
@ -304,26 +293,14 @@ int main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void signal_handler(int sig)
|
||||
static void signal_handler(int signal, gpointer data)
|
||||
{
|
||||
switch (sig) {
|
||||
case SIGUSR1:
|
||||
fprintf(stderr, "Caught SIGUSR1 signal. Restarting.");
|
||||
if (signal == SIGUSR1) {
|
||||
fprintf(stderr, "Caught signal %d. Restarting.\n", signal);
|
||||
ob_restart();
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
case SIGPIPE:
|
||||
fprintf(stderr, "Caught signal %d. Exiting.", sig);
|
||||
} else {
|
||||
fprintf(stderr, "Caught signal %d. Exiting.\n", signal);
|
||||
ob_exit();
|
||||
break;
|
||||
|
||||
case SIGFPE:
|
||||
case SIGSEGV:
|
||||
fprintf(stderr, "Caught signal %d. Aborting and dumping core.", sig);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +395,7 @@ void ob_restart()
|
|||
|
||||
void ob_exit()
|
||||
{
|
||||
shutdown = TRUE;
|
||||
ob_main_loop_exit(ob_main_loop);
|
||||
}
|
||||
|
||||
Cursor ob_cursor(ObCursor cursor)
|
||||
|
|
|
@ -14,9 +14,13 @@
|
|||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct _ObMainLoop;
|
||||
|
||||
extern RrInstance *ob_rr_inst;
|
||||
extern RrTheme *ob_rr_theme;
|
||||
|
||||
extern struct _ObMainLoop *ob_main_loop;
|
||||
|
||||
/*! The X display */
|
||||
extern Display *ob_display;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "debug.h"
|
||||
#include "openbox.h"
|
||||
#include "mainloop.h"
|
||||
#include "dock.h"
|
||||
#include "xerror.h"
|
||||
#include "prop.h"
|
||||
#include "startup.h"
|
||||
#include "grab.h"
|
||||
#include "timer.h"
|
||||
#include "config.h"
|
||||
#include "screen.h"
|
||||
#include "client.h"
|
||||
|
@ -50,7 +50,6 @@ static Popup *desktop_cycle_popup;
|
|||
#ifdef USE_LIBSN
|
||||
static SnMonitorContext *sn_context;
|
||||
static int sn_busy_cnt;
|
||||
static ObTimer *sn_timer;
|
||||
|
||||
static void sn_event_func(SnMonitorEvent *event, void *data);
|
||||
#endif
|
||||
|
@ -1077,13 +1076,13 @@ static void set_root_cursor()
|
|||
}
|
||||
|
||||
#ifdef USE_LIBSN
|
||||
static void sn_timeout(ObTimer *t, void *data)
|
||||
static gboolean sn_timeout(gpointer data)
|
||||
{
|
||||
timer_stop(sn_timer);
|
||||
sn_timer = NULL;
|
||||
sn_busy_cnt = 0;
|
||||
|
||||
set_root_cursor();
|
||||
|
||||
return FALSE; /* don't repeat */
|
||||
}
|
||||
|
||||
static void sn_event_func(SnMonitorEvent *ev, void *data)
|
||||
|
@ -1104,26 +1103,20 @@ static void sn_event_func(SnMonitorEvent *ev, void *data)
|
|||
switch (sn_monitor_event_get_type(ev)) {
|
||||
case SN_MONITOR_EVENT_INITIATED:
|
||||
++sn_busy_cnt;
|
||||
if (sn_timer)
|
||||
timer_stop(sn_timer);
|
||||
ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
|
||||
/* 30 second timeout for apps to start */
|
||||
sn_timer = timer_start(30 * 1000000, sn_timeout, NULL);
|
||||
ob_main_loop_timeout_add(ob_main_loop, 30 * G_USEC_PER_SEC,
|
||||
sn_timeout, NULL, NULL);
|
||||
break;
|
||||
case SN_MONITOR_EVENT_CHANGED:
|
||||
break;
|
||||
case SN_MONITOR_EVENT_COMPLETED:
|
||||
if (sn_busy_cnt) --sn_busy_cnt;
|
||||
if (sn_timer) {
|
||||
timer_stop(sn_timer);
|
||||
sn_timer = NULL;
|
||||
}
|
||||
ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
|
||||
break;
|
||||
case SN_MONITOR_EVENT_CANCELED:
|
||||
if (sn_busy_cnt) --sn_busy_cnt;
|
||||
if (sn_timer) {
|
||||
timer_stop(sn_timer);
|
||||
sn_timer = NULL;
|
||||
}
|
||||
ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
|
||||
};
|
||||
|
||||
if (sn_busy_cnt != cnt)
|
||||
|
|
137
openbox/timer.c
137
openbox/timer.c
|
@ -1,137 +0,0 @@
|
|||
#include "timer.h"
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
static GTimeVal now;
|
||||
static GTimeVal ret_wait;
|
||||
static GSList *timers; /* nearest timer is at the top */
|
||||
|
||||
#define NEAREST_TIMEOUT (((ObTimer*)timers->data)->timeout)
|
||||
|
||||
static long timecompare(GTimeVal *a, GTimeVal *b)
|
||||
{
|
||||
long r;
|
||||
|
||||
if ((r = b->tv_sec - a->tv_sec)) return r;
|
||||
return b->tv_usec - a->tv_usec;
|
||||
|
||||
}
|
||||
|
||||
static void insert_timer(ObTimer *self)
|
||||
{
|
||||
GSList *it;
|
||||
for (it = timers; it != NULL; it = it->next) {
|
||||
ObTimer *t = it->data;
|
||||
if (timecompare(&self->timeout, &t->timeout) <= 0) {
|
||||
timers = g_slist_insert_before(timers, it, self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it == NULL) /* didnt fit anywhere in the list */
|
||||
timers = g_slist_append(timers, self);
|
||||
}
|
||||
|
||||
void timer_startup()
|
||||
{
|
||||
g_get_current_time(&now);
|
||||
timers = NULL;
|
||||
}
|
||||
|
||||
void timer_shutdown()
|
||||
{
|
||||
GSList *it;
|
||||
for (it = timers; it != NULL; it = it->next) {
|
||||
g_free(it->data);
|
||||
}
|
||||
g_slist_free(timers);
|
||||
timers = NULL;
|
||||
}
|
||||
|
||||
ObTimer *timer_start(long delay, ObTimeoutHandler cb, void *data)
|
||||
{
|
||||
ObTimer *self = g_new(ObTimer, 1);
|
||||
self->delay = delay;
|
||||
self->action = cb;
|
||||
self->data = data;
|
||||
self->del_me = FALSE;
|
||||
g_get_current_time(&now);
|
||||
self->last = self->timeout = now;
|
||||
g_time_val_add(&self->timeout, delay);
|
||||
|
||||
insert_timer(self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void timer_stop(ObTimer *self)
|
||||
{
|
||||
self->del_me = TRUE;
|
||||
}
|
||||
|
||||
/* find the time to wait for the nearest timeout */
|
||||
static gboolean nearest_timeout_wait(GTimeVal *tm)
|
||||
{
|
||||
if (timers == NULL)
|
||||
return FALSE;
|
||||
|
||||
tm->tv_sec = NEAREST_TIMEOUT.tv_sec - now.tv_sec;
|
||||
tm->tv_usec = NEAREST_TIMEOUT.tv_usec - 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;
|
||||
}
|
||||
|
||||
|
||||
void timer_dispatch(GTimeVal **wait)
|
||||
{
|
||||
g_get_current_time(&now);
|
||||
|
||||
while (timers != NULL) {
|
||||
ObTimer *curr = timers->data; /* get the top element */
|
||||
/* since timer_stop doesn't actually free the timer, we have to do our
|
||||
real freeing in here.
|
||||
*/
|
||||
if (curr->del_me) {
|
||||
timers = g_slist_delete_link(timers, timers); /* delete the top */
|
||||
g_free(curr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* the queue is sorted, so if this timer shouldn't fire, none are
|
||||
ready */
|
||||
if (timecompare(&NEAREST_TIMEOUT, &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.
|
||||
*/
|
||||
timers = g_slist_delete_link(timers, timers);
|
||||
g_time_val_add(&curr->last, curr->delay);
|
||||
curr->action(curr, curr->data);
|
||||
g_time_val_add(&curr->timeout, curr->delay);
|
||||
insert_timer(curr);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
ret_wait.tv_sec = ret_wait.tv_usec = 0;
|
||||
*wait = &ret_wait;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nearest_timeout_wait(&ret_wait))
|
||||
*wait = &ret_wait;
|
||||
else
|
||||
*wait = NULL;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef __timer_h
|
||||
#define __timer_h
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct _ObTimer ObTimer;
|
||||
|
||||
/*! Data type of Timer callback */
|
||||
typedef void (*ObTimeoutHandler)(ObTimer *t, void *data);
|
||||
|
||||
struct _ObTimer
|
||||
{
|
||||
/*! Microseconds between timer firings */
|
||||
long delay;
|
||||
/*! Callback for timer expiry */
|
||||
ObTimeoutHandler action;
|
||||
/*! Data sent to callback */
|
||||
void *data;
|
||||
/*! We overload the delete operator to just set this to true */
|
||||
gboolean del_me;
|
||||
/*! The time the last fire should've been at */
|
||||
GTimeVal last;
|
||||
/*! When this timer will next trigger */
|
||||
GTimeVal timeout;
|
||||
};
|
||||
|
||||
/*! Initializes the timer subsection */
|
||||
void timer_startup();
|
||||
/*! Destroys the timer subsection */
|
||||
void timer_shutdown();
|
||||
|
||||
/* Creates a new timer with a given delay */
|
||||
ObTimer *timer_start(long delay, ObTimeoutHandler cb, void *data);
|
||||
/* Stops and frees a timer */
|
||||
void timer_stop(ObTimer *self);
|
||||
|
||||
/*! Dispatch all pending timers. Sets wait to the amount of time to wait for
|
||||
the next timer, or NULL if there are no timers to wait for */
|
||||
void timer_dispatch(GTimeVal **wait);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue