]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Support xwayland view resize (LAB_DECO_PART_LEFT)
authorJohan Malm <jgm323@gmail.com>
Mon, 25 May 2020 12:42:40 +0000 (13:42 +0100)
committerJohan Malm <jgm323@gmail.com>
Mon, 25 May 2020 12:42:40 +0000 (13:42 +0100)
.clang-format
deco.c
labwc.h
main.c
output.c
server.c
view.c

index 7ac923e8723add4ec014b3bed106eef3fb1cb86d..0a012ef9f0536688bdda80fe18bd9fcc31a767bb 100644 (file)
@@ -145,6 +145,7 @@ Cpp11BracedListStyle: false
 ForEachMacros:
   - 'wl_list_for_each'
   - 'wl_list_for_each_reverse'
+  - 'wl_list_for_each_safe'
 
 # The maximum number of consecutive empty lines to keep.
 MaxEmptyLinesToKeep: 1
diff --git a/deco.c b/deco.c
index 5623df5a950ea51d0ac2e3300ebdc967b7a5263c..f50296886c2bed0e7cdf39250b920f55b7b1dfb3 100644 (file)
--- a/deco.c
+++ b/deco.c
@@ -39,9 +39,11 @@ struct wlr_box deco_box(struct view *view, enum deco_part deco_part)
 
 enum deco_part deco_at(struct view *view, double lx, double ly)
 {
-       struct wlr_box box;
-       box = deco_box(view, LAB_DECO_PART_TOP);
-       if (wlr_box_contains_point(&box, lx, ly))
-               return LAB_DECO_PART_TOP;
+       enum deco_part deco_part;
+       for (deco_part = 0; deco_part < LAB_DECO_NONE; ++deco_part) {
+               struct wlr_box box = deco_box(view, deco_part);
+               if (wlr_box_contains_point(&box, lx, ly))
+                       return deco_part;
+       }
        return LAB_DECO_NONE;
 }
diff --git a/labwc.h b/labwc.h
index 46be920a78357eed28c42bedaf6c770bc2218162..26f7bcf82b991316e66e8de8f29ef617cdfd0583 100644 (file)
--- a/labwc.h
+++ b/labwc.h
@@ -34,7 +34,7 @@
 #define XCURSOR_MOVE "grabbing"
 #define XWL_TITLEBAR_HEIGHT (10)
 #define XWL_WINDOW_BORDER (3)
