diff --git a/include/labwc.h b/include/labwc.h index 416fb03c..7f7d6aa0 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -306,6 +306,7 @@ struct view { bool been_mapped; bool minimized; bool maximized; + bool is_tiled; struct wlr_output *fullscreen; /* geometry of the wlr_surface contained within the view */ @@ -314,6 +315,9 @@ struct view { /* geometry before maximize */ struct wlr_box unmaximized_geometry; + /* geometry before tiling */ + struct wlr_box untiled_geometry; + /* * margin refers to the space between the extremities of the * wlr_surface and the max extents of the server-side decorations. diff --git a/src/interactive.c b/src/interactive.c index 8ade121a..857fc10f 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -17,28 +17,46 @@ max_move_scale(double pos_cursor, double pos_current, void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges) { - if (view->maximized) { - if (mode == LAB_INPUT_STATE_MOVE) { - int new_x = max_move_scale(view->server->seat.cursor->x, - view->x, view->w, view->unmaximized_geometry.width); - int new_y = max_move_scale(view->server->seat.cursor->y, - view->y, view->h, view->unmaximized_geometry.height); - view->unmaximized_geometry.x = new_x; - view->unmaximized_geometry.y = new_y; - view_maximize(view, false); - /* - * view_maximize() indirectly calls view->impl->configure - * which is async but we are using the current values in - * server->grab_box. We pretend the configure already - * happened by setting them manually. - */ - view->x = new_x; - view->y = new_y; - view->w = view->unmaximized_geometry.width; - view->h = view->unmaximized_geometry.height; + if (mode == LAB_INPUT_STATE_RESIZE && view->maximized) { + return; + } + if (mode == LAB_INPUT_STATE_MOVE && (view->maximized || view->is_tiled)) { + /** + * Disable tiling or maximized mode by resizing to the old size + * but modifying the x and y coordinates to match the cursor. + */ + + /* Order of branches matter, a view may be maximized and tiled */ + struct wlr_box *old_geo; + if (view->is_tiled) { + old_geo = &view->untiled_geometry; } else { - return; + old_geo = &view->unmaximized_geometry; } + + /* Recalculate x and y based on cursor position */ + old_geo->x = max_move_scale(view->server->seat.cursor->x, + view->x, view->w, old_geo->width); + old_geo->y = max_move_scale(view->server->seat.cursor->y, + view->y, view->h, old_geo->height); + + if (view->is_tiled) { + view_move_resize(view, *old_geo); + view->is_tiled = false; + view->maximized = false; + } else { + view_maximize(view, false); + } + /** + * view_move_resize() / view_maximize() indirectly calls + * view->impl->configure which is async but we are using + * the current values in server->grab_box. We pretend the + * configure already happened by setting them manually. + */ + view->x = old_geo->x; + view->y = old_geo->y; + view->w = old_geo->width; + view->h = old_geo->height; } /* @@ -65,6 +83,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges) cursor_set(&server->seat, "grab"); break; case LAB_INPUT_STATE_RESIZE: + view->is_tiled = false; cursor_set(&server->seat, wlr_xcursor_get_resize_name(edges)); break; default: diff --git a/src/view.c b/src/view.c index e82dd6d3..2d248938 100644 --- a/src/view.c +++ b/src/view.c @@ -668,6 +668,23 @@ view_snap_to_edge(struct view *view, const char *direction) view_edge_invert(edge)); } + /* Remember old geometry */ + if (!view->is_tiled) { + if (!view->maximized) { + /* Store current geometry */ + view->untiled_geometry.x = view->x; + view->untiled_geometry.y = view->y; + view->untiled_geometry.width = view->w; + view->untiled_geometry.height = view->h; + } else { + /* Reuse unmaximized geometry */ + memcpy(&view->untiled_geometry, &view->unmaximized_geometry, + sizeof(view->untiled_geometry)); + } + view->is_tiled = true; + } + view->maximized = false; + if (view->w == dst.width && view->h == dst.height) { /* move horizontally/vertically without changing size */ view_move(view, dst.x, dst.y);