X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=bdafd126e6acbc1f89796e908756347371e903b9;hb=6b7737acc3f6daa4ca0d4546d2bf4cddc7236e2d;hp=4398c97724d9469d1668fa68245328e30226a8f2;hpb=79a352a40bd16924b1ca3df49f6c82d77e956a0e;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 4398c977..bdafd126 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -8,6 +8,7 @@ #include "menu.h" #include "framerender.h" #include "focus.h" +#include "moveresize.h" #include "stacking.h" #include "extensions.h" #include "timer.h" @@ -25,6 +26,13 @@ static void event_handle_root(XEvent *e); static void event_handle_client(Client *c, XEvent *e); static void event_handle_menu(Menu *menu, XEvent *e); +#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \ + (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 */ @@ -79,6 +87,7 @@ void event_loop() XEvent e; int x_fd; struct timeval *wait; + gboolean had_event = FALSE; while (TRUE) { /* @@ -105,13 +114,16 @@ void event_loop() XNextEvent(ob_display, &e); event_process(&e); + had_event = TRUE; + } + + if (!had_event) { + timer_dispatch((GTimeVal**)&wait); + x_fd = ConnectionNumber(ob_display); + FD_ZERO(&selset); + FD_SET(x_fd, &selset); + select(x_fd + 1, &selset, NULL, NULL, wait); } - - timer_dispatch((GTimeVal**)&wait); - x_fd = ConnectionNumber(ob_display); - FD_ZERO(&selset); - FD_SET(x_fd, &selset); - select(x_fd + 1, &selset, NULL, NULL, wait); } static Window event_get_window(XEvent *e) @@ -234,19 +246,18 @@ static gboolean event_ignore(XEvent *e, Client *client) { switch(e->type) { case FocusIn: -#ifdef DEBUG_FOCUS - g_message("FocusIn on %lx mode %d detail %d", window, - e->xfocus.mode, e->xfocus.detail); -#endif /* 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 (e->xfocus.detail == NotifyInferior || - e->xfocus.detail > NotifyNonlinearVirtual || + if (INVALID_FOCUSIN(e) || client == NULL) { +#ifdef DEBUG_FOCUS + g_message("FocusIn on %lx mode %d detail %d IGNORED", 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. */ @@ -255,54 +266,92 @@ static gboolean event_ignore(XEvent *e, Client *client) } #ifdef DEBUG_FOCUS - g_message("FocusIn on %lx", window); + g_message("FocusIn on %lx mode %d detail %d", e->xfocus.window, + e->xfocus.mode, e->xfocus.detail); #endif break; case FocusOut: + if (INVALID_FOCUSOUT(e)) { #ifdef DEBUG_FOCUS - g_message("FocusOut on %lx mode %d detail %d", window, - e->xfocus.mode, e->xfocus.detail); + g_message("FocusOut on %lx mode %d detail %d IGNORED", + e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif - if (e->xfocus.mode == NotifyGrab || - e->xfocus.detail == NotifyInferior || - e->xfocus.detail == NotifyAncestor || - e->xfocus.detail > NotifyNonlinearVirtual) return TRUE; - + return TRUE; + } + #ifdef DEBUG_FOCUS - g_message("FocusOut on %lx", window); + g_message("FocusOut on %lx mode %d detail %d", + e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif + /* Try process a FocusIn first, and if a legit one isn't found, then do the fallback shiznit. */ { - XEvent fi, fo; - gboolean isfo = FALSE; - - if (XCheckTypedEvent(ob_display, FocusIn, &fi)) { - event_process(&fi); - - /* when we have gotten a fi/fo pair, then see if there are any - more fo's coming. if there are, then don't fallback just yet - */ - if ((isfo = XCheckTypedEvent(ob_display, FocusOut, &fo))) - XPutBackEvent(ob_display, &fo); - - /* secret magic way of event_process telling us that no client - was found for the FocusIn event. ^_^ */ - if (!isfo && fi.xfocus.window == None) - focus_fallback(Fallback_NoFocus); - if (fi.xfocus.window == e->xfocus.window) - return TRUE; - } else + XEvent fe; + gboolean fallback = TRUE; + + while (TRUE) { + if (!XCheckTypedEvent(ob_display, FocusOut, &fe)) + if (!XCheckTypedEvent(ob_display, FocusIn, &fe)) + break; + if (fe.type == FocusOut) { +#ifdef DEBUG_FOCUS + g_message("found pending FocusOut"); +#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 + g_message("found pending FocusIn"); +#endif + /* 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); + /* secret magic way of event_process telling us that no + client was found for the FocusIn event. ^_^ */ + if (fe.xfocus.window != None) { + fallback = FALSE; + break; + } + } + } + if (fallback) { +#ifdef DEBUG_FOCUS + g_message("no valid FocusIn and no FocusOut events found, " + "falling back"); +#endif focus_fallback(Fallback_NoFocus); + } } break; case EnterNotify: case LeaveNotify: /* NotifyUngrab occurs when a mouse button is released and the event is caused, like when lowering a window */ + /* NotifyVirtual occurs when ungrabbing the pointer */ if (e->xcrossing.mode == NotifyGrab || - e->xcrossing.detail == NotifyInferior) + e->xcrossing.detail == NotifyInferior || + (e->xcrossing.mode == NotifyUngrab && + e->xcrossing.detail == NotifyVirtual)) { +#ifdef DEBUG_FOCUS + g_message("%sNotify mode %d detail %d on %lx IGNORED", + (e->type == EnterNotify ? "Enter" : "Leave"), + e->xcrossing.mode, + e->xcrossing.detail, client?client->window:0); +#endif return TRUE; + } +#ifdef DEBUG_FOCUS + g_message("%sNotify mode %d detail %d on %lx", + (e->type == EnterNotify ? "Enter" : "Leave"), + e->xcrossing.mode, + e->xcrossing.detail, client?client->window:0); +#endif break; } return FALSE; @@ -323,9 +372,10 @@ static void event_process(XEvent *e) return; /* deal with it in the kernel */ - if (menu) + if (menu) { event_handle_menu(menu, e); - else if (client) + return; + } else if (client) event_handle_client(client, e); else if (window == ob_root) event_handle_root(e); @@ -352,6 +402,16 @@ static void event_process(XEvent *e) xerror_set_ignore(FALSE); } + if (moveresize_in_progress) + if (e->type == MotionNotify || e->type == ButtonRelease || + e->type == ButtonPress || + e->type == KeyPress || e->type == KeyRelease) { + moveresize_event(e); + + return; /* no dispatch! */ + + } + /* user input (action-bound) events */ /* if (e->type == ButtonPress || e->type == ButtonRelease || @@ -646,7 +706,66 @@ static void event_handle_client(Client *client, XEvent *e) client_shade(client, FALSE); client_focus(client); stacking_raise(client); - } + } else if (msgtype == prop_atoms.net_wm_moveresize) { + g_message("net_wm_moveresize for 0x%lx", client->window); + if ((Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_topleft || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_top || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_topright || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_right || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_right || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_bottomright || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_bottom || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_bottomleft || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_left || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_move || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_size_keyboard || + (Atom)e->xclient.data.l[2] == + prop_atoms.net_wm_moveresize_move_keyboard) { + + moveresize_start(client, e->xclient.data.l[0], + e->xclient.data.l[1], e->xclient.data.l[3], + e->xclient.data.l[2]); + } + } else if (msgtype == prop_atoms.net_moveresize_window) { + int oldg = client->gravity; + int tmpg, x, y, w, h; + + if (e->xclient.data.l[0] & 0xff) + tmpg = e->xclient.data.l[0] & 0xff; + else + tmpg = oldg; + + if (e->xclient.data.l[0] & 1 << 8) + x = e->xclient.data.l[1]; + else + x = client->area.x; + if (e->xclient.data.l[0] & 1 << 9) + y = e->xclient.data.l[2]; + else + y = client->area.y; + if (e->xclient.data.l[0] & 1 << 10) + w = e->xclient.data.l[3]; + else + w = client->area.y; + if (e->xclient.data.l[0] & 1 << 11) + h = e->xclient.data.l[4]; + else + h = client->area.y; + client->gravity = tmpg; + client_configure(client, Corner_TopLeft, x, y, w, h, TRUE, TRUE); + client->gravity = oldg; + } break; case PropertyNotify: /* validate cuz we query stuff off the client here */ @@ -711,7 +830,32 @@ static void event_handle_menu(Menu *menu, XEvent *e) { MenuEntry *entry; + g_message("EVENT %d", e->type); switch (e->type) { + case ButtonPress: + if (e->xbutton.button == 3) + menu_hide(menu); + break; + case ButtonRelease: + if (!menu->shown) break; + +/* grab_pointer_window(FALSE, None, menu->frame);*/ + + entry = menu_find_entry(menu, e->xbutton.window); + if (entry) { + int junk; + Window wjunk; + guint ujunk, b, w, h; + XGetGeometry(ob_display, e->xbutton.window, + &wjunk, &junk, &junk, &w, &h, &b, &ujunk); + if (e->xbutton.x >= (signed)-b && + e->xbutton.y >= (signed)-b && + e->xbutton.x < (signed)(w+b) && + e->xbutton.y < (signed)(h+b)) { + menu_entry_fire(entry); + } + } + break; case EnterNotify: case LeaveNotify: g_message("enter/leave");