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(®ion, x - 1, y - 1, + window->width + 2, + window->height + 2); + if (!pixman_region32_equal(®ion, + &window->surface->pending.opaque)) { + pixman_region32_copy(&window->surface->pending.opaque, ®ion); + 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(®ion); +} + +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
