Fix terminal resizing
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 11 Jan 2011 15:00:52 +0000 (10:00 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 11 Jan 2011 15:00:52 +0000 (10:00 -0500)
Get snapping to character grid working again, avoid crashes when attempting
to resize below 1x1 character cell, only redraw when size actually changes.

Also, rename window_get_child_rectangle() to window_get_child_allocation().

clients/dnd.c
clients/gears.c
clients/image.c
clients/resizor.c
clients/terminal.c
clients/view.c
clients/window.c
clients/window.h

index b7f9f39..feea336 100644 (file)
@@ -169,20 +169,20 @@ item_create(struct display *display, int x, int y, int seed)
 static void
 dnd_draw(struct dnd *dnd)
 {
-       struct rectangle rectangle;
+       struct rectangle allocation;
        cairo_t *cr;
        cairo_surface_t *wsurface, *surface;
        int i;
 
        window_draw(dnd->window);
 
-       window_get_child_rectangle(dnd->window, &rectangle);
+       window_get_child_allocation(dnd->window, &allocation);
 
        wsurface = window_get_surface(dnd->window);
        surface = cairo_surface_create_similar(wsurface,
                                               CAIRO_CONTENT_COLOR_ALPHA,
-                                              rectangle.width,
-                                              rectangle.height);
+                                              allocation.width,
+                                              allocation.height);
        cairo_surface_destroy(wsurface);
 
        cr = cairo_create(surface);
@@ -201,7 +201,7 @@ dnd_draw(struct dnd *dnd)
 
        cairo_destroy(cr);
 
-       window_copy_surface(dnd->window, &rectangle, surface);
+       window_copy_surface(dnd->window, &allocation, surface);
        cairo_surface_destroy(surface);
        window_flush(dnd->window);
 }
@@ -251,13 +251,13 @@ static struct item *
 dnd_get_item(struct dnd *dnd, int32_t x, int32_t y)
 {
        struct item *item;
-       struct rectangle rectangle;
+       struct rectangle allocation;
        int i;
 
-       window_get_child_rectangle(dnd->window, &rectangle);
+       window_get_child_allocation(dnd->window, &allocation);
 
-       x -= rectangle.x;
-       y -= rectangle.y;
+       x -= allocation.x;
+       y -= allocation.y;
 
        for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
                item = dnd->items[i];
@@ -559,16 +559,16 @@ dnd_button_handler(struct window *window,
        struct dnd *dnd = data;
        int32_t x, y;
        struct item *item;
-       struct rectangle rectangle;
+       struct rectangle allocation;
        struct dnd_drag *dnd_drag;
        struct wl_drag *drag;
        int i;
 
-       window_get_child_rectangle(dnd->window, &rectangle);
+       window_get_child_allocation(dnd->window, &allocation);
        input_get_position(input, &x, &y);
        item = dnd_get_item(dnd, x, y);
-       x -= rectangle.x;
-       y -= rectangle.y;
+       x -= allocation.x;
+       y -= allocation.y;
 
        if (item && state == 1) {
                fprintf(stderr, "start drag, item %p\n", item);
@@ -624,7 +624,7 @@ dnd_create(struct display *display)
        struct dnd *dnd;
        gchar *title;
        int i, x, y;
-       struct rectangle rectangle;
+       int32_t width, height;
 
        dnd = malloc(sizeof *dnd);
        if (dnd == NULL)
@@ -656,9 +656,9 @@ dnd_create(struct display *display)
        window_set_motion_handler(dnd->window,
                                  dnd_motion_handler);
 
-       rectangle.width = 4 * (item_width + item_padding) + item_padding;
-       rectangle.height = 4 * (item_height + item_padding) + item_padding;
-       window_set_child_size(dnd->window, &rectangle);
+       width = 4 * (item_width + item_padding) + item_padding;
+       height = 4 * (item_height + item_padding) + item_padding;
+       window_set_child_size(dnd->window, width, height);
 
        dnd_draw(dnd);
 
index a080741..b8e6cca 100644 (file)
@@ -49,7 +49,6 @@ struct gears {
        struct window *window;
 
        struct display *d;
-       struct rectangle rectangle;
 
        EGLDisplay display;
        EGLContext context;
@@ -208,19 +207,8 @@ static void
 allocate_buffer(struct gears *gears)
 {
        EGLImageKHR image;
+       struct rectangle allocation;
 
-       /* Constrain child size to be square and at least 300x300 */
-       window_get_child_rectangle(gears->window, &gears->rectangle);
-       if (gears->rectangle.width > gears->rectangle.height)
-               gears->rectangle.height = gears->rectangle.width;
-       else
-               gears->rectangle.width = gears->rectangle.height;
-       if (gears->rectangle.width < 300) {
-               gears->rectangle.width = 300;
-               gears->rectangle.height = 300;
-       }
-
-       window_set_child_size(gears->window, &gears->rectangle);
        window_draw(gears->window);
 
        gears->surface[gears->current] = window_get_surface(gears->window);
@@ -239,16 +227,18 @@ allocate_buffer(struct gears *gears)
        glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
 
        glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo);
+       window_get_child_allocation(gears->window, &allocation);
        glRenderbufferStorage(GL_RENDERBUFFER_EXT,
                              GL_DEPTH_COMPONENT,
-                             gears->rectangle.width + 20 + 32,
-                             gears->rectangle.height + 60 + 32);
+                             allocation.width + 20 + 32,
+                             allocation.height + 60 + 32);
 }
 
 static void
 draw_gears(struct gears *gears)
 {
        GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+       struct rectangle allocation;
 
        if (gears->surface[gears->current] == NULL)
                allocate_buffer(gears);
@@ -258,10 +248,11 @@ draw_gears(struct gears *gears)
                                  GL_RENDERBUFFER_EXT,
                                  gears->color_rbo[gears->current]);
 
-       glViewport(gears->rectangle.x, gears->rectangle.y,
-                  gears->rectangle.width, gears->rectangle.height);
-       glScissor(gears->rectangle.x, gears->rectangle.y,
-                  gears->rectangle.width, gears->rectangle.height);
+       window_get_child_allocation(gears->window, &allocation);
+       glViewport(allocation.x, allocation.y,
+                  allocation.width, allocation.height);
+       glScissor(allocation.x, allocation.y,
+                  allocation.width, allocation.height);
 
        glEnable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -301,7 +292,8 @@ draw_gears(struct gears *gears)
 }
 
 static void
-resize_handler(struct window *window, void *data)
+resize_handler(struct window *window,
+              int32_t width, int32_t height, void *data)
 {
        struct gears *gears = data;
 
@@ -309,6 +301,18 @@ resize_handler(struct window *window, void *data)
        gears->surface[0] = NULL;
        cairo_surface_destroy(gears->surface[1]);
        gears->surface[1] = NULL;
+
+       /* Constrain child size to be square and at least 300x300 */
+       if (width > height)
+               height = width;
+       else
+               width = height;
+       if (width < 300) {
+               width = 300;
+               height = 300;
+       }
+
+       window_set_child_size(gears->window, width, height);
 }
 
 static void
@@ -316,8 +320,10 @@ keyboard_focus_handler(struct window *window,
                       struct input *device, void *data)
 {
        struct gears *gears = data;
+       struct rectangle allocation;
 
-       resize_handler(window, gears);
+       window_get_child_allocation(gears->window, &allocation);
+       resize_handler(window, allocation.width, allocation.height, gears);
 }
 
 static void
index f9bbeb2..61d8b25 100644 (file)
@@ -137,18 +137,18 @@ set_source_pixbuf(cairo_t         *cr,
 static void
 image_draw(struct image *image)
 {
-       struct rectangle rectangle;
+       struct rectangle allocation;
        GdkPixbuf *pb;
        cairo_t *cr;
        cairo_surface_t *wsurface, *surface;
 
        window_draw(image->window);
 
-       window_get_child_rectangle(image->window, &rectangle);
+       window_get_child_allocation(image->window, &allocation);
 
        pb = gdk_pixbuf_new_from_file_at_size(image->filename,
-                                             rectangle.width,
-                                             rectangle.height,
+                                             allocation.width,
+                                             allocation.height,
                                              NULL);
        if (pb == NULL)
                return;
@@ -156,8 +156,8 @@ image_draw(struct image *image)
        wsurface = window_get_surface(image->window);
        surface = cairo_surface_create_similar(wsurface,
                                               CAIRO_CONTENT_COLOR_ALPHA,
-                                              rectangle.width,
-                                              rectangle.height);
+                                              allocation.width,
+                                              allocation.height);
 
        cairo_surface_destroy(wsurface);
        cr = cairo_create(surface);
@@ -166,14 +166,14 @@ image_draw(struct image *image)
        cairo_paint(cr);
        set_source_pixbuf(cr, pb,
                          0, 0,
-                         rectangle.width, rectangle.height);
+                         allocation.width, allocation.height);
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
        cairo_paint(cr);
        cairo_destroy(cr);
 
        g_object_unref(pb);
 
-       window_copy_surface(image->window, &rectangle, surface);
+       window_copy_surface(image->window, &allocation, surface);
        window_flush(image->window);
        cairo_surface_destroy(surface);
 }
