Fix resizing
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 15 Jun 2010 03:22:15 +0000 (23:22 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 15 Jun 2010 03:22:15 +0000 (23:22 -0400)
clients/image.c
clients/terminal.c
clients/view.c
clients/window.c

index 4e4074e..77f5cf1 100644 (file)
@@ -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);
 
index a16fdcb..9718ac6 100644 (file)
@@ -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;
        }
 }
 
@@ -417,19 +408,6 @@ resize_handler(struct window *window, void *data)
 }
 
 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;
index b9d348b..401960c 100644 (file)
@@ -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;
        }
 }
 
@@ -174,23 +171,6 @@ resize_handler(struct window *window, void *data)
 }
 
 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);
index be6e7ea..fab1638 100644 (file)
@@ -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);
        }