From fdb2843561f8e7840120d3e102f2d578637d5947 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Mon, 15 Apr 2024 13:56:11 +0200 Subject: [PATCH] improve basic multi output support --- cursor.c | 4 + diyac.h | 10 +-- foreign.c | 7 +- output.c | 50 ++++++++++- output.h | 3 +- protocol/server-decoration.xml | 94 -------------------- protocol/wlr-input-inhibitor-unstable-v1.xml | 67 -------------- view.c | 61 +++++++------ xdg.c | 6 +- 9 files changed, 100 insertions(+), 202 deletions(-) delete mode 100644 protocol/server-decoration.xml delete mode 100644 protocol/wlr-input-inhibitor-unstable-v1.xml diff --git a/cursor.c b/cursor.c index 91f9fba..e05f844 100644 --- a/cursor.c +++ b/cursor.c @@ -57,6 +57,10 @@ 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->output) + { + return; + } if (toplevel->state.fullscreen) { return; diff --git a/diyac.h b/diyac.h index 41fc75c..fb3d4de 100644 --- a/diyac.h +++ b/diyac.h @@ -18,7 +18,7 @@ #include #define LAYER_TREE_SZ 4 -/* For brevity's sake, struct members are annotated where they are used. */ + enum diyac_cursor_mode { DIYAC_CURSOR_PASSTHROUGH, @@ -83,7 +83,7 @@ struct diyac_popup void *parent; }; -struct diyac_layer_scenes +struct diyac_output_scenes { struct wlr_scene_tree *background; struct wlr_scene_tree *bottom; @@ -161,8 +161,8 @@ struct diyac_output struct wlr_box usable_area; // layer output - struct diyac_layer_scenes scenes; - // alias to diyac_layer_scenes elements + struct diyac_output_scenes scenes; + // alias to diyac_output_scenes elements struct wlr_scene_tree *layer_tree[LAYER_TREE_SZ]; }; @@ -207,7 +207,7 @@ struct diyac_view struct wl_listener request_maximize; struct wl_listener request_fullscreen; - struct wl_listener set_app_id; // only useful when using SSD + struct wl_listener set_app_id; struct wl_listener new_popup; struct wl_listener set_title; diff --git a/foreign.c b/foreign.c index a49bc5e..8014027 100644 --- a/foreign.c +++ b/foreign.c @@ -94,8 +94,11 @@ void diyac_init_foreign_toplevel(struct diyac_view *view) toplevel->destroy.notify = handle_destroy; wl_signal_add(&toplevel->handle->events.destroy, &toplevel->destroy); - wlr_foreign_toplevel_handle_v1_output_enter( - view->toplevel.handle, view->output->wlr_output); + if(view->output) + { + wlr_foreign_toplevel_handle_v1_output_enter( + view->toplevel.handle, view->output->wlr_output); + } //wlr_foreign_toplevel_handle_v1_output_enter struct wlr_xdg_toplevel *xdg_toplevel = view->xdg_toplevel; if (!xdg_toplevel->parent) diff --git a/output.c b/output.c index 4df26e9..cd1cf6e 100644 --- a/output.c +++ b/output.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "output.h" #include "layer.h" #include "node.h" @@ -38,10 +39,34 @@ static void output_destroy(struct wl_listener *listener, void *data) { struct diyac_output *output = wl_container_of(listener, output, destroy); + wlr_scene_node_destroy(&output->scenes.background->node); + wlr_scene_node_destroy(&output->scenes.bottom->node); + wlr_scene_node_destroy(&output->scenes.top->node); + wlr_scene_node_destroy(&output->scenes.popup->node); + wlr_scene_node_destroy(&output->scenes.overlay->node); + wlr_scene_node_destroy(&output->scenes.session->node); + + wl_list_remove(&output->frame.link); wl_list_remove(&output->request_state.link); wl_list_remove(&output->destroy.link); wl_list_remove(&output->link); + + struct diyac_server* server = output->server; + struct diyac_view * view; + wl_list_for_each(view, &server->views, link) { + if (view->output == output) { + /** + * TODO: testing this case + */ + view->output = NULL; + if(&server->outputs != server->outputs.next) + { + view->output = wl_container_of(server->outputs.next, view->output, link); + diyac_view_update_geometry(view, false); + } + } + } free(output); } @@ -187,11 +212,11 @@ struct diyac_output *diyac_output_from_cursor(struct diyac_server *server) return output->data; } -struct wlr_box diyac_output_usable_area(struct diyac_output *output) +void diyac_output_usable_area(struct diyac_output *output,struct wlr_box* area) { - if (!output) + if(!area | !output) { - return (struct wlr_box){0}; + return; } struct wlr_box box = output->usable_area; double ox = 0, oy = 0; @@ -199,5 +224,22 @@ struct wlr_box diyac_output_usable_area(struct diyac_output *output) output->wlr_output, &ox, &oy); box.x -= ox; box.y -= oy; - return box; + memcpy(area,&box,sizeof(box)); +} + +void diyac_output_full_area(struct diyac_output *output,struct wlr_box* area) +{ + if(!area | !output) + { + return; + } + struct wlr_box box = {0}; + wlr_output_effective_resolution(output->wlr_output, + &box.width, &box.height); + double ox = 0, oy = 0; + wlr_output_layout_output_coords(output->server->output_layout, + output->wlr_output, &ox, &oy); + box.x -= ox; + box.y -= oy; + memcpy(area,&box,sizeof(box)); } \ No newline at end of file diff --git a/output.h b/output.h index 0a1d831..e5afee8 100644 --- a/output.h +++ b/output.h @@ -5,5 +5,6 @@ void diyac_server_new_output(struct wl_listener *listener, void *data); void diyac_output_update_usable_area(struct diyac_output *output); struct diyac_output *diyac_output_from_cursor(struct diyac_server *server); -struct wlr_box diyac_output_usable_area(struct diyac_output * output); +void diyac_output_usable_area(struct diyac_output * output,struct wlr_box* box); +void diyac_output_full_area(struct diyac_output *output,struct wlr_box* area); #endif \ No newline at end of file diff --git a/protocol/server-decoration.xml b/protocol/server-decoration.xml deleted file mode 100644 index 45f1128..0000000 --- a/protocol/server-decoration.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - . - ]]> - - - This interface allows to coordinate whether the server should create - a server-side window decoration around a wl_surface representing a - shell surface (wl_shell_surface or similar). By announcing support - for this interface the server indicates that it supports server - side decorations. - - - - When a client creates a server-side decoration object it indicates - that it supports the protocol. The client is supposed to tell the - server whether it wants server-side decorations or will provide - client-side decorations. - - If the client does not create a server-side decoration object for - a surface the server interprets this as lack of support for this - protocol and considers it as client-side decorated. Nevertheless a - client-side decorated surface should use this protocol to indicate - to the server that it does not want a server-side deco. - - - - - - - - - - - - - This event is emitted directly after binding the interface. It contains - the default mode for the decoration. When a new server decoration object - is created this new object will be in the default mode until the first - request_mode is requested. - - The server may change the default mode at any time. - - - - - - - - - - - - - - - - - - - - - This event is emitted directly after the decoration is created and - represents the base decoration policy by the server. E.g. a server - which wants all surfaces to be client-side decorated will send Client, - a server which wants server-side decoration will send Server. - - The client can request a different mode through the decoration request. - The server will acknowledge this by another event with the same mode. So - even if a server prefers server-side decoration it's possible to force a - client-side decoration. - - The server may emit this event at any time. In this case the client can - again request a different mode. It's the responsibility of the server to - prevent a feedback loop. - - - - - diff --git a/protocol/wlr-input-inhibitor-unstable-v1.xml b/protocol/wlr-input-inhibitor-unstable-v1.xml deleted file mode 100644 index b62d1bb..0000000 --- a/protocol/wlr-input-inhibitor-unstable-v1.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Copyright © 2018 Drew DeVault - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - Clients can use this interface to prevent input events from being sent to - any surfaces but its own, which is useful for example in lock screen - software. It is assumed that access to this interface will be locked down - to whitelisted clients by the compositor. - - - - - Activates the input inhibitor. As long as the inhibitor is active, the - compositor will not send input events to other clients. - - - - - - - - - - - - While this resource exists, input to clients other than the owner of the - inhibitor resource will not receive input events. The client that owns - this resource will receive all input events normally. The compositor will - also disable all of its own input processing (such as keyboard shortcuts) - while the inhibitor is active. - - The compositor may continue to send input events to selected clients, - such as an on-screen keyboard (via the input-method protocol). - - - - - Destroy the inhibitor and allow other clients to receive input. - - - - diff --git a/view.c b/view.c index 9129b24..9443512 100644 --- a/view.c +++ b/view.c @@ -195,13 +195,22 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed) // if (wlr_output_layout_intersects(view->server->output_layout, // view->output->wlr_output, &view->current)) //{ - if (!view->mapped) + if (!view->mapped || !view->output) { wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); return false; } - struct wlr_box usable = diyac_output_usable_area(view->output); + struct diyac_view *root = diyac_get_root_view(view); struct diyac_server *server = view->server; + struct wlr_box usable = {0}; + if((root && root->state.fullscreen) || view->requested.fullscreen) + { + diyac_output_full_area(view->output, &usable); + } + else + { + diyac_output_usable_area(view->output, &usable); + } // invalidate old state if change state if (view->state.fullscreen && !view->requested.fullscreen) { @@ -232,21 +241,13 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed) } else if (!view->state.fullscreen && view->requested.fullscreen) { - struct wlr_box box = {0}; - wlr_output_effective_resolution(view->output->wlr_output, - &box.width, &box.height); - double ox = 0, oy = 0; - wlr_output_layout_output_coords(view->server->output_layout, - view->output->wlr_output, &ox, &oy); - box.x -= ox; - box.y -= oy; wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, true); wlr_scene_node_set_enabled(&view->output->scenes.top->node, false); if (view->toplevel.handle) { wlr_foreign_toplevel_handle_v1_set_fullscreen(view->toplevel.handle, true); } - diyac_view_configure(view, box); + diyac_view_configure(view, usable); updated = true; } else if (view->requested.maximized) @@ -265,38 +266,42 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed) // view->output->wlr_output, &view->current)) //{ /**Normal state, recalculate current geometry*/ - struct diyac_view *root = diyac_get_root_view(view); struct wlr_box geometry = view->pending_size; - if (!root) + // Only adjust position only when not in fullscreen mode + if(!grabbed) { - root = view; - } - if (!root->state.fullscreen) - { - - // Only adjust position only when not in fullscreen mode - - if (!grabbed && geometry.x < usable.x) + if (geometry.x > (usable.x + usable.width)) + { + geometry.x = (usable.x + usable.width) - (geometry.width / 2); + } + if (geometry.y > (usable.y + usable.height)) + { + geometry.y = (usable.y + usable.height) - (geometry.height / 2); + } + if (geometry.x < usable.x) { geometry.x = usable.x; } - if (!grabbed && geometry.y < usable.y) + if (geometry.y < usable.y) { geometry.y = usable.y; } - if (grabbed && server->seat.cursor->x <= usable.x) + } + else + { + if (server->seat.cursor->x <= usable.x) { geometry.x = usable.x - server->grab_x; } - if (grabbed && server->seat.cursor->y <= usable.y) + if (server->seat.cursor->y <= usable.y) { geometry.y = usable.y; } - if (grabbed && server->seat.cursor->x >= usable.x + usable.width) + if (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) + if (server->seat.cursor->y >= usable.y + usable.height) { geometry.y = usable.y + usable.height - server->grab_y; } @@ -349,12 +354,12 @@ 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; - if (view->state.fullscreen) + if (view->state.fullscreen && view->output) { wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box); return box; } - if (view->state.maximized) + if (view->state.maximized && view->output) { return view->output->usable_area; } diff --git a/xdg.c b/xdg.c index a548318..c4db649 100644 --- a/xdg.c +++ b/xdg.c @@ -114,7 +114,7 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { diyac_reset_cursor_mode(toplevel->server); } - if (toplevel->state.fullscreen) + if (toplevel->state.fullscreen && toplevel->output) { /** * When a client exit during fullscreen mode, the top layer shall @@ -241,6 +241,10 @@ static void handle_xdg_popup_destroy(struct wl_listener *listener, void *data) static void popup_unconstrain(struct diyac_popup *popup) { struct diyac_view *view = popup->parent; + if(!view->output) + { + return; + } struct diyac_server *server = view->server; struct wlr_output_layout *output_layout = server->output_layout; struct wlr_output *wlr_output = view->output->wlr_output;