-#define LAB_DISABLE_CSD (1)
+#define LAB_DISABLE_CSD (0)
 
 enum cursor_mode {
        TINYWL_CURSOR_PASSTHROUGH,
@@ -79,6 +79,9 @@ struct server {
        struct wlr_output_layout *output_layout;
        struct wl_list outputs;
        struct wl_listener new_output;
+
+       /* For use in cycle (alt-tab) mode */
+       struct view *cycle_view;
 };
 
 struct output {
@@ -90,7 +93,8 @@ struct output {
 
 enum view_type { LAB_XDG_SHELL_VIEW, LAB_XWAYLAND_VIEW };
 
-enum deco_part { LAB_DECO_NONE, LAB_DECO_PART_TOP, LAB_DECO_PART_LEFT };
+/* Keep LAB_DECO_NONE last for the purpose of iterating */
+enum deco_part { LAB_DECO_PART_TOP = 0, LAB_DECO_PART_LEFT, LAB_DECO_NONE };
 
 struct view {
        enum view_type type;
diff --git a/main.c b/main.c
index b62afd668445d6b70040b8cbe7a1c2054b1f601e..692684c151b3a60e97b78d873b9c01136c89672f 100644 (file)
--- a/main.c
+++ b/main.c
@@ -134,8 +134,8 @@ int main(int argc, char *argv[])
        wlr_cursor_attach_output_layout(server.cursor, server.output_layout);
 
        // This is done below
-       //server.cursor_mgr = wlr_xcursor_manager_create(NULL, XCURSOR_SIZE);
-       //if (!server.cursor_mgr) {
+       // server.cursor_mgr = wlr_xcursor_manager_create(NULL, XCURSOR_SIZE);
+       // if (!server.cursor_mgr) {
        //      wlr_log(WLR_ERROR, "cannot create xcursor manager");
        //      return 1;
        //}
@@ -279,10 +279,10 @@ int main(int argc, char *argv[])
                wl_list_remove(&_output->link);
                free(_output);
        }
-       struct output *_keyboard, *_keyboard_tmp;
-       wl_list_for_each_safe (_keyboard, _keyboard_tmp, &server.keyboards, link) {
-               wl_list_remove(&_keyboard->link);
-               free(_keyboard);
+       struct output *k, *k_tmp;
+       wl_list_for_each_safe (k, k_tmp, &server.keyboards, link) {
+               wl_list_remove(&k->link);
+               free(k);
        }
        wlr_cursor_destroy(server.cursor);
        wlr_output_layout_destroy(server.output_layout);
index ba9ffcee15a8f726bb8e65aba12c24594d0c2363..8cd684bb9d8b4a7ccd9b870499ea5132f7f0adf7 100644 (file)
--- a/output.c
+++ b/output.c
@@ -7,6 +7,47 @@ struct render_data {
        struct timespec *when;
 };
 
+static void render_grab(struct output *output)
+{
+       if (output->server->cursor_mode == TINYWL_CURSOR_PASSTHROUGH)
+               return;
+
+       if (output->server->cursor_mode == TINYWL_CURSOR_RESIZE) {
+               float grab_box_color[] = { 0.0, 1.0, 0.0, 0.3 };
+               wlr_render_rect(output->server->renderer,
+                               &output->server->grab_box, grab_box_color,
+                               output->wlr_output->transform_matrix);
+       }
+
+       float grab_point_color[] = { 1.0, 0.0, 1.0, 1.0 };
+       struct wlr_box point = { .x = output->server->grab_x +
+                                     output->server->grabbed_view->x - 1,
+                                .y = output->server->grab_y +
+                                     output->server->grabbed_view->y - 1,
+                                .width = 3,
+                                .height = 3 };
+       fprintf(stderr, "XX grab_x=%f; grab_y=%f\n", output->server->grab_x,
+               output->server->grab_y);
+       wlr_render_rect(output->server->renderer, &point, grab_point_color,
+                       output->wlr_output->transform_matrix);
+}
+
+static void render_cycle_box(struct output *output)
+{
+       if (!output->server->cycle_view)
+               return;
+       struct view *view;
+       wl_list_for_each_reverse (view, &output->server->views, link) {
+               if (view != output->server->cycle_view)
+                       continue;
+               struct wlr_box box = deco_max_extents(view);
+               float cycle_color[] = { 0.0, 0.0, 0.0, 0.2 };
+               wlr_render_rect(output->server->renderer, &box, cycle_color,
+                               output->wlr_output->transform_matrix);
+               return;
+       }
+}
+
 static void render_decorations(struct wlr_output *output, struct view *view)
 {
        if (!view_want_deco(view))
@@ -144,6 +185,10 @@ void output_frame(struct wl_listener *listener, void *data)
                }
        }
 
+       /* If in cycle (alt-tab) mode, highlight selected view */
+       render_cycle_box(output);
+       render_grab(output);
+
        /* Hardware cursors are rendered by the GPU on a separate plane, and can
         * be moved around without re-rendering what's beneath them - which is
         * more efficient. However, not all hardware supports hardware cursors.
index 6368e94bdba53a0d7ff28effe1bd0178df7af7cf..52b89ee2842e2e52de6dcdee656270a6335b6cfc 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1,10 +1,21 @@
 #include "labwc.h"
 
-static bool in_alt_tab_mode;
-static struct view *alt_tab_view;
+static struct wlr_box view_geometry(struct view *view)
+{
+       struct wlr_box box = { 0 };
+       switch (view->type) {
+       case LAB_XDG_SHELL_VIEW:
+               wlr_xdg_surface_get_geometry(view->xdg_surface, &box);
+               break;
+       case LAB_XWAYLAND_VIEW:
+               box.width = view->xwayland_surface->width;
+               box.height = view->xwayland_surface->height;
+               break;
+       }
+       return box;
+}
 
-void begin_interactive(struct view *view, enum cursor_mode mode,
-                      uint32_t edges)
+void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges)
 {
        /* This function sets up an interactive move or resize operation, where
         * the compositor stops propegating pointer events to clients and
@@ -13,24 +24,13 @@ void begin_interactive(struct view *view, enum cursor_mode mode,
        server->grabbed_view = view;
        server->cursor_mode = mode;
 
-       if (mode == TINYWL_CURSOR_MOVE) {
+       switch (mode) {
+       case TINYWL_CURSOR_MOVE:
                server->grab_x = server->cursor->x - view->x;
                server->grab_y = server->cursor->y - view->y;
-       } else {
-               struct wlr_box geo_box;
-               switch (view->type) {
-               case LAB_XDG_SHELL_VIEW:
-                       wlr_xdg_surface_get_geometry(view->xdg_surface,
-                                                    &geo_box);
-                       break;
-               case LAB_XWAYLAND_VIEW:
-                       geo_box.x = view->xwayland_surface->x;
-                       geo_box.y = view->xwayland_surface->y;
-                       geo_box.width = view->xwayland_surface->width;
-                       geo_box.height = view->xwayland_surface->height;
-                       break;
-               }
-
+               break;
+       case TINYWL_CURSOR_RESIZE: {
+               struct wlr_box geo_box = view_geometry(view);
                double border_x =
                        (view->x + geo_box.x) +
                        ((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0);
@@ -43,6 +43,9 @@ void begin_interactive(struct view *view, enum cursor_mode mode,
                server->grab_box.x += view->x;
                server->grab_box.y += view->y;
                server->resize_edges = edges;
+       } break;
+       default:
+               break;
        }
 }
 
@@ -79,9 +82,8 @@ static bool handle_keybinding(struct server *server, xkb_keysym_t sym)
                break;
        case XKB_KEY_F1:
        case XKB_KEY_F2:
-               in_alt_tab_mode = true;
-               alt_tab_view = next_toplevel(view_front_toplevel(server));
-               fprintf(stderr, "alt_tab_view=%p\n", (void *)alt_tab_view);
+               server->cycle_view = next_toplevel(view_front_toplevel(server));
+               fprintf(stderr, "cycle_view=%p\n", (void *)server->cycle_view);
                break;
        case XKB_KEY_F3:
                if (fork() == 0) {
@@ -120,17 +122,17 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data)
        uint32_t modifiers =
                wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 
-       if (in_alt_tab_mode) {
+       if (server->cycle_view) {
                if ((syms[0] == XKB_KEY_Alt_L) &&
                    event->state == WLR_KEY_RELEASED) {
                        /* end cycle */
-                       in_alt_tab_mode = false;
-                       view_focus(alt_tab_view);
+                       view_focus(server->cycle_view);
+                       server->cycle_view = NULL;
                } else if (event->state == WLR_KEY_PRESSED) {
                        /* cycle to next */
-                       alt_tab_view = next_toplevel(alt_tab_view);
-                       fprintf(stderr, "alt_tab_view=%p\n",
-                               (void *)alt_tab_view);
+                       server->cycle_view = next_toplevel(server->cycle_view);
+                       fprintf(stderr, "cycle_view=%p\n",
+                               (void *)server->cycle_view);
                        return;
                }
        }
@@ -268,11 +270,6 @@ static void process_cursor_move(struct server *server, uint32_t time)
 static void process_cursor_resize(struct server *server, uint32_t time)
 {
        /*
-        * Resizing the grabbed view can be a little bit complicated, because we
-        * could be resizing from any corner or edge. This not only resizes the
-        * view on one or two axes, but can also move the view if you resize
-        * from the top or left edges (or top-left corner).
-        *
         * TODO: Wait for the client to prepare a buffer at the new size, then
         * commit any movement that was prepared.
         */
@@ -303,14 +300,22 @@ static void process_cursor_resize(struct server *server, uint32_t time)
                        new_right = new_left + 1;
        }
 
-       struct wlr_box geo_box;
-       wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box);
+       struct wlr_box geo_box = view_geometry(view);
        view->x = new_left - geo_box.x;
        view->y = new_top - geo_box.y;
 
        int new_width = new_right - new_left;
        int new_height = new_bottom - new_top;
