Use GMainLoop instead of ObtMainLoop
This commit is contained in:
parent
2e94af28e4
commit
fd77a0a7b3
22 changed files with 281 additions and 1136 deletions
|
@ -134,8 +134,6 @@ obt_libobt_la_SOURCES = \
|
||||||
obt/internal.h \
|
obt/internal.h \
|
||||||
obt/keyboard.h \
|
obt/keyboard.h \
|
||||||
obt/keyboard.c \
|
obt/keyboard.c \
|
||||||
obt/mainloop.h \
|
|
||||||
obt/mainloop.c \
|
|
||||||
obt/xml.h \
|
obt/xml.h \
|
||||||
obt/xml.c \
|
obt/xml.c \
|
||||||
obt/ddparse.h \
|
obt/ddparse.h \
|
||||||
|
@ -147,8 +145,6 @@ obt_libobt_la_SOURCES = \
|
||||||
obt/prop.h \
|
obt/prop.h \
|
||||||
obt/prop.c \
|
obt/prop.c \
|
||||||
obt/util.h \
|
obt/util.h \
|
||||||
obt/xevent.h \
|
|
||||||
obt/xevent.c \
|
|
||||||
obt/xqueue.h \
|
obt/xqueue.h \
|
||||||
obt/xqueue.c
|
obt/xqueue.c
|
||||||
|
|
||||||
|
@ -437,13 +433,11 @@ obtpubinclude_HEADERS = \
|
||||||
obt/link.h \
|
obt/link.h \
|
||||||
obt/display.h \
|
obt/display.h \
|
||||||
obt/keyboard.h \
|
obt/keyboard.h \
|
||||||
obt/mainloop.h \
|
|
||||||
obt/xml.h \
|
obt/xml.h \
|
||||||
obt/paths.h \
|
obt/paths.h \
|
||||||
obt/prop.h \
|
obt/prop.h \
|
||||||
obt/util.h \
|
obt/util.h \
|
||||||
obt/version.h \
|
obt/version.h \
|
||||||
obt/xevent.h \
|
|
||||||
obt/xqueue.h
|
obt/xqueue.h
|
||||||
|
|
||||||
nodist_pkgconfig_DATA = \
|
nodist_pkgconfig_DATA = \
|
||||||
|
|
698
obt/mainloop.c
698
obt/mainloop.c
|
@ -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 <stdio.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
#include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SIGNAL_H
|
|
||||||
#include <signal.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
|
@ -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 <X11/Xlib.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
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
|
|
140
obt/xevent.c
140
obt/xevent.c
|
@ -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);
|
|
||||||
}
|
|
48
obt/xevent.h
48
obt/xevent.h
|
@ -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 <X11/Xlib.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
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*/
|
|
66
obt/xqueue.c
66
obt/xqueue.c
|
@ -318,3 +318,69 @@ gboolean xqueue_pending_local(void)
|
||||||
if (!qnum) read_events(FALSE);
|
if (!qnum) read_events(FALSE);
|
||||||
return qnum != 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -87,6 +87,15 @@ gboolean xqueue_exists_local(xqueue_match_func match, gpointer data);
|
||||||
gboolean xqueue_remove_local(XEvent *event_return,
|
gboolean xqueue_remove_local(XEvent *event_return,
|
||||||
xqueue_match_func match, gpointer data);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
ButtonMotionMask)
|
ButtonMotionMask)
|
||||||
|
|
||||||
static ObDock *dock;
|
static ObDock *dock;
|
||||||
|
static guint show_timeout_id;
|
||||||
|
static guint hide_timeout_id;
|
||||||
|
|
||||||
StrutPartial dock_strut;
|
StrutPartial dock_strut;
|
||||||
|
|
||||||
|
@ -628,15 +630,19 @@ static gboolean hide_timeout(gpointer data)
|
||||||
dock->hidden = TRUE;
|
dock->hidden = TRUE;
|
||||||
dock_configure();
|
dock_configure();
|
||||||
|
|
||||||
|
hide_timeout_id = 0;
|
||||||
|
|
||||||
return FALSE; /* don't repeat */
|
return FALSE; /* don't repeat */
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean show_timeout(gpointer data)
|
static gboolean show_timeout(gpointer data)
|
||||||
{
|
{
|
||||||
/* hide */
|
/* show */
|
||||||
dock->hidden = FALSE;
|
dock->hidden = FALSE;
|
||||||
dock_configure();
|
dock_configure();
|
||||||
|
|
||||||
|
show_timeout_id = 0;
|
||||||
|
|
||||||
return FALSE; /* don't repeat */
|
return FALSE; /* don't repeat */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,21 +650,21 @@ void dock_hide(gboolean hide)
|
||||||
{
|
{
|
||||||
if (!hide) {
|
if (!hide) {
|
||||||
if (dock->hidden && config_dock_hide) {
|
if (dock->hidden && config_dock_hide) {
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
show_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
config_dock_show_delay * 1000,
|
config_dock_show_delay,
|
||||||
show_timeout, NULL,
|
show_timeout, NULL, NULL);
|
||||||
g_direct_equal, NULL);
|
} else if (!dock->hidden && config_dock_hide && hide_timeout_id) {
|
||||||
} else if (!dock->hidden && config_dock_hide) {
|
if (hide_timeout_id) g_source_remove(hide_timeout_id);
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, hide_timeout);
|
hide_timeout_id = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!dock->hidden && config_dock_hide) {
|
if (!dock->hidden && config_dock_hide) {
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
hide_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
config_dock_hide_delay * 1000,
|
config_dock_show_delay,
|
||||||
hide_timeout, NULL,
|
hide_timeout, NULL, NULL);
|
||||||
g_direct_equal, NULL);
|
} else if (dock->hidden && config_dock_hide && show_timeout_id) {
|
||||||
} else if (dock->hidden && config_dock_hide) {
|
if (show_timeout_id) g_source_remove(show_timeout_id);
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, show_timeout);
|
show_timeout_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 event_ignore_enter_range(gulong start, gulong end);
|
||||||
|
|
||||||
static void focus_delay_dest(gpointer data);
|
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 focus_delay_func(gpointer data);
|
||||||
static gboolean unfocus_delay_func(gpointer data);
|
static gboolean unfocus_delay_func(gpointer data);
|
||||||
static void focus_delay_client_dest(ObClient *client, 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;
|
static gboolean waiting_for_focusin = FALSE;
|
||||||
/*! A list of ObSerialRanges which are to be ignored for mouse enter events */
|
/*! A list of ObSerialRanges which are to be ignored for mouse enter events */
|
||||||
static GSList *ignore_serials = NULL;
|
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
|
#ifdef USE_SM
|
||||||
static void ice_handler(gint fd, gpointer conn)
|
static gboolean ice_handler(GIOChannel *source, GIOCondition cond,
|
||||||
|
gpointer conn)
|
||||||
{
|
{
|
||||||
Bool b;
|
Bool b;
|
||||||
IceProcessMessages(conn, NULL, &b);
|
IceProcessMessages(conn, NULL, &b);
|
||||||
|
return TRUE; /* don't remove the event source */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ice_watch(IceConn conn, IcePointer data, Bool opening,
|
static void ice_watch(IceConn conn, IcePointer data, Bool opening,
|
||||||
IcePointer *watch_data)
|
IcePointer *watch_data)
|
||||||
{
|
{
|
||||||
static gint fd = -1;
|
static guint id = 0;
|
||||||
|
|
||||||
if (opening) {
|
if (opening) {
|
||||||
fd = IceConnectionNumber(conn);
|
GIOChannel *ch;
|
||||||
obt_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
|
|
||||||
} else {
|
ch = g_io_channel_unix_new(IceConnectionNumber(conn));
|
||||||
obt_main_loop_fd_remove(ob_main_loop, fd);
|
id = g_io_add_watch(ch, G_IO_IN, ice_handler, conn);
|
||||||
fd = -1;
|
g_io_channel_unref(ch);
|
||||||
|
} else if (id) {
|
||||||
|
g_source_remove(id);
|
||||||
|
id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,7 +148,7 @@ void event_startup(gboolean reconfig)
|
||||||
{
|
{
|
||||||
if (reconfig) return;
|
if (reconfig) return;
|
||||||
|
|
||||||
obt_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
|
xqueue_add_callback(event_process, NULL);
|
||||||
|
|
||||||
#ifdef USE_SM
|
#ifdef USE_SM
|
||||||
IceAddConnectionWatch(ice_watch, NULL);
|
IceAddConnectionWatch(ice_watch, NULL);
|
||||||
|
@ -806,17 +815,20 @@ void event_enter_client(ObClient *client)
|
||||||
if (config_focus_delay) {
|
if (config_focus_delay) {
|
||||||
ObFocusDelayData *data;
|
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 = g_slice_new(ObFocusDelayData);
|
||||||
data->client = client;
|
data->client = client;
|
||||||
data->time = event_time();
|
data->time = event_time();
|
||||||
data->serial = event_curserial;
|
data->serial = event_curserial;
|
||||||
|
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
focus_delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
config_focus_delay * 1000,
|
config_focus_delay,
|
||||||
focus_delay_func,
|
focus_delay_func,
|
||||||
data, focus_delay_cmp, focus_delay_dest);
|
data,
|
||||||
|
focus_delay_dest);
|
||||||
|
focus_delay_timeout_client = client;
|
||||||
} else {
|
} else {
|
||||||
ObFocusDelayData data;
|
ObFocusDelayData data;
|
||||||
data.client = client;
|
data.client = client;
|
||||||
|
@ -841,17 +853,20 @@ void event_leave_client(ObClient *client)
|
||||||
if (config_focus_delay) {
|
if (config_focus_delay) {
|
||||||
ObFocusDelayData *data;
|
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 = g_slice_new(ObFocusDelayData);
|
||||||
data->client = client;
|
data->client = client;
|
||||||
data->time = event_time();
|
data->time = event_time();
|
||||||
data->serial = event_curserial;
|
data->serial = event_curserial;
|
||||||
|
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
unfocus_delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
config_focus_delay * 1000,
|
config_focus_delay,
|
||||||
unfocus_delay_func,
|
unfocus_delay_func,
|
||||||
data, focus_delay_cmp, focus_delay_dest);
|
data,
|
||||||
|
unfocus_delay_dest);
|
||||||
|
unfocus_delay_timeout_client = client;
|
||||||
} else {
|
} else {
|
||||||
ObFocusDelayData data;
|
ObFocusDelayData data;
|
||||||
data.client = client;
|
data.client = client;
|
||||||
|
@ -1060,10 +1075,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
delay is up */
|
delay is up */
|
||||||
e->xcrossing.detail != NotifyInferior)
|
e->xcrossing.detail != NotifyInferior)
|
||||||
{
|
{
|
||||||
if (config_focus_delay)
|
if (config_focus_delay && focus_delay_timeout_id)
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop,
|
g_source_remove(focus_delay_timeout_id);
|
||||||
focus_delay_func,
|
|
||||||
client, FALSE);
|
|
||||||
if (config_unfocus_leave)
|
if (config_unfocus_leave)
|
||||||
event_leave_client(client);
|
event_leave_client(client);
|
||||||
}
|
}
|
||||||
|
@ -1113,10 +1126,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
e->xcrossing.serial,
|
e->xcrossing.serial,
|
||||||
(client?client->window:0));
|
(client?client->window:0));
|
||||||
if (config_focus_follow) {
|
if (config_focus_follow) {
|
||||||
if (config_focus_delay)
|
if (config_focus_delay && unfocus_delay_timeout_id)
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop,
|
g_source_remove(unfocus_delay_timeout_id);
|
||||||
unfocus_delay_func,
|
|
||||||
client, FALSE);
|
|
||||||
event_enter_client(client);
|
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)
|
static void focus_delay_dest(gpointer data)
|
||||||
{
|
{
|
||||||
g_slice_free(ObFocusDelayData, 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;
|
g_slice_free(ObFocusDelayData, data);
|
||||||
return f1->client == d2;
|
unfocus_delay_timeout_id = 0;
|
||||||
|
unfocus_delay_timeout_client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean focus_delay_func(gpointer data)
|
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)
|
static void focus_delay_client_dest(ObClient *client, gpointer data)
|
||||||
{
|
{
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
|
if (focus_delay_timeout_client == client && focus_delay_timeout_id)
|
||||||
client, FALSE);
|
g_source_remove(focus_delay_timeout_id);
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, unfocus_delay_func,
|
if (unfocus_delay_timeout_client == client && unfocus_delay_timeout_id)
|
||||||
client, FALSE);
|
g_source_remove(unfocus_delay_timeout_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_halt_focus_delay(void)
|
void event_halt_focus_delay(void)
|
||||||
{
|
{
|
||||||
/* ignore all enter events up till the event which caused this to occur */
|
/* ignore all enter events up till the event which caused this to occur */
|
||||||
if (event_curserial) event_ignore_enter_range(1, event_curserial);
|
if (event_curserial) event_ignore_enter_range(1, event_curserial);
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
|
if (focus_delay_timeout_id) g_source_remove(focus_delay_timeout_id);
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func);
|
if (unfocus_delay_timeout_id) g_source_remove(unfocus_delay_timeout_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
gulong event_start_ignore_all_enters(void)
|
gulong event_start_ignore_all_enters(void)
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
EnterWindowMask | LeaveWindowMask)
|
EnterWindowMask | LeaveWindowMask)
|
||||||
|
|
||||||
#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
|
#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)
|
#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)
|
void frame_release_client(ObFrame *self)
|
||||||
{
|
{
|
||||||
/* if there was any animation going on, kill it */
|
/* if there was any animation going on, kill it */
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
|
if (self->iconify_animation_timer)
|
||||||
self, FALSE);
|
g_source_remove(self->iconify_animation_timer);
|
||||||
|
|
||||||
/* check if the app has already reparented its window away */
|
/* check if the app has already reparented its window away */
|
||||||
if (!xqueue_exists_local(find_reparent, self)) {
|
if (!xqueue_exists_local(find_reparent, self)) {
|
||||||
|
@ -1118,7 +1118,7 @@ void frame_release_client(ObFrame *self)
|
||||||
window_remove(self->rgriptop);
|
window_remove(self->rgriptop);
|
||||||
window_remove(self->rgripbottom);
|
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? */
|
/* is there anything present between us and the label? */
|
||||||
|
@ -1674,12 +1674,9 @@ void frame_flash_start(ObFrame *self)
|
||||||
self->flash_on = self->focused;
|
self->flash_on = self->focused;
|
||||||
|
|
||||||
if (!self->flashing)
|
if (!self->flashing)
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
self->flash_timer = g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
G_USEC_PER_SEC * 0.6,
|
600, flash_timeout, self,
|
||||||
flash_timeout,
|
flash_done);
|
||||||
self,
|
|
||||||
g_direct_equal,
|
|
||||||
flash_done);
|
|
||||||
g_get_current_time(&self->flash_end);
|
g_get_current_time(&self->flash_end);
|
||||||
g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
|
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) {
|
if (new_anim) {
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
|
if (self->iconify_animation_timer)
|
||||||
self, FALSE);
|
g_source_remove(self->iconify_animation_timer);
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
self->iconify_animation_timer =
|
||||||
FRAME_ANIMATE_ICONIFY_STEP_TIME,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
frame_animate_iconify, self,
|
FRAME_ANIMATE_ICONIFY_STEP_TIME,
|
||||||
g_direct_equal, NULL);
|
frame_animate_iconify, self, NULL);
|
||||||
|
|
||||||
|
|
||||||
/* do the first step */
|
/* do the first step */
|
||||||
frame_animate_iconify(self);
|
frame_animate_iconify(self);
|
||||||
|
|
|
@ -190,12 +190,14 @@ struct _ObFrame
|
||||||
gboolean flashing;
|
gboolean flashing;
|
||||||
gboolean flash_on;
|
gboolean flash_on;
|
||||||
GTimeVal flash_end;
|
GTimeVal flash_end;
|
||||||
|
guint flash_timer;
|
||||||
|
|
||||||
/*! Is the frame currently in an animation for iconify or restore.
|
/*! 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 that it is not animating. > 0 means it is animating an iconify.
|
||||||
< 0 means it is animating a restore.
|
< 0 means it is animating a restore.
|
||||||
*/
|
*/
|
||||||
gint iconify_animation_going;
|
gint iconify_animation_going;
|
||||||
|
guint iconify_animation_timer;
|
||||||
GTimeVal iconify_animation_end;
|
GTimeVal iconify_animation_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
KeyBindingTree *keyboard_firstnode = NULL;
|
KeyBindingTree *keyboard_firstnode = NULL;
|
||||||
static ObPopup *popup = NULL;
|
static ObPopup *popup = NULL;
|
||||||
static KeyBindingTree *curpos;
|
static KeyBindingTree *curpos;
|
||||||
|
static guint chain_timer = 0;
|
||||||
|
|
||||||
static void grab_keys(gboolean grab)
|
static void grab_keys(gboolean grab)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +69,11 @@ static gboolean chain_timeout(gpointer data)
|
||||||
return FALSE; /* don't repeat */
|
return FALSE; /* don't repeat */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chain_done(gpointer data)
|
||||||
|
{
|
||||||
|
chain_timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void set_curpos(KeyBindingTree *newpos)
|
static void set_curpos(KeyBindingTree *newpos)
|
||||||
{
|
{
|
||||||
if (curpos == newpos) return;
|
if (curpos == newpos) return;
|
||||||
|
@ -93,7 +99,7 @@ static void set_curpos(KeyBindingTree *newpos)
|
||||||
a = screen_physical_area_primary(FALSE);
|
a = screen_physical_area_primary(FALSE);
|
||||||
popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10);
|
popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10);
|
||||||
/* 1 second delay for the popup to show */
|
/* 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);
|
g_free(text);
|
||||||
} else {
|
} else {
|
||||||
popup_hide(popup);
|
popup_hide(popup);
|
||||||
|
@ -226,7 +232,7 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
|
||||||
if (e->xkey.keycode == config_keyboard_reset_keycode &&
|
if (e->xkey.keycode == config_keyboard_reset_keycode &&
|
||||||
mods == config_keyboard_reset_state)
|
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);
|
keyboard_reset_chains(-1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -243,11 +249,12 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
|
||||||
menu_frame_hide_all();
|
menu_frame_hide_all();
|
||||||
|
|
||||||
if (p->first_child != NULL) { /* part of a chain */
|
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 */
|
/* 3 second timeout for chains */
|
||||||
obt_main_loop_timeout_add(ob_main_loop, 3 * G_USEC_PER_SEC,
|
chain_timer =
|
||||||
chain_timeout, NULL,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
g_direct_equal, NULL);
|
3000, chain_timeout, NULL,
|
||||||
|
chain_done);
|
||||||
set_curpos(p);
|
set_curpos(p);
|
||||||
} else if (p->chroot) /* an empty chroot */
|
} else if (p->chroot) /* an empty chroot */
|
||||||
set_curpos(p);
|
set_curpos(p);
|
||||||
|
@ -322,7 +329,7 @@ void keyboard_startup(gboolean reconfig)
|
||||||
|
|
||||||
void keyboard_shutdown(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();
|
keyboard_unbind_all();
|
||||||
set_curpos(NULL);
|
set_curpos(NULL);
|
||||||
|
|
|
@ -486,10 +486,10 @@ void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
|
||||||
menu_can_hide = TRUE;
|
menu_can_hide = TRUE;
|
||||||
else {
|
else {
|
||||||
menu_can_hide = FALSE;
|
menu_can_hide = FALSE;
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
config_menu_hide_delay * 1000,
|
config_menu_hide_delay,
|
||||||
menu_hide_delay_func,
|
menu_hide_delay_func,
|
||||||
NULL, g_direct_equal, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ GList *menu_frame_visible;
|
||||||
GHashTable *menu_frame_map;
|
GHashTable *menu_frame_map;
|
||||||
|
|
||||||
static RrAppearance *a_sep;
|
static RrAppearance *a_sep;
|
||||||
|
static guint submenu_show_timer = 0;
|
||||||
|
static guint submenu_hide_timer = 0;
|
||||||
|
|
||||||
static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
|
static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
|
||||||
ObMenuFrame *frame);
|
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)
|
static void remove_submenu_hide_timeout(ObMenuFrame *child)
|
||||||
{
|
{
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout,
|
if (submenu_hide_timer) g_source_remove(submenu_hide_timer);
|
||||||
child, FALSE);
|
submenu_hide_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
||||||
|
@ -1107,7 +1109,8 @@ void menu_frame_hide_all(void)
|
||||||
|
|
||||||
if (config_submenu_show_delay) {
|
if (config_submenu_show_delay) {
|
||||||
/* remove any submenu open requests */
|
/* 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)))
|
if ((it = g_list_last(menu_frame_visible)))
|
||||||
menu_frame_hide(it->data);
|
menu_frame_hide(it->data);
|
||||||
|
@ -1188,7 +1191,8 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
|
||||||
|
|
||||||
if (config_submenu_show_delay) {
|
if (config_submenu_show_delay) {
|
||||||
/* remove any submenu open requests */
|
/* 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;
|
self->selected = entry;
|
||||||
|
@ -1208,12 +1212,13 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
|
||||||
submenu */
|
submenu */
|
||||||
if (immediate || config_submenu_hide_delay == 0)
|
if (immediate || config_submenu_hide_delay == 0)
|
||||||
menu_frame_hide(oldchild);
|
menu_frame_hide(oldchild);
|
||||||
else if (config_submenu_hide_delay > 0)
|
else if (config_submenu_hide_delay > 0) {
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
if (submenu_hide_timer) g_source_remove(submenu_hide_timer);
|
||||||
config_submenu_hide_delay * 1000,
|
submenu_hide_timer =
|
||||||
submenu_hide_timeout,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
oldchild, g_direct_equal,
|
config_submenu_hide_delay,
|
||||||
NULL);
|
submenu_hide_timeout, oldchild, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,12 +1230,15 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
|
||||||
if (oldchild_entry != self->selected) {
|
if (oldchild_entry != self->selected) {
|
||||||
if (immediate || config_submenu_hide_delay == 0)
|
if (immediate || config_submenu_hide_delay == 0)
|
||||||
menu_entry_frame_show_submenu(self->selected);
|
menu_entry_frame_show_submenu(self->selected);
|
||||||
else if (config_submenu_hide_delay > 0)
|
else if (config_submenu_hide_delay > 0) {
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
if (submenu_show_timer)
|
||||||
config_submenu_show_delay * 1000,
|
g_source_remove(submenu_show_timer);
|
||||||
submenu_show_timeout,
|
submenu_show_timer =
|
||||||
self->selected, g_direct_equal,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
NULL);
|
config_submenu_show_delay,
|
||||||
|
submenu_show_timeout,
|
||||||
|
self->selected, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* hide the grandchildren of this menu. and move the cursor to
|
/* hide the grandchildren of this menu. and move the cursor to
|
||||||
the current menu */
|
the current menu */
|
||||||
|
|
|
@ -61,9 +61,11 @@ static guint button;
|
||||||
static guint32 corner;
|
static guint32 corner;
|
||||||
static ObDirection edge_warp_dir = -1;
|
static ObDirection edge_warp_dir = -1;
|
||||||
static gboolean edge_warp_odd = FALSE;
|
static gboolean edge_warp_odd = FALSE;
|
||||||
|
static guint edge_warp_timer = 0;
|
||||||
static ObDirection key_resize_edge = -1;
|
static ObDirection key_resize_edge = -1;
|
||||||
#ifdef SYNC
|
#ifdef SYNC
|
||||||
static guint waiting_for_sync;
|
static guint waiting_for_sync;
|
||||||
|
static guint sync_timer = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ObPopup *popup = NULL;
|
static ObPopup *popup = NULL;
|
||||||
|
@ -319,7 +321,8 @@ void moveresize_end(gboolean cancel)
|
||||||
moveresize_alarm = None;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,10 +436,8 @@ static void do_resize(void)
|
||||||
|
|
||||||
waiting_for_sync = 1;
|
waiting_for_sync = 1;
|
||||||
|
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
|
if (sync_timer) g_source_remove(sync_timer);
|
||||||
obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
|
sync_timer = g_timeout_add(2000, sync_timeout_func, NULL);
|
||||||
sync_timeout_func,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -461,8 +462,10 @@ static gboolean sync_timeout_func(gpointer data)
|
||||||
++waiting_for_sync; /* we timed out waiting for our sync... */
|
++waiting_for_sync; /* we timed out waiting for our sync... */
|
||||||
do_resize(); /* ...so let any pending resizes through */
|
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 */
|
return FALSE; /* don't repeat */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return TRUE; /* keep waiting */
|
return TRUE; /* keep waiting */
|
||||||
}
|
}
|
||||||
|
@ -649,10 +652,8 @@ static void do_edge_warp(gint x, gint y)
|
||||||
cancel_edge_warp();
|
cancel_edge_warp();
|
||||||
if (dir != (ObDirection)-1) {
|
if (dir != (ObDirection)-1) {
|
||||||
edge_warp_odd = TRUE; /* switch on the first timeout */
|
edge_warp_odd = TRUE; /* switch on the first timeout */
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
edge_warp_timer = g_timeout_add(config_mouse_screenedgetime,
|
||||||
config_mouse_screenedgetime * 1000,
|
edge_warp_delay_func, NULL);
|
||||||
edge_warp_delay_func,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
edge_warp_dir = dir;
|
edge_warp_dir = dir;
|
||||||
}
|
}
|
||||||
|
@ -660,7 +661,8 @@ static void do_edge_warp(gint x, gint y)
|
||||||
|
|
||||||
static void cancel_edge_warp(void)
|
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)
|
static void move_with_keys(KeySym sym, guint state)
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "obrender/render.h"
|
#include "obrender/render.h"
|
||||||
#include "obrender/theme.h"
|
#include "obrender/theme.h"
|
||||||
#include "obt/display.h"
|
#include "obt/display.h"
|
||||||
|
#include "obt/xqueue.h"
|
||||||
#include "obt/prop.h"
|
#include "obt/prop.h"
|
||||||
#include "obt/keyboard.h"
|
#include "obt/keyboard.h"
|
||||||
#include "obt/xml.h"
|
#include "obt/xml.h"
|
||||||
|
@ -83,7 +84,7 @@
|
||||||
RrInstance *ob_rr_inst;
|
RrInstance *ob_rr_inst;
|
||||||
RrImageCache *ob_rr_icons;
|
RrImageCache *ob_rr_icons;
|
||||||
RrTheme *ob_rr_theme;
|
RrTheme *ob_rr_theme;
|
||||||
ObtMainLoop *ob_main_loop;
|
GMainLoop *ob_main_loop;
|
||||||
gint ob_screen;
|
gint ob_screen;
|
||||||
gboolean ob_replace_wm = FALSE;
|
gboolean ob_replace_wm = FALSE;
|
||||||
gboolean ob_sm_use = TRUE;
|
gboolean ob_sm_use = TRUE;
|
||||||
|
@ -157,18 +158,18 @@ gint main(gint argc, gchar **argv)
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ob_main_loop = obt_main_loop_new();
|
ob_main_loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
|
||||||
/* set up signal handler */
|
/* 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, 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, 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, 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, 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, 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, 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, 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, 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, SIGTTOU, signal_handler, NULL,NULL);
|
||||||
|
|
||||||
ob_screen = DefaultScreen(obt_display);
|
ob_screen = DefaultScreen(obt_display);
|
||||||
|
|
||||||
|
@ -316,6 +317,10 @@ gint main(gint argc, gchar **argv)
|
||||||
menu_startup(reconfigure);
|
menu_startup(reconfigure);
|
||||||
prompt_startup(reconfigure);
|
prompt_startup(reconfigure);
|
||||||
|
|
||||||
|
/* do this after everything is started so no events will get
|
||||||
|
missed */
|
||||||
|
xqueue_listen();
|
||||||
|
|
||||||
if (!reconfigure) {
|
if (!reconfigure) {
|
||||||
guint32 xid;
|
guint32 xid;
|
||||||
ObWindow *w;
|
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_set_state(reconfigure ?
|
||||||
OB_STATE_RECONFIGURING : OB_STATE_EXITING);
|
OB_STATE_RECONFIGURING : OB_STATE_EXITING);
|
||||||
|
|
||||||
|
@ -741,14 +746,14 @@ void ob_reconfigure(void)
|
||||||
void ob_exit(gint code)
|
void ob_exit(gint code)
|
||||||
{
|
{
|
||||||
exitcode = code;
|
exitcode = code;
|
||||||
obt_main_loop_exit(ob_main_loop);
|
g_main_loop_quit(ob_main_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ob_exit_replace(void)
|
void ob_exit_replace(void)
|
||||||
{
|
{
|
||||||
exitcode = 0;
|
exitcode = 0;
|
||||||
being_replaced = TRUE;
|
being_replaced = TRUE;
|
||||||
obt_main_loop_exit(ob_main_loop);
|
g_main_loop_quit(ob_main_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor ob_cursor(ObCursor cursor)
|
Cursor ob_cursor(ObCursor cursor)
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include "obrender/render.h"
|
#include "obrender/render.h"
|
||||||
#include "obrender/theme.h"
|
#include "obrender/theme.h"
|
||||||
#include "obt/mainloop.h"
|
|
||||||
#include "obt/display.h"
|
#include "obt/display.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -32,7 +31,7 @@ extern RrInstance *ob_rr_inst;
|
||||||
extern RrImageCache *ob_rr_icons;
|
extern RrImageCache *ob_rr_icons;
|
||||||
extern RrTheme *ob_rr_theme;
|
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 */
|
/*! The number of the screen on which we're running */
|
||||||
extern gint ob_screen;
|
extern gint ob_screen;
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "openbox.h"
|
#include "openbox.h"
|
||||||
#include "obt/mainloop.h"
|
|
||||||
#include "obt/prop.h"
|
#include "obt/prop.h"
|
||||||
|
|
||||||
typedef struct _ObPingTarget
|
typedef struct _ObPingTarget
|
||||||
|
@ -30,13 +29,14 @@ typedef struct _ObPingTarget
|
||||||
ObClient *client;
|
ObClient *client;
|
||||||
ObPingEventHandler h;
|
ObPingEventHandler h;
|
||||||
guint32 id;
|
guint32 id;
|
||||||
|
guint loopid;
|
||||||
gint waiting;
|
gint waiting;
|
||||||
} ObPingTarget;
|
} ObPingTarget;
|
||||||
|
|
||||||
static GHashTable *ping_ids = NULL;
|
static GHashTable *ping_ids = NULL;
|
||||||
static guint32 ping_next_id = 1;
|
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 */
|
/*! Warn the user after this many PING_TIMEOUT intervals */
|
||||||
#define PING_TIMEOUT_WARN 2
|
#define PING_TIMEOUT_WARN 2
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h)
|
||||||
t->client = client;
|
t->client = client;
|
||||||
t->h = h;
|
t->h = h;
|
||||||
|
|
||||||
obt_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout,
|
t->loopid = g_timeout_add_full(G_PRIORITY_DEFAULT, PING_TIMEOUT,
|
||||||
t, g_direct_equal, NULL);
|
ping_timeout, t, NULL);
|
||||||
/* act like we just timed out immediately, to start the pinging process
|
/* act like we just timed out immediately, to start the pinging process
|
||||||
now instead of after the first delay. this makes sure the client
|
now instead of after the first delay. this makes sure the client
|
||||||
ends up in the ping_ids hash table now. */
|
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))) {
|
if ((t = g_hash_table_find(ping_ids, find_client, client))) {
|
||||||
g_hash_table_remove(ping_ids, &t->id);
|
g_hash_table_remove(ping_ids, &t->id);
|
||||||
|
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, ping_timeout,
|
g_source_remove(t->loopid);
|
||||||
t, FALSE);
|
|
||||||
|
|
||||||
g_slice_free(ObPingTarget, t);
|
g_slice_free(ObPingTarget, t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,11 +146,12 @@ static gboolean popup_show_timeout(gpointer data)
|
||||||
stacking_raise(INTERNAL_AS_WINDOW(self));
|
stacking_raise(INTERNAL_AS_WINDOW(self));
|
||||||
self->mapped = TRUE;
|
self->mapped = TRUE;
|
||||||
self->delay_mapped = FALSE;
|
self->delay_mapped = FALSE;
|
||||||
|
self->delay_timer = 0;
|
||||||
|
|
||||||
return FALSE; /* don't repeat */
|
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 l, t, r, b;
|
||||||
gint x, y, w, h;
|
gint x, y, w, h;
|
||||||
|
@ -292,12 +293,11 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
|
||||||
|
|
||||||
/* do the actual showing */
|
/* do the actual showing */
|
||||||
if (!self->mapped) {
|
if (!self->mapped) {
|
||||||
if (usec) {
|
if (msec) {
|
||||||
/* don't kill previous show timers */
|
/* don't kill previous show timers */
|
||||||
if (!self->delay_mapped) {
|
if (!self->delay_mapped) {
|
||||||
obt_main_loop_timeout_add(ob_main_loop, usec,
|
self->delay_timer =
|
||||||
popup_show_timeout, self,
|
g_timeout_add(msec, popup_show_timeout, self);
|
||||||
g_direct_equal, NULL);
|
|
||||||
self->delay_mapped = TRUE;
|
self->delay_mapped = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -319,7 +319,8 @@ void popup_hide(ObPopup *self)
|
||||||
|
|
||||||
event_end_ignore_all_enters(ignore_start);
|
event_end_ignore_all_enters(ignore_start);
|
||||||
} else if (self->delay_mapped) {
|
} 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;
|
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)
|
gchar *text, RrImage *icon)
|
||||||
{
|
{
|
||||||
if (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;
|
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)
|
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)
|
gchar *text, guint desk)
|
||||||
{
|
{
|
||||||
guint i;
|
guint i;
|
||||||
|
@ -557,7 +558,7 @@ void pager_popup_delay_show(ObPagerPopup *self, gulong usec,
|
||||||
self->desks = screen_num_desktops;
|
self->desks = screen_num_desktops;
|
||||||
self->curdesk = desk;
|
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)
|
void pager_popup_icon_size_multiplier(ObPagerPopup *self, guint wm, guint hm)
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct _ObPopup
|
||||||
guint iconhm; /* icon height multiplier. multipled by the normal height */
|
guint iconhm; /* icon height multiplier. multipled by the normal height */
|
||||||
gboolean mapped;
|
gboolean mapped;
|
||||||
gboolean delay_mapped;
|
gboolean delay_mapped;
|
||||||
|
guint delay_timer;
|
||||||
|
|
||||||
void (*draw_icon)(gint x, gint y, gint w, gint h, gpointer data);
|
void (*draw_icon)(gint x, gint y, gint w, gint h, gpointer data);
|
||||||
gpointer draw_icon_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);
|
void popup_set_text_align(ObPopup *self, RrJustify align);
|
||||||
|
|
||||||
#define popup_show(s, t) popup_delay_show((s),0,(t))
|
#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);
|
void popup_hide(ObPopup *self);
|
||||||
|
|
||||||
RrAppearance *popup_icon_appearance(ObPopup *self);
|
RrAppearance *popup_icon_appearance(ObPopup *self);
|
||||||
|
@ -109,7 +110,7 @@ ObIconPopup *icon_popup_new(void);
|
||||||
void icon_popup_free(ObIconPopup *self);
|
void icon_popup_free(ObIconPopup *self);
|
||||||
|
|
||||||
#define icon_popup_show(s, t, i) icon_popup_delay_show((s),0,(t),(i))
|
#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);
|
gchar *text, RrImage *icon);
|
||||||
#define icon_popup_hide(p) popup_hide((p)->popup)
|
#define icon_popup_hide(p) popup_hide((p)->popup)
|
||||||
#define icon_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y))
|
#define icon_popup_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);
|
void pager_popup_free(ObPagerPopup *self);
|
||||||
|
|
||||||
#define pager_popup_show(s, t, d) pager_popup_delay_show((s),0,(t),(d))
|
#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);
|
gchar *text, guint desk);
|
||||||
#define pager_popup_hide(p) popup_hide((p)->popup)
|
#define pager_popup_hide(p) popup_hide((p)->popup)
|
||||||
#define pager_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y))
|
#define pager_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y))
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "obt/display.h"
|
#include "obt/display.h"
|
||||||
#include "obt/xqueue.h"
|
#include "obt/xqueue.h"
|
||||||
#include "obt/prop.h"
|
#include "obt/prop.h"
|
||||||
#include "obt/mainloop.h"
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
|
@ -71,6 +70,7 @@ Time screen_desktop_user_time = CurrentTime;
|
||||||
static Size screen_physical_size;
|
static Size screen_physical_size;
|
||||||
static guint screen_old_desktop;
|
static guint screen_old_desktop;
|
||||||
static gboolean screen_desktop_timeout = TRUE;
|
static gboolean screen_desktop_timeout = TRUE;
|
||||||
|
static guint screen_desktop_timer = 0;
|
||||||
/*! An array of desktops, holding an array of areas per monitor */
|
/*! An array of desktops, holding an array of areas per monitor */
|
||||||
static Rect *monitor_area = NULL;
|
static Rect *monitor_area = NULL;
|
||||||
/*! An array of desktops, holding an array of struts */
|
/*! An array of desktops, holding an array of struts */
|
||||||
|
@ -80,11 +80,12 @@ static GSList *struts_right = NULL;
|
||||||
static GSList *struts_bottom = NULL;
|
static GSList *struts_bottom = NULL;
|
||||||
|
|
||||||
static ObPagerPopup *desktop_popup;
|
static ObPagerPopup *desktop_popup;
|
||||||
|
static guint desktop_popup_timer = 0;
|
||||||
static gboolean desktop_popup_perm;
|
static gboolean desktop_popup_perm;
|
||||||
|
|
||||||
/*! The number of microseconds that you need to be on a desktop before it will
|
/*! The number of microseconds that you need to be on a desktop before it will
|
||||||
replace the remembered "last desktop" */
|
replace the remembered "last desktop" */
|
||||||
#define REMEMBER_LAST_DESKTOP_TIME 750000
|
#define REMEMBER_LAST_DESKTOP_TIME 750
|
||||||
|
|
||||||
static gboolean replace_wm(void)
|
static gboolean replace_wm(void)
|
||||||
{
|
{
|
||||||
|
@ -601,7 +602,8 @@ static void screen_fallback_focus(void)
|
||||||
static gboolean last_desktop_func(gpointer data)
|
static gboolean last_desktop_func(gpointer data)
|
||||||
{
|
{
|
||||||
screen_desktop_timeout = TRUE;
|
screen_desktop_timeout = TRUE;
|
||||||
return FALSE;
|
screen_desktop_timer = 0;
|
||||||
|
return FALSE; /* don't repeat */
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_set_desktop(guint num, gboolean dofocus)
|
void screen_set_desktop(guint num, gboolean dofocus)
|
||||||
|
@ -683,9 +685,9 @@ void screen_set_desktop(guint num, gboolean dofocus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
screen_desktop_timeout = FALSE;
|
screen_desktop_timeout = FALSE;
|
||||||
obt_main_loop_timeout_remove(ob_main_loop, last_desktop_func);
|
if (screen_desktop_timer) g_source_remove(screen_desktop_timer);
|
||||||
obt_main_loop_timeout_add(ob_main_loop, REMEMBER_LAST_DESKTOP_TIME,
|
screen_desktop_timer = g_timeout_add(REMEMBER_LAST_DESKTOP_TIME,
|
||||||
last_desktop_func, NULL, NULL, NULL);
|
last_desktop_func, NULL);
|
||||||
|
|
||||||
ob_debug("Moving to desktop %d", num+1);
|
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)
|
static gboolean hide_desktop_popup_func(gpointer data)
|
||||||
{
|
{
|
||||||
pager_popup_hide(desktop_popup);
|
pager_popup_hide(desktop_popup);
|
||||||
|
desktop_popup_timer = 0;
|
||||||
return FALSE; /* don't repeat */
|
return FALSE; /* don't repeat */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,21 +962,21 @@ void screen_show_desktop_popup(guint d, gboolean perm)
|
||||||
MAX(a->width/3, POPUP_WIDTH));
|
MAX(a->width/3, POPUP_WIDTH));
|
||||||
pager_popup_show(desktop_popup, screen_desktop_names[d], d);
|
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)
|
if (!perm && !desktop_popup_perm)
|
||||||
/* only hide if its not already being show permanently */
|
/* only hide if its not already being show permanently */
|
||||||
obt_main_loop_timeout_add(ob_main_loop,
|
desktop_popup_timer = g_timeout_add(config_desktop_popup_time,
|
||||||
config_desktop_popup_time * 1000,
|
hide_desktop_popup_func,
|
||||||
hide_desktop_popup_func, desktop_popup,
|
desktop_popup);
|
||||||
g_direct_equal, NULL);
|
|
||||||
if (perm)
|
if (perm)
|
||||||
desktop_popup_perm = TRUE;
|
desktop_popup_perm = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_hide_desktop_popup(void)
|
void screen_hide_desktop_popup(void)
|
||||||
{
|
{
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
|
if (desktop_popup_timer) g_source_remove(desktop_popup_timer);
|
||||||
desktop_popup, FALSE);
|
desktop_popup_timer = 0;
|
||||||
pager_popup_hide(desktop_popup);
|
pager_popup_hide(desktop_popup);
|
||||||
desktop_popup_perm = FALSE;
|
desktop_popup_perm = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "startupnotify.h"
|
#include "startupnotify.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "obt/xqueue.h"
|
||||||
|
|
||||||
#ifdef HAVE_STDLIB_H
|
#ifdef HAVE_STDLIB_H
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
@ -67,7 +68,7 @@ void sn_startup(gboolean reconfig)
|
||||||
sn_event_func, NULL, NULL);
|
sn_event_func, NULL, NULL);
|
||||||
sn_launcher = sn_launcher_context_new(sn_display, ob_screen);
|
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)
|
void sn_shutdown(gboolean reconfig)
|
||||||
|
@ -76,7 +77,7 @@ void sn_shutdown(gboolean reconfig)
|
||||||
|
|
||||||
if (reconfig) return;
|
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))
|
for (it = sn_waits; it; it = g_slist_next(it))
|
||||||
sn_startup_sequence_unref((SnStartupSequence*)it->data);
|
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);
|
sn_waits = g_slist_prepend(sn_waits, seq);
|
||||||
/* 20 second timeout for apps to start if the launcher doesn't
|
/* 20 second timeout for apps to start if the launcher doesn't
|
||||||
have a timeout */
|
have a timeout */
|
||||||
obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
sn_wait_timeout, seq,
|
20 * 1000, sn_wait_timeout, seq,
|
||||||
g_direct_equal,
|
(GDestroyNotify)sn_startup_sequence_unref);
|
||||||
(GDestroyNotify)sn_startup_sequence_unref);
|
|
||||||
change = TRUE;
|
change = TRUE;
|
||||||
break;
|
break;
|
||||||
case SN_MONITOR_EVENT_CHANGED:
|
case SN_MONITOR_EVENT_CHANGED:
|
||||||
|
@ -153,8 +153,7 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data)
|
||||||
case SN_MONITOR_EVENT_CANCELED:
|
case SN_MONITOR_EVENT_CANCELED:
|
||||||
if ((seq = sequence_find(sn_startup_sequence_get_id(seq)))) {
|
if ((seq = sequence_find(sn_startup_sequence_get_id(seq)))) {
|
||||||
sn_waits = g_slist_remove(sn_waits, seq);
|
sn_waits = g_slist_remove(sn_waits, seq);
|
||||||
obt_main_loop_timeout_remove_data(ob_main_loop, sn_wait_timeout,
|
g_source_remove_by_user_data(seq);
|
||||||
seq, FALSE);
|
|
||||||
change = TRUE;
|
change = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -260,10 +259,9 @@ void sn_setup_spawn_environment(const gchar *program, const gchar *name,
|
||||||
|
|
||||||
/* 20 second timeout for apps to start */
|
/* 20 second timeout for apps to start */
|
||||||
sn_launcher_context_ref(sn_launcher);
|
sn_launcher_context_ref(sn_launcher);
|
||||||
obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
|
g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
sn_launch_wait_timeout, sn_launcher,
|
20 * 1000, sn_launch_wait_timeout, sn_launcher,
|
||||||
g_direct_equal,
|
(GDestroyNotify)sn_launcher_context_unref);
|
||||||
(GDestroyNotify)sn_launcher_context_unref);
|
|
||||||
|
|
||||||
setenv("DESKTOP_STARTUP_ID", id, TRUE);
|
setenv("DESKTOP_STARTUP_ID", id, TRUE);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue