clients: Implement a toy-menu for testing the menu surface type
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 19 Dec 2011 20:40:10 +0000 (15:40 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 19 Dec 2011 20:40:10 +0000 (15:40 -0500)
clients/resizor.c
clients/window.c
clients/window.h

index 87c7af3..a31e0d7 100644 (file)
@@ -157,15 +157,17 @@ key_handler(struct window *window, struct input *input, uint32_t time,
 static void
 show_menu(struct resizor *resizor, struct input *input)
 {
-       int32_t x, y, width = 200, height = 200;
+       int32_t x, y;
+       static const char *entries[] = {
+               "Roy", "Pris", "Leon", "Zhora"
+       };
 
        input_get_position(input, &x, &y);
-       resizor->menu = window_create_transient(resizor->display,
-                                               resizor->window,
-                                               x - 10, y - 10, width, height);
+       resizor->menu = window_create_menu(resizor->display,
+                                          resizor->window,
+                                          x - 10, y - 10, entries, 4);
 
-       window_draw(resizor->menu);
-       window_flush(resizor->menu);
+       window_schedule_redraw(resizor->menu);
 }
 
 static void
@@ -179,8 +181,6 @@ button_handler(struct window *window,
        case BTN_RIGHT:
                if (state)
                        show_menu(resizor, input);
-               else
-                       window_destroy(resizor->menu);
                break;
        }
 }
index d06d4aa..09e9b70 100644 (file)
@@ -100,6 +100,7 @@ enum {
        TYPE_TOPLEVEL,
        TYPE_FULLSCREEN,
        TYPE_TRANSIENT,
+       TYPE_MENU,
        TYPE_CUSTOM
 };
        
@@ -772,6 +773,8 @@ window_set_type(struct window *window)
                                               window->parent->shell_surface,
                                               window->x, window->y, 0);
                break;
+       case TYPE_MENU:
+               break;
        case TYPE_CUSTOM:
                break;
        }
@@ -930,28 +933,6 @@ window_create_surface(struct window *window)
 }
 
 static void
-window_draw_menu(struct window *window)
-{
-       cairo_t *cr;
-       int width, height, r = 5;
-
-       window_create_surface(window);
-
-       cr = cairo_create(window->cairo_surface);
-       cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-       cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
-       cairo_paint(cr);
-
-       width = window->allocation.width;
-       height = window->allocation.height;
-       rounded_rect(cr, r, r, width - r, height - r, r);
-       cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-       cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5);
-       cairo_fill(cr);
-       cairo_destroy(cr);
-}
-
-static void
 window_draw_decorations(struct window *window)
 {
        cairo_t *cr;
@@ -1090,9 +1071,7 @@ item_get_user_data(struct item *item)
 void
 window_draw(struct window *window)
 {
-       if (window->parent)
-               window_draw_menu(window);
-       else if (!window->decoration)
+       if (!window->decoration)
                window_create_surface(window);
        else
                window_draw_decorations(window);
@@ -2041,6 +2020,146 @@ window_create_transient(struct display *display, struct window *parent,
        return window;
 }
 
+struct menu {
+       struct window *window;
+       const char **entries;
+       int current;
+       int count;
+};
+
+static int
+menu_set_item(struct window *window, struct menu *menu, int sy)
+{
+       int next;
+
+       next = (sy - 8) / 20;
+       if (menu->current != next) {
+               menu->current = next;
+               window_schedule_redraw(window);
+       }
+
+       return POINTER_LEFT_PTR;
+}
+
+static int
+menu_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)
+{
+       return menu_set_item(window, data, sy);
+}
+
+static int
+menu_enter_handler(struct window *window,
+                   struct input *input, uint32_t time,
+                   int32_t x, int32_t y, void *data)
+{
+       return menu_set_item(window, data, y);
+}
+
+static void
+menu_leave_handler(struct window *window,
+                  struct input *input, uint32_t time, void *data)
+{
+       menu_set_item(window, data, -200);
+}
+
+static void
+menu_button_handler(struct window *window,
+                   struct input *input, uint32_t time,
+                   int button, int state, void *data)
+
+{
+       struct menu *menu = data;
+
+       /* Either relase after press-drag-release or click-motion-click. */
+       if (state == 0 && 0 <= menu->current && menu->current < menu->count)
+               window_destroy(window);
+}
+
+static void
+menu_redraw_handler(struct window *window, void *data)
+{
+       cairo_t *cr;
+       const int32_t r = 3, margin = 3;
+       struct menu *menu = data;
+       int32_t width, height, i;
+
+       width = 200;
+       height = menu->count * 20 + margin * 2;
+       window_set_child_size(window, width, height);
+       window_create_surface(window);
+
+       cr = cairo_create(window->cairo_surface);
+       cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+       cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
+       cairo_paint(cr);
+
+       width = window->allocation.width;
+       height = window->allocation.height;
+       rounded_rect(cr, 0, 0, width, height, r);
+       cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+       cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
+       cairo_fill(cr);
+
+       for (i = 0; i < menu->count; i++) {
+               if (i == menu->current) {
+                       cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+                       cairo_rectangle(cr, margin, i * 20 + margin,
+                                       width - 2 * margin, 20);
+                       cairo_fill(cr);
+                       cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+                       cairo_move_to(cr, 10, i * 20 + 16);
+                       cairo_show_text(cr, menu->entries[i]);
+               } else {
+                       cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+                       cairo_move_to(cr, 10, i * 20 + 16);
+                       cairo_show_text(cr, menu->entries[i]);
+               }
+       }
+
+       cairo_destroy(cr);
+       window_flush(window);
+}
+
+struct window *
+window_create_menu(struct display *display, struct window *parent,
+                  int32_t x, int32_t y, const char **entries, int count)
+{
+       struct window *window;
+       struct menu *menu;
+
+       menu = malloc(sizeof *menu);
+       if (!menu)
+               return NULL;
+
+       window = window_create_internal(parent->display, parent, 0, 0);
+       if (!window)
+               return NULL;
+
+       menu->window = window;
+       menu->entries = entries;
+       menu->count = count;
+       window->decoration = 0;
+       window->type = TYPE_MENU;
+       window->x = x;
+       window->y = y;
+
+       wl_shell_surface_set_transient(window->shell_surface,
+                                 window->parent->shell_surface,
+                                 window->x, window->y, 0);
+
+       window_set_motion_handler(window, menu_motion_handler);
+       window_set_enter_handler(window, menu_enter_handler);
+       window_set_leave_handler(window, menu_leave_handler);
+       window_set_button_handler(window, menu_button_handler);
+       window_set_redraw_handler(window, menu_redraw_handler);
+       window_set_user_data(window, menu);
+
+       return window;
+}
+
 void
 window_set_buffer_type(struct window *window, enum window_buffer_type type)
 {
index e5dc008..59397f0 100644 (file)
@@ -196,6 +196,9 @@ window_create(struct display *display, int32_t width, int32_t height);
 struct window *
 window_create_transient(struct display *display, struct window *parent,
                        int32_t x, int32_t y, int32_t width, int32_t height);
+struct window *
+window_create_menu(struct display *display, struct window *parent,
+                  int32_t x, int32_t y, const char **entries, int count);
 
 void
 window_destroy(struct window *window);