X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=e431e8f40972c47fdaad81c12f26b65b8fb63d6c;hb=0b646b4e891dacb70f41a43307cbb0dd7304f92a;hp=271114a27d0907f77a8aee42533fe2dd11add46d;hpb=c2c84c3f5ed75561d7d6502f787ab06bc7d984d2;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 271114a2..e431e8f4 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -131,7 +131,7 @@ void event_startup(gboolean reconfig) IceAddConnectionWatch(ice_watch, NULL); #endif - client_add_destructor(focus_delay_client_dest, NULL); + client_add_destroy_notify(focus_delay_client_dest, NULL); } void event_shutdown(gboolean reconfig) @@ -142,7 +142,7 @@ void event_shutdown(gboolean reconfig) IceRemoveConnectionWatch(ice_watch, NULL); #endif - client_remove_destructor(focus_delay_client_dest); + client_remove_destroy_notify(focus_delay_client_dest); } static Window event_get_window(XEvent *e) @@ -293,24 +293,40 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only) /* These are the ones we want.. */ - if (win == RootWindow(ob_display, ob_screen) && !in_client_only) { + if (win == RootWindow(ob_display, ob_screen)) { + /* If looking for a focus in on a client, then always return + FALSE for focus in's to the root window */ + if (in_client_only) + return FALSE; /* This means focus reverted off of a client */ - if (detail == NotifyPointerRoot || detail == NotifyDetailNone || - detail == NotifyInferior) + else if (detail == NotifyPointerRoot || + detail == NotifyDetailNone || + detail == NotifyInferior) return TRUE; else return FALSE; } + /* This means focus moved to the frame window */ + if (detail == NotifyInferior && !in_client_only) + return TRUE; + + /* It was on a client, was it a valid one? + It's possible to get a FocusIn event for a client that was managed + but has disappeared. Don't even parse those FocusIn events. + */ + { + ObWindow *w = g_hash_table_lookup(window_map, &e->xfocus.window); + if (!w || !WINDOW_IS_CLIENT(w)) + return FALSE; + } + /* This means focus moved from the root window to a client */ if (detail == NotifyVirtual) return TRUE; /* This means focus moved from one client to another */ if (detail == NotifyNonlinearVirtual) return TRUE; - /* This means focus moved to the frame window */ - if (detail == NotifyInferior && !in_client_only) - return TRUE; /* Otherwise.. */ return FALSE; @@ -344,12 +360,12 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only) } } -static Bool look_for_focusin(Display *d, XEvent *e, XPointer arg) +static Bool event_look_for_focusin(Display *d, XEvent *e, XPointer arg) { return e->type == FocusIn && wanted_focusevent(e, FALSE); } -static Bool look_for_focusin_client(Display *d, XEvent *e, XPointer arg) +Bool event_look_for_focusin_client(Display *d, XEvent *e, XPointer arg) { return e->type == FocusIn && wanted_focusevent(e, TRUE); } @@ -464,6 +480,7 @@ static void event_process(const XEvent *ec, gpointer data) e->xfocus.detail == NotifyInferior) { XEvent ce; + ob_debug_type(OB_DEBUG_FOCUS, "Focus went to pointer root/none or to our frame " "window\n"); @@ -481,7 +498,9 @@ static void event_process(const XEvent *ec, gpointer data) But if the other focus in is something like PointerRoot then we still want to fall back. */ - if (XCheckIfEvent(ob_display, &ce, look_for_focusin_client, NULL)){ + if (XCheckIfEvent(ob_display, &ce, event_look_for_focusin_client, + NULL)) + { XPutBackEvent(ob_display, &ce); ob_debug_type(OB_DEBUG_FOCUS, " but another FocusIn is coming\n"); @@ -500,7 +519,8 @@ static void event_process(const XEvent *ec, gpointer data) if (!focus_left_screen) focus_fallback(TRUE); } - } else if (client && client != focus_client) { + } + else if (client != focus_client) { focus_left_screen = FALSE; frame_adjust_focus(client->frame, TRUE); focus_set_client(client); @@ -512,7 +532,7 @@ static void event_process(const XEvent *ec, gpointer data) XEvent ce; /* Look for the followup FocusIn */ - if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) { + if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) { /* There is no FocusIn, this means focus went to a window that is not being managed, or a window on another screen. */ Window win, root; @@ -577,9 +597,6 @@ static void event_process(const XEvent *ec, gpointer data) ObClient *c = client_fake_manage(e->xclient.window); gulong vals[4]; - /* adjust the decorations so we know the sizes */ - frame_adjust_area(c->frame, FALSE, TRUE, TRUE); - /* set the frame extents on the window */ vals[0] = c->frame->size.left; vals[1] = c->frame->size.right; @@ -593,7 +610,7 @@ static void event_process(const XEvent *ec, gpointer data) } } else if (e->type == ConfigureRequest) { - /* unhandled config5Aure requests must be used to configure the + /* unhandled configure requests must be used to configure the window directly */ XWindowChanges xwc; @@ -663,7 +680,7 @@ static void event_handle_root(XEvent *e) if (d > 0) screen_set_num_desktops(d); } else if (msgtype == prop_atoms.net_showing_desktop) { - screen_show_desktop(e->xclient.data.l[0] != 0, TRUE); + screen_show_desktop(e->xclient.data.l[0] != 0, NULL); } else if (msgtype == prop_atoms.openbox_control) { if (e->xclient.data.l[0] == 1) ob_reconfigure(); @@ -953,70 +970,33 @@ static void event_handle_client(ObClient *client, XEvent *e) break; } case ConfigureRequest: + { /* dont compress these unless you're going to watch for property notifies in between (these can change what the configure would do to the window). also you can't compress stacking events */ - ob_debug("ConfigureRequest desktop %d wmstate %d vis %d\n", - screen_desktop, client->wmstate, client->frame->visible); + gint x, y, w, h; - /* don't allow clients to move shaded windows (fvwm does this) */ - if (client->shaded) { - e->xconfigurerequest.value_mask &= ~CWX; - e->xconfigurerequest.value_mask &= ~CWY; - } + /* if nothing is changed, then a configurenotify is needed */ + gboolean config = TRUE; - /* resize, then move, as specified in the EWMH section 7.7 */ - if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight | - CWX | CWY | - CWBorderWidth)) { - gint x, y, w, h; + x = client->area.x; + y = client->area.y; + w = client->area.width; + h = client->area.height; - if (e->xconfigurerequest.value_mask & CWBorderWidth) - client->border_width = e->xconfigurerequest.border_width; + ob_debug("ConfigureRequest desktop %d wmstate %d visibile %d\n", + screen_desktop, client->wmstate, client->frame->visible); - x = (e->xconfigurerequest.value_mask & CWX) ? - e->xconfigurerequest.x : client->area.x; - y = (e->xconfigurerequest.value_mask & CWY) ? - e->xconfigurerequest.y : client->area.y; - w = (e->xconfigurerequest.value_mask & CWWidth) ? - e->xconfigurerequest.width : client->area.width; - h = (e->xconfigurerequest.value_mask & CWHeight) ? - e->xconfigurerequest.height : client->area.height; - - ob_debug("ConfigureRequest x %d %d y %d %d\n", - e->xconfigurerequest.value_mask & CWX, x, - e->xconfigurerequest.value_mask & CWY, y); - - /* check for broken apps moving to their root position - - XXX remove this some day...that would be nice. right now all - kde apps do this when they try activate themselves on another - desktop. eg. open amarok window on desktop 1, switch to desktop - 2, click amarok tray icon. it will move by its decoration size. - */ - if (x != client->area.x && - x == (client->frame->area.x + client->frame->size.left - - (gint)client->border_width) && - y != client->area.y && - y == (client->frame->area.y + client->frame->size.top - - (gint)client->border_width)) - { - ob_debug_type(OB_DEBUG_APP_BUGS, - "Application %s is trying to move via " - "ConfigureRequest to it's root window position " - "but it is not using StaticGravity\n", - client->title); - /* don't move it */ - x = client->area.x; - y = client->area.y; + if (e->xconfigurerequest.value_mask & CWBorderWidth) + if (client->border_width != e->xconfigurerequest.border_width) { + client->border_width = e->xconfigurerequest.border_width; + /* if only the border width is changing, then it's not needed*/ + config = FALSE; } - client_find_onscreen(client, &x, &y, w, h, FALSE); - client_configure_full(client, x, y, w, h, FALSE, TRUE, TRUE); - } if (e->xconfigurerequest.value_mask & CWStackMode) { ObClient *sibling = NULL; @@ -1030,10 +1010,81 @@ static void event_handle_client(ObClient *client, XEvent *e) sibling = WINDOW_AS_CLIENT(win); } + /* activate it rather than just focus it */ stacking_restack_request(client, sibling, - e->xconfigurerequest.detail); + e->xconfigurerequest.detail, TRUE); + + /* if a stacking change is requested then it is needed */ + config = TRUE; + } + + /* don't allow clients to move shaded windows (fvwm does this) */ + if (client->shaded && (e->xconfigurerequest.value_mask & CWX || + e->xconfigurerequest.value_mask & CWY)) + { + e->xconfigurerequest.value_mask &= ~CWX; + e->xconfigurerequest.value_mask &= ~CWY; + + /* if the client tried to move and we aren't letting it then a + synthetic event is needed */ + config = TRUE; + } + + if (e->xconfigurerequest.value_mask & CWX || + e->xconfigurerequest.value_mask & CWY || + e->xconfigurerequest.value_mask & CWWidth || + e->xconfigurerequest.value_mask & CWHeight) + { + if (e->xconfigurerequest.value_mask & CWX) + x = e->xconfigurerequest.x; + if (e->xconfigurerequest.value_mask & CWY) + y = e->xconfigurerequest.y; + if (e->xconfigurerequest.value_mask & CWWidth) + w = e->xconfigurerequest.width; + if (e->xconfigurerequest.value_mask & CWHeight) + h = e->xconfigurerequest.height; + + /* if a new position or size is requested, then a configure is + needed */ + config = TRUE; + } + + ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d\n", + e->xconfigurerequest.value_mask & CWX, x, + e->xconfigurerequest.value_mask & CWY, y, + e->xconfigurerequest.value_mask & CWWidth, w, + e->xconfigurerequest.value_mask & CWHeight, h); + + /* check for broken apps moving to their root position + + XXX remove this some day...that would be nice. right now all + kde apps do this when they try activate themselves on another + desktop. eg. open amarok window on desktop 1, switch to desktop + 2, click amarok tray icon. it will move by its decoration size. + */ + if (x != client->area.x && + x == (client->frame->area.x + client->frame->size.left - + (gint)client->border_width) && + y != client->area.y && + y == (client->frame->area.y + client->frame->size.top - + (gint)client->border_width)) + { + ob_debug_type(OB_DEBUG_APP_BUGS, + "Application %s is trying to move via " + "ConfigureRequest to it's root window position " + "but it is not using StaticGravity\n", + client->title); + /* don't move it */ + x = client->area.x; + y = client->area.y; + } + + if (config) { + client_find_onscreen(client, &x, &y, w, h, FALSE); + client_configure_full(client, x, y, w, h, FALSE, TRUE); } break; + } case UnmapNotify: if (client->ignore_unmaps) { client->ignore_unmaps--; @@ -1236,12 +1287,21 @@ static void event_handle_client(ObClient *client, XEvent *e) e->xclient.data.l[2] == TopIf || e->xclient.data.l[2] == Opposite) { + /* just raise, don't activate */ stacking_restack_request(client, sibling, - e->xclient.data.l[2]); - } - ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_RESTACK_WINDOW sent " - "for window %s with invalid detail 0d\n", - client->title, e->xclient.data.l[2]); + e->xclient.data.l[2], FALSE); + /* send a synthetic ConfigureNotify, cuz this is supposed + to be like a ConfigureRequest. */ + client_configure_full(client, client->area.x, + client->area.y, + client->area.width, + client->area.height, + FALSE, TRUE); + } else + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s " + "with invalid detail %d\n", + client->title, e->xclient.data.l[2]); } } break; @@ -1551,6 +1611,7 @@ static gboolean event_handle_menu(XEvent *ev) { menu_frame_select(e->frame, NULL, FALSE); } + break; case MotionNotify: if ((e = menu_entry_frame_under(ev->xmotion.x_root, ev->xmotion.y_root)))