window.c: Move window items to window.c
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 21 Sep 2011 01:43:54 +0000 (21:43 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 21 Sep 2011 01:43:54 +0000 (21:43 -0400)
clients/desktop-shell.c
clients/window.c
clients/window.h

index d7833e5..496d0d1 100644 (file)
@@ -46,14 +46,12 @@ struct desktop {
 
 struct panel {
        struct window *window;
-       struct wl_list item_list;
-       struct panel_item *focus;
 };
 
 struct panel_item {
-       struct wl_list link;
+       struct item *item;
+       struct panel *panel;
        cairo_surface_t *icon;
-       int x, y, width, height;
        int pressed;
        const char *path;
 };
@@ -88,41 +86,38 @@ panel_activate_item(struct panel *panel, struct panel_item *item)
        }
 }
 
-static struct panel_item *
-panel_find_item(struct panel *panel, int32_t x, int32_t y)
-{
-       struct panel_item *item;
-
-       wl_list_for_each(item, &panel->item_list, link) {
-               if (item->x <= x && x < item->x + item->width &&
-                   item->y <= y && y < item->y + item->height) {
-                       return item;
-               }
-       }
-
-       return NULL;
-}
-
 static void
-panel_draw_item(struct panel *panel, cairo_t *cr, struct panel_item *item)
+panel_draw_item(struct item *item, void *data)
 {
-       int x, y;
-
-       if (item->pressed) {
-               x = item->x + 1;
-               y = item->y + 1;
-       } else {
-               x = item->x;
-               y = item->y;
+       cairo_t *cr = data;
+       struct panel_item *pi;
+       int x, y, width, height;
+       double dx, dy;
+
+       pi = item_get_user_data(item);
+       width = cairo_image_surface_get_width(pi->icon);
+       height = cairo_image_surface_get_height(pi->icon);
+       x = 0;
+       y = -height / 2;
+       if (pi->pressed) {
+               x++;
+               y++;
        }
 
-       cairo_set_source_surface(cr, item->icon, x, y);
+       dx = x;
+       dy = y;
+       cairo_user_to_device(cr, &dx, &dy);
+       item_set_allocation(item, dx, dy, width, height);
+
+       cairo_set_source_surface(cr, pi->icon, x, y);
        cairo_paint(cr);
 
-       if (panel->focus == item) {
+       if (window_get_focus_item(pi->panel->window) == item) {
                cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
-               cairo_mask_surface(cr, item->icon, x, y);
+               cairo_mask_surface(cr, pi->icon, x, y);
        }
+
+       cairo_translate(cr, width + 10, 0);
 }
 
 static void
@@ -130,8 +125,6 @@ panel_redraw_handler(struct window *window, void *data)
 {
        cairo_surface_t *surface;
        cairo_t *cr;
-       struct panel *panel = window_get_user_data(window);
-       struct panel_item *item;
 
        window_draw(window);
        surface = window_get_surface(window);
@@ -141,8 +134,8 @@ panel_redraw_handler(struct window *window, void *data)
        cairo_paint(cr);
 
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-       wl_list_for_each(item, &panel->item_list, link)
-               panel_draw_item(panel, cr, item);
+       cairo_translate(cr, 10, 32 / 2);
+       window_for_each_item(window, panel_draw_item, cr);
 
        cairo_destroy(cr);
        cairo_surface_destroy(surface);
@@ -150,54 +143,10 @@ panel_redraw_handler(struct window *window, void *data)
 }
 
 static void
-panel_set_focus(struct panel *panel, struct panel_item *focus)
+panel_item_focus_handler(struct window *window,
+                        struct item *focus, void *data)
 {
-       if (focus == panel->focus)
-               return;
-
-       panel->focus = focus;
-       window_schedule_redraw(panel->window);
-}
-
-static int
-panel_enter_handler(struct window *window,
-                   struct input *input, uint32_t time,
-                   int32_t x, int32_t y, void *data)
-{
-       struct panel *panel = data;
-       struct panel_item *item;
-
-       item = panel_find_item(panel, x, y);
-       panel_set_focus(panel, item);
-
-       return POINTER_LEFT_PTR;
-}
-
-static void
-panel_leave_handler(struct window *window,
-                   struct input *input, uint32_t time, void *data)
-{
-       struct panel *panel = data;
-
-       panel_set_focus(panel, NULL);
-}
-
-static int
-panel_motion_handler(struct window *window,
-                    struct input *input, uint32_t time,
-                    int32_t x, int32_t y,
-                    int32_t sx, int32_t sy, void *data)
-{
-       struct panel *panel = data;
-       struct panel_item *item;
-
-       if (panel->focus && panel->focus->pressed)
-               return POINTER_LEFT_PTR;
-
-       item = panel_find_item(panel, sx, sy);
-       panel_set_focus(panel, item);
-
-       return POINTER_LEFT_PTR;
+       window_schedule_redraw(window);
 }
 
 static void
@@ -206,20 +155,15 @@ panel_button_handler(struct window *window,
                     int button, int state, void *data)
 {
        struct panel *panel = data;
-       struct panel_item *item;
-       int32_t x, y;
+       struct panel_item *pi;
+       struct item *focus;
 
-       if (panel->focus && button == BTN_LEFT) {
-               panel->focus->pressed = state;
+       focus = window_get_focus_item(panel->window);
+       if (focus && button == BTN_LEFT) {
+               pi = item_get_user_data(focus);
                window_schedule_redraw(panel->window);
-
-               if (state == 0) {
-                       panel_activate_item(panel, panel->focus);
-
-                       input_get_position(input, &x, &y);
-                       item = panel_find_item(panel, x, y);
-                       panel_set_focus(panel, item);
-               }
+               if (state == 0)
+                       panel_activate_item(panel, pi);
        }
 }
 
@@ -230,7 +174,6 @@ panel_create(struct display *display)
 
        panel = malloc(sizeof *panel);
        memset(panel, 0, sizeof *panel);
-       wl_list_init(&panel->item_list);
 
        panel->window = window_create(display, 0, 0);
 
@@ -239,10 +182,8 @@ panel_create(struct display *display)
        window_set_redraw_handler(panel->window, panel_redraw_handler);
        window_set_custom(panel->window);
        window_set_user_data(panel->window, panel);
-       window_set_enter_handler(panel->window, panel_enter_handler);
-       window_set_leave_handler(panel->window, panel_leave_handler);
-       window_set_motion_handler(panel->window, panel_motion_handler);
        window_set_button_handler(panel->window, panel_button_handler);
+       window_set_item_focus_handler(panel->window, panel_item_focus_handler);
 
        return panel;
 }
@@ -256,27 +197,8 @@ panel_add_item(struct panel *panel, const char *icon, const char *path)
        memset(item, 0, sizeof *item);
        item->icon = cairo_image_surface_create_from_png(icon);
        item->path = strdup(path);
-       wl_list_insert(panel->item_list.prev, &item->link);
-
-       item->width = cairo_image_surface_get_width(item->icon);
-       item->height = cairo_image_surface_get_height(item->icon);
-}
-
-static void
-panel_allocate(struct panel *panel, int width, int height)
-{
-       struct panel_item *item;
-       int x;
-
-       window_set_child_size(panel->window, width, height);
-       window_schedule_redraw(panel->window);
-
-       x = 10;
-       wl_list_for_each(item, &panel->item_list, link) {
-               item->x = x;
-               item->y = (height - item->height) / 2;
-               x += item->width + 10;
-       }
+       item->panel = panel;
+       window_add_item(panel->window, item);
 }
 
 static void
@@ -324,7 +246,8 @@ desktop_shell_configure(void *data,
        struct desktop *desktop = data;
 
        if (surface == window_get_wl_surface(desktop->panel->window)) {
-               panel_allocate(desktop->panel, width, 32);
+               window_set_child_size(desktop->panel->window, width, 32);
+               window_schedule_redraw(desktop->panel->window);
        } else if (surface == window_get_wl_surface(desktop->background)) {
                background_draw(desktop->background,
                                width, height, desktop->background_path);
index e7a61ef..9e92adb 100644 (file)
@@ -125,11 +125,22 @@ struct window {
        window_motion_handler_t motion_handler;
        window_enter_handler_t enter_handler;
        window_leave_handler_t leave_handler;
+       window_item_focus_handler_t item_focus_handler;
+
+       struct wl_list item_list;
+       struct item *focus_item;
+       uint32_t item_grab_button;
 
        void *user_data;
        struct wl_list link;
 };
 
+struct item {
+       struct wl_list link;
+       struct rectangle allocation;
+       void *user_data;
+};
+
 struct input {
        struct display *display;
        struct wl_input_device *input_device;
@@ -949,6 +960,73 @@ window_destroy(struct window *window)
        free(window);
 }
 
+static struct item *
+window_find_item(struct window *window, int32_t x, int32_t y)
+{
+       struct item *item;
+
+       wl_list_for_each(item, &window->item_list, link) {
+               if (item->allocation.x <= x &&
+                   x < item->allocation.x + item->allocation.width &&
+                   item->allocation.y <= y &&
+                   y < item->allocation.y + item->allocation.height) {
+                       return item;
+               }
+       }
+
+       return NULL;
+}
+
+struct item *
+window_add_item(struct window *window, void *data)
+{
+       struct item *item;
+
+       item = malloc(sizeof *item);
+       memset(item, 0, sizeof *item);
+       item->user_data = data;
+       wl_list_insert(window->item_list.prev, &item->link);
+
+       return item;
+}
+
+void
+window_for_each_item(struct window *window, item_func_t func, void *data)
+{
+       struct item *item;
+
+       wl_list_for_each(item, &window->item_list, link)
+               func(item, data);
+}
+
+struct item *
+window_get_focus_item(struct window *window)
+{
+       return window->focus_item;
+}
+
+void
+item_get_allocation(struct item *item, struct rectangle *allocation)
+{
+       *allocation = item->allocation;
+}
+
+void
+item_set_allocation(struct item *item,
+                   int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       item->allocation.x = x;
+       item->allocation.y = y;
+       item->allocation.width = width;
+       item->allocation.height = height;
+}
+
+void *
+item_get_user_data(struct item *item)
+{
+       return item->user_data;
+}
+
 void
 display_flush_cairo_device(struct display *display)
 {
@@ -1079,12 +1157,27 @@ set_pointer_image(struct input *input, uint32_t time, int pointer)
 }
 
 static void
+window_set_focus_item(struct window *window, struct item *focus)
+{
+       void *data;
+
+       if (focus == window->focus_item)
+               return;
+
+       window->focus_item = focus;
+       data = focus ? focus->user_data : NULL;
+       if (window->item_focus_handler)
+               window->item_focus_handler(window, focus, data);
+}
+
+static void
 window_handle_motion(void *data, struct wl_input_device *input_device,
                     uint32_t time,
                     int32_t x, int32_t y, int32_t sx, int32_t sy)
 {
        struct input *input = data;
        struct window *window = input->pointer_focus;
+       struct item *item;
        int pointer = POINTER_LEFT_PTR;
 
        input->x = x;
@@ -1092,6 +1185,11 @@ window_handle_motion(void *data, struct wl_input_device *input_device,
        input->sx = sx;
        input->sy = sy;
 
+       if (!window->focus_item || !window->item_grab_button) {
+               item = window_find_item(window, sx, sy);
+               window_set_focus_item(window, item);
+       }
+
        if (window->motion_handler)
                pointer = (*window->motion_handler)(window, input, time,
                                                    x, y, sx, sy,
@@ -1107,8 +1205,12 @@ window_handle_button(void *data,
 {
        struct input *input = data;
        struct window *window = input->pointer_focus;
+       struct item *item;
        int location;
 
+       if (window->focus_item && window->item_grab_button == 0 && state)
+               window->item_grab_button = button;
+
        location = get_pointer_location(window, input->sx, input->sy);
 
        if (button == BTN_LEFT && state == 1) {
@@ -1144,6 +1246,13 @@ window_handle_button(void *data,
                                                  button, state,
                                                  window->user_data);
        }
+
+       if (window->focus_item &&
+           window->item_grab_button == button && !state) {
+               window->item_grab_button = 0;
+               item = window_find_item(window, input->sx, input->sy);
+               window_set_focus_item(window, item);
+       }
 }
 
 static void
@@ -1184,10 +1293,13 @@ window_handle_pointer_focus(void *data,
 {
        struct input *input = data;
        struct window *window;
+       struct item *item;
        int pointer;
 
        window = input->pointer_focus;
        if (window && window->surface != surface) {
+               window_set_focus_item(window, NULL);
+
                if (window->leave_handler)
                        window->leave_handler(window, input,
                                              time, window->user_data);
@@ -1210,8 +1322,10 @@ window_handle_pointer_focus(void *data,
                                                        time, sx, sy,
                                                        window->user_data);
 
-               set_pointer_image(input, time, pointer);
+               item = window_find_item(window, x, y);
+               window_set_focus_item(window, item);
 
+               set_pointer_image(input, time, pointer);
        }
 }
 
@@ -1504,6 +1618,13 @@ window_set_keyboard_focus_handler(struct window *window,
 }
 
 void
+window_set_item_focus_handler(struct window *window,
+                             window_item_focus_handler_t handler)
+{
+       window->item_focus_handler = handler;
+}
+
+void
 window_set_transparent(struct window *window, int transparent)
 {
        window->transparent = transparent;
@@ -1562,6 +1683,7 @@ window_create_internal(struct display *display, struct window *parent,
        window->margin = 16;
        window->decoration = 1;
        window->transparent = 1;
+       wl_list_init(&window->item_list);
 
        if (display->dpy)
 #ifdef HAVE_CAIRO_EGL
index df819bf..2409197 100644 (file)
@@ -29,6 +29,9 @@
 #include <cairo.h>
 
 struct window;
+struct item;
+struct display;
+struct input;
 
 struct task {
        void (*run)(struct task *task, uint32_t events);
@@ -42,9 +45,6 @@ struct rectangle {
        int32_t height;
 };
 
-struct display;
-struct input;
-
 struct display *
 display_create(int *argc, char **argv[], const GOptionEntry *option_entries);
 
@@ -156,6 +156,9 @@ typedef int (*window_motion_handler_t)(struct window *window,
                                       int32_t x, int32_t y,
                                       int32_t sx, int32_t sy, void *data);
 
+typedef void (*window_item_focus_handler_t)(struct window *window,
+                                           struct item *focus, void *data);
+
 struct window *
 window_create(struct display *display, int32_t width, int32_t height);
 struct window *
@@ -165,6 +168,17 @@ window_create_transient(struct display *display, struct window *parent,
 void
 window_destroy(struct window *window);
 
+struct item *
+window_add_item(struct window *window, void *data);
+
+typedef void (*item_func_t)(struct item *item, void *data);
+
+void
+window_for_each_item(struct window *window, item_func_t func, void *data);
+
+struct item *
+window_get_focus_item(struct window *window);
+
 void
 window_move(struct window *window, struct input *input, uint32_t time);
 
@@ -265,6 +279,10 @@ window_set_keyboard_focus_handler(struct window *window,
                                  window_keyboard_focus_handler_t handler);
 
 void
+window_set_item_focus_handler(struct window *window,
+                             window_item_focus_handler_t handler);
+
+void
 window_set_title(struct window *window, const char *title);
 
 const char *
@@ -278,6 +296,16 @@ window_activate_drag(struct wl_drag *drag, struct window *window,
                     struct input *input, uint32_t time);
 
 void
+item_get_allocation(struct item *item, struct rectangle *allocation);
+
+void
+item_set_allocation(struct item *item,
+                   int32_t x, int32_t y, int32_t width, int32_t height);
+
+void *
+item_get_user_data(struct item *item);
+
+void
 input_get_position(struct input *input, int32_t *x, int32_t *y);
 
 uint32_t