diff --git a/clients/image.c b/clients/image.c index 4e4074e0..77f5cf1a 100644 --- a/clients/image.c +++ b/clients/image.c @@ -48,9 +48,7 @@ struct image { uint32_t key; gboolean redraw_scheduled; - gboolean redraw_pending; - cairo_surface_t *surface; gchar *filename; }; @@ -149,8 +147,9 @@ image_draw(struct image *image) struct rectangle rectangle; GdkPixbuf *pb; cairo_t *cr; + cairo_surface_t *wsurface, *surface; - image->redraw_pending = 0; + image->redraw_scheduled = 0; window_draw(image->window); @@ -163,10 +162,13 @@ image_draw(struct image *image) if (pb == NULL) return; - image->surface = - window_create_surface(image->window, &rectangle); + wsurface = window_get_surface(image->window); + surface = cairo_surface_create_similar(wsurface, + CAIRO_CONTENT_COLOR_ALPHA, + rectangle.width, + rectangle.height); - cr = cairo_create(image->surface); + cr = cairo_create(surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_paint(cr); @@ -179,11 +181,9 @@ image_draw(struct image *image) g_object_unref(pb); - window_copy_surface(image->window, - &rectangle, - image->surface); - + window_copy_surface(image->window, &rectangle, surface); window_commit(image->window, image->key); + cairo_surface_destroy(surface); } static gboolean @@ -202,8 +202,6 @@ image_schedule_redraw(struct image *image) if (!image->redraw_scheduled) { image->redraw_scheduled = 1; g_idle_add(image_idle_redraw, image); - } else { - image->redraw_pending = 1; } } @@ -224,23 +222,6 @@ keyboard_focus_handler(struct window *window, image_schedule_redraw(image); } -static void -acknowledge_handler(struct window *window, - uint32_t key, uint32_t frame, void *data) -{ - struct image *image = data; - - if (image->key != key) - return; - - cairo_surface_destroy(image->surface); - image->redraw_scheduled = 0; - if (image->redraw_pending) { - image->redraw_pending = 0; - image_schedule_redraw(image); - } -} - static struct image * image_create(struct display *display, uint32_t key, const char *filename) { @@ -265,11 +246,9 @@ image_create(struct display *display, uint32_t key, const char *filename) /* FIXME: Window uses key 1 for moves, need some kind of * allocation scheme here. Or maybe just a real toolkit. */ image->key = key + 100; - image->redraw_scheduled = 1; window_set_resize_handler(image->window, resize_handler, image); window_set_keyboard_focus_handler(image->window, keyboard_focus_handler, image); - window_set_acknowledge_handler(image->window, acknowledge_handler, image); image_draw(image); diff --git a/clients/terminal.c b/clients/terminal.c index a16fdcbb..9718ac67 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -50,7 +50,7 @@ static int option_fullscreen; struct terminal { struct window *window; struct display *display; - int redraw_scheduled, redraw_pending; + int redraw_scheduled; char *data; int width, height, start, row, column; int fd, master; @@ -63,6 +63,7 @@ struct terminal { int fullscreen; int focused; struct color_scheme *color_scheme; + cairo_font_extents_t extents; }; static char * @@ -195,30 +196,21 @@ static void terminal_draw(struct terminal *terminal) { struct rectangle rectangle; - cairo_surface_t *surface; - cairo_font_extents_t extents; - cairo_t *cr; int32_t width, height; window_get_child_rectangle(terminal->window, &rectangle); - surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); - cr = cairo_create(surface); - cairo_select_font_face (cr, "mono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 14); - cairo_font_extents(cr, &extents); - cairo_destroy(cr); - cairo_surface_destroy(surface); - - width = (rectangle.width - 2 * terminal->margin) / (int32_t) extents.max_x_advance; - height = (rectangle.height - 2 * terminal->margin) / (int32_t) extents.height; + width = (rectangle.width - 2 * terminal->margin) / + (int32_t) terminal->extents.max_x_advance; + height = (rectangle.height - 2 * terminal->margin) / + (int32_t) terminal->extents.height; terminal_resize(terminal, width, height); if (!terminal->fullscreen) { - rectangle.width = terminal->width * extents.max_x_advance + 2 * terminal->margin; - rectangle.height = terminal->height * extents.height + 2 * terminal->margin; + rectangle.width = terminal->width * + terminal->extents.max_x_advance + 2 * terminal->margin; + rectangle.height = terminal->height * + terminal->extents.height + 2 * terminal->margin; window_set_child_size(terminal->window, &rectangle); } @@ -233,6 +225,7 @@ idle_redraw(void *data) struct terminal *terminal = data; terminal_draw(terminal); + terminal->redraw_scheduled = 0; return FALSE; } @@ -249,8 +242,6 @@ terminal_schedule_redraw(struct terminal *terminal) if (!terminal->redraw_scheduled) { g_idle_add(idle_redraw, terminal); terminal->redraw_scheduled = 1; - } else { - terminal->redraw_pending = 1; } } @@ -416,19 +407,6 @@ resize_handler(struct window *window, void *data) terminal_schedule_redraw(terminal); } -static void -acknowledge_handler(struct window *window, - uint32_t key, uint32_t frame, void *data) -{ - struct terminal *terminal = data; - - terminal->redraw_scheduled = 0; - if (terminal->redraw_pending) { - terminal->redraw_pending = 0; - terminal_schedule_redraw(terminal); - } -} - static void key_handler(struct window *window, uint32_t key, uint32_t unicode, uint32_t state, uint32_t modifiers, void *data) @@ -465,6 +443,8 @@ static struct terminal * terminal_create(struct display *display, int fullscreen) { struct terminal *terminal; + cairo_surface_t *surface; + cairo_t *cr; terminal = malloc(sizeof *terminal); if (terminal == NULL) @@ -476,17 +456,26 @@ terminal_create(struct display *display, int fullscreen) terminal->window = window_create(display, "Wayland Terminal", 500, 100, 500, 400); terminal->display = display; - terminal->redraw_scheduled = 1; terminal->margin = 5; window_set_fullscreen(terminal->window, terminal->fullscreen); window_set_resize_handler(terminal->window, resize_handler, terminal); - window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal); window_set_key_handler(terminal->window, key_handler, terminal); window_set_keyboard_focus_handler(terminal->window, keyboard_focus_handler, terminal); + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + cr = cairo_create(surface); + cairo_select_font_face (cr, "mono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 14); + cairo_font_extents(cr, &terminal->extents); + cairo_destroy(cr); + cairo_surface_destroy(surface); + + terminal_draw(terminal); return terminal; diff --git a/clients/view.c b/clients/view.c index b9d348b1..401960cf 100644 --- a/clients/view.c +++ b/clients/view.c @@ -52,9 +52,7 @@ struct view { uint32_t key; gboolean redraw_scheduled; - gboolean redraw_pending; - cairo_surface_t *surface; gchar *filename; PopplerDocument *document; int page; @@ -66,11 +64,12 @@ static void view_draw(struct view *view) { struct rectangle rectangle; + cairo_surface_t *surface; cairo_t *cr; PopplerPage *page; double width, height, doc_aspect, window_aspect, scale; - view->redraw_pending = 0; + view->redraw_scheduled = 0; window_draw(view->window); @@ -78,10 +77,13 @@ view_draw(struct view *view) page = poppler_document_get_page(view->document, view->page); - view->surface = - window_create_surface(view->window, &rectangle); + surface = window_get_surface(view->window); + + cr = cairo_create(surface); + cairo_rectangle(cr, rectangle.x, rectangle.y, + rectangle.width, rectangle.height); + cairo_clip(cr); - cr = cairo_create(view->surface); cairo_set_source_rgba(cr, 0, 0, 0, 0.8); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); @@ -92,6 +94,7 @@ view_draw(struct view *view) scale = rectangle.height / height; else scale = rectangle.width / width; + cairo_translate(cr, rectangle.x, rectangle.y); cairo_scale(cr, scale, scale); cairo_translate(cr, (rectangle.width - width * scale) / 2 / scale, @@ -104,10 +107,6 @@ view_draw(struct view *view) cairo_destroy(cr); g_object_unref(G_OBJECT(page)); - window_copy_surface(view->window, - &rectangle, - view->surface); - window_commit(view->window, 0); } @@ -127,8 +126,6 @@ view_schedule_redraw(struct view *view) if (!view->redraw_scheduled) { view->redraw_scheduled = 1; g_idle_add(view_idle_redraw, view); - } else { - view->redraw_pending = 1; } } @@ -173,23 +170,6 @@ resize_handler(struct window *window, void *data) view_schedule_redraw(view); } -static void -acknowledge_handler(struct window *window, - uint32_t key, uint32_t frame, void *data) -{ - struct view *view = data; - - if (view->key != key) - return; - - cairo_surface_destroy(view->surface); - view->redraw_scheduled = 0; - if (view->redraw_pending) { - view->redraw_pending = 0; - view_schedule_redraw(view); - } -} - static void keyboard_focus_handler(struct window *window, struct wl_input_device *device, void *data) @@ -232,7 +212,6 @@ view_create(struct display *display, uint32_t key, const char *filename) window_set_key_handler(view->window, key_handler, view); window_set_keyboard_focus_handler(view->window, keyboard_focus_handler, view); - window_set_acknowledge_handler(view->window, acknowledge_handler, view); view->document = poppler_document_new_from_file(view->filename, NULL, &error); diff --git a/clients/window.c b/clients/window.c index be6e7ea0..fab1638f 100644 --- a/clients/window.c +++ b/clients/window.c @@ -67,7 +67,7 @@ struct window { struct display *display; struct wl_surface *surface; const char *title; - struct rectangle allocation, saved_allocation; + struct rectangle allocation, saved_allocation, surface_allocation; int minimum_width, minimum_height; int margin; int drag_x, drag_y; @@ -81,7 +81,6 @@ struct window { EGLImageKHR *image; cairo_surface_t *cairo_surface, *pending_surface; - int new_surface; window_resize_handler_t resize_handler; window_key_handler_t key_handler; @@ -170,36 +169,39 @@ window_attach_surface(struct window *window) if (window->pending_surface != NULL) return; - window->pending_surface = - cairo_surface_reference(window->cairo_surface); + window->pending_surface = window->cairo_surface; + window->cairo_surface = NULL; - data = cairo_surface_get_user_data (window->cairo_surface, &surface_data_key); - eglExportDRMImageMESA(window->display->dpy, data->image, &name, NULL, &stride); + data = cairo_surface_get_user_data (window->pending_surface, + &surface_data_key); + eglExportDRMImageMESA(window->display->dpy, + data->image, &name, NULL, &stride); visual = wl_display_get_premultiplied_argb_visual(window->display->display); wl_surface_attach(window->surface, name, - window->allocation.width, - window->allocation.height, + window->surface_allocation.width, + window->surface_allocation.height, stride, visual); wl_surface_map(window->surface, - window->allocation.x - window->margin, - window->allocation.y - window->margin, - window->allocation.width, - window->allocation.height); + window->surface_allocation.x - window->margin, + window->surface_allocation.y - window->margin, + window->surface_allocation.width, + window->surface_allocation.height); + + wl_compositor_commit(window->display->compositor, 0); } void window_commit(struct window *window, uint32_t key) { - if (window->new_surface) { + if (window->cairo_surface) { window_attach_surface(window); - window->new_surface = 0; + } else { + wl_compositor_commit(window->display->compositor, key); } - - wl_compositor_commit(window->display->compositor, key); } static void @@ -214,6 +216,7 @@ window_draw_decorations(struct window *window) window->cairo_surface = window_create_surface(window, &window->allocation); + window->surface_allocation = window->allocation; outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1); bright = cairo_pattern_create_rgb(0.8, 0.8, 0.8); @@ -224,6 +227,11 @@ window_draw_decorations(struct window *window) width = window->allocation.width - window->margin * 2; height = window->allocation.height - window->margin * 2; + cairo_set_source_rgba(cr, 0, 0, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_translate(cr, window->margin + shadow_dx, window->margin + shadow_dy); cairo_set_line_width (cr, border); @@ -303,6 +311,7 @@ window_draw_fullscreen(struct window *window) { window->cairo_surface = window_create_surface(window, &window->allocation); + window->surface_allocation = window->allocation; } void @@ -315,8 +324,6 @@ window_draw(struct window *window) window_draw_fullscreen(window); else window_draw_decorations(window); - - window->new_surface = 1; } cairo_surface_t * @@ -804,11 +811,10 @@ display_handle_acknowledge(void *data, * window buffer if we resized and render the next frame into * our back buffer.. */ wl_list_for_each(window, &d->window_list, link) { - pending = window->pending_surface; + cairo_surface_destroy(window->pending_surface); window->pending_surface = NULL; - if (pending != window->cairo_surface) + if (window->cairo_surface) window_attach_surface(window); - cairo_surface_destroy(pending); if (window->acknowledge_handler) (*window->acknowledge_handler)(window, key, frame, window->user_data); }