summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeandro Ribeiro <leandro.ribeiro@collabora.com>2024-04-15 10:14:58 -0300
committerPekka Paalanen <pq@iki.fi>2024-04-26 14:15:28 +0000
commitcfc886fcb373c907f67c7b0dc50567a293a81c20 (patch)
tree34f1dfacad46d0e89e0a4cfb74b1582e99d96f77
parentc427ae5a49577cfee5557627db4c18b27aedfa8a (diff)
clients/image: display image in a subsurface
In the next commits we'll add support to extract the ICC information from the images and use the CM&HDR protocol extension to present them with the ICC data. Currently the decorations, background and the image content are presented on the same surface. As we want to apply the ICC only on the image content, move it to a subsurface. Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
-rw-r--r--clients/image.c136
1 files changed, 90 insertions, 46 deletions
diff --git a/clients/image.c b/clients/image.c
index 5f1d9c89..f1c28099 100644
--- a/clients/image.c
+++ b/clients/image.c
@@ -50,6 +50,9 @@ struct image {
/* Decorations, buttons, etc. */
struct widget *frame_widget;
+ /* Where we draw the image content. */
+ struct widget *image_widget;
+
struct display *display;
char *filename;
cairo_surface_t *image;
@@ -109,27 +112,45 @@ clamp_view(struct image *image)
}
static void
-redraw_handler(struct widget *widget, void *data)
+frame_redraw_handler(struct widget *widget, void *data)
+{
+ struct rectangle allocation;
+ cairo_t *cr;
+
+ widget_get_allocation(widget, &allocation);
+
+ cr = widget_cairo_create(widget);
+ cairo_rectangle(cr, allocation.x, allocation.y,
+ allocation.width, allocation.height);
+ cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+}
+
+static void
+frame_resize_handler(struct widget *widget,
+ int32_t width, int32_t height, void *data)
+{
+ struct image *image = data;
+
+ clamp_view(image);
+}
+
+static void
+image_redraw_handler(struct widget *widget, void *data)
{
struct image *image = data;
struct rectangle allocation;
cairo_t *cr;
- cairo_surface_t *surface;
double width, height, doc_aspect, window_aspect, scale;
- cairo_matrix_t matrix;
- cairo_matrix_t translate;
- surface = window_get_surface(image->window);
- cr = cairo_create(surface);
widget_get_allocation(widget, &allocation);
+
+ cr = widget_cairo_create(widget);
cairo_rectangle(cr, allocation.x, allocation.y,
allocation.width, allocation.height);
- cairo_clip(cr);
- cairo_push_group(cr);
- cairo_translate(cr, allocation.x, allocation.y);
-
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
if (!image->initialized) {
@@ -151,29 +172,25 @@ redraw_handler(struct widget *widget, void *data)
clamp_view(image);
}
- matrix = image->matrix;
- cairo_matrix_init_translate(&translate, allocation.x, allocation.y);
- cairo_matrix_multiply(&matrix, &matrix, &translate);
- cairo_set_matrix(cr, &matrix);
-
+ cairo_set_matrix(cr, &image->matrix);
cairo_set_source_surface(cr, image->image, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_paint(cr);
-
- cairo_pop_group_to_source(cr);
- cairo_paint(cr);
cairo_destroy(cr);
-
- cairo_surface_destroy(surface);
}
static void
-resize_handler(struct widget *widget,
- int32_t width, int32_t height, void *data)
+image_resize_handler(struct widget *widget,
+ int32_t width, int32_t height, void *data)
{
struct image *image = data;
+ struct rectangle allocation;
- clamp_view(image);
+ widget_get_allocation(image->frame_widget, &allocation);
+
+ widget_set_allocation(widget,
+ allocation.x, allocation.y,
+ allocation.width, allocation.height);
}
static void
@@ -186,9 +203,9 @@ keyboard_focus_handler(struct window *window,
}
static int
-enter_handler(struct widget *widget,
- struct input *input,
- float x, float y, void *data)
+image_enter_handler(struct widget *widget,
+ struct input *input,
+ float x, float y, void *data)
{
struct image *image = data;
struct rectangle allocation;
@@ -218,9 +235,9 @@ move_viewport(struct image *image, double dx, double dy)
}
static int
-motion_handler(struct widget *widget,
- struct input *input, uint32_t time,
- float x, float y, void *data)
+image_motion_handler(struct widget *widget,
+ struct input *input, uint32_t time,
+ float x, float y, void *data)
{
struct image *image = data;
struct rectangle allocation;
@@ -240,11 +257,11 @@ motion_handler(struct widget *widget,
}
static void
-button_handler(struct widget *widget,
- struct input *input, uint32_t time,
- uint32_t button,
- enum wl_pointer_button_state state,
- void *data)
+image_button_handler(struct widget *widget,
+ struct input *input, uint32_t time,
+ uint32_t button,
+ enum wl_pointer_button_state state,
+ void *data)
{
struct image *image = data;
@@ -314,8 +331,8 @@ key_handler(struct window *window, struct input *input, uint32_t time,
}
static void
-axis_handler(struct widget *widget, struct input *input, uint32_t time,
- uint32_t axis, wl_fixed_t value, void *data)
+image_axis_handler(struct widget *widget, struct input *input, uint32_t time,
+ uint32_t axis, wl_fixed_t value, void *data)
{
struct image *image = data;
@@ -352,12 +369,27 @@ close_handler(void *data)
if (*image->image_counter == 0)
display_exit(image->display);
+ widget_destroy(image->image_widget);
widget_destroy(image->frame_widget);
window_destroy(image->window);
free(image);
}
+static void
+set_empty_input_region(struct widget *widget, struct display *display)
+{
+ struct wl_compositor *compositor;
+ struct wl_surface *surface;
+ struct wl_region *region;
+
+ compositor = display_get_compositor(display);
+ surface = widget_get_wl_surface(widget);
+ region = wl_compositor_create_region(compositor);
+ wl_surface_set_input_region(surface, region);
+ wl_region_destroy(region);
+}
+
static struct image *
image_create(struct display *display, const char *filename,
int *image_counter)
@@ -384,7 +416,6 @@ image_create(struct display *display, const char *filename,
}
image->window = window_create(display);
- image->frame_widget = window_frame_create(image->window, image);
window_set_title(image->window, title);
window_set_appid(image->window, "org.freedesktop.weston.wayland-image");
image->display = display;
@@ -393,18 +424,31 @@ image_create(struct display *display, const char *filename,
image->initialized = false;
window_set_user_data(image->window, image);
- widget_set_redraw_handler(image->frame_widget, redraw_handler);
- widget_set_resize_handler(image->frame_widget, resize_handler);
window_set_keyboard_focus_handler(image->window,
keyboard_focus_handler);
window_set_fullscreen_handler(image->window, fullscreen_handler);
window_set_close_handler(image->window, close_handler);
-
- widget_set_enter_handler(image->frame_widget, enter_handler);
- widget_set_motion_handler(image->frame_widget, motion_handler);
- widget_set_button_handler(image->frame_widget, button_handler);
- widget_set_axis_handler(image->frame_widget, axis_handler);
window_set_key_handler(image->window, key_handler);
+
+ image->frame_widget = window_frame_create(image->window, image);
+ widget_set_redraw_handler(image->frame_widget, frame_redraw_handler);
+ widget_set_resize_handler(image->frame_widget, frame_resize_handler);
+
+ image->image_widget = window_add_subsurface(image->window, image,
+ SUBSURFACE_SYNCHRONIZED);
+ /* We set the input region of the subsurface where the image is draw as
+ * NULL, as the input region of the parent surface is automatically set
+ * by the toytoolkit. But as the window that finds the widget in a
+ * certain (x, y) position looks for surfaces that are on top first, it
+ * will call the image_widget handlers for input related stuff. */
+ set_empty_input_region(image->image_widget, display);
+ widget_set_redraw_handler(image->image_widget, image_redraw_handler);
+ widget_set_resize_handler(image->image_widget, image_resize_handler);
+ widget_set_enter_handler(image->image_widget, image_enter_handler);
+ widget_set_motion_handler(image->image_widget, image_motion_handler);
+ widget_set_button_handler(image->image_widget, image_button_handler);
+ widget_set_axis_handler(image->image_widget, image_axis_handler);
+
widget_schedule_resize(image->frame_widget, 500, 400);
return image;