-       wlr_xdg_toplevel_set_size(view->xdg_surface, new_width, new_height);
+       switch (view->type) {
+       case LAB_XDG_SHELL_VIEW:
+               wlr_xdg_toplevel_set_size(view->xdg_surface, new_width,
+                                         new_height);
+               break;
+       case LAB_XWAYLAND_VIEW:
+               wlr_xwayland_surface_configure(view->xwayland_surface, view->x,
+                                              view->y, new_width, new_height);
+               break;
+       }
 }
 
 static void process_cursor_motion(struct server *server, uint32_t time)
@@ -345,6 +350,10 @@ static void process_cursor_motion(struct server *server, uint32_t time)
                wlr_xcursor_manager_set_cursor_image(
                        server->cursor_mgr, "left_ptr", server->cursor);
                break;
+       case LAB_DECO_PART_LEFT:
+               wlr_xcursor_manager_set_cursor_image(
+                       server->cursor_mgr, "left_side", server->cursor);
+               break;
        }
        if (surface) {
                bool focus_changed = seat->pointer_state.focused_surface !=
@@ -431,6 +440,10 @@ void server_cursor_button(struct wl_listener *listener, void *data)
                case LAB_DECO_PART_TOP:
                        begin_interactive(view, TINYWL_CURSOR_MOVE, 0);
                        break;
+               case LAB_DECO_PART_LEFT:
+                       begin_interactive(view, TINYWL_CURSOR_RESIZE,
+                                         WLR_EDGE_LEFT);
+                       break;
                }
        }
 }
diff --git a/view.c b/view.c
index 8d8912a57d7055cd2a096e0117585f0e797a16a6..ea0b33c2d4d7b5ff633e0aa09c613ad8dbb6894c 100644 (file)
--- a/view.c
+++ b/view.c
@@ -165,6 +165,10 @@ struct view *view_at(struct server *server, double lx, double ly,
                        *view_area = LAB_DECO_PART_TOP;
                        return view;
                }
+               if (deco_at(view, lx, ly) == LAB_DECO_PART_LEFT) {
+                       *view_area = LAB_DECO_PART_LEFT;
+                       return view;
+               }
        }
        return NULL;
 }