From 441338cb75202f6def0619bdecc3cc15fd1e5cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 10 Jan 2012 13:52:34 -0500 Subject: [PATCH] window: Keep widgets in a tree instead of a list --- clients/desktop-shell.c | 4 +- clients/window.c | 98 ++++++++++++++++++++++++++--------------- clients/window.h | 9 ++-- 3 files changed, 69 insertions(+), 42 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 7d8f5267..49aa0131 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -334,7 +334,7 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path) launcher->panel = panel; wl_list_insert(panel->launcher_list.prev, &launcher->link); - launcher->widget = window_add_widget(panel->window, launcher); + launcher->widget = widget_add_widget(panel->widget, launcher); widget_set_enter_handler(launcher->widget, panel_launcher_enter_handler); widget_set_leave_handler(launcher->widget, @@ -508,7 +508,7 @@ unlock_dialog_create(struct desktop *desktop) window_set_user_data(dialog->window, dialog); window_set_keyboard_focus_handler(dialog->window, unlock_dialog_keyboard_focus_handler); - dialog->button = window_add_widget(dialog->window, NULL); + dialog->button = widget_add_widget(dialog->widget, dialog); widget_set_redraw_handler(dialog->widget, unlock_dialog_redraw_handler); widget_set_enter_handler(dialog->button, diff --git a/clients/window.c b/clients/window.c index 4e506a54..67e8dd05 100644 --- a/clients/window.c +++ b/clients/window.c @@ -134,7 +134,7 @@ struct window { window_drop_handler_t drop_handler; window_close_handler_t close_handler; - struct wl_list widget_list; + struct widget *widget; struct widget *focus_widget; uint32_t widget_grab_button; @@ -146,6 +146,7 @@ struct window { struct widget { struct window *window; + struct wl_list child_list; struct wl_list link; struct rectangle allocation; widget_resize_handler_t resize_handler; @@ -1036,24 +1037,28 @@ window_destroy(struct window *window) } static struct widget * -window_find_widget(struct window *window, int32_t x, int32_t y) +widget_find_widget(struct widget *widget, int32_t x, int32_t y) { - struct widget *widget; + struct widget *child, *target; - wl_list_for_each(widget, &window->widget_list, link) { - if (widget->allocation.x <= x && - x < widget->allocation.x + widget->allocation.width && - widget->allocation.y <= y && - y < widget->allocation.y + widget->allocation.height) { - return widget; - } + wl_list_for_each(child, &widget->child_list, link) { + target = widget_find_widget(child, x, y); + if (target) + 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) { + return widget; } return NULL; } -struct widget * -window_add_widget(struct window *window, void *data) +static struct widget * +widget_create(struct window *window, void *data) { struct widget *widget; @@ -1062,18 +1067,36 @@ window_add_widget(struct window *window, void *data) widget->window = window; widget->user_data = data; widget->allocation = window->allocation; - wl_list_insert(&window->widget_list, &widget->link); + wl_list_init(&widget->child_list); + + return widget; +} + +struct widget * +window_add_widget(struct window *window, void *data) +{ + window->widget = widget_create(window, data); + wl_list_init(&window->widget->link); + + return window->widget; +} + +struct widget * +widget_add_widget(struct widget *parent, void *data) +{ + struct widget *widget; + + widget = widget_create(parent->window, data); + wl_list_insert(parent->child_list.prev, &widget->link); return widget; } void -window_for_each_widget(struct window *window, widget_func_t func, void *data) +widget_destroy(struct widget *widget) { - struct widget *widget; - - wl_list_for_each(widget, &window->widget_list, link) - func(widget, data); + wl_list_remove(&widget->link); + free(widget); } struct widget * @@ -1308,7 +1331,7 @@ input_handle_motion(void *data, struct wl_input_device *input_device, input->sy = sy; if (!window->focus_widget || !window->widget_grab_button) { - widget = window_find_widget(window, sx, sy); + widget = widget_find_widget(window->widget, sx, sy); window_set_focus_widget(window, widget, input, time, sx, sy); } @@ -1425,7 +1448,8 @@ input_handle_button(void *data, if (window->focus_widget && window->widget_grab_button == button && !state) { window->widget_grab_button = 0; - widget = window_find_widget(window, input->sx, input->sy); + widget = widget_find_widget(window->widget, + input->sx, input->sy); window_set_focus_widget(window, widget, input, time, input->sx, input->sy); } @@ -1500,7 +1524,7 @@ input_handle_pointer_focus(void *data, input->sy = sy; pointer = POINTER_LEFT_PTR; - widget = window_find_widget(window, sx, sy); + widget = widget_find_widget(window->widget, sx, sy); window_set_focus_widget(window, widget, input, time, sx, sy); pointer = input_get_pointer_image_for_location(input, pointer); @@ -1878,7 +1902,6 @@ window_move(struct window *window, struct input *input, uint32_t time) static void window_resize(struct window *window, int32_t width, int32_t height) { - struct widget *widget; struct rectangle allocation; if (window->decoration) { @@ -1896,15 +1919,14 @@ window_resize(struct window *window, int32_t width, int32_t 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, + widget_set_allocation(window->widget, allocation.x, allocation.y, + allocation.width, allocation.height); + + if (window->widget->resize_handler) + window->widget->resize_handler(window->widget, allocation.width, allocation.height, - widget->user_data); - else - widget->allocation = allocation; - } + window->widget->user_data); window_schedule_redraw(window); } @@ -2003,24 +2025,32 @@ window_set_child_size(struct window *window, int32_t width, int32_t height) } } +static void +widget_redraw(struct widget *widget) +{ + struct widget *child; + + if (widget->redraw_handler) + widget->redraw_handler(widget, widget->user_data); + wl_list_for_each(child, &widget->child_list, link) + widget_redraw(child); +} + static void idle_redraw(struct task *task, uint32_t events) { struct window *window = container_of(task, struct window, redraw_task); - struct widget *widget; window_create_surface(window); if (window->decoration) window_draw_decorations(window); - wl_list_for_each_reverse(widget, &window->widget_list, link) - widget->redraw_handler(widget, widget->user_data); + widget_redraw(window->widget); window_flush(window); window->redraw_scheduled = 0; - } void @@ -2181,8 +2211,6 @@ window_create_internal(struct display *display, struct window *parent, window->decoration = 1; window->transparent = 1; - wl_list_init(&window->widget_list); - if (display->dpy) #ifdef HAVE_CAIRO_EGL /* FIXME: make TYPE_EGL_IMAGE choosable for testing */ diff --git a/clients/window.h b/clients/window.h index 6d35d66f..0bc7e5a9 100644 --- a/clients/window.h +++ b/clients/window.h @@ -215,14 +215,9 @@ window_destroy(struct window *window); struct widget * window_add_widget(struct window *window, void *data); -typedef void (*widget_func_t)(struct widget *widget, void *data); - typedef void (*data_func_t)(void *data, size_t len, int32_t x, int32_t y, void *user_data); -void -window_for_each_widget(struct window *window, widget_func_t func, void *data); - struct widget * window_get_focus_widget(struct window *window); struct display * @@ -329,6 +324,10 @@ window_set_title(struct window *window, const char *title); const char * window_get_title(struct window *window); +struct widget * +widget_add_widget(struct widget *parent, void *data); +void +widget_destroy(struct widget *widget); void widget_get_allocation(struct widget *widget, struct rectangle *allocation);