event_curtime is replaced (publicly) by event_time()
authorDana Jansens <danakj@orodu.net>
Sat, 17 Apr 2010 02:23:37 +0000 (22:23 -0400)
committerDana Jansens <danakj@orodu.net>
Sat, 17 Apr 2010 02:23:37 +0000 (22:23 -0400)
This function never returns CurrentTime, which is nice, cuz using CurrentTime for XSetFocus always sucks.

If the current XEvent did not have a timestamp, then event_time() will find one.  It finds the first timestamp available in the X event queue, meaning the earliest timestamp >= the current (nontimestamped) event. All future events should have a timestamp >= event_time(), so using this in XSetFocus() should not mess up any future calls we make to it.

This change seems to work well, as it appears to fix bug #3648.

openbox/client.c
openbox/event.c
openbox/event.h
openbox/focus.c
openbox/grab.c
openbox/mouse.c
openbox/moveresize.c
openbox/prompt.c
openbox/screen.c
openbox/startupnotify.c

index 3399b50..605a191 100644 (file)
@@ -209,9 +209,6 @@ void client_manage(Window window, ObPrompt *prompt)
 
     ob_debug("Managing window: 0x%lx", window);
 
-    /* we want to always have a valid time when the window is mapping */
-    g_assert(event_curtime != CurrentTime);
-
     /* choose the events we want to receive on the CLIENT window
        (ObPrompt windows can request events too) */
     attrib_set.event_mask = CLIENT_EVENTMASK |
@@ -273,7 +270,7 @@ void client_manage(Window window, ObPrompt *prompt)
     launch_time = sn_app_started(self->startup_id, self->class, self->name);
 
     if (!OBT_PROP_GET32(self->window, NET_WM_USER_TIME, CARDINAL, &user_time))
-        user_time = event_curtime;
+        user_time = event_time();
 
     /* do this after we have a frame.. it uses the frame to help determine the
        WM_STATE to apply. */
@@ -442,7 +439,7 @@ void client_manage(Window window, ObPrompt *prompt)
     ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s",
                   activate ? "yes" : "no");
     if (activate) {
-        activate = client_can_steal_focus(self, event_curtime, launch_time);
+        activate = client_can_steal_focus(self, event_time(), launch_time);
 
         if (!activate) {
             /* if the client isn't stealing focus, then hilite it so the user
@@ -3400,7 +3397,7 @@ void client_close(ObClient *self)
     else {
         /* request the client to close with WM_DELETE_WINDOW */
         OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS,
-                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime,
+                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_time(),
                         0, 0, 0, NoEventMask);
 
         /* we're trying to close the window, so see if it is responding. if it
@@ -3854,7 +3851,7 @@ gboolean client_focus(ObClient *self)
 
     ob_debug_type(OB_DEBUG_FOCUS,
                   "Focusing client \"%s\" (0x%x) at time %u",
-                  self->title, self->window, event_curtime);
+                  self->title, self->window, event_time());
 
     /* if using focus_delay, stop the timer now so that focus doesn't
        go moving on us */
@@ -3866,7 +3863,7 @@ gboolean client_focus(ObClient *self)
         /* This can cause a BadMatch error with CurrentTime, or if an app
            passed in a bad time for _NET_WM_ACTIVE_WINDOW. */
         XSetInputFocus(obt_display, self->window, RevertToPointerRoot,
-                       event_curtime);
+                       event_time());
     }
 
     if (self->focus_notify) {
@@ -3877,7 +3874,7 @@ gboolean client_focus(ObClient *self)
         ce.xclient.window = self->window;
         ce.xclient.format = 32;
         ce.xclient.data.l[0] = OBT_PROP_ATOM(WM_TAKE_FOCUS);
-        ce.xclient.data.l[1] = event_curtime;
+        ce.xclient.data.l[1] = event_time();
         ce.xclient.data.l[2] = 0l;
         ce.xclient.data.l[3] = 0l;
         ce.xclient.data.l[4] = 0l;
@@ -3925,7 +3922,7 @@ void client_activate(ObClient *self, gboolean desktop,
     if ((user && (desktop ||
                   self->desktop == DESKTOP_ALL ||
                   self->desktop == screen_desktop)) ||
-        client_can_steal_focus(self, event_curtime, CurrentTime))
+        client_can_steal_focus(self, event_time(), CurrentTime))
     {
         client_present(self, here, raise, unshade);
     }
index bcf887f..02e9dcd 100644 (file)
@@ -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 */
@@ -140,9 +145,9 @@ void event_startup(gboolean reconfig)
 
     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();
+    event_curtime = CurrentTime;
+    event_sourcetime = CurrentTime;
+    event_last_user_time = CurrentTime;
 }
 
 void event_shutdown(gboolean reconfig)
