diff --git a/include/waybox/server.h b/include/waybox/server.h index 67492a5..c5a843d 100644 --- a/include/waybox/server.h +++ b/include/waybox/server.h @@ -54,6 +54,7 @@ struct wb_server { struct wlr_renderer *renderer; struct wlr_scene *scene; struct wlr_scene_output_layout *scene_layout; + struct wlr_session *session; struct wlr_subcompositor *subcompositor; struct wlr_output_manager_v1 *wlr_output_manager; diff --git a/include/waybox/xdg_shell.h b/include/waybox/xdg_shell.h index 4855d26..e54c546 100644 --- a/include/waybox/xdg_shell.h +++ b/include/waybox/xdg_shell.h @@ -1,10 +1,17 @@ #ifndef _WB_XDG_SHELL_H #define _WB_XDG_SHELL_H +#include + #include "waybox/server.h" +struct wb_popup { + struct wlr_xdg_popup *xdg_popup; + struct wl_listener commit; + struct wl_listener destroy; +}; + struct wb_toplevel { - struct wl_list link; struct wb_server *server; struct wlr_xdg_toplevel *xdg_toplevel; struct wlr_scene_tree *scene_tree; @@ -13,6 +20,7 @@ struct wb_toplevel { struct wl_listener map; struct wl_listener unmap; + struct wl_listener commit; struct wl_listener destroy; struct wl_listener new_popup; struct wl_listener request_fullscreen; @@ -23,6 +31,8 @@ struct wb_toplevel { struct wlr_box geometry; struct wlr_box previous_geometry; + + struct wl_list link; }; void init_xdg_shell(struct wb_server *server); diff --git a/meson.build b/meson.build index 17811b7..a5e71ea 100644 --- a/meson.build +++ b/meson.build @@ -15,6 +15,7 @@ add_project_arguments( '-Wno-unused-parameter', '-D_DEFAULT_SOURCE', '-D_POSIX_C_SOURCE=200112L', + '-DWL_HIDE_DEPRECATED', # Hide the deprecated parts of the Wayland API '-DWLR_USE_UNSTABLE', '-DPACKAGE_NAME="' + meson.project_name() + '"', '-DPACKAGE_VERSION="' + meson.project_version() + '"', diff --git a/waybox/layer_shell.c b/waybox/layer_shell.c index 6c9365d..78ec531 100644 --- a/waybox/layer_shell.c +++ b/waybox/layer_shell.c @@ -111,6 +111,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (!surface->output || current_toplevel->xdg_toplevel->current.fullscreen) { return; } + wlr_fractional_scale_v1_notify_scale(surface->scene->layer_surface->surface, surface->output->wlr_output->scale); struct wlr_layer_surface_v1 *layer_surface = surface->scene->layer_surface; uint32_t committed = layer_surface->current.committed; @@ -183,6 +184,8 @@ static void wb_layer_surface_destroy(struct wb_layer_surface *surface) { return; } + wlr_fractional_scale_v1_notify_scale(surface->scene->layer_surface->surface, surface->output->wlr_output->scale); + wl_list_remove(&surface->map.link); wl_list_remove(&surface->unmap.link); wl_list_remove(&surface->surface_commit.link); diff --git a/waybox/output.c b/waybox/output.c index 017e34b..d027e0d 100644 --- a/waybox/output.c +++ b/waybox/output.c @@ -21,7 +21,6 @@ void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_gamma_control_v1 *gamma_control = wlr_gamma_control_manager_v1_get_control(output->server->gamma_control_manager, output->wlr_output); -#if WLR_CHECK_VERSION(0, 18, 0) struct wlr_output_state pending; if (!wlr_scene_output_build_state(scene_output, &pending, NULL)) return; @@ -38,16 +37,6 @@ void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_output_state_finish(&pending); -#else - if (!wlr_gamma_control_v1_apply(gamma_control, &output->wlr_output->pending)) { - return; - } - - if (!wlr_output_test(output->wlr_output)) { - wlr_output_rollback(output->wlr_output); - wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); - } -#endif } /* Render the scene if needed and commit the output */ diff --git a/waybox/seat.c b/waybox/seat.c index 8152f06..a927e72 100644 --- a/waybox/seat.c +++ b/waybox/seat.c @@ -58,18 +58,17 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32 * Returns true if the keybinding is handled, false to send it to the * client. */ - - struct wlr_session *session = wlr_backend_get_session (server->backend); - + + /* TODO: Make these configurable through rc.xml */ if (modifiers & (WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT) && sym >= XKB_KEY_XF86Switch_VT_1 && sym <= XKB_KEY_XF86Switch_VT_12) { unsigned int vt = sym - XKB_KEY_XF86Switch_VT_1 + 1; - wlr_session_change_vt (session, vt); - + wlr_session_change_vt (server->session, vt); + return true; } - + if (!server->config) { /* Some default key bindings, when the rc.xml file can't be * parsed. */ diff --git a/waybox/server.c b/waybox/server.c index 982d7ea..843aa59 100644 --- a/waybox/server.c +++ b/waybox/server.c @@ -1,3 +1,5 @@ +#include + #include "idle.h" #include "waybox/server.h" #include "waybox/xdg_shell.h" @@ -22,9 +24,9 @@ bool wb_create_backend(struct wb_server* server) { * backend based on the current environment, such as opening an X11 window * if an X11 server is running. */ #if WLR_CHECK_VERSION(0, 18, 0) - server->backend = wlr_backend_autocreate(server->wl_event_loop, NULL); + server->backend = wlr_backend_autocreate(server->wl_event_loop, &server->session); #else - server->backend = wlr_backend_autocreate(server->wl_display, NULL); + server->backend = wlr_backend_autocreate(server->wl_display, &server->session); #endif if (server->backend == NULL) { wlr_log(WLR_ERROR, "%s", _("Failed to create backend")); @@ -120,6 +122,8 @@ bool wb_start_server(struct wb_server* server) { */ init_xdg_shell(server); + wlr_fractional_scale_manager_v1_create(server->wl_display, 1); + return true; } diff --git a/waybox/xdg_shell.c b/waybox/xdg_shell.c index 8f37e55..acf079e 100644 --- a/waybox/xdg_shell.c +++ b/waybox/xdg_shell.c @@ -145,12 +145,43 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { } } +static void update_fractional_scale(struct wlr_surface *surface) { + float scale = 1; + struct wlr_surface_output *surface_output; + wl_list_for_each(surface_output, &surface->current_outputs, link) { + if (surface_output->output->scale > scale) { + scale = surface_output->output->scale; + } + } + wlr_fractional_scale_v1_notify_scale(surface, scale); + wlr_surface_set_preferred_buffer_scale(surface, (int) scale); +} + +static void xdg_toplevel_commit(struct wl_listener *listener, void *data) { + struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, commit); + struct wlr_xdg_surface *base = toplevel->xdg_toplevel->base; + + struct wlr_output *output = get_active_output(toplevel); + wlr_surface_send_enter(base->surface, output); + update_fractional_scale(base->surface); + + if (base->initial_commit) { + wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0); + } +} + static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { /* Called when the xdg_toplevel is destroyed and should never be shown again. */ struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, destroy); + struct wlr_output *output = get_active_output(toplevel); + struct wlr_xdg_surface *base = toplevel->xdg_toplevel->base; + wlr_surface_send_leave(base->surface, output); + update_fractional_scale(base->surface); + wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->unmap.link); + wl_list_remove(&toplevel->commit.link); wl_list_remove(&toplevel->destroy.link); wl_list_remove(&toplevel->new_popup.link); @@ -297,6 +328,25 @@ static void xdg_toplevel_request_resize( begin_interactive(toplevel, WB_CURSOR_RESIZE, event->edges); } +static void xdg_popup_commit(struct wl_listener *listener, void *data) { + struct wb_popup *popup = wl_container_of(listener, popup, commit); + struct wlr_xdg_surface *base = popup->xdg_popup->base; + + if (base->initial_commit) { + update_fractional_scale(base->surface); + wlr_xdg_surface_schedule_configure(base); + } +} + +static void xdg_popup_destroy(struct wl_listener *listener, void *data) { + struct wb_popup *popup = wl_container_of(listener, popup, destroy); + update_fractional_scale(popup->xdg_popup->base->surface); + + wl_list_remove(&popup->commit.link); + wl_list_remove(&popup->destroy.link); + free(popup); +} + static void handle_new_popup(struct wl_listener *listener, void *data) { struct wlr_xdg_popup *popup = data; struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, new_popup); @@ -336,6 +386,17 @@ static void handle_new_xdg_popup(struct wl_listener *listener, void *data) { xdg_popup->base->data = wlr_scene_xdg_surface_create( parent_tree, xdg_popup->base); } + + struct wb_popup *popup = calloc(1, sizeof(struct wb_popup)); + popup->commit.notify = xdg_popup_commit; + wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit); + + popup->destroy.notify = xdg_popup_destroy; +#if WLR_CHECK_VERSION (0, 18, 0) + wl_signal_add(&xdg_popup->events.destroy, &popup->destroy); +#else + wl_signal_add(&xdg_popup->base->events.destroy, &popup->destroy); +#endif } static void handle_new_xdg_toplevel(struct wl_listener *listener, void *data) { @@ -358,6 +419,8 @@ static void handle_new_xdg_toplevel(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map); toplevel->unmap.notify = xdg_toplevel_unmap; wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap); + toplevel->commit.notify = xdg_toplevel_commit; + wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit); toplevel->destroy.notify = xdg_toplevel_destroy; #if WLR_CHECK_VERSION (0, 18, 0) wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);