window: Make resize and redraw handlers widget vfuncs
diff --git a/clients/window.c b/clients/window.c
index 5f80721..b736b81 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -115,6 +115,8 @@
int resize_edges;
int redraw_scheduled;
struct task redraw_task;
+ int resize_scheduled;
+ struct task resize_task;
int minimum_width, minimum_height;
int margin;
int type;
@@ -126,8 +128,6 @@
cairo_surface_t *cairo_surface, *pending_surface;
- window_resize_handler_t resize_handler;
- window_redraw_handler_t redraw_handler;
window_key_handler_t key_handler;
window_keyboard_focus_handler_t keyboard_focus_handler;
window_data_handler_t data_handler;
@@ -148,6 +148,8 @@
struct window *window;
struct wl_list link;
struct rectangle allocation;
+ widget_resize_handler_t resize_handler;
+ widget_redraw_handler_t redraw_handler;
widget_enter_handler_t enter_handler;
widget_leave_handler_t leave_handler;
widget_motion_handler_t motion_handler;
@@ -1009,6 +1011,8 @@
if (window->redraw_scheduled)
wl_list_remove(&window->redraw_task.link);
+ if (window->resize_scheduled)
+ wl_list_remove(&window->resize_task.link);
wl_list_for_each(input, &display->input_list, link) {
if (input->pointer_focus == window)
@@ -1101,6 +1105,20 @@
}
void
+widget_set_resize_handler(struct widget *widget,
+ widget_resize_handler_t handler)
+{
+ widget->resize_handler = handler;
+}
+
+void
+widget_set_redraw_handler(struct widget *widget,
+ widget_redraw_handler_t handler)
+{
+ widget->redraw_handler = handler;
+}
+
+void
widget_set_enter_handler(struct widget *widget, widget_enter_handler_t handler)
{
widget->enter_handler = handler;
@@ -1858,39 +1876,75 @@
}
static void
+window_resize(struct window *window, int32_t width, int32_t height)
+{
+ struct widget *widget;
+ struct rectangle allocation;
+
+ if (window->decoration) {
+ allocation.x = 20;
+ allocation.y = 60;
+ allocation.width = width - 20 - window->margin * 2;
+ allocation.height = height - 60 - window->margin * 2;
+ } else {
+ allocation.x = 0;
+ allocation.y = 0;
+ allocation.width = width;
+ allocation.height = height;
+ }
+
+ window->allocation.width = width;
+ window->allocation.height = height;
+
+ wl_list_for_each(widget, &window->widget_list, link) {
+ if (widget->resize_handler)
+ widget->resize_handler(widget,
+ allocation.width,
+ allocation.height,
+ widget->user_data);
+ else
+ widget->allocation = allocation;
+ }
+
+ window_schedule_redraw(window);
+}
+
+static void
+idle_resize(struct task *task, uint32_t events)
+{
+ struct window *window =
+ container_of(task, struct window, resize_task);
+
+ window_resize(window,
+ window->allocation.width, window->allocation.height);
+ window->resize_scheduled = 0;
+}
+
+void
+window_schedule_resize(struct window *window, int width, int height)
+{
+ if (!window->resize_scheduled) {
+ window->allocation.width = width;
+ window->allocation.height = height;
+ window->resize_task.run = idle_resize;
+ display_defer(window->display, &window->resize_task);
+ window->resize_scheduled = 1;
+ }
+}
+
+static void
handle_configure(void *data, struct wl_shell_surface *shell_surface,
uint32_t time, uint32_t edges,
int32_t width, int32_t height)
{
struct window *window = data;
- struct widget *widget;
- int32_t child_width, child_height;
- /* FIXME: this is probably the wrong place to check for width
- * or height <= 0, but it prevents the compositor from crashing
- */
if (width <= 0 || height <= 0)
return;
window->resize_edges = edges;
- 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->allocation.width = width;
- window->allocation.height = height;
-
- if (window->redraw_handler)
- window_schedule_redraw(window);
- }
-
- wl_list_for_each(widget, &window->widget_list, link)
- widget->allocation = window->allocation;
+ window_resize(window, width, height);
}
static void
@@ -1954,12 +2008,14 @@
{
struct window *window =
container_of(task, struct window, redraw_task);
+ struct widget *widget;
window_create_surface(window);
if (window->decoration)
window_draw_decorations(window);
- window->redraw_handler(window, window->user_data);
+ wl_list_for_each_reverse(widget, &window->widget_list, link)
+ widget->redraw_handler(widget, widget->user_data);
window_flush(window);
@@ -2006,7 +2062,7 @@
window->decoration = 1;
}
- (*window->resize_handler)(window, width, height, window->user_data);
+ window_resize(window, width, height);
}
void
@@ -2028,20 +2084,6 @@
}
void
-window_set_resize_handler(struct window *window,
- window_resize_handler_t handler)
-{
- window->resize_handler = handler;
-}
-
-void
-window_set_redraw_handler(struct window *window,
- window_redraw_handler_t handler)
-{
- window->redraw_handler = handler;
-}
-
-void
window_set_key_handler(struct window *window,
window_key_handler_t handler)
{
@@ -2246,12 +2288,13 @@
}
static void
-menu_redraw_handler(struct window *window, void *data)
+menu_redraw_handler(struct widget *widget, void *data)
{
cairo_t *cr;
const int32_t r = 3, margin = 3;
struct menu *menu = data;
int32_t width, height, i;
+ struct window *window = widget->window;
cr = cairo_create(window->cairo_surface);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
@@ -2319,9 +2362,7 @@
window->parent->shell_surface,
window->x, window->y, 0);
- window_set_redraw_handler(window, menu_redraw_handler);
- window_set_user_data(window, menu);
-
+ widget_set_redraw_handler(menu->widget, menu_redraw_handler);
widget_set_enter_handler(menu->widget, menu_enter_handler);
widget_set_leave_handler(menu->widget, menu_leave_handler);
widget_set_motion_handler(menu->widget, menu_motion_handler);