summaryrefslogtreecommitdiff
path: root/clients/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/window.c')
-rw-r--r--clients/window.c76
1 files changed, 72 insertions, 4 deletions
diff --git a/clients/window.c b/clients/window.c
index 06a74321..5f250d52 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -82,6 +82,7 @@ typedef void *EGLContext;
#include "shared/string-helpers.h"
#include "window.h"
+#include "viewporter-client-protocol.h"
#define ZWP_RELATIVE_POINTER_MANAGER_V1_VERSION 1
#define ZWP_POINTER_CONSTRAINTS_V1_VERSION 1
@@ -147,6 +148,7 @@ struct display {
int has_rgb565;
int data_device_manager_version;
+ struct wp_viewporter *viewporter;
};
struct window_output {
@@ -222,6 +224,7 @@ struct surface {
cairo_surface_t *cairo_surface;
struct wl_list link;
+ struct wp_viewport *viewport;
};
struct window {
@@ -320,6 +323,8 @@ struct widget {
* redraw handler is going to do completely custom rendering
* such as using EGL directly */
int use_cairo;
+ int viewport_dest_width;
+ int viewport_dest_height;
};
struct touch_point {
@@ -1398,6 +1403,7 @@ display_get_pointer_image(struct display *display, int pointer)
static void
surface_flush(struct surface *surface)
{
+ struct widget *widget = surface->widget;
if (!surface->cairo_surface)
return;
@@ -1415,6 +1421,12 @@ surface_flush(struct surface *surface)
surface->input_region = NULL;
}
+ if (surface->viewport) {
+ wp_viewport_set_destination(surface->viewport,
+ widget->viewport_dest_width,
+ widget->viewport_dest_height);
+ }
+
surface->toysurface->swap(surface->toysurface,
surface->buffer_transform, surface->buffer_scale,
&surface->server_allocation);
@@ -1620,6 +1632,8 @@ static struct widget *
widget_find_widget(struct widget *widget, int32_t x, int32_t y)
{
struct widget *child, *target;
+ int alloc_x, alloc_y, width, height;
+ double scale;
wl_list_for_each(child, &widget->child_list, link) {
target = widget_find_widget(child, x, y);
@@ -1627,10 +1641,24 @@ widget_find_widget(struct widget *widget, int32_t x, int32_t y)
return target;
}
- if (widget->allocation.x <= x &&
- x < widget->allocation.x + widget->allocation.width &&
- widget->allocation.y <= y &&
- y < widget->allocation.y + widget->allocation.height) {
+ alloc_x = widget->allocation.x;
+ alloc_y = widget->allocation.y;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ if (widget->viewport_dest_width != -1 &&
+ widget->viewport_dest_height != -1) {
+ scale = widget->viewport_dest_width / (double) width;
+ alloc_x = alloc_x * scale;
+ width = widget->viewport_dest_width;
+
+ scale = widget->viewport_dest_height / (double) height;
+ alloc_y = alloc_y * scale;
+ height = widget->viewport_dest_height;
+ }
+
+ if (alloc_x <= x && x < alloc_x + width &&
+ alloc_y <= y && y < alloc_y + height) {
return widget;
}
@@ -1668,6 +1696,8 @@ widget_create(struct window *window, struct surface *surface, void *data)
widget->tooltip_count = 0;
widget->default_cursor = CURSOR_LEFT_PTR;
widget->use_cairo = 1;
+ widget->viewport_dest_width = -1;
+ widget->viewport_dest_height = -1;
return widget;
}
@@ -2025,6 +2055,39 @@ widget_set_use_cairo(struct widget *widget,
widget->use_cairo = use_cairo;
}
+int
+widget_set_viewport_destination(struct widget *widget, int width, int height)
+{
+ struct window *window = widget->window;
+ struct display *display = window->display;
+ struct surface *surface = widget->surface;
+ if (!display->viewporter)
+ return -1;
+
+ if (width == -1 && height == -1) {
+ if (surface->viewport) {
+ wp_viewport_destroy(surface->viewport);
+ surface->viewport = NULL;
+ }
+
+ widget->viewport_dest_width = -1;
+ widget->viewport_dest_height = -1;
+ return 0;
+ }
+
+ if (!surface->viewport) {
+ surface->viewport = wp_viewporter_get_viewport(display->viewporter,
+ surface->surface);
+ if (!surface->viewport)
+ return -1;
+ }
+
+ widget->viewport_dest_width = width;
+ widget->viewport_dest_height = height;
+
+ return 0;
+}
+
cairo_surface_t *
window_get_surface(struct window *window)
{
@@ -5165,6 +5228,7 @@ surface_create(struct window *window)
wl_surface_add_listener(surface->surface, &surface_listener, window);
wl_list_insert(&window->subsurface_list, &surface->link);
+ surface->viewport = NULL;
return surface;
}
@@ -6003,6 +6067,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
d->subcompositor =
wl_registry_bind(registry, id,
&wl_subcompositor_interface, 1);
+ } else if (!strcmp(interface, "wp_viewporter")) {
+ d->viewporter =
+ wl_registry_bind(registry, id,
+ &wp_viewporter_interface, 1);
}
if (d->global_handler)