X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=5e526d2342ac110f051371f5c6cc96d51b1e9ff5;hb=f6e423399dc0e1f57a7b31b39307039da6e616af;hp=f466234bc2e25b235214ed8c63f14cc13c7472c3;hpb=4f93731cdbecbf43b82aa000c07ec8b40f97dd03;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index f466234b..5e526d23 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -97,10 +97,15 @@ static gboolean focus_delay_func(gpointer data); static gboolean unfocus_delay_func(gpointer data); static void focus_delay_client_dest(ObClient *client, gpointer data); -Time event_curtime = CurrentTime; -Time event_last_user_time = CurrentTime; -/*! The serial of the current X event */ +Time event_last_user_time; + +/*! The time of the current X event (if it had a timestamp) */ +static Time event_curtime; +/*! The source time that started the current X event (user-provided, so not + to be trusted) */ +static Time event_sourcetime; +/*! The serial of the current X event */ static gulong event_curserial; static gboolean focus_left_screen = FALSE; /*! A list of ObSerialRanges which are to be ignored for mouse enter events */ @@ -139,6 +144,10 @@ void event_startup(gboolean reconfig) #endif client_add_destroy_notify(focus_delay_client_dest, NULL); + + event_curtime = CurrentTime; + event_sourcetime = CurrentTime; + event_last_user_time = CurrentTime; } void event_shutdown(gboolean reconfig) @@ -207,7 +216,7 @@ static Window event_get_window(XEvent *e) return window; } -static void event_set_curtime(XEvent *e) +static inline Time event_get_timestamp(const XEvent *e) { Time t = CurrentTime; @@ -238,7 +247,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,12 +255,20 @@ static void event_set_curtime(XEvent *e) break; } + return t; +} + +static void event_set_curtime(XEvent *e) +{ + Time t = event_get_timestamp(e); + /* 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 */ if (t && event_last_user_time && event_time_after(event_last_user_time, t)) event_last_user_time = CurrentTime; + event_sourcetime = CurrentTime; event_curtime = t; } @@ -729,7 +746,7 @@ static void event_process(const XEvent *ec, gpointer data) /* if something happens and it's not from an XEvent, then we don't know the time */ - event_curtime = CurrentTime; + event_curtime = event_sourcetime = CurrentTime; event_curserial = 0; } @@ -750,11 +767,12 @@ static void event_handle_root(XEvent *e) if (msgtype == OBT_PROP_ATOM(NET_CURRENT_DESKTOP)) { guint d = e->xclient.data.l[0]; if (d < screen_num_desktops) { - event_curtime = e->xclient.data.l[1]; - if (event_curtime == 0) + if (e->xclient.data.l[1] == 0) ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_CURRENT_DESKTOP message is missing " "a timestamp"); + else + event_sourcetime = e->xclient.data.l[1]; screen_set_desktop(d, TRUE); } } else if (msgtype == OBT_PROP_ATOM(NET_NUMBER_OF_DESKTOPS)) { @@ -813,7 +831,7 @@ void event_enter_client(ObClient *client) data = g_slice_new(ObFocusDelayData); data->client = client; - data->time = event_curtime; + data->time = event_time(); data->serial = event_curserial; obt_main_loop_timeout_add(ob_main_loop, @@ -823,7 +841,7 @@ void event_enter_client(ObClient *client) } else { ObFocusDelayData data; data.client = client; - data.time = event_curtime; + data.time = event_time(); data.serial = event_curserial; focus_delay_func(&data); } @@ -848,7 +866,7 @@ void event_leave_client(ObClient *client) data = g_slice_new(ObFocusDelayData); data->client = client; - data->time = event_curtime; + data->time = event_time(); data->serial = event_curserial; obt_main_loop_timeout_add(ob_main_loop, @@ -858,7 +876,7 @@ void event_leave_client(ObClient *client) } else { ObFocusDelayData data; data.client = client; - data.time = event_curtime; + data.time = event_time(); data.serial = event_curserial; unfocus_delay_func(&data); } @@ -1247,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; @@ -1296,10 +1352,6 @@ static void event_handle_client(ObClient *client, XEvent *e) to an already unmapped window. */ - /* we don't want the reparent event, put it back on the stack for the - X server to deal with after we unmanage the window */ - XPutBackEvent(obt_display, e); - ob_debug("ReparentNotify for window 0x%x", client->window); client_unmanage(client); break; @@ -1357,7 +1409,17 @@ 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_sourcetime = 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" @@ -1572,8 +1634,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); @@ -1832,7 +1897,7 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (sym == XK_Return) { + else if (sym == XK_Return || sym == XK_KP_Enter) { frame->press_doexec = TRUE; ret = TRUE; } @@ -2009,7 +2074,7 @@ static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2) static gboolean focus_delay_func(gpointer data) { ObFocusDelayData *d = data; - Time old = event_curtime; + Time old = event_curtime; /* save the curtime */ event_curtime = d->time; event_curserial = d->serial; @@ -2022,7 +2087,7 @@ static gboolean focus_delay_func(gpointer data) static gboolean unfocus_delay_func(gpointer data) { ObFocusDelayData *d = data; - Time old = event_curtime; + Time old = event_curtime; /* save the curtime */ event_curtime = d->time; event_curserial = d->serial; @@ -2153,14 +2218,35 @@ gboolean event_time_after(guint32 t1, guint32 t2) return t1 >= t2 && t1 < (t2 + TIME_HALF); } -Time event_get_server_time(void) +Bool find_timestamp(Display *d, XEvent *e, XPointer a) +{ + const Time t = event_get_timestamp(e); + return t != CurrentTime; +} + +Time event_time(void) { - /* Generate a timestamp */ XEvent event; + if (event_curtime) return event_curtime; + + /* Some events don't come with timestamps :( + ...but we can get one anyways >:) */ + + /* 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); - return event.xproperty.time; + + /* Grab the first timestamp available */ + XPeekIfEvent(obt_display, &event, find_timestamp, NULL); + + /* Save the time so we don't have to do this again for this event */ + return event_curtime = event.xproperty.time; +} + +Time event_source_time(void) +{ + return event_sourcetime; }