the old event code

This commit is contained in:
Mikael Magnusson 2004-03-18 11:54:15 +00:00
parent d50f491716
commit 0e6161b0d4
4 changed files with 186 additions and 134 deletions

View file

@ -55,8 +55,12 @@ See the COPYING file for a copy of the GNU General Public License.
#include <X11/ICE/ICElib.h>
#endif
typedef struct
{
gboolean ignored;
} ObEventData;
static void event_process(const XEvent *e, gpointer data);
static void event_done(gpointer data);
static void event_client_dest(ObClient *client, gpointer data);
static void event_handle_root(XEvent *e);
static void event_handle_menu(XEvent *e);
@ -70,6 +74,14 @@ static void focus_delay_client_dest(ObClient *client, gpointer data);
static gboolean menu_hide_delay_func(gpointer data);
#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
(e)->xfocus.detail == NotifyAncestor || \
(e)->xfocus.detail > NotifyNonlinearVirtual)
#define INVALID_FOCUSOUT(e) ((e)->xfocus.mode == NotifyGrab || \
(e)->xfocus.detail == NotifyInferior || \
(e)->xfocus.detail == NotifyAncestor || \
(e)->xfocus.detail > NotifyNonlinearVirtual)
Time event_lasttime = 0;
/*! The value of the mask for the NumLock modifier */
@ -89,8 +101,6 @@ static guint ignore_enter_focus = 0;
static gboolean menu_can_hide;
static ObClient *focus_in, *focus_out;
#ifdef USE_SM
static void ice_handler(gint fd, gpointer conn)
{
@ -142,7 +152,7 @@ void event_startup(gboolean reconfig)
}
}
ob_main_loop_x_add(ob_main_loop, event_process, event_done, NULL, NULL);
ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
#ifdef USE_SM
IceAddConnectionWatch(ice_watch, NULL);
@ -301,83 +311,127 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
return TRUE;
break;
case FocusIn:
if (e->xfocus.detail > NotifyNonlinearVirtual)
/* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
because of RevertToPointerRoot. If the focus ends up reverting to
pointer root on a workspace change, then the FocusIn event that we
want will be of type NotifyAncestor. This situation does not occur
for FocusOut, so it is safely ignored there.
*/
if (INVALID_FOCUSIN(e) ||
client == NULL) {
#ifdef DEBUG_FOCUS
ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
/* says a client was not found for the event (or a valid FocusIn
event was not found.
*/
e->xfocus.window = None;
return TRUE;
}
#ifdef DEBUG_FOCUS
ob_debug("FocusIn on %lx mode %d detail %d\n", e->xfocus.window,
e->xfocus.mode, e->xfocus.detail);
#endif
break;
case FocusOut:
if (e->xfocus.detail > NotifyNonlinearVirtual)
return TRUE;
if (e->xfocus.detail == NotifyInferior ||
e->xfocus.mode == NotifyGrab)
if (INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS
ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
return TRUE;
}
#ifdef DEBUG_FOCUS
ob_debug("FocusOut on %lx mode %d detail %d\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
{
XEvent fe;
gboolean fallback = TRUE;
while (TRUE) {
if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window,
FocusOut, &fe))
if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
break;
if (fe.type == FocusOut) {
#ifdef DEBUG_FOCUS
ob_debug("found pending FocusOut\n");
#endif
if (!INVALID_FOCUSOUT(&fe)) {
/* if there is a VALID FocusOut still coming, don't
fallback focus yet, we'll deal with it then */
XPutBackEvent(ob_display, &fe);
fallback = FALSE;
break;
}
} else {
#ifdef DEBUG_FOCUS
ob_debug("found pending FocusIn\n");
#endif
/* is the focused window getting a FocusOut/In back to
itself?
*/
if (fe.xfocus.window == e->xfocus.window &&
!event_ignore(&fe, client)) {
/*
if focus_client is not set, then we can't do
this. we need the FocusIn. This happens in the
case when the set_focus_client(NULL) in the
focus_fallback function fires and then
focus_fallback picks the currently focused
window (such as on a SendToDesktop-esque action.
*/
if (focus_client) {
#ifdef DEBUG_FOCUS
ob_debug("focused window got an Out/In back to "
"itself IGNORED both\n");
#endif
return TRUE;
} else {
event_process(&fe, NULL);
#ifdef DEBUG_FOCUS
ob_debug("focused window got an Out/In back to "
"itself but focus_client was null "
"IGNORED just the Out\n");
#endif
return TRUE;
}
}
{
ObEventData d;
/* 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, &d);
if (!d.ignored) {
#ifdef DEBUG_FOCUS
ob_debug("FocusIn was OK, so don't fallback\n");
#endif
fallback = FALSE;
break;
}
}
}
}
if (fallback) {
#ifdef DEBUG_FOCUS
ob_debug("no valid FocusIn and no FocusOut events found, "
"falling back\n");
#endif
focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
}
}
break;
}
return FALSE;
}
static void event_client_dest(ObClient *client, gpointer data)
{
if (client == focus_in)
focus_in = NULL;
if (client == focus_out)
focus_out = NULL;
if (client == focus_hilite)
focus_hilite = NULL;
}
static void event_done(gpointer data)
{
static ObClient *last = NULL;
/* sometimes focus_hilite can be on an unfocused window, this make sure
it loses its focus hilite when focus moves */
if (focus_hilite &&
(focus_in && focus_hilite != focus_in) &&
(focus_out && focus_hilite != focus_out))
{
frame_adjust_focus(focus_hilite->frame, FALSE);
}
if (focus_in) {
if (focus_in != focus_client) {
focus_set_client(focus_in);
frame_adjust_focus(focus_in->frame, TRUE);
client_calc_layer(focus_in);
}
focus_hilite = focus_in;
}
if (focus_out) {
if (focus_out == focus_client)
focus_set_client(NULL);
frame_adjust_focus(focus_out->frame, FALSE);
client_calc_layer(focus_out);
if (!focus_in)
focus_hilite = NULL;
}
if (focus_client != last) {
if (!focus_client) {
Window w;
gint r;
/* is focus anywhere valid? */
XGetInputFocus(ob_display, &w, &r);
#ifdef DEBUG_FOCUS
ob_debug("Focus was found on 0x%x revert %d\n", w, r);
#endif
if (!w || w == PointerRoot)
focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
}
last = focus_client;
}
focus_in = focus_out = NULL;
}
static void event_process(const XEvent *ec, gpointer data)
{
Window window;
@ -387,6 +441,7 @@ static void event_process(const XEvent *ec, gpointer data)
ObDockApp *dockapp = NULL;
ObWindow *obwin = NULL;
XEvent ee, *e;
ObEventData *ed = data;
/* make a copy we can mangle */
ee = *ec;
@ -416,8 +471,12 @@ static void event_process(const XEvent *ec, gpointer data)
event_set_lasttime(e);
event_hack_mods(e);
if (event_ignore(e, client))
if (event_ignore(e, client)) {
if (ed)
ed->ignored = TRUE;
return;
} else if (ed)
ed->ignored = FALSE;
/* deal with it in the kernel */
if (group)
@ -613,9 +672,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
e->xfocus.window, client->window,
e->xfocus.mode, e->xfocus.detail);
#endif
focus_in = client;
if (focus_out == client)
focus_out = NULL;
if (client != focus_client) {
focus_set_client(client);
frame_adjust_focus(client->frame, TRUE);
client_calc_layer(client);
}
break;
case FocusOut:
#ifdef DEBUG_FOCUS
@ -623,10 +684,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
e->xfocus.window, client->window,
e->xfocus.mode, e->xfocus.detail);
#endif
if (focus_hilite == client || focus_client == client)
focus_out = client;
if (focus_in == client)
focus_in = NULL;
focus_hilite = NULL;
frame_adjust_focus(client->frame, FALSE);
client_calc_layer(client);
break;
case LeaveNotify:
con = frame_context(client, e->xcrossing.window);
@ -1218,6 +1278,12 @@ static void focus_delay_client_dest(ObClient *client, gpointer data)
ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, client);
}
static void event_client_dest(ObClient *client, gpointer data)
{
if (client == focus_hilite)
focus_hilite = NULL;
}
void event_halt_focus_delay()
{
ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);