@@ -211,7 +216,7 @@ static Window event_get_window(XEvent *e)
     return window;
 }
 
-static inline Time event_time(const XEvent *e)
+static inline Time event_get_timestamp(const XEvent *e)
 {
     Time t = CurrentTime;
 
@@ -255,14 +260,7 @@ static inline Time event_time(const XEvent *e)
 
 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();
-    }
+    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
@@ -270,6 +268,7 @@ static void event_set_curtime(XEvent *e)
     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;
 }
 
@@ -747,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;
 }
 
@@ -768,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)) {
@@ -831,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,
@@ -841,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);
         }
@@ -866,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,
@@ -876,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);
         }
@@ -1423,13 +1423,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
                    so do not use this timestamp in event_curtime, as this would
                    be used in XSetInputFocus.
                 */
-                /*event_curtime = e->xclient.data.l[1];*/
+                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"
                                   " 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 "
@@ -2080,7 +2078,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;
@@ -2093,7 +2091,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;
@@ -2226,14 +2224,19 @@ gboolean event_time_after(guint32 t1, guint32 t2)
 
 Bool find_timestamp(Display *d, XEvent *e, XPointer a)
 {
-    const Time t = event_time(e);
+    const Time t = event_get_timestamp(e);
     return t != CurrentTime;
 }
 
-Time event_get_server_time(void)
+Time event_time(void)
 {
     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,
@@ -2243,5 +2246,11 @@ Time event_get_server_time(void)
     /* Grab the first timestamp available */
     XPeekIfEvent(obt_display, &event, find_timestamp, NULL);
 
-    return event.xproperty.time;
+    /* 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;
 }
index 4a8d790..8a2a4cb 100644 (file)
@@ -28,8 +28,6 @@ struct _ObClient;
     to determine if the user is working in another window */
 #define OB_EVENT_USER_TIME_DELAY (500) /* 0.5 seconds */
 
-/*! Time at which the last event with a timestamp occured. */
-extern Time event_curtime;
 /*! The last user-interaction time, as given by the clients */
 extern Time event_last_user_time;
 
@@ -66,6 +64,14 @@ void event_halt_focus_delay(void);
     comes at the same time or later than t2. */
 gboolean event_time_after(guint32 t1, guint32 t2);
 
-Time event_get_server_time(void);
+/*! Time at which the current event occured.  If this is not known, this
+  is a time at or after it, but at or before any other events we will process
+*/
+Time event_time(void);
+/*! A time at which an event happened that caused this current event to be
+  generated.  This is a user-provided time and not to be trusted.
+  Returns CurrentTime if there was no source time provided.
+ */
+Time event_source_time(void);
 
 #endif
index d86f1c0..8c02361 100644 (file)
@@ -194,7 +194,7 @@ void focus_nothing(void)
 
     /* when nothing will be focused, send focus to the backup target */
     XSetInputFocus(obt_display, screen_support_win, RevertToPointerRoot,
-                   event_curtime);
+                   event_time());
 }
 
 void focus_order_add_new(ObClient *c)
