window: Workaround a stuck frame callback on the cursor surface
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Mon, 16 Jul 2012 11:15:49 +0000 (14:15 +0300)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 16 Jul 2012 17:35:25 +0000 (13:35 -0400)
It is possible that a client loses the focus between receiving a
pointer.enter event and sending a pointer.set_cursor request. In that
case, the cursor surface might not be mapped and the frame callback
requested on it will never trigger.

Work around this by trying to remap the cursor surface whenever there
is a frame callback and the serial for the enter event is higher than
the cursor serial.

clients/window.c

index ab9d155..93299e1 100644 (file)
@@ -2437,14 +2437,27 @@ static const struct wl_callback_listener pointer_surface_listener = {
 void
 input_set_pointer_image(struct input *input, int pointer)
 {
-       if (pointer == input->current_cursor &&
-           input->pointer_enter_serial == input->cursor_serial)
+       int force = 0;
+
+       if (input->pointer_enter_serial > input->cursor_serial)
+               force = 1;
+
+       if (!force && pointer == input->current_cursor)
                return;
 
        input->current_cursor = pointer;
        input->cursor_serial = input->pointer_enter_serial;
        if (!input->cursor_frame_cb)
                pointer_surface_frame_callback(input, NULL, 0);
+       else if (force) {
+               /* The current frame callback may be stuck if, for instance,
+                * the set cursor request was processed by the server after
+                * this client lost the focus. In this case the cursor surface
+                * might not be mapped and the frame callback wouldn't ever
+                * complete. Send a set_cursor and attach to try to map the
+                * cursor surface again so that the callback will finish */
+               input_set_pointer_image_index(input, 0);
+       }
 }
 
 struct wl_data_device *