X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=bcf887f6ffbaf9d61b11f7bbeef2df705ae021a5;hb=171e476ba3faaa3dbd95e9e95f4121fae2db6564;hp=a4943f46fa0048a20af2271bddaa0e362cce6241;hpb=08269cefbce2fe600269c989f9a6a22a98641ba1;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index a4943f46..bcf887f6 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -139,6 +139,10 @@ void event_startup(gboolean reconfig) #endif client_add_destroy_notify(focus_delay_client_dest, NULL); + + /* get an initial time for event_curtime (mapping the initial windows needs + a timestamp) */ + event_curtime = event_get_server_time(); } void event_shutdown(gboolean reconfig) @@ -207,7 +211,7 @@ static Window event_get_window(XEvent *e) return window; } -static void event_set_curtime(XEvent *e) +static inline Time event_time(const XEvent *e) { Time t = CurrentTime; @@ -238,7 +242,7 @@ static void event_set_curtime(XEvent *e) if (obt_display_extension_sync && e->type == obt_display_extension_sync_basep + XSyncAlarmNotify) { - t = ((XSyncAlarmNotifyEvent*)e)->time; + t = ((const XSyncAlarmNotifyEvent*)e)->time; } #endif /* if more event types are anticipated, get their timestamp @@ -246,6 +250,20 @@ static void event_set_curtime(XEvent *e) break; } + return t; +} + +static void event_set_curtime(XEvent *e) +{ + Time t = event_time(e); + + if (t == CurrentTime) { + /* Some events don't come with timestamps :( + ...but we want the time anyways. */ + if (e->type == MapRequest) + t = event_get_server_time(); + } + /* watch that if we get an event earlier than the last specified user_time, which can happen if the clock goes backwards, we erase the last specified user_time */ @@ -638,7 +656,6 @@ static void event_process(const XEvent *ec, gpointer data) modifier map, and rebind all the key bindings as appropriate */ ob_debug("Keyboard map changed. Reloading keyboard bindings."); ob_set_state(OB_STATE_RECONFIGURING); - XRefreshKeyboardMapping(&e->xmapping); obt_keyboard_reload(); keyboard_rebind(); ob_set_state(OB_STATE_RUNNING); @@ -812,7 +829,7 @@ void event_enter_client(ObClient *client) obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func); - data = g_new(ObFocusDelayData, 1); + data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_curtime; data->serial = event_curserial; @@ -847,7 +864,7 @@ void event_leave_client(ObClient *client) obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); - data = g_new(ObFocusDelayData, 1); + data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_curtime; data->serial = event_curserial; @@ -1248,6 +1265,44 @@ static void event_handle_client(ObClient *client, XEvent *e) notify is sent or not */ } + /* check for broken apps (java swing) moving to 0,0 when there is a + strut there. + + XXX remove this some day...that would be nice. but really unexpected + from Sun Microsystems. + */ + if (x == 0 && y == 0 && client->gravity == NorthWestGravity && + client_normal(client)) + { + const Rect to = { x, y, w, h }; + + /* oldschool fullscreen windows are allowed */ + if (!client_is_oldfullscreen(client, &to)) { + Rect *r; + + r = screen_area(client->desktop, SCREEN_AREA_ALL_MONITORS, + NULL); + if (r->x || r->y) { + /* move the window only to the corner outside struts */ + x = r->x; + y = r->y; + + ob_debug_type(OB_DEBUG_APP_BUGS, + "Application %s is trying to move via " + "ConfigureRequest to 0,0 using " + "NorthWestGravity, while there is a " + "strut there. " + "Moving buggy app from (0,0) to (%d,%d)", + client->title, r->x, r->y); + } + + g_slice_free(Rect, r); + + /* they still requested a move, so don't change whether a + notify is sent or not */ + } + } + { gint lw, lh; @@ -1358,11 +1413,23 @@ static void event_handle_client(ObClient *client, XEvent *e) (e->xclient.data.l[0] == 2 ? "user" : "INVALID")))); /* XXX make use of data.l[2] !? */ if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) { - event_curtime = e->xclient.data.l[1]; + /* we can not trust the timestamp from applications. + e.g. chromium passes a very old timestamp. openbox thinks + the window will get focus and calls XSetInputFocus with the + (old) timestamp, which doesn't end up moving focus at all. + but the window is raised, not hilited, etc, as if it was + really going to get focus. + + so do not use this timestamp in event_curtime, as this would + be used in XSetInputFocus. + */ + /*event_curtime = e->xclient.data.l[1];*/ if (e->xclient.data.l[1] == 0) ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is" " missing a timestamp", client->title); + + event_curtime = event_get_server_time(); } else ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is " @@ -1573,8 +1640,11 @@ static void event_handle_client(ObClient *client, XEvent *e) } else if (msgtype == XA_WM_HINTS) { client_update_wmhints(client); } else if (msgtype == XA_WM_TRANSIENT_FOR) { - client_update_transient_for(client); + /* get the transient-ness first, as this affects if the client + decides to be transient for the group or not in + client_update_transient_for() */ client_get_type_and_transientness(client); + client_update_transient_for(client); /* type may have changed, so update the layer */ client_calc_layer(client); client_setup_decor_and_functions(client, TRUE); @@ -1777,20 +1847,20 @@ static gboolean event_handle_menu_input(XEvent *ev) /* Allow control while going thru the menu */ else if (ev->type == KeyPress && (mods & ~ControlMask) == 0) { gunichar unikey; + KeySym sym; frame->got_press = TRUE; frame->press_keycode = ev->xkey.keycode; frame->press_doexec = FALSE; - unikey = obt_keyboard_keypress_to_unichar(menu_frame_ic(frame), - &ev->xkey); + sym = obt_keyboard_keypress_to_keysym(ev); - if (ob_keycode_match(ev->xkey.keycode, OB_KEY_ESCAPE)) { + if (sym == XK_Escape) { menu_frame_hide_all(); ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_LEFT)) { + else if (sym == XK_Left) { /* Left goes to the parent menu */ if (frame->parent) { /* remove focus from the child */ @@ -1802,7 +1872,7 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_RIGHT)) { + else if (sym == XK_Right) { /* Right goes to the selected submenu */ if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { @@ -1813,28 +1883,37 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_UP)) { + else if (sym == XK_Up) { menu_frame_select_previous(frame); ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_DOWN)) { + else if (sym == XK_Down) { menu_frame_select_next(frame); ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_HOME)) { + else if (sym == XK_Home) { menu_frame_select_first(frame); ret = TRUE; } - else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_END)) { + else if (sym == XK_End) { menu_frame_select_last(frame); ret = TRUE; } + else if (sym == XK_Return || sym == XK_KP_Enter) { + frame->press_doexec = TRUE; + ret = TRUE; + } + /* keyboard accelerator shortcuts. (if it was a valid key) */ - else if (unikey) { + else if (frame->entries && + (unikey = + obt_keyboard_keypress_to_unichar(menu_frame_ic(frame), + ev))) + { GList *start; GList *it; ObMenuEntryFrame *found = NULL; @@ -1885,27 +1964,15 @@ static gboolean event_handle_menu_input(XEvent *ev) doesn't get sent to the focused application. Allow ControlMask only, and don't bother if the menu is empty */ - else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0 && - frame->entries && frame->got_press) - { - if (ob_keycode_match(ev->xkey.keycode, OB_KEY_RETURN)) { - /* Enter runs the active item or goes into the submenu. - Control-Enter runs it without closing the menu. */ - if (frame->child) - menu_frame_select_next(frame->child); - else if (frame->selected) - menu_entry_frame_execute(frame->selected, ev->xkey.state); - - ret = TRUE; - } - + else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0) { if (frame->press_keycode == ev->xkey.keycode && + frame->got_press && frame->press_doexec) { - if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) - menu_entry_frame_execute(frame->selected, ev->xkey.state); - else + if (frame->child) menu_frame_select_next(frame->child); + else if (frame->selected) + menu_entry_frame_execute(frame->selected, ev->xkey.state); } } } @@ -2001,7 +2068,7 @@ static gboolean event_handle_user_input(ObClient *client, XEvent *e) static void focus_delay_dest(gpointer data) { - g_free(data); + g_slice_free(ObFocusDelayData, data); } static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2) @@ -2063,7 +2130,7 @@ static void event_ignore_enter_range(gulong start, gulong end) g_assert(start != 0); g_assert(end != 0); - r = g_new(ObSerialRange, 1); + r = g_slice_new(ObSerialRange); r->start = start; r->end = end; ignore_serials = g_slist_prepend(ignore_serials, r); @@ -2098,7 +2165,7 @@ static gboolean is_enter_focus_event_ignored(gulong serial) if ((glong)(serial - r->end) > 0) { /* past the end */ ignore_serials = g_slist_delete_link(ignore_serials, it); - g_free(r); + g_slice_free(ObSerialRange, r); } else if ((glong)(serial - r->start) >= 0) return TRUE; @@ -2157,14 +2224,24 @@ gboolean event_time_after(guint32 t1, guint32 t2) return t1 >= t2 && t1 < (t2 + TIME_HALF); } +Bool find_timestamp(Display *d, XEvent *e, XPointer a) +{ + const Time t = event_time(e); + return t != CurrentTime; +} + Time event_get_server_time(void) { - /* Generate a timestamp */ XEvent event; + /* Generate a timestamp so there is guaranteed at least one in the queue + eventually */ XChangeProperty(obt_display, screen_support_win, OBT_PROP_ATOM(WM_CLASS), OBT_PROP_ATOM(STRING), 8, PropModeAppend, NULL, 0); - XWindowEvent(obt_display, screen_support_win, PropertyChangeMask, &event); + + /* Grab the first timestamp available */ + XPeekIfEvent(obt_display, &event, find_timestamp, NULL); + return event.xproperty.time; }