commit 5f0e5d591c85c13948b9b469ee7441fe0a79db25
parent 57bad52d1604a3cbdb8d0e1f64b1fde97c858a20
Author: Michael Forney <mforney@mforney.org>
Date: Sat, 16 Aug 2014 16:43:54 -0700
window: Implement interactive resizing
Diffstat:
5 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/libswc/panel.c b/libswc/panel.c
@@ -152,7 +152,8 @@ static const struct swc_panel_interface panel_implementation = {
.set_strut = &set_strut
};
-static void handle_resize(struct view_handler * handler)
+static void handle_resize(struct view_handler * handler,
+ uint32_t old_width, uint32_t old_height)
{
struct panel * panel = wl_container_of(handler, panel, view_handler);
diff --git a/libswc/view.c b/libswc/view.c
@@ -106,9 +106,12 @@ bool view_set_size(struct view * view, uint32_t width, uint32_t height)
if (view->geometry.width == width && view->geometry.height == height)
return false;
+ uint32_t old_width = view->geometry.width,
+ old_height = view->geometry.height;
+
view->geometry.width = width;
view->geometry.height = height;
- HANDLE(view, handler, resize);
+ HANDLE(view, handler, resize, old_width, old_height);
return true;
}
diff --git a/libswc/view.h b/libswc/view.h
@@ -74,7 +74,8 @@ struct view_handler_impl
/* Called after the view's position changes. */
void (* move)(struct view_handler * handler);
/* Called after the view's size changes. */
- void (* resize)(struct view_handler * handler);
+ void (* resize)(struct view_handler * handler,
+ uint32_t old_width, uint32_t old_height);
/* Called when the set of screens the view is visible on changes. */
void (* screens)(struct view_handler * handler,
uint32_t left, uint32_t entered);
diff --git a/libswc/window.c b/libswc/window.c
@@ -263,7 +263,22 @@ static bool move_motion(struct pointer_handler * handler, uint32_t time,
static bool resize_motion(struct pointer_handler * handler, uint32_t time,
wl_fixed_t fx, wl_fixed_t fy)
{
- /* TODO: Implement interactive resizing */
+ struct window * window
+ = wl_container_of(handler, window, resize.interaction.handler);
+ const struct swc_rectangle * geometry = &window->view->base.geometry;
+ uint32_t width = geometry->width, height = geometry->height;
+
+ if (window->resize.edges & SWC_WINDOW_EDGE_LEFT)
+ width -= wl_fixed_to_int(fx) + window->resize.offset.x - geometry->x;
+ else if (window->resize.edges & SWC_WINDOW_EDGE_RIGHT)
+ width = wl_fixed_to_int(fx) + window->resize.offset.x - geometry->x;
+
+ if (window->resize.edges & SWC_WINDOW_EDGE_TOP)
+ height -= wl_fixed_to_int(fy) + window->resize.offset.y - geometry->y;
+ else if (window->resize.edges & SWC_WINDOW_EDGE_BOTTOM)
+ height = wl_fixed_to_int(fy) + window->resize.offset.y - geometry->y;
+
+ window->impl->configure(window, width, height);
return true;
}
@@ -286,6 +301,30 @@ static bool handle_button(struct pointer_handler * handler, uint32_t time,
return true;
}
+static void handle_resize(struct view_handler * handler,
+ uint32_t old_width, uint32_t old_height)
+{
+ struct window * window = wl_container_of(handler, window, view_handler);
+
+ if (window->resize.interaction.active
+ && window->resize.edges & (SWC_WINDOW_EDGE_TOP | SWC_WINDOW_EDGE_LEFT))
+ {
+ const struct swc_rectangle * geometry = &window->view->base.geometry;
+ int32_t x = geometry->x, y = geometry->y;
+
+ if (window->resize.edges & SWC_WINDOW_EDGE_LEFT)
+ x += old_width - geometry->width;
+ if (window->resize.edges & SWC_WINDOW_EDGE_TOP)
+ y += old_height - geometry->height;
+
+ view_move(&window->view->base, x, y);
+ }
+}
+
+static const struct view_handler_impl view_handler_impl = {
+ .resize = &handle_resize,
+};
+
bool window_initialize(struct window * window, const struct window_impl * impl,
struct swc_surface * surface)
{
@@ -300,6 +339,7 @@ bool window_initialize(struct window * window, const struct window_impl * impl,
window->impl = impl;
window->handler = &null_handler;
+ window->view_handler.impl = &view_handler_impl;
window->view->window = window;
window->managed = false;
window->mode = WINDOW_MODE_STACKED;
@@ -314,6 +354,8 @@ bool window_initialize(struct window * window, const struct window_impl * impl,
.button = &handle_button
};
+ wl_list_insert(&window->view->base.handlers, &window->view_handler.link);
+
return true;
}
@@ -401,13 +443,24 @@ void window_begin_resize(struct window * window, uint32_t edges,
return;
}
+ struct swc_rectangle * geometry = &window->view->base.geometry;
+ int32_t px = wl_fixed_to_int(swc.seat->pointer->x),
+ py = wl_fixed_to_int(swc.seat->pointer->y);
+
begin_interaction(&window->resize.interaction, button);
if (!edges)
{
- /* TODO: Calculate edges to use */
+ edges |= (px < geometry->x + geometry->width / 2)
+ ? SWC_WINDOW_EDGE_LEFT : SWC_WINDOW_EDGE_RIGHT;
+ edges |= (py < geometry->y + geometry->height / 2)
+ ? SWC_WINDOW_EDGE_TOP : SWC_WINDOW_EDGE_BOTTOM;
}
+ window->resize.offset.x = geometry->x - px
+ + ((edges & SWC_WINDOW_EDGE_RIGHT) ? geometry->width : 0);
+ window->resize.offset.y = geometry->y - py
+ + ((edges & SWC_WINDOW_EDGE_BOTTOM) ? geometry->height : 0);
window->resize.edges = edges;
}
diff --git a/libswc/window.h b/libswc/window.h
@@ -52,6 +52,7 @@ struct window
void * handler_data;
struct compositor_view * view;
+ struct view_handler view_handler;
bool managed;
enum window_mode mode;
@@ -64,6 +65,7 @@ struct window
struct
{
struct window_pointer_interaction interaction;
+ struct { int32_t x, y; } offset;
uint32_t edges;
} resize;
};