From 0d84bd388c6452995f5148ae8ed03e9e47247219 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Mon, 1 Apr 2024 22:12:35 +0200 Subject: [PATCH] improvement on xdg request handles --- cursor.c | 4 +++- diyac.c | 27 ++++++++++++++++------ diyac.h | 4 +++- seat.c | 2 +- view.c | 21 ++++++++++++----- view.h | 2 +- xdg.c | 68 ++++++++++++++++++++++++++++++++------------------------ xdg.h | 1 - 8 files changed, 83 insertions(+), 46 deletions(-) diff --git a/cursor.c b/cursor.c index 039a593..5823d1c 100644 --- a/cursor.c +++ b/cursor.c @@ -48,7 +48,6 @@ void diyac_reset_cursor_mode(struct diyac_server *server) /* Reset the cursor mode to passthrough. */ server->seat.cursor_mode = DIYAC_CURSOR_PASSTHROUGH; server->grabbed_view = NULL; - //struct diyac_view * view = diyac_view_at() } static void process_cursor_move(struct diyac_server *server, uint32_t time) @@ -57,6 +56,9 @@ static void process_cursor_move(struct diyac_server *server, uint32_t time) struct diyac_view *toplevel = server->grabbed_view; if(toplevel->state != DIYAC_VIEW_NORMAL) { + // cancel maximize or fullscreen state + wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, false); + wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); // move the windows to cursor server->grab_x = toplevel->original.width * server->grab_x / toplevel->output->usable_area.width; } diff --git a/diyac.c b/diyac.c index 9057d74..a646eb1 100644 --- a/diyac.c +++ b/diyac.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "output.h" #include "xdg.h" #include "cursor.h" @@ -84,6 +86,17 @@ int main(int argc, char *argv[]) wlr_compositor_create(server.wl_display, 5, server.renderer); wlr_subcompositor_create(server.wl_display); wlr_data_device_manager_create(server.wl_display); + /* + * Empirically, primary selection doesn't work with Gtk apps unless the + * device manager is one of the earliest globals to be advertised. All + * credit to Wayfire for discovering this, though their symptoms + * (crash) are not the same as ours (silently does nothing). When adding + * more globals above this line it would be as well to check that + * middle-button paste still works with any Gtk app of your choice + * + * https://wayfire.org/2020/08/04/Wayfire-0-5.html + */ + wlr_primary_selection_v1_device_manager_create(server.wl_display); /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ @@ -103,25 +116,25 @@ int main(int argc, char *argv[]) */ server.scene = wlr_scene_create(); server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout); - - /* Set up xdg-shell version 3. The xdg-shell is a Wayland protocol which is + wlr_fractional_scale_manager_v1_create(server.wl_display,1); + /* Set up xdg-shell version 6 The xdg-shell is a Wayland protocol which is * used for application windows. For more detail on shells, refer to * https://drewdevault.com/2018/07/29/Wayland-shells.html. */ wl_list_init(&server.views); server.view_tree = wlr_scene_tree_create(&server.scene->tree); server.xdg_popup_tree = wlr_scene_tree_create(&server.scene->tree); - - server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 3); + + server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 6); server.new_xdg_surface.notify = diyac_new_xdg_surface; wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface); - server.layer_shell = wlr_layer_shell_v1_create(server.wl_display,4); + server.layer_shell = wlr_layer_shell_v1_create(server.wl_display, 4); server.new_layer_surface.notify = diyac_new_layer_surface; wl_signal_add(&server.layer_shell->events.new_surface, - &server.new_layer_surface); - + &server.new_layer_surface); + diyac_init_cursor_manager(&server); /* diff --git a/diyac.h b/diyac.h index 775da04..ea9948d 100644 --- a/diyac.h +++ b/diyac.h @@ -12,6 +12,7 @@ #include #include #include +#include #define LAYER_TREE_SZ 4 /* For brevity's sake, struct members are annotated where they are used. */ @@ -106,6 +107,7 @@ struct diyac_server struct wl_listener new_xdg_surface; struct wl_listener new_layer_surface; struct wl_list views; + /* * Popups need to be rendered above always-on-top views, so we reparent * them to this dedicated tree @@ -180,7 +182,7 @@ struct diyac_view struct wl_listener request_maximize; struct wl_listener request_fullscreen; - struct wl_listener set_app_id; + struct wl_listener set_app_id; // only useful when using SSD struct wl_listener new_popup; }; diff --git a/seat.c b/seat.c index 9c5bac4..1ebb4d5 100644 --- a/seat.c +++ b/seat.c @@ -293,7 +293,7 @@ void diyac_seat_focus_layer(struct diyac_seat *seat, struct wlr_layer_surface_v1 if (!layer) { seat->focused_layer = NULL; - diyac_focus_topmost_view(seat->server); + diyac_focus_topmost_view(seat->server, false); return; } seat_focus(seat, layer->surface, /*is_lock_surface*/ false); diff --git a/view.c b/view.c index 2894409..6f368dd 100644 --- a/view.c +++ b/view.c @@ -21,11 +21,17 @@ void diyac_focus_view(struct diyac_view *toplevel, bool raise) { return; } + if(!toplevel->mapped) + { + // dont focus unmapped view + return; + } struct diyac_server *server = toplevel->server; struct wlr_surface *prev_surface = server->seat.wlr_seat->keyboard_state.focused_surface; if (prev_surface == toplevel->xdg_toplevel->base->surface) { // Don't re-focus an already focused surface. + wlr_log(WLR_DEBUG, "Don't re-focus an already focused surface"); return; } if (prev_surface) @@ -42,10 +48,6 @@ void diyac_focus_view(struct diyac_view *toplevel, bool raise) wlr_xdg_toplevel_set_activated(prev_toplevel, false); } } - if(!toplevel->mapped) - { - return; - } raise_to_front(toplevel); if (raise) { @@ -80,11 +82,20 @@ struct diyac_view *diyac_view_at( return node_descriptor->data; } -void diyac_focus_topmost_view(struct diyac_server *server) +void diyac_focus_topmost_view(struct diyac_server *server, bool raise) { struct diyac_view *view = diyac_topmost_focusable_view(server); if (view) { + if(raise) + { + struct diyac_view * root = diyac_get_root_view(view); + if(root) + { + diyac_focus_view(root, true); + return; + } + } diyac_focus_view(view, false); } else diff --git a/view.h b/view.h index 93778ad..9236729 100644 --- a/view.h +++ b/view.h @@ -5,7 +5,7 @@ void diyac_focus_view(struct diyac_view *toplevel, bool raise); struct diyac_view *diyac_view_at( struct diyac_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); -void diyac_focus_topmost_view(struct diyac_server *server); +void diyac_focus_topmost_view(struct diyac_server *server, bool raise); struct diyac_view * diyac_topmost_focusable_view(struct diyac_server *server); bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed); void diyac_arrange_all_views(struct diyac_server *server); diff --git a/xdg.c b/xdg.c index 83d21ff..cf97a0a 100644 --- a/xdg.c +++ b/xdg.c @@ -63,11 +63,11 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data) wl_list_insert(&toplevel->server->views, &toplevel->link); toplevel->original.x = (toplevel->output->usable_area.width - toplevel->original.width) / 2; toplevel->original.y = (toplevel->output->usable_area.height - toplevel->original.height) / 2; - if(toplevel->original.width > toplevel->output->usable_area.width) + if (toplevel->original.width > toplevel->output->usable_area.width) { toplevel->original.width = toplevel->output->usable_area.width; } - if(toplevel->original.height > toplevel->output->usable_area.height) + if (toplevel->original.height > toplevel->output->usable_area.height) { toplevel->original.height = toplevel->output->usable_area.height; } @@ -88,21 +88,7 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { diyac_reset_cursor_mode(toplevel->server); } - - if(toplevel->server->grabbed_view == toplevel) - { - toplevel->server->grabbed_view = NULL; - } - struct diyac_view * root = diyac_get_root_view(toplevel); wl_list_remove(&toplevel->link); - if(root && root->mapped) - { - diyac_focus_view(root, true); - } - else - { - diyac_cursor_focus(toplevel->server); - } } static void xdg_toplevel_request_move( @@ -113,6 +99,7 @@ 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); } @@ -125,6 +112,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); @@ -158,18 +146,24 @@ static void xdg_toplevel_request_maximize( } else { - wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, true); + wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, true); toplevel->state = DIYAC_VIEW_MAXIMIZE; } diyac_view_update_geometry(toplevel, false); - //wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base); + // wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base); } -static void xdg_toplevel_request_fullscreen( - struct wl_listener *listener, void *data) +static void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void *data) { struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_fullscreen); + wlr_log(WLR_INFO, "Cursor state %d", toplevel->server->seat.cursor_mode); + if (toplevel->server->seat.cursor_mode != DIYAC_CURSOR_PASSTHROUGH) + { + wlr_log(WLR_INFO, "The view is under move/resize, disable fullcreen event"); + wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); + return; + } if (!toplevel->mapped) { wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); @@ -181,7 +175,7 @@ static void xdg_toplevel_request_fullscreen( diyac_reset_cursor_mode(toplevel->server); wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); /* - + if (toplevel->state == DIYAC_VIEW_FULL_SCREEN) { toplevel->state = DIYAC_VIEW_NORMAL; @@ -194,7 +188,7 @@ static void xdg_toplevel_request_fullscreen( } */ - diyac_view_update_geometry(toplevel, false); + // diyac_view_update_geometry(toplevel, false); } static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *data) @@ -218,6 +212,16 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) /* Called when the xdg_toplevel is destroyed. */ struct diyac_view *toplevel = wl_container_of(listener, toplevel, destroy); + struct diyac_view *root = diyac_get_root_view(toplevel); + if (root && root->mapped) + { + diyac_focus_view(root, true); + } + else + { + diyac_focus_topmost_view(toplevel->server, true); + } + wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->unmap.link); wl_list_remove(&toplevel->destroy.link); @@ -262,14 +266,14 @@ static void popup_unconstrain(struct diyac_popup *popup) static void handle_xdg_popup_commit(struct wl_listener *listener, void *data) { struct diyac_popup *popup = wl_container_of(listener, popup, commit); - struct wlr_box popup_box ; + struct wlr_box popup_box; wlr_xdg_surface_get_geometry(popup->wlr_popup->base, &popup_box); popup_unconstrain(popup); if (!wlr_box_empty(&popup_box)) - //if (popup->wlr_popup->base->initial_commit) + // if (popup->wlr_popup->base->initial_commit) { struct diyac_view *view = popup->parent; - //wlr_output_commit(view->output->wlr_output); + // wlr_output_commit(view->output->wlr_output); /* Prevent getting called over and over again */ wl_list_remove(&popup->commit.link); popup->commit.notify = NULL; @@ -330,10 +334,10 @@ static void xdg_popup_create(struct diyac_view *view, struct wlr_xdg_popup *wlr_ wlr_scene_node_set_position(&view->server->xdg_popup_tree->node, box.x, box.y); } - struct wlr_scene_tree* tree= wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base); + struct wlr_scene_tree *tree = wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base); wlr_popup->base->surface->data = tree; - - //wlr_scene_node_set_enabled(&parent_tree->node, false); + + // wlr_scene_node_set_enabled(&parent_tree->node, false); diyac_node_descriptor_create(wlr_popup->base->surface->data, DIYAC_NODE_XDG_POPUP, view); } @@ -381,7 +385,6 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); wlr_log(WLR_INFO, "diyac_new_xdg_surface: Creating new application windows"); 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; @@ -393,6 +396,13 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) toplevel->scene_tree = wlr_scene_xdg_surface_create( toplevel->server->view_tree, toplevel->xdg_toplevel->base); xdg_surface->data = toplevel; + + if (toplevel->output) + { + wlr_fractional_scale_v1_notify_scale(xdg_surface->surface, + toplevel->output->wlr_output->scale); + } + wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false); diyac_node_descriptor_create(&toplevel->scene_tree->node, DIYAC_NODE_VIEW, toplevel); diff --git a/xdg.h b/xdg.h index 294f0c6..d423931 100644 --- a/xdg.h +++ b/xdg.h @@ -3,5 +3,4 @@ #include "diyac.h" void diyac_new_xdg_surface(struct wl_listener *listener, void *data); - #endif \ No newline at end of file