window: Don't needlessly sync parent and geometry
[platform/upstream/weston.git] / clients / window.c
index 85c25f7..e44d65c 100644 (file)
@@ -217,6 +217,7 @@ struct window {
        struct rectangle saved_allocation;
        struct rectangle min_allocation;
        struct rectangle pending_allocation;
+       struct rectangle last_geometry;
        int x, y;
        int redraw_needed;
        int redraw_task_scheduled;
@@ -246,6 +247,7 @@ struct window {
        struct xdg_popup *xdg_popup;
 
        struct window *parent;
+       struct wl_surface *last_parent_surface;
 
        struct window_frame *frame;
 
@@ -365,6 +367,9 @@ struct window_frame {
        struct widget *widget;
        struct widget *child;
        struct frame *frame;
+
+       uint32_t last_time;
+       uint32_t did_double, double_click;
 };
 
 struct menu {
@@ -2233,19 +2238,61 @@ frame_get_pointer_image_for_location(struct window_frame *frame,
        }
 }
 
+static void
+frame_menu_func(void *data, struct input *input, int index)
+{
+       struct window *window = data;
+       struct display *display;
+
+       switch (index) {
+       case 0: /* close */
+               window_close(window);
+               break;
+       case 1: /* move to workspace above */
+               display = window->display;
+               if (display->workspace > 0)
+                       workspace_manager_move_surface(
+                               display->workspace_manager,
+                               window->main_surface->surface,
+                               display->workspace - 1);
+               break;
+       case 2: /* move to workspace below */
+               display = window->display;
+               if (display->workspace < display->workspace_count - 1)
+                       workspace_manager_move_surface(
+                               display->workspace_manager,
+                               window->main_surface->surface,
+                               display->workspace + 1);
+               break;
+       case 3: /* fullscreen */
+               /* we don't have a way to get out of fullscreen for now */
+               if (window->fullscreen_handler)
+                       window->fullscreen_handler(window, window->user_data);
+               break;
+       }
+}
+
 void
 window_show_frame_menu(struct window *window,
                       struct input *input, uint32_t time)
 {
        int32_t x, y;
+       int count;
 
-       if (window->xdg_surface) {
-               input_get_position(input, &x, &y);
-               xdg_surface_show_window_menu(window->xdg_surface,
-                                            input_get_seat(input),
-                                            window->display->serial,
-                                            x - 10, y - 10);
-       }
+       static const char *entries[] = {
+               "Close",
+               "Move to workspace above", "Move to workspace below",
+               "Fullscreen"
+       };
+
+       if (window->fullscreen_handler)
+               count = ARRAY_LENGTH(entries);
+       else
+               count = ARRAY_LENGTH(entries) - 1;
+
+       input_get_position(input, &x, &y);
+       window_show_menu(window->display, input, time, window,
+                        x - 10, y - 10, frame_menu_func, entries, count);
 }
 
 static int
@@ -2340,6 +2387,7 @@ frame_handle_status(struct window_frame *frame, struct input *input,
        }
 }
 
+#define DOUBLE_CLICK_PERIOD 250
 static void
 frame_button_handler(struct widget *widget,
                     struct input *input, uint32_t time,
@@ -2350,7 +2398,27 @@ frame_button_handler(struct widget *widget,
        struct window_frame *frame = data;
        enum theme_location location;
 
-       location = frame_pointer_button(frame->frame, input, button, state);
+       frame->double_click = 0;
+       if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
+               if (time - frame->last_time <= DOUBLE_CLICK_PERIOD) {
+                       frame->double_click = 1;
+                       frame->did_double = 1;
+               } else
+                       frame->did_double = 0;
+
+               frame->last_time = time;
+       } else if (frame->did_double == 1) {
+               frame->double_click = 1;
+               frame->did_double = 0;
+       }
+
+       if (frame->double_click)
+               location = frame_double_click(frame->frame, input,
+                                             button, state);
+       else
+               location = frame_pointer_button(frame->frame, input,
+                                               button, state);
+
        frame_handle_status(frame, input, time, location);
 }
 
@@ -3927,7 +3995,11 @@ window_sync_parent(struct window *window)
        else
                parent_surface = NULL;
 
+       if (parent_surface == window->last_parent_surface)
+               return;
+
        xdg_surface_set_parent(window->xdg_surface, parent_surface);
+       window->last_parent_surface = parent_surface;
 }
 
 static void
@@ -3952,12 +4024,18 @@ window_sync_geometry(struct window *window)
                return;
 
        window_get_geometry(window, &geometry);
+       if (geometry.x == window->last_geometry.x &&
+           geometry.y == window->last_geometry.y &&
+           geometry.width == window->last_geometry.width &&
+           geometry.height == window->last_geometry.height)
+               return;
 
        xdg_surface_set_window_geometry(window->xdg_surface,
                                        geometry.x,
                                        geometry.y,
                                        geometry.width,
                                        geometry.height);
+       window->last_geometry = geometry;
 }
 
 static void