Fix resizing

dev
Kristian Høgsberg 15 years ago
parent a946821b4f
commit 0953162db8
  1. 41
      clients/image.c
  2. 59
      clients/terminal.c
  3. 39
      clients/view.c
  4. 48
      clients/window.c

@ -48,9 +48,7 @@ struct image {
uint32_t key; uint32_t key;
gboolean redraw_scheduled; gboolean redraw_scheduled;
gboolean redraw_pending;
cairo_surface_t *surface;
gchar *filename; gchar *filename;
}; };
@ -149,8 +147,9 @@ image_draw(struct image *image)
struct rectangle rectangle; struct rectangle rectangle;
GdkPixbuf *pb; GdkPixbuf *pb;
cairo_t *cr; cairo_t *cr;
cairo_surface_t *wsurface, *surface;
image->redraw_pending = 0; image->redraw_scheduled = 0;
window_draw(image->window); window_draw(image->window);
@ -163,10 +162,13 @@ image_draw(struct image *image)
if (pb == NULL) if (pb == NULL)
return; return;
image->surface = wsurface = window_get_surface(image->window);
window_create_surface(image->window, &rectangle); 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_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_paint(cr); cairo_paint(cr);
@ -179,11 +181,9 @@ image_draw(struct image *image)
g_object_unref(pb); g_object_unref(pb);
window_copy_surface(image->window, window_copy_surface(image->window, &rectangle, surface);
&rectangle,
image->surface);
window_commit(image->window, image->key); window_commit(image->window, image->key);
cairo_surface_destroy(surface);
} }
static gboolean static gboolean
@ -202,8 +202,6 @@ image_schedule_redraw(struct image *image)
if (!image->redraw_scheduled) { if (!image->redraw_scheduled) {
image->redraw_scheduled = 1; image->redraw_scheduled = 1;
g_idle_add(image_idle_redraw, image); 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); 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 * static struct image *
image_create(struct display *display, uint32_t key, const char *filename) 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 /* FIXME: Window uses key 1 for moves, need some kind of
* allocation scheme here. Or maybe just a real toolkit. */ * allocation scheme here. Or maybe just a real toolkit. */
image->key = key + 100; image->key = key + 100;
image->redraw_scheduled = 1;
window_set_resize_handler(image->window, resize_handler, image); window_set_resize_handler(image->window, resize_handler, image);
window_set_keyboard_focus_handler(image->window, keyboard_focus_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); image_draw(image);

@ -50,7 +50,7 @@ static int option_fullscreen;
struct terminal { struct terminal {
struct window *window; struct window *window;
struct display *display; struct display *display;
int redraw_scheduled, redraw_pending; int redraw_scheduled;
char *data; char *data;
int width, height, start, row, column; int width, height, start, row, column;
int fd, master; int fd, master;
@ -63,6 +63,7 @@ struct terminal {
int fullscreen; int fullscreen;
int focused; int focused;
struct color_scheme *color_scheme; struct color_scheme *color_scheme;
cairo_font_extents_t extents;
}; };
static char * static char *
@ -195,30 +196,21 @@ static void
terminal_draw(struct terminal *terminal) terminal_draw(struct terminal *terminal)
{ {
struct rectangle rectangle; struct rectangle rectangle;
cairo_surface_t *surface;
cairo_font_extents_t extents;
cairo_t *cr;
int32_t width, height; int32_t width, height;
window_get_child_rectangle(terminal->window, &rectangle); window_get_child_rectangle(terminal->window, &rectangle);
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); width = (rectangle.width - 2 * terminal->margin) /
cr = cairo_create(surface); (int32_t) terminal->extents.max_x_advance;
cairo_select_font_face (cr, "mono", height = (rectangle.height - 2 * terminal->margin) /
CAIRO_FONT_SLANT_NORMAL, (int32_t) terminal->extents.height;
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;
terminal_resize(terminal, width, height); terminal_resize(terminal, width, height);
if (!terminal->fullscreen) { if (!terminal->fullscreen) {
rectangle.width = terminal->width * extents.max_x_advance + 2 * terminal->margin; rectangle.width = terminal->width *
rectangle.height = terminal->height * extents.height + 2 * terminal->margin; 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); window_set_child_size(terminal->window, &rectangle);
} }
@ -233,6 +225,7 @@ idle_redraw(void *data)
struct terminal *terminal = data; struct terminal *terminal = data;
terminal_draw(terminal); terminal_draw(terminal);
terminal->redraw_scheduled = 0;
return FALSE; return FALSE;
} }
@ -249,8 +242,6 @@ terminal_schedule_redraw(struct terminal *terminal)
if (!terminal->redraw_scheduled) { if (!terminal->redraw_scheduled) {
g_idle_add(idle_redraw, terminal); g_idle_add(idle_redraw, terminal);
terminal->redraw_scheduled = 1; terminal->redraw_scheduled = 1;
} else {
terminal->redraw_pending = 1;
} }
} }
@ -416,19 +407,6 @@ resize_handler(struct window *window, void *data)
terminal_schedule_redraw(terminal); 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 static void
key_handler(struct window *window, uint32_t key, uint32_t unicode, key_handler(struct window *window, uint32_t key, uint32_t unicode,
uint32_t state, uint32_t modifiers, void *data) uint32_t state, uint32_t modifiers, void *data)
@ -465,6 +443,8 @@ static struct terminal *
terminal_create(struct display *display, int fullscreen) terminal_create(struct display *display, int fullscreen)
{ {
struct terminal *terminal; struct terminal *terminal;
cairo_surface_t *surface;
cairo_t *cr;
terminal = malloc(sizeof *terminal); terminal = malloc(sizeof *terminal);
if (terminal == NULL) if (terminal == NULL)
@ -476,17 +456,26 @@ terminal_create(struct display *display, int fullscreen)
terminal->window = window_create(display, "Wayland Terminal", terminal->window = window_create(display, "Wayland Terminal",
500, 100, 500, 400); 500, 100, 500, 400);
terminal->display = display; terminal->display = display;
terminal->redraw_scheduled = 1;
terminal->margin = 5; terminal->margin = 5;
window_set_fullscreen(terminal->window, terminal->fullscreen); window_set_fullscreen(terminal->window, terminal->fullscreen);
window_set_resize_handler(terminal->window, resize_handler, terminal); 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_key_handler(terminal->window, key_handler, terminal);
window_set_keyboard_focus_handler(terminal->window, window_set_keyboard_focus_handler(terminal->window,
keyboard_focus_handler, terminal); 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); terminal_draw(terminal);
return terminal; return terminal;

@ -52,9 +52,7 @@ struct view {
uint32_t key; uint32_t key;
gboolean redraw_scheduled; gboolean redraw_scheduled;
gboolean redraw_pending;
cairo_surface_t *surface;
gchar *filename; gchar *filename;
PopplerDocument *document; PopplerDocument *document;
int page; int page;
@ -66,11 +64,12 @@ static void
view_draw(struct view *view) view_draw(struct view *view)
{ {
struct rectangle rectangle; struct rectangle rectangle;
cairo_surface_t *surface;
cairo_t *cr; cairo_t *cr;
PopplerPage *page; PopplerPage *page;
double width, height, doc_aspect, window_aspect, scale; double width, height, doc_aspect, window_aspect, scale;
view->redraw_pending = 0; view->redraw_scheduled = 0;
window_draw(view->window); window_draw(view->window);
@ -78,10 +77,13 @@ view_draw(struct view *view)
page = poppler_document_get_page(view->document, view->page); page = poppler_document_get_page(view->document, view->page);
view->surface = surface = window_get_surface(view->window);
window_create_surface(view->window, &rectangle);
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_source_rgba(cr, 0, 0, 0, 0.8);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr); cairo_paint(cr);
@ -92,6 +94,7 @@ view_draw(struct view *view)
scale = rectangle.height / height; scale = rectangle.height / height;
else else
scale = rectangle.width / width; scale = rectangle.width / width;
cairo_translate(cr, rectangle.x, rectangle.y);
cairo_scale(cr, scale, scale); cairo_scale(cr, scale, scale);
cairo_translate(cr, cairo_translate(cr,
(rectangle.width - width * scale) / 2 / scale, (rectangle.width - width * scale) / 2 / scale,
@ -104,10 +107,6 @@ view_draw(struct view *view)
cairo_destroy(cr); cairo_destroy(cr);
g_object_unref(G_OBJECT(page)); g_object_unref(G_OBJECT(page));
window_copy_surface(view->window,
&rectangle,
view->surface);
window_commit(view->window, 0); window_commit(view->window, 0);
} }
@ -127,8 +126,6 @@ view_schedule_redraw(struct view *view)
if (!view->redraw_scheduled) { if (!view->redraw_scheduled) {
view->redraw_scheduled = 1; view->redraw_scheduled = 1;
g_idle_add(view_idle_redraw, view); 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); 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 static void
keyboard_focus_handler(struct window *window, keyboard_focus_handler(struct window *window,
struct wl_input_device *device, void *data) 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_key_handler(view->window, key_handler, view);
window_set_keyboard_focus_handler(view->window, window_set_keyboard_focus_handler(view->window,
keyboard_focus_handler, view); keyboard_focus_handler, view);
window_set_acknowledge_handler(view->window, acknowledge_handler, view);
view->document = poppler_document_new_from_file(view->filename, view->document = poppler_document_new_from_file(view->filename,
NULL, &error); NULL, &error);

@ -67,7 +67,7 @@ struct window {
struct display *display; struct display *display;
struct wl_surface *surface; struct wl_surface *surface;
const char *title; const char *title;
struct rectangle allocation, saved_allocation; struct rectangle allocation, saved_allocation, surface_allocation;
int minimum_width, minimum_height; int minimum_width, minimum_height;
int margin; int margin;
int drag_x, drag_y; int drag_x, drag_y;
@ -81,7 +81,6 @@ struct window {
EGLImageKHR *image; EGLImageKHR *image;
cairo_surface_t *cairo_surface, *pending_surface; cairo_surface_t *cairo_surface, *pending_surface;
int new_surface;
window_resize_handler_t resize_handler; window_resize_handler_t resize_handler;
window_key_handler_t key_handler; window_key_handler_t key_handler;
@ -170,36 +169,39 @@ window_attach_surface(struct window *window)
if (window->pending_surface != NULL) if (window->pending_surface != NULL)
return; return;
window->pending_surface = window->pending_surface = window->cairo_surface;
cairo_surface_reference(window->cairo_surface); window->cairo_surface = NULL;
data = cairo_surface_get_user_data (window->cairo_surface, &surface_data_key); data = cairo_surface_get_user_data (window->pending_surface,
eglExportDRMImageMESA(window->display->dpy, data->image, &name, NULL, &stride); &surface_data_key);
eglExportDRMImageMESA(window->display->dpy,
data->image, &name, NULL, &stride);
visual = wl_display_get_premultiplied_argb_visual(window->display->display); visual = wl_display_get_premultiplied_argb_visual(window->display->display);
wl_surface_attach(window->surface, wl_surface_attach(window->surface,
name, name,
window->allocation.width, window->surface_allocation.width,
window->allocation.height, window->surface_allocation.height,
stride, stride,
visual); visual);
wl_surface_map(window->surface, wl_surface_map(window->surface,
window->allocation.x - window->margin, window->surface_allocation.x - window->margin,
window->allocation.y - window->margin, window->surface_allocation.y - window->margin,
window->allocation.width, window->surface_allocation.width,
window->allocation.height); window->surface_allocation.height);
wl_compositor_commit(window->display->compositor, 0);
} }
void void
window_commit(struct window *window, uint32_t key) window_commit(struct window *window, uint32_t key)
{ {
if (window->new_surface) { if (window->cairo_surface) {
window_attach_surface(window); 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 static void
@ -214,6 +216,7 @@ window_draw_decorations(struct window *window)
window->cairo_surface = window->cairo_surface =
window_create_surface(window, &window->allocation); window_create_surface(window, &window->allocation);
window->surface_allocation = window->allocation;
outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1); outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1);
bright = cairo_pattern_create_rgb(0.8, 0.8, 0.8); 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; width = window->allocation.width - window->margin * 2;
height = window->allocation.height - 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, cairo_translate(cr, window->margin + shadow_dx,
window->margin + shadow_dy); window->margin + shadow_dy);
cairo_set_line_width (cr, border); cairo_set_line_width (cr, border);
@ -303,6 +311,7 @@ window_draw_fullscreen(struct window *window)
{ {
window->cairo_surface = window->cairo_surface =
window_create_surface(window, &window->allocation); window_create_surface(window, &window->allocation);
window->surface_allocation = window->allocation;
} }
void void
@ -315,8 +324,6 @@ window_draw(struct window *window)
window_draw_fullscreen(window); window_draw_fullscreen(window);
else else
window_draw_decorations(window); window_draw_decorations(window);
window->new_surface = 1;
} }
cairo_surface_t * cairo_surface_t *
@ -804,11 +811,10 @@ display_handle_acknowledge(void *data,
* window buffer if we resized and render the next frame into * window buffer if we resized and render the next frame into
* our back buffer.. */ * our back buffer.. */
wl_list_for_each(window, &d->window_list, link) { wl_list_for_each(window, &d->window_list, link) {
pending = window->pending_surface; cairo_surface_destroy(window->pending_surface);
window->pending_surface = NULL; window->pending_surface = NULL;
if (pending != window->cairo_surface) if (window->cairo_surface)
window_attach_surface(window); window_attach_surface(window);
cairo_surface_destroy(pending);
if (window->acknowledge_handler) if (window->acknowledge_handler)
(*window->acknowledge_handler)(window, key, frame, window->user_data); (*window->acknowledge_handler)(window, key, frame, window->user_data);
} }

Loading…
Cancel
Save