index f82592f..4518c43 100644 (file)
@@ -44,7 +44,7 @@ static ObtIC *ic = NULL;
 
 static Time ungrab_time(void)
 {
-    Time t = event_curtime;
+    Time t = event_time();
     if (grab_time == CurrentTime ||
         !(t == CurrentTime || event_time_after(t, grab_time)))
         /* When the time moves backward on the server, then we can't use
@@ -87,12 +87,12 @@ gboolean grab_keyboard_full(gboolean grab)
         if (kgrabs++ == 0) {
             ret = XGrabKeyboard(obt_display, grab_window(),
                                 False, GrabModeAsync, GrabModeAsync,
-                                event_curtime) == Success;
+                                event_time()) == Success;
             if (!ret)
                 --kgrabs;
             else {
                 passive_count = 0;
-                grab_time = event_curtime;
+                grab_time = event_time();
             }
         } else
             ret = TRUE;
@@ -117,11 +117,11 @@ gboolean grab_pointer_full(gboolean grab, gboolean owner_events,
                                GRAB_PTR_MASK,
                                GrabModeAsync, GrabModeAsync,
                                (confine ? obt_root(ob_screen) : None),
-                               ob_cursor(cur), event_curtime) == Success;
+                               ob_cursor(cur), event_time()) == Success;
             if (!ret)
                 --pgrabs;
             else
-                grab_time = event_curtime;
+                grab_time = event_time();
         } else
             ret = TRUE;
     } else if (pgrabs > 0) {
@@ -238,7 +238,7 @@ void ungrab_passive_key(void)
     /*ob_debug("ungrabbing %d passive grabs\n", passive_count);*/
     if (passive_count) {
         /* kill our passive grab */
-        XUngrabKeyboard(obt_display, event_curtime);
+        XUngrabKeyboard(obt_display, event_time());
         passive_count = 0;
     }
 }
index a7601f6..2f8604e 100644 (file)
@@ -200,7 +200,7 @@ void mouse_replay_pointer(void)
 {
     if (replay_pointer_needed) {
         /* replay the pointer event before any windows move */
-        XAllowEvents(obt_display, ReplayPointer, event_curtime);
+        XAllowEvents(obt_display, ReplayPointer, event_time());
         replay_pointer_needed = FALSE;
     }
 }
index aa1957a..cb0d210 100644 (file)
@@ -388,7 +388,7 @@ static void do_resize(void)
             ce.xclient.window = moveresize_client->window;
             ce.xclient.format = 32;
             ce.xclient.data.l[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST);
-            ce.xclient.data.l[1] = event_curtime;
+            ce.xclient.data.l[1] = event_time();
             ce.xclient.data.l[2] = XSyncValueLow32(val);
             ce.xclient.data.l[3] = XSyncValueHigh32(val);
             ce.xclient.data.l[4] = 0l;
index 50d0903..77398c5 100644 (file)
@@ -462,7 +462,7 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal)
         /* activate the prompt */
         OBT_PROP_MSG(ob_screen, self->super.window, NET_ACTIVE_WINDOW,
                      1, /* from an application.. */
-                     event_curtime,
+                     event_time(),
                      0,
                      0, 0);
         return;
index e939b01..2ff950a 100644 (file)
@@ -116,7 +116,7 @@ static gboolean replace_wm(void)
             current_wm_sn_owner = None;
     }
 
-    timestamp = event_get_server_time();
+    timestamp = event_time();
 
     XSetSelectionOwner(obt_display, wm_sn_atom, screen_support_win,
                        timestamp);
@@ -731,8 +731,8 @@ void screen_set_desktop(guint num, gboolean dofocus)
 
     event_end_ignore_all_enters(ignore_start);
 
-    if (event_curtime != CurrentTime)
-        screen_desktop_user_time = event_curtime;
+    if (event_source_time() != CurrentTime)
+        screen_desktop_user_time = event_source_time();
 }
 
 void screen_add_desktop(gboolean current)
index aa6db7e..c300d57 100644 (file)
@@ -255,7 +255,7 @@ void sn_setup_spawn_environment(const gchar *program, const gchar *name,
     if (desktop >= 0 && (unsigned) desktop < screen_num_desktops)
         sn_launcher_context_set_workspace(sn_launcher, (signed) desktop);
     sn_launcher_context_initiate(sn_launcher, "openbox", program,
-                                 event_curtime);
+                                 event_time());
     id = sn_launcher_context_get_startup_id(sn_launcher);
 
     /* 20 second timeout for apps to start */