index f308983..cd9bfdc 100644 (file)
@@ -38,7 +38,7 @@
 struct resizor {
        struct display *display;
        struct window *window;
-       struct rectangle child_allocation;
+       int32_t width;
 
        struct {
                double current;
@@ -71,9 +71,7 @@ frame_callback(void *data, uint32_t time)
                resizor->height.previous = 200;
        }
 
-       resizor->child_allocation.height = height + 0.5;
-       window_set_child_size(resizor->window,
-                             &resizor->child_allocation);
+       window_set_child_size(resizor->window, resizor->width, height + 0.5);
 
        window_schedule_redraw(resizor->window);
 }
@@ -83,21 +81,21 @@ resizor_draw(struct resizor *resizor)
 {
        cairo_surface_t *surface;
        cairo_t *cr;
+       struct rectangle allocation;
 
        window_draw(resizor->window);
 
-       window_get_child_rectangle(resizor->window,
-                                  &resizor->child_allocation);
+       window_get_child_allocation(resizor->window, &allocation);
 
        surface = window_get_surface(resizor->window);
 
        cr = cairo_create(surface);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        cairo_rectangle(cr,
-                       resizor->child_allocation.x,
-                       resizor->child_allocation.y,
-                       resizor->child_allocation.width,
-                       resizor->child_allocation.height);
+                       allocation.x,
+                       allocation.y,
+                       allocation.width,
+                       allocation.height);
        cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
        cairo_fill(cr);
        cairo_destroy(cr);
