diff --git a/clients/Makefile.am b/clients/Makefile.am index c2e423c6..37135f28 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -1,10 +1,20 @@ -noinst_PROGRAMS = gears flower screenshot terminal image view dnd smoke resizor +noinst_PROGRAMS = \ + gears \ + flower \ + screenshot \ + terminal \ + image \ + $(poppler_programs) \ + dnd \ + smoke \ + resizor + noinst_LTLIBRARIES = libtoytoolkit.la INCLUDES = \ -I$(top_srcdir)/wayland \ -I$(top_builddir)/wayland \ - $(CLIENT_CFLAGS) $(POPPLER_CFLAGS) + $(CLIENT_CFLAGS) LDADD = libtoytoolkit.la \ $(top_builddir)/wayland/libwayland-client.la \ @@ -27,7 +37,6 @@ gears_SOURCES = gears.c screenshot_SOURCES = screenshot.c screenshooter-protocol.c terminal_SOURCES = terminal.c image_SOURCES = image.c -view_SOURCES = view.c dnd_SOURCES = dnd.c resizor_SOURCES = resizor.c @@ -40,4 +49,10 @@ CLEANFILES = $(BUILT_SOURCES) include $(top_srcdir)/wayland/scanner.mk terminal_LDADD = $(LDADD) -lutil + +if HAVE_POPPLER +poppler_programs = view +view_SOURCES = view.c view_LDADD = $(LDADD) $(POPPLER_LIBS) +view_CPPFLAGS = $(POPPLER_CFLAGS) +endif diff --git a/clients/dnd.c b/clients/dnd.c index b7f9f397..feea3369 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -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); diff --git a/clients/gears.c b/clients/gears.c index a0807418..b8e6cca0 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -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 diff --git a/clients/image.c b/clients/image.c index f9bbeb21..61d8b25f 100644 --- a/clients/image.c +++ b/clients/image.c @@ -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); } diff --git a/clients/resizor.c b/clients/resizor.c index f3089834..cd9bfdc5 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -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); diff --git a/clients/terminal.c b/clients/terminal.c index bf4041e7..5c508e90 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -323,7 +323,7 @@ struct attr { }; struct color_scheme { struct terminal_color palette[16]; - struct terminal_color border; + char border; struct attr default_attr; }; @@ -389,7 +389,7 @@ struct terminal { struct color_scheme *color_scheme; struct terminal_color color_table[256]; cairo_font_extents_t extents; - cairo_font_face_t *font_normal, *font_bold; + cairo_scaled_font_t *font_normal, *font_bold; }; /* Create default tab stops, every 8 characters */ @@ -473,7 +473,8 @@ terminal_get_row(struct terminal *terminal, int row) } static struct attr* -terminal_get_attr_row(struct terminal *terminal, int row) { +terminal_get_attr_row(struct terminal *terminal, int row) +{ int index; index = (row + terminal->start) % terminal->height; @@ -481,9 +482,54 @@ terminal_get_attr_row(struct terminal *terminal, int row) { return &terminal->data_attr[index * terminal->width]; } -static struct attr -terminal_get_attr(struct terminal *terminal, int row, int col) { - return terminal_get_attr_row(terminal, row)[col]; +union decoded_attr { + struct { + unsigned char foreground; + unsigned char background; + unsigned char bold; + unsigned char underline; + }; + uint32_t key; +}; + +static void +terminal_decode_attr(struct terminal *terminal, int row, int col, + union decoded_attr *decoded) +{ + struct attr attr; + int foreground, background, tmp; + + /* get the attributes for this character cell */ + attr = terminal_get_attr_row(terminal, row)[col]; + if ((attr.a & ATTRMASK_INVERSE) || + ((terminal->mode & MODE_SHOW_CURSOR) && + terminal->focused && terminal->row == row && + terminal->column == col)) { + foreground = attr.bg; + background = attr.fg; + if (attr.a & ATTRMASK_BOLD) { + if (foreground <= 16) foreground |= 0x08; + if (background <= 16) background &= 0x07; + } + } else { + foreground = attr.fg; + background = attr.bg; + } + + if (terminal->mode & MODE_INVERSE) { + tmp = foreground; + foreground = background; + background = tmp; + if (attr.a & ATTRMASK_BOLD) { + if (foreground <= 16) foreground |= 0x08; + if (background <= 16) background &= 0x07; + } + } + + decoded->foreground = foreground; + decoded->background = background; + decoded->bold = attr.a & (ATTRMASK_BOLD | ATTRMASK_BLINK); + decoded->underline = attr.a & ATTRMASK_UNDERLINE; } static void @@ -610,12 +656,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); @@ -664,26 +726,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); } @@ -706,92 +754,125 @@ struct color_scheme DEFAULT_COLORS = { {0.33, 1, 1, 1}, /* high cyan */ {1, 1, 1, 1} /* white */ }, - {0, 0, 0, 1}, /* black border */ + 0, /* black border */ {7, 0, 0, } /* bg:black (0), fg:light gray (7) */ }; +static void +terminal_set_color(struct terminal *terminal, cairo_t *cr, int index) +{ + cairo_set_source_rgba(cr, + terminal->color_table[index].r, + terminal->color_table[index].g, + terminal->color_table[index].b, + terminal->color_table[index].a); +} + +struct glyph_run { + struct terminal *terminal; + cairo_t *cr; + int count; + union decoded_attr attr; + cairo_glyph_t glyphs[256], *g; +}; + +static void +glyph_run_init(struct glyph_run *run, struct terminal *terminal, cairo_t *cr) +{ + run->terminal = terminal; + run->cr = cr; + run->g = run->glyphs; + run->count = 0; + run->attr.key = 0; +} + +static void +glyph_run_flush(struct glyph_run *run, union decoded_attr attr) +{ + cairo_scaled_font_t *font; + + if (run->count == 0) + run->attr = attr; + if (run->count > ARRAY_LENGTH(run->glyphs) - 10 || + (attr.key != run->attr.key)) { + if (run->attr.bold) + font = run->terminal->font_bold; + else + font = run->terminal->font_normal; + cairo_set_scaled_font(run->cr, font); + terminal_set_color(run->terminal, run->cr, + run->attr.foreground); + + cairo_show_glyphs (run->cr, run->glyphs, run->count); + run->g = run->glyphs; + run->count = 0; + } +} + +static void +glyph_run_add(struct glyph_run *run, int x, int y, union utf8_char *c) +{ + int num_glyphs; + cairo_scaled_font_t *font; + + num_glyphs = ARRAY_LENGTH(run->glyphs) - run->count; + + if (run->attr.bold) + font = run->terminal->font_bold; + else + font = run->terminal->font_normal; + + cairo_move_to(run->cr, x, y); + cairo_scaled_font_text_to_glyphs (font, x, y, + (char *) c->byte, 4, + &run->g, &num_glyphs, + NULL, NULL, NULL); + run->g += num_glyphs; + run->count += num_glyphs; +} + 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; int row, col; - struct attr attr; union utf8_char *p_row; - struct utf8_chars { - union utf8_char c; - char null; - } toShow; - int foreground, background, bold, underline, concealed, tmp; + union decoded_attr attr; int text_x, text_y; cairo_surface_t *surface; double d; + struct glyph_run run; - 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, - terminal->color_scheme->border.r, - terminal->color_scheme->border.g, - terminal->color_scheme->border.b, - terminal->color_scheme->border.a); + terminal_set_color(terminal, cr, terminal->color_scheme->border); cairo_paint(cr); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_font_face(cr, terminal->font_normal); - cairo_set_font_size(cr, 14); + cairo_set_scaled_font(cr, terminal->font_normal); 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); + /* paint the background */ for (row = 0; row < terminal->height; row++) { p_row = terminal_get_row(terminal, row); for (col = 0; col < terminal->width; col++) { /* get the attributes for this character cell */ - attr = terminal_get_attr(terminal, row, col); - if ((attr.a & ATTRMASK_INVERSE) || - ((terminal->mode & MODE_SHOW_CURSOR) && - terminal->focused && terminal->row == row && - terminal->column == col)) - { - foreground = attr.bg; - background = attr.fg; - if (attr.a & ATTRMASK_BOLD) { - if (foreground <= 16) foreground |= 0x08; - if (background <= 16) background &= 0x07; - } - } else { - foreground = attr.fg; - background = attr.bg; - } - if (terminal->mode & MODE_INVERSE) { - tmp = foreground; - foreground = background; - background = tmp; - if (attr.a & ATTRMASK_BOLD) { - if (foreground <= 16) foreground |= 0x08; - if (background <= 16) background &= 0x07; - } - } - bold = attr.a & (ATTRMASK_BOLD | ATTRMASK_BLINK); - underline = attr.a & ATTRMASK_UNDERLINE; - concealed = attr.a & ATTRMASK_CONCEALED; - - /* paint the background */ - cairo_set_source_rgba(cr, - terminal->color_table[background].r, - terminal->color_table[background].g, - terminal->color_table[background].b, - terminal->color_table[background].a); + terminal_decode_attr(terminal, row, col, &attr); + + if (attr.background == terminal->color_scheme->border) + continue; + + terminal_set_color(terminal, cr, attr.background); cairo_move_to(cr, side_margin + (col * extents.max_x_advance), top_margin + (row * extents.height)); cairo_rel_line_to(cr, extents.max_x_advance, 0); @@ -799,33 +880,36 @@ terminal_draw_contents(struct terminal *terminal) cairo_rel_line_to(cr, -extents.max_x_advance, 0); cairo_close_path(cr); cairo_fill(cr); + } + } - /* paint the foreground */ - if (concealed) continue; - if (bold) - cairo_set_font_face(cr, terminal->font_bold); - else - cairo_set_font_face(cr, terminal->font_normal); - cairo_set_source_rgba(cr, - terminal->color_table[foreground].r, - terminal->color_table[foreground].g, - terminal->color_table[foreground].b, - terminal->color_table[foreground].a); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + + /* paint the foreground */ + glyph_run_init(&run, terminal, cr); + for (row = 0; row < terminal->height; row++) { + p_row = terminal_get_row(terminal, row); + for (col = 0; col < terminal->width; col++) { + /* get the attributes for this character cell */ + terminal_decode_attr(terminal, row, col, &attr); + + glyph_run_flush(&run, attr); text_x = side_margin + col * extents.max_x_advance; text_y = top_margin + extents.ascent + row * extents.height; - if (underline) { + if (attr.underline) { cairo_move_to(cr, text_x, (double)text_y + 1.5); cairo_line_to(cr, text_x + extents.max_x_advance, (double) text_y + 1.5); cairo_stroke(cr); } - cairo_move_to(cr, text_x, text_y); - - toShow.c = p_row[col]; - cairo_show_text(cr, (char *) toShow.c.byte); + + glyph_run_add(&run, text_x, text_y, &p_row[col]); } } + attr.key = ~0; + glyph_run_flush(&run, attr); + if ((terminal->mode & MODE_SHOW_CURSOR) && !terminal->focused) { d = 0.5; @@ -842,31 +926,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); @@ -1960,6 +2042,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, @@ -1967,16 +2050,19 @@ terminal_create(struct display *display, int fullscreen) surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); cr = cairo_create(surface); - terminal->font_bold = cairo_toy_font_face_create ("mono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD); - cairo_font_face_reference(terminal->font_bold); - terminal->font_normal = cairo_toy_font_face_create ("mono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_font_face_reference(terminal->font_normal); - cairo_set_font_face(cr, terminal->font_normal); cairo_set_font_size(cr, 14); + cairo_select_font_face (cr, "mono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + terminal->font_bold = cairo_get_scaled_font (cr); + cairo_scaled_font_reference(terminal->font_bold); + + cairo_select_font_face (cr, "mono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + terminal->font_normal = cairo_get_scaled_font (cr); + cairo_scaled_font_reference(terminal->font_normal); + cairo_font_extents(cr, &terminal->extents); cairo_destroy(cr); cairo_surface_destroy(surface); diff --git a/clients/view.c b/clients/view.c index b085c678..5b81c456 100644 --- a/clients/view.c +++ b/clients/view.c @@ -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); diff --git a/clients/window.c b/clients/window.c index 67002352..efd8fa44 100644 --- a/clients/window.c +++ b/clients/window.c @@ -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; } } diff --git a/clients/window.h b/clients/window.h index 79c7a82b..e775127a 100644 --- a/clients/window.h +++ b/clients/window.h @@ -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, diff --git a/configure.ac b/configure.ac index 55682186..31654a6d 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,10 @@ PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(COMPOSITOR, [egl glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes) PKG_CHECK_MODULES(CLIENT, [egl gl cairo gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm]) -PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0]) +PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0], + [have_poppler=yes], [have_poppler=no]) +AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes") + PKG_CHECK_MODULES(CAIRO_GL, [cairo-gl], [have_cairo_gl=yes], [have_cairo_gl=no]) AS_IF([test "x$have_cairo_gl" = "xyes"],