From bca498f3873b0c9aaba4fca4f817307169394584 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Wed, 3 Apr 2024 00:48:59 +0200 Subject: [PATCH] better handling different window state, support fullscreen mode --- cursor.c | 14 ++++--- diyac.h | 16 ++++--- view.c | 124 ++++++++++++++++++++++++++++++------------------------- view.h | 3 ++ xdg.c | 61 +++++++++++++++------------ 5 files changed, 123 insertions(+), 95 deletions(-) diff --git a/cursor.c b/cursor.c index ae553be..e811134 100644 --- a/cursor.c +++ b/cursor.c @@ -54,18 +54,16 @@ static void process_cursor_move(struct diyac_server *server, uint32_t time) { struct diyac_view *toplevel = server->grabbed_view; /* Move the grabbed toplevel to the new position. */ - if (toplevel->state == DIYAC_VIEW_FULL_SCREEN) + if (toplevel->state.fullscreen) { return; } - if (toplevel->state == DIYAC_VIEW_MAXIMIZE) + if (toplevel->state.maximized) { - // cancel maximize state - wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, false); + toplevel->requested.maximized = false; // move the windows to cursor server->grab_x = toplevel->original.width * server->grab_x / toplevel->output->usable_area.width; } - toplevel->requested = DIYAC_VIEW_NORMAL; toplevel->original.y = server->seat.cursor->y - server->grab_y; toplevel->original.x = server->seat.cursor->x - server->grab_x; @@ -90,6 +88,10 @@ static void process_cursor_resize(struct diyac_server *server, uint32_t time) * size, then commit any movement that was prepared. */ struct diyac_view *toplevel = server->grabbed_view; + if(toplevel->state.fullscreen) + { + return; + } double border_x = server->seat.cursor->x - server->grab_x; double border_y = server->seat.cursor->y - server->grab_y; int new_left = server->grab_geobox.x; @@ -138,7 +140,7 @@ static void process_cursor_resize(struct diyac_server *server, uint32_t time) int new_height = new_bottom - new_top; toplevel->original.width = new_width; toplevel->original.height = new_height; - toplevel->requested = DIYAC_VIEW_NORMAL; + toplevel->requested.maximized = false; diyac_view_update_geometry(toplevel, false); /* wlr_scene_node_set_position(&toplevel->scene_tree->node, diff --git a/diyac.h b/diyac.h index 7097d1c..2576f46 100644 --- a/diyac.h +++ b/diyac.h @@ -37,11 +37,15 @@ enum diyac_node_descriptor_type // LAB_NODE_TREE, // LAB_NODE_SSD_BUTTON, }; -enum diyac_view_state +struct diyac_view_state { - DIYAC_VIEW_NORMAL = 0, - DIYAC_VIEW_MAXIMIZE, - DIYAC_VIEW_FULL_SCREEN, + bool maximized; + bool fullscreen; + bool minimized; + /** + * if neither state is on, it means that + * the current state is normal + */ }; struct diyac_seat @@ -165,8 +169,8 @@ struct diyac_view struct wlr_xdg_surface *xdg_surface; struct wlr_xdg_toplevel *xdg_toplevel; struct wlr_scene_tree *scene_tree; - enum diyac_view_state state; - enum diyac_view_state requested; + struct diyac_view_state state; + struct diyac_view_state requested; /* * Geometry of the wlr_surface contained within the view, as * currently displayed. Should be kept in sync with the diff --git a/view.c b/view.c index f4d8e45..08b82f5 100644 --- a/view.c +++ b/view.c @@ -172,72 +172,84 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed) struct diyac_server *server = view->server; wlr_box_intersection(&intersect_box,geometry, &usable); wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); - if ( wlr_box_equal(geometry, &geo_box) && (view->state == view->requested) && wlr_box_empty(&intersect_box)) + if ( wlr_box_equal(geometry, &geo_box) && diyac_view_state_equal(view->state,view->requested) && wlr_box_empty(&intersect_box)) { wlr_log(WLR_INFO, "No geometry update needed"); return false; } - // invalidate old state if change state - if(view->requested != view->state) + // invalidate old state if change state + if(view->state.fullscreen && !view->requested.fullscreen) { - switch (view->state) - { - case DIYAC_VIEW_MAXIMIZE: - wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, false); - break; - case DIYAC_VIEW_FULL_SCREEN: - wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false); - wlr_scene_node_set_enabled(&view->output->scenes.top->node, true); - break; - default: - break; - } + wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false); + wlr_scene_node_set_enabled(&view->output->scenes.top->node, true); + view->state.fullscreen = false; } - switch (view->requested) + if(view->state.maximized && !view->requested.maximized) + { + wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, false); + view->state.maximized = false; + } + view->state = view->requested; + + if(view->requested.minimized) + { + // TODO implement minimize + return false; + } + else if(view->requested.fullscreen) { - case DIYAC_VIEW_MAXIMIZE: - wlr_scene_node_set_position(&view->scene_tree->node, usable.x, usable.y); - wlr_xdg_toplevel_set_size(view->xdg_toplevel, usable.width, usable.height); - wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, true); - view->state = DIYAC_VIEW_MAXIMIZE; - return true; - case DIYAC_VIEW_FULL_SCREEN: wlr_scene_node_set_enabled(&view->output->scenes.top->node, false); wlr_scene_node_set_position(&view->scene_tree->node, 0, 0); wlr_xdg_toplevel_set_size(view->xdg_toplevel, view->output->wlr_output->width, view->output->wlr_output->height); - view->state = DIYAC_VIEW_FULL_SCREEN; wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false); - return false; - - default: + return true; + } + else if(view->requested.maximized) + { + wlr_scene_node_set_position(&view->scene_tree->node, usable.x, usable.y); + wlr_xdg_toplevel_set_size(view->xdg_toplevel, usable.width, usable.height); + wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, true); + return true; + } + else + { // if (wlr_output_layout_intersects(view->server->output_layout, // view->output->wlr_output, &view->current)) //{ /**Normal state, recalculate current geometry*/ - view->state = DIYAC_VIEW_NORMAL; - if (!grabbed && geometry->x < usable.x) + struct diyac_view * root = diyac_get_root_view(view); + if(!root) { - geometry->x = usable.x; + root = view; } - if (!grabbed && geometry->y < usable.y) + if(!root->state.fullscreen) { - geometry->y = usable.y; - } - if (grabbed && server->seat.cursor->x <= usable.x) - { - geometry->x = usable.x - server->grab_x; - } - if (grabbed && server->seat.cursor->y <= usable.y) - { - geometry->y = usable.y; - } - if (grabbed && server->seat.cursor->x >= usable.x + usable.width) - { - geometry->x = usable.x + usable.width - server->grab_x; - } - if (grabbed && server->seat.cursor->y >= usable.y + usable.height) - { - geometry->y = usable.y + usable.height - server->grab_y; + // Only adjust position only when not in fullscreen mode + + if (!grabbed && geometry->x < usable.x) + { + geometry->x = usable.x; + } + if (!grabbed && geometry->y < usable.y) + { + geometry->y = usable.y; + } + if (grabbed && server->seat.cursor->x <= usable.x) + { + geometry->x = usable.x - server->grab_x; + } + if (grabbed && server->seat.cursor->y <= usable.y) + { + geometry->y = usable.y; + } + if (grabbed && server->seat.cursor->x >= usable.x + usable.width) + { + geometry->x = usable.x + usable.width - server->grab_x; + } + if (grabbed && server->seat.cursor->y >= usable.y + usable.height) + { + geometry->y = usable.y + usable.height - server->grab_y; + } } wlr_log(WLR_DEBUG, "diyac_view_update_geometry: updating geometry: %d %d %d %d", geometry->x, geometry->y, geometry->width, geometry->height); @@ -282,14 +294,14 @@ struct diyac_view *diyac_get_root_view(struct diyac_view *view) struct wlr_box diyac_view_get_geometry(struct diyac_view *view) { struct wlr_box box; - switch(view->state) + if(view->state.fullscreen) { - case DIYAC_VIEW_FULL_SCREEN: - wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box); - return box; - case DIYAC_VIEW_MAXIMIZE: - return view->output->usable_area; - default: - return view->original; + wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box); + return box; } + if(view->state.maximized) + { + return view->output->usable_area; + } + return view->original; } \ No newline at end of file diff --git a/view.h b/view.h index 9236729..4aafa01 100644 --- a/view.h +++ b/view.h @@ -1,6 +1,9 @@ #ifndef DIYAC_VIEW_H #define DIYAC_VIEW_H #include "diyac.h" +#define diyac_view_state_equal(a,b) ((a.fullscreen == b.fullscreen) \ + && (a.maximized == b.maximized) \ + && (a.minimized == b.minimized)) void diyac_focus_view(struct diyac_view *toplevel, bool raise); struct diyac_view *diyac_view_at( struct diyac_server *server, double lx, double ly, diff --git a/xdg.c b/xdg.c index e582386..e43bbc5 100644 --- a/xdg.c +++ b/xdg.c @@ -92,6 +92,14 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { diyac_reset_cursor_mode(toplevel->server); } + if(toplevel->state.fullscreen) + { + /** + * When a client exit during fullscreen mode, the top layer shall + * be restored as it is currently disabled + */ + wlr_scene_node_set_enabled(&toplevel->output->scenes.top->node, true); + } wl_list_remove(&toplevel->link); } @@ -103,7 +111,6 @@ static void xdg_toplevel_request_move( * decorations. Note that a more sophisticated compositor should check the * provided serial against a list of button press serials sent to this * client, to prevent the client from requesting this whenever they want. */ - wlr_log(WLR_INFO, "Request move"); struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_move); begin_interactive(toplevel, DIYAC_CURSOR_MOVE, 0); } @@ -116,7 +123,7 @@ static void xdg_toplevel_request_resize( * decorations. Note that a more sophisticated compositor should check the * provided serial against a list of button press serials sent to this * client, to prevent the client from requesting this whenever they want. */ - wlr_log(WLR_INFO, "Request resize"); + struct wlr_xdg_toplevel_resize_event *event = data; struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_resize); begin_interactive(toplevel, DIYAC_CURSOR_RESIZE, event->edges); @@ -133,15 +140,7 @@ static void xdg_toplevel_request_maximize( struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_maximize); - if(toplevel->xdg_toplevel->requested.maximized) - { - toplevel->requested = DIYAC_VIEW_MAXIMIZE; - } - else if(toplevel->state == DIYAC_VIEW_MAXIMIZE) - { - toplevel->requested = DIYAC_VIEW_NORMAL; - } - wlr_log(WLR_INFO, "Request maximize"); + toplevel->requested.maximized = toplevel->xdg_toplevel->requested.maximized; diyac_reset_cursor_mode(toplevel->server); diyac_view_update_geometry(toplevel, false); } @@ -150,15 +149,11 @@ static void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void * { struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_fullscreen); - if(toplevel->xdg_toplevel->requested.fullscreen) - { - toplevel->requested = DIYAC_VIEW_FULL_SCREEN; - } - else if(toplevel->state == DIYAC_VIEW_FULL_SCREEN) - { - toplevel->requested = DIYAC_VIEW_NORMAL; - } - wlr_log(WLR_INFO, "Request fullscreen"); + toplevel->requested.fullscreen = toplevel->xdg_toplevel->requested.fullscreen; + /** + * TODO: use client specific output for fullscreen + * toplevel->xdg_toplevel->requested.fullscreen_output + */ diyac_reset_cursor_mode(toplevel->server); diyac_view_update_geometry(toplevel, false); } @@ -167,6 +162,8 @@ static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *da { struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_minimize); + toplevel->requested.minimized = toplevel->xdg_toplevel->requested.minimized; + //TODO implement minimize wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base); } @@ -215,13 +212,23 @@ static void popup_unconstrain(struct diyac_popup *popup) struct diyac_server *server = view->server; struct wlr_output_layout *output_layout = server->output_layout; struct wlr_output *wlr_output = view->output->wlr_output; - + struct wlr_box usable = { + .x = 0, + .y = 0, + .width = view->output->wlr_output->width, + .height = view->output->wlr_output->height + }; + struct diyac_view *root = diyac_get_root_view(view); + if(!root || ! root->state.fullscreen) + { + usable = view->output->usable_area; + } struct wlr_box geo_box = diyac_view_get_geometry(view); struct wlr_box output_toplevel_box = { - .x = view->output->usable_area.x - geo_box.x, - .y = view->output->usable_area.y - geo_box.y, - .width = view->output->usable_area.width, - .height = view->output->usable_area.height, + .x = usable.x - geo_box.x, + .y = usable.y - geo_box.y, + .width = usable.width, + .height = usable.height, }; wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box); } @@ -350,8 +357,8 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) wlr_xdg_surface_ping(xdg_surface); /* Allocate a diyac_view for this surface */ struct diyac_view *toplevel = calloc(1, sizeof(*toplevel)); - toplevel->state = DIYAC_VIEW_NORMAL; - toplevel->requested = DIYAC_VIEW_NORMAL; + memset(&toplevel->state, 0, sizeof(toplevel->state)); + memset(&toplevel->requested, 0, sizeof(toplevel->requested)); toplevel->server = server; toplevel->xdg_toplevel = xdg_surface->toplevel; toplevel->xdg_surface = xdg_surface;