View file

@ -121,7 +121,6 @@ struct _ObMainLoopXHandlerType
ObMainLoop *loop;
gpointer data;
ObMainLoopXHandler func;
ObMainLoopXDoneHandler done_func;
GDestroyNotify destroy;
};
@ -294,7 +293,7 @@ void ob_main_loop_run(ObMainLoop *loop)
for (i = 0; i < NUM_SIGNALS; ++i) {
while (loop->signals_fired[i]) {
for (it = loop->signal_handlers[i];
it; it = g_slist_next(it)) {
it; it = g_slist_next(it)) {
ObMainLoopSignalHandlerType *h = it->data;
h->func(i, h->data);
}
@ -313,60 +312,51 @@ void ob_main_loop_run(ObMainLoop *loop)
h->func(&e, h->data);
}
} while (XPending(loop->display));
} else {
for (it = loop->x_handlers; it; it = g_slist_next(it)) {
ObMainLoopXHandlerType *h = it->data;
if (h->done_func)
h->done_func(h->data);
}
} else if (loop->action_queue) {
/* only fire off one action at a time, then go back for more
X events, since the action might cause some X events (like
FocusIn :) */
if (loop->action_queue) {
/* only fire off one action at a time, then go back for more
X events, since the action might cause some X events (like
FocusIn :) */
do {
act = loop->action_queue->data;
if (act->data.any.client_action ==
OB_CLIENT_ACTION_ALWAYS &&
!act->data.any.c)
{
loop->action_queue =
g_slist_delete_link(loop->action_queue,
loop->action_queue);
action_unref(act);
act = NULL;
}
} while (!act && loop->action_queue);
if (act) {
act->func(&act->data);
do {
act = loop->action_queue->data;
if (act->data.any.client_action == OB_CLIENT_ACTION_ALWAYS &&
!act->data.any.c)
{
loop->action_queue =
g_slist_delete_link(loop->action_queue,
loop->action_queue);
loop->action_queue);
action_unref(act);
act = NULL;
}
} else {
/* this only runs if there were no x events received */
} while (!act && loop->action_queue);
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);
if (act) {
act->func(&act->data);
loop->action_queue =
g_slist_delete_link(loop->action_queue,
loop->action_queue);
action_unref(act);
}
} else {
/* this only runs if there were no x events received */
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);
}
}
@ -384,7 +374,6 @@ void ob_main_loop_exit(ObMainLoop *loop)
void ob_main_loop_x_add(ObMainLoop *loop,
ObMainLoopXHandler handler,
ObMainLoopXDoneHandler done_handler,
gpointer data,
GDestroyNotify notify)
{
@ -393,7 +382,6 @@ void ob_main_loop_x_add(ObMainLoop *loop,
h = g_new(ObMainLoopXHandlerType, 1);
h->loop = loop;
h->func = handler;
h->done_func = done_handler;
h->data = data;
h->destroy = notify;
loop->x_handlers = g_slist_prepend(loop->x_handlers, h);

View file

@ -28,11 +28,9 @@ ObMainLoop *ob_main_loop_new(Display *display);
void ob_main_loop_destroy(ObMainLoop *loop);
typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data);
typedef void (*ObMainLoopXDoneHandler) (gpointer data);
void ob_main_loop_x_add(ObMainLoop *loop,
ObMainLoopXHandler handler,
ObMainLoopXDoneHandler done_handler,
gpointer data,
GDestroyNotify notify);
void ob_main_loop_x_remove(ObMainLoop *loop,

View file

@ -59,7 +59,7 @@ void sn_startup(gboolean reconfig)
sn_context = sn_monitor_context_new(sn_display, ob_screen,
sn_event_func, NULL, NULL);
ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL, NULL);
ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
}
void sn_shutdown(gboolean reconfig)