Instead of issuing draw commands immediately after we map or
reconfigure, wait for the server to send us an Expose event, thus making
sure our drawing doesn't get lost.

Signed-off-by: Daniel Stone <[email protected]>
---
 src/xwayland/window-manager.c |  218 +++++++++++++++++++++--------------------
 1 file changed, 112 insertions(+), 106 deletions(-)

diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 4d44527..3ceff63 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -99,7 +99,6 @@ struct weston_wm_window {
        struct weston_surface *surface;
        struct shell_surface *shsurf;
        struct wl_listener surface_destroy_listener;
-       struct wl_event_source *repaint_source;
        struct wl_event_source *configure_source;
        int properties_dirty;
        int pid;
@@ -118,9 +117,6 @@ struct weston_wm_window {
 static struct weston_wm_window *
 get_wm_window(struct weston_surface *surface);
 
-static void
-weston_wm_window_schedule_repaint(struct weston_wm_window *window);
-
 const char *
 get_atom_name(xcb_connection_t *c, xcb_atom_t atom)
 {
@@ -412,6 +408,81 @@ weston_wm_window_get_child_position(struct 
weston_wm_window *window,
 }
 
 static void
+weston_wm_window_draw_decoration(void *data)
+{
+       struct weston_wm_window *window = data;
+       struct weston_wm *wm = window->wm;
+       struct theme *t = wm->theme;
+       cairo_t *cr;
+       int x, y, width, height;
+       const char *title;
+       uint32_t flags = 0;
+       struct pixman_region32 region;
+
+       weston_wm_window_read_properties(window);
+
+       if (window->frame_id == XCB_WINDOW_NONE) {
+               if (window->surface != NULL) {
+                       pixman_region32_fini(&window->surface->pending.opaque);
+                       
pixman_region32_init_rect(&window->surface->pending.opaque,
+                                                 0, 0,
+                                                 window->width, 
window->height);
+                       window->surface->geometry.dirty = 1;
+                       weston_surface_schedule_repaint(window->surface);
+               }
+               return;
+       }
+
+       if (window->decorate) {
+               weston_wm_window_get_frame_size(window, &width, &height);
+               weston_wm_window_get_child_position(window, &x, &y);
+
+               cairo_xcb_surface_set_size(window->cairo_surface, width, 
height);
+
+               cr = cairo_create(window->cairo_surface);
+               if (wm->focus_window == window)
+                       flags |= THEME_FRAME_ACTIVE;
+
+               if (window->name)
+                       title = window->name;
+               else
+                       title = "untitled";
+
+               theme_render_frame(t, cr, width, height, title, flags);
+               cairo_destroy(cr);
+       }
+
+       xcb_flush(wm->conn);
+
+       if (!window->surface)
+               return;
+
+       /* We leave an extra pixel around the X window area to
+        * make sure we don't sample from the undefined alpha
+        * channel when filtering. */
+       pixman_region32_init_rect(&region, x - 1, y - 1,
+                                 window->width + 2,
+                                 window->height + 2);
+       if (!pixman_region32_equal(&region,
+                                  &window->surface->pending.opaque)) {
+               pixman_region32_copy(&window->surface->pending.opaque, &region);
+               pixman_region32_copy(&window->surface->opaque,
+                                    &window->surface->pending.opaque);
+               pixman_region32_fini(&window->surface->pending.input);
+               pixman_region32_init_rect(&window->surface->pending.input,
+                                         t->margin, t->margin,
+                                         width - 2 * t->margin,
+                                         height - 2 * t->margin);
+               pixman_region32_intersect_rect(&window->surface->pending.opaque,
+                                              &window->surface->pending.opaque,
+                                              x - 1, y - 1,
+                                              window->width + 2,
+                                              window->height + 2);
+       }
+       pixman_region32_fini(&region);
+}
+
+static void
 weston_wm_handle_configure_request(struct weston_wm *wm, xcb_generic_event_t 
*event)
 {
        xcb_configure_request_event_t *configure_request = 
@@ -458,7 +529,7 @@ weston_wm_handle_configure_request(struct weston_wm *wm, 
xcb_generic_event_t *ev
        mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
        xcb_configure_window(wm->conn, window->frame_id, mask, values);
 
-       weston_wm_window_schedule_repaint(window);
+       weston_wm_window_draw_decoration(window);
 }
 
 static void
@@ -509,9 +580,10 @@ static void
 weston_wm_window_activate(struct wl_listener *listener, void *data)
 {
        struct weston_surface *surface = data;
-       struct weston_wm_window *window = get_wm_window(surface);
        struct weston_wm *wm =
                container_of(listener, struct weston_wm, activate_listener);
+       struct weston_wm_window *window = get_wm_window(surface);
+       struct weston_wm_window *old_focus = wm->focus_window;
        xcb_client_message_event_t client_message;
 
        if (window) {
@@ -535,13 +607,16 @@ weston_wm_window_activate(struct wl_listener *listener, 
void *data)
                                     XCB_TIME_CURRENT_TIME);
        }
 
-       if (wm->focus_window)
-               weston_wm_window_schedule_repaint(wm->focus_window);
+       if (wm->focus_window == window)
+               return;
+
        wm->focus_window = window;
        if (window)
                wm->focus_latest = window;
        if (wm->focus_window)
-               weston_wm_window_schedule_repaint(wm->focus_window);
+               weston_wm_window_draw_decoration(wm->focus_window);
+       if (old_focus)
+               weston_wm_window_draw_decoration(old_focus);
 }
 
 static int
@@ -610,7 +685,8 @@ weston_wm_handle_map_request(struct weston_wm *wm, 
xcb_generic_event_t *event)
                XCB_EVENT_MASK_ENTER_WINDOW |
                XCB_EVENT_MASK_LEAVE_WINDOW |
                XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
-               XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+               XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
+               XCB_EVENT_MASK_EXPOSURE;
 
        window->frame_id = xcb_generate_id(wm->conn);
        xcb_create_window(wm->conn,
@@ -650,6 +726,7 @@ static void
 weston_wm_handle_map_notify(struct weston_wm *wm, xcb_generic_event_t *event)
 {
        xcb_map_notify_event_t *map_notify = (xcb_map_notify_event_t *) event;
+       struct weston_wm_window *window;
 
        if (our_resource(wm, map_notify->window)) {
                        weston_log("XCB_MAP_NOTIFY (window %d, ours)\n",
@@ -657,10 +734,27 @@ weston_wm_handle_map_notify(struct weston_wm *wm, 
xcb_generic_event_t *event)
                        return;
        }
 
+       window = hash_table_lookup(wm->window_hash, map_notify->window);
+       if (window && window->override_redirect)
+               weston_wm_window_draw_decoration(window);
+
        weston_log("XCB_MAP_NOTIFY (window %d)\n", map_notify->window);
 }
 
 static void
+weston_wm_handle_expose(struct weston_wm *wm, xcb_generic_event_t *event)
+{
+       xcb_expose_event_t *expose = (xcb_expose_event_t *) event;
+       struct weston_wm_window *window;
+
+       window = hash_table_lookup(wm->window_hash, expose->window);
+       if (window && expose->window == window->frame_id)
+               weston_wm_window_draw_decoration(window);
+
+       weston_log("XCB_EXPOSE (window %d)\n", expose->window);
+}
+
+static void
 weston_wm_handle_unmap_notify(struct weston_wm *wm, xcb_generic_event_t *event)
 {
        xcb_unmap_notify_event_t *unmap_notify =
@@ -681,8 +775,6 @@ weston_wm_handle_unmap_notify(struct weston_wm *wm, 
xcb_generic_event_t *event)
                return;
 
        window = hash_table_lookup(wm->window_hash, unmap_notify->window);
-       if (window->repaint_source)
-               wl_event_source_remove(window->repaint_source);
        if (window->cairo_surface)
                cairo_surface_destroy(window->cairo_surface);
 
@@ -702,97 +794,6 @@ weston_wm_handle_unmap_notify(struct weston_wm *wm, 
xcb_generic_event_t *event)
 }
 
 static void
-weston_wm_window_draw_decoration(void *data)
-{
-       struct weston_wm_window *window = data;
-       struct weston_wm *wm = window->wm;
-       struct theme *t = wm->theme;
-       cairo_t *cr;
-       int x, y, width, height;
-       const char *title;
-       uint32_t flags = 0;
-
-       weston_wm_window_read_properties(window);
-
-       window->repaint_source = NULL;
-
-       weston_wm_window_get_frame_size(window, &width, &height);
-       weston_wm_window_get_child_position(window, &x, &y);
-
-       cairo_xcb_surface_set_size(window->cairo_surface, width, height);
-       cr = cairo_create(window->cairo_surface);
-
-       if (window->decorate) {
-               if (wm->focus_window == window)
-                       flags |= THEME_FRAME_ACTIVE;
-
-               if (window->name)
-                       title = window->name;
-               else
-                       title = "untitled";
-
-               theme_render_frame(t, cr, width, height, title, flags);
-       } else {
-               cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-               cairo_set_source_rgba(cr, 0, 0, 0, 0);
-               cairo_paint(cr);
-
-               cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-               cairo_set_source_rgba(cr, 0, 0, 0, 0.45);
-               tile_mask(cr, t->shadow, 2, 2, width + 8, height + 8, 64, 64);
-       }
-
-       cairo_destroy(cr);
-
-       if (window->surface) {
-               pixman_region32_fini(&window->surface->opaque);
-               pixman_region32_init_rect(&window->surface->opaque, 0, 0,
-                                         width, height);
-
-               /* We leave an extra pixel around the X window area to
-                * make sure we don't sample from the undefined alpha
-                * channel when filtering. */
-               pixman_region32_intersect_rect(&window->surface->opaque,
-                                              &window->surface->opaque,
-                                              x - 1, y - 1,
-                                              window->width + 2,
-                                              window->height + 2);
-               window->surface->geometry.dirty = 1;
-
-               pixman_region32_init_rect(&window->surface->input,
-                                         t->margin, t->margin,
-                                         width - 2 * t->margin,
-                                         height - 2 * t->margin);
-       }
-}
-
-static void
-weston_wm_window_schedule_repaint(struct weston_wm_window *window)
-{
-       struct weston_wm *wm = window->wm;
-       int width, height;
-
-       if (window->frame_id == XCB_WINDOW_NONE) {
-               if (window->surface != NULL) {
-                       weston_wm_window_get_frame_size(window, &width, 
&height);
-                       pixman_region32_fini(&window->surface->opaque);
-                       pixman_region32_init_rect(&window->surface->opaque, 0, 
0,
-                                                 width, height);
-                       window->surface->geometry.dirty = 1;
-               }
-               return;
-       }
-
-       if (window->repaint_source)
-               return;
-
-       window->repaint_source =
-               wl_event_loop_add_idle(wm->server->loop,
-                                      weston_wm_window_draw_decoration,
-                                      window);
-}
-
-static void
 weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t 
*event)
 {
        xcb_property_notify_event_t *property_notify =
@@ -814,7 +815,7 @@ weston_wm_handle_property_notify(struct weston_wm *wm, 
xcb_generic_event_t *even
        if (window &&
            (property_notify->atom == wm->atom.net_wm_name ||
             property_notify->atom == XCB_ATOM_WM_NAME))
-               weston_wm_window_schedule_repaint(window);
+               weston_wm_window_draw_decoration(window);
 }
 
 static void
@@ -1240,6 +1241,11 @@ weston_wm_handle_event(int fd, uint32_t mask, void *data)
                case XCB_CLIENT_MESSAGE:
                        weston_wm_handle_client_message(wm, event);
                        break;
+               case XCB_EXPOSE:
+                       weston_wm_handle_expose(wm, event);
+                       break;
+               default:
+                       break;
                }
 
                free(event);
@@ -1580,7 +1586,7 @@ weston_wm_window_configure(void *data)
 
        window->configure_source = NULL;
 
-       weston_wm_window_schedule_repaint(window);
+       weston_wm_window_draw_decoration(window);
 }
 
 static void
@@ -1685,7 +1691,7 @@ xserver_set_window_id(struct wl_client *client, struct 
wl_resource *resource,
        wl_signal_add(&surface->resource.destroy_signal,
                      &window->surface_destroy_listener);
 
-       weston_wm_window_schedule_repaint(window);
+       weston_wm_window_draw_decoration(window);
        xserver_map_shell_surface(wm, window);
 }
 
-- 
1.7.10.4

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to