@@ -141,12 +139,10 @@ key_handler(struct window *window, uint32_t key, uint32_t sym,
        switch (sym) {
        case XK_Down:
                resizor->height.target = 400;
-               resizor->height.current = resizor->child_allocation.height;
                frame_callback(resizor, 0);
                break;
        case XK_Up:
                resizor->height.target = 200;
-               resizor->height.current = resizor->child_allocation.height;
                frame_callback(resizor, 0);
                break;
        }
@@ -156,6 +152,7 @@ static struct resizor *
 resizor_create(struct display *display)
 {
        struct resizor *resizor;
+       int32_t height;
 
        resizor = malloc(sizeof *resizor);
        if (resizor == NULL)
@@ -171,15 +168,13 @@ resizor_create(struct display *display)
        window_set_keyboard_focus_handler(resizor->window,
                                          keyboard_focus_handler);
 
-       resizor->child_allocation.x = 0;
-       resizor->child_allocation.y = 0;
-       resizor->child_allocation.width = 300;
-       resizor->child_allocation.height = 400;
+       resizor->width = 300;
        resizor->height.current = 400;
-       resizor->height.previous = 400;
-       resizor->height.target = 400;
+       resizor->height.previous = resizor->height.current;
+       resizor->height.target = resizor->height.current;
+       height = resizor->height.current + 0.5;
 
-       window_set_child_size(resizor->window, &resizor->child_allocation);
+       window_set_child_size(resizor->window, resizor->width, height);
 
        resizor_draw(resizor);
 
index 1c7cbbf..e5db3db 100644 (file)
@@ -589,12 +589,28 @@ terminal_resize(struct terminal *terminal, int width, int height)
        char *tab_ruler;
        int data_pitch, attr_pitch;
        int i, l, total_rows, start;
-       struct rectangle rectangle;
+       struct rectangle allocation;
        struct winsize ws;
+       int32_t pixel_width, pixel_height;
 
+       if (width < 1)
+               width = 1;
+       if (height < 1)
+               height = 1;
        if (terminal->width == width && terminal->height == height)
                return;
 
+       if (!terminal->fullscreen) {
+               pixel_width = width *
+                       terminal->extents.max_x_advance + 2 * terminal->margin;
+               pixel_height = height *
+                       terminal->extents.height + 2 * terminal->margin;
+               window_set_child_size(terminal->window,
+                                     pixel_width, pixel_height);
+       }
+
+       window_schedule_redraw (terminal->window);
+
        data_pitch = width * sizeof(union utf8_char);
        size = data_pitch * height;
        data = malloc(size);
@@ -643,26 +659,12 @@ terminal_resize(struct terminal *terminal, int width, int height)
        terminal->tab_ruler = tab_ruler;
        terminal_init_tabs(terminal);
 
-       if (terminal->row >= terminal->height)
-               terminal->row = terminal->height - 1;
-       if (terminal->column >= terminal->width)
-               terminal->column = terminal->width - 1;
-       terminal->start = 0;
-       
-       if (!terminal->fullscreen) {
-               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);
-       }
-
        /* Update the window size */
        ws.ws_row = terminal->height;
        ws.ws_col = terminal->width;
-       window_get_child_rectangle(terminal->window, &rectangle);
-       ws.ws_xpixel = rectangle.width;
-       ws.ws_ypixel = rectangle.height;
+       window_get_child_allocation(terminal->window, &allocation);
+       ws.ws_xpixel = allocation.width;
+       ws.ws_ypixel = allocation.height;
        ioctl(terminal->master, TIOCSWINSZ, &ws);
 }
 
@@ -692,7 +694,7 @@ struct color_scheme DEFAULT_COLORS = {
 static void
 terminal_draw_contents(struct terminal *terminal)
 {
-       struct rectangle rectangle;
+       struct rectangle allocation;
        cairo_t *cr;
        cairo_font_extents_t extents;
        int top_margin, side_margin;
@@ -710,9 +712,9 @@ terminal_draw_contents(struct terminal *terminal)
 
        toShow.null = 0;
 
-       window_get_child_rectangle(terminal->window, &rectangle);
+       window_get_child_allocation(terminal->window, &allocation);
 
-       surface = display_create_surface(terminal->display, &rectangle);
+       surface = display_create_surface(terminal->display, &allocation);
        cr = cairo_create(surface);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        cairo_set_source_rgba(cr,
@@ -727,8 +729,8 @@ terminal_draw_contents(struct terminal *terminal)
        cairo_set_font_size(cr, 14);
 
        cairo_font_extents(cr, &extents);
-       side_margin = (rectangle.width - terminal->width * extents.max_x_advance) / 2;
-       top_margin = (rectangle.height - terminal->height * extents.height) / 2;
+       side_margin = (allocation.width - terminal->width * extents.max_x_advance) / 2;
+       top_margin = (allocation.height - terminal->height * extents.height) / 2;
 
        cairo_set_line_width(cr, 1.0);
 
@@ -819,31 +821,29 @@ terminal_draw_contents(struct terminal *terminal)
 
        cairo_destroy(cr);
 
-       window_copy_surface(terminal->window,
-                           &rectangle,
-                           surface);
+       window_copy_surface(terminal->window, &allocation, surface);
 
        cairo_surface_destroy(surface);
 }
 
 static void
-terminal_draw(struct terminal *terminal)
+resize_handler(struct window *window,
+              int32_t pixel_width, int32_t pixel_height, void *data)
 {
-       struct rectangle rectangle;
+       struct terminal *terminal = data;
        int32_t width, height;
 
-       window_get_child_rectangle(terminal->window, &rectangle);
-
-       width = (rectangle.width - 2 * terminal->margin) /
+       width = (pixel_width - 2 * terminal->margin) /
                (int32_t) terminal->extents.max_x_advance;
-       height = (rectangle.height - 2 * terminal->margin) /
+       height = (pixel_height - 2 * terminal->margin) /
                (int32_t) terminal->extents.height;
 
-       if (width < 0 || height < 0)
-               return;
-
        terminal_resize(terminal, width, height);
+}
 
+static void
+terminal_draw(struct terminal *terminal)
+{
        window_draw(terminal->window);
        terminal_draw_contents(terminal);
        window_flush(terminal->window);
@@ -1838,6 +1838,7 @@ terminal_create(struct display *display, int fullscreen)
        window_set_fullscreen(terminal->window, terminal->fullscreen);
        window_set_user_data(terminal->window, terminal);
        window_set_redraw_handler(terminal->window, redraw_handler);
+       window_set_resize_handler(terminal->window, resize_handler);
 
        window_set_key_handler(terminal->window, key_handler);
        window_set_keyboard_focus_handler(terminal->window,
index b085c67..5b81c45 100644 (file)
@@ -57,7 +57,7 @@ struct view {
 static void
 view_draw(struct view *view)
 {
-       struct rectangle rectangle;
+       struct rectangle allocation;
        cairo_surface_t *surface;
        cairo_t *cr;
        PopplerPage *page;
@@ -65,15 +65,15 @@ view_draw(struct view *view)
 
        window_draw(view->window);
 
-       window_get_child_rectangle(view->window, &rectangle);
+       window_get_child_allocation(view->window, &allocation);
 
        page = poppler_document_get_page(view->document, view->page);
 
        surface = window_get_surface(view->window);
 
        cr = cairo_create(surface);
-       cairo_rectangle(cr, rectangle.x, rectangle.y,
-                        rectangle.width, rectangle.height);
+       cairo_rectangle(cr, allocation.x, allocation.y,
+                        allocation.width, allocation.height);
        cairo_clip(cr);
 
        cairo_set_source_rgba(cr, 0, 0, 0, 0.8); 
@@ -81,16 +81,16 @@ view_draw(struct view *view)
        cairo_paint(cr);
        poppler_page_get_size(page, &width, &height);
        doc_aspect = width / height;
-       window_aspect = (double) rectangle.width / rectangle.height;
+       window_aspect = (double) allocation.width / allocation.height;
        if (doc_aspect < window_aspect)
-               scale = rectangle.height / height;
+               scale = allocation.height / height;
        else
-               scale = rectangle.width / width;
-       cairo_translate(cr, rectangle.x, rectangle.y);
+               scale = allocation.width / width;
+       cairo_translate(cr, allocation.x, allocation.y);
        cairo_scale(cr, scale, scale);
        cairo_translate(cr,
-                       (rectangle.width - width * scale) / 2 / scale,
-                       (rectangle.height - height * scale) / 2 / scale);
+                       (allocation.width - width * scale) / 2 / scale,
+                       (allocation.height - height * scale) / 2 / scale);
        cairo_rectangle(cr, 0, 0, width, height);
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
        cairo_set_source_rgb(cr, 1, 1, 1);
index 6700235..efd8fa4 100644 (file)
@@ -1042,15 +1042,23 @@ handle_configure(void *data, struct wl_shell *shell,
                 struct wl_surface *surface, int32_t width, int32_t height)
 {
        struct window *window = wl_surface_get_user_data(surface);
+       int32_t child_width, child_height;
 
-       window->resize_edges = edges;
-       window->allocation.width = width;
-       window->allocation.height = height;
+       if (window->resize_handler) {
+               child_width = width - 20 - window->margin * 2;
+               child_height = height - 60 - window->margin * 2;
+
+               (*window->resize_handler)(window,
+                                         child_width, child_height,
+                                         window->user_data);
+       } else {
+               window->resize_edges = edges;
+               window->allocation.width = width;
+               window->allocation.height = height;
 
-       if (window->resize_handler)
-               (*window->resize_handler)(window, window->user_data);
-       if (window->redraw_handler)
-               window_schedule_redraw(window);
+               if (window->redraw_handler)
+                       window_schedule_redraw(window);
+       }
 }
 
 static const struct wl_shell_listener shell_listener = {
@@ -1058,28 +1066,27 @@ static const struct wl_shell_listener shell_listener = {
 };
 
 void
-window_get_child_rectangle(struct window *window,
-                          struct rectangle *rectangle)
+window_get_child_allocation(struct window *window,
+                           struct rectangle *allocation)
 {
        if (window->fullscreen && !window->decoration) {
-               *rectangle = window->allocation;
+               *allocation = window->allocation;
        } else {
-               rectangle->x = window->margin + 10;
-               rectangle->y = window->margin + 50;
-               rectangle->width = window->allocation.width - 20 - window->margin * 2;
-               rectangle->height = window->allocation.height - 60 - window->margin * 2;
+               allocation->x = window->margin + 10;
+               allocation->y = window->margin + 50;
+               allocation->width =
+                       window->allocation.width - 20 - window->margin * 2;
+               allocation->height =
+                       window->allocation.height - 60 - window->margin * 2;
        }
 }
 
 void
-window_set_child_size(struct window *window,
-                     struct rectangle *rectangle)
+window_set_child_size(struct window *window, int32_t width, int32_t height)
 {
        if (!window->fullscreen) {
-               window->allocation.width =
-                       rectangle->width + 20 + window->margin * 2;
-               window->allocation.height =
-                       rectangle->height + 60 + window->margin * 2;
+               window->allocation.width = width + 20 + window->margin * 2;
+               window->allocation.height = height + 60 + window->margin * 2;
        }
 }
 
index 79c7a82..e775127 100644 (file)
@@ -105,7 +105,9 @@ enum pointer_type {
        POINTER_HAND1,
 };
 
-typedef void (*window_resize_handler_t)(struct window *window, void *data);
+typedef void (*window_resize_handler_t)(struct window *window,
+                                       int32_t width, int32_t height,
+                                       void *data);
 typedef void (*window_redraw_handler_t)(struct window *window, void *data);
 typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data);
 typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode,
@@ -135,11 +137,10 @@ window_move(struct window *window, struct input *input, uint32_t time);
 void
 window_draw(struct window *window);
 void
-window_get_child_rectangle(struct window *window,
-                          struct rectangle *rectangle);
+window_get_child_allocation(struct window *window,
+                           struct rectangle *allocation);
 void
-window_set_child_size(struct window *window,
-                     struct rectangle *rectangle);
+window_set_child_size(struct window *window, int32_t width, int32_t height);
 void
 window_copy_image(struct window *window,
                  struct rectangle *rectangle,