kranewl

A wlroots-based dynamic Wayland compositor, written in C++, configurable with Lua
git clone git://git.deurzen.net/kranewl
Log | Files | Refs | LICENSE

commit 81b4be77799991f14b2f42a61f3e972918dda24e
parent a619f30fd0f4a4183bf3969d446ca9d1027eeb2b
Author: deurzen <m.deurzen@tum.de>
Date:   Mon, 23 May 2022 00:51:56 +0200

adds initial view mapping functionality

Diffstat:
Minclude/kranewl/server.hh | 2++
Minclude/kranewl/tree/view.hh | 13+++++++++----
Minclude/kranewl/tree/xwayland_view.hh | 2+-
Minclude/version.hh | 4++--
Msrc/kranewl/model.cc | 1-
Msrc/kranewl/server.cc | 18++++++++++++++++++
Msrc/kranewl/tree/view.cc | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/kranewl/tree/xdg_view.cc | 30++++++++++++++++++++++++++++++
Msrc/kranewl/tree/xwayland_view.cc | 15++++++++++++++-
9 files changed, 155 insertions(+), 10 deletions(-)

diff --git a/include/kranewl/server.hh b/include/kranewl/server.hh @@ -41,6 +41,7 @@ private: static void handle_inhibit_deactivate(struct wl_listener*, void*); static void handle_idle_inhibitor_create(struct wl_listener*, void*); static void handle_idle_inhibitor_destroy(struct wl_listener*, void*); + static void handle_xdg_new_toplevel_decoration(struct wl_listener*, void*); static void handle_xdg_toplevel_map(struct wl_listener*, void*); static void handle_xdg_toplevel_unmap(struct wl_listener*, void*); static void handle_xdg_toplevel_destroy(struct wl_listener*, void*); @@ -104,6 +105,7 @@ private: struct wl_listener ml_inhibit_deactivate; struct wl_listener ml_idle_inhibitor_create; struct wl_listener ml_idle_inhibitor_destroy; + struct wl_listener ml_xdg_new_toplevel_decoration; #ifdef XWAYLAND struct wl_listener ml_xwayland_ready; struct wl_listener ml_new_xwayland_surface; diff --git a/include/kranewl/tree/view.hh b/include/kranewl/tree/view.hh @@ -23,7 +23,7 @@ typedef class Output* Output_ptr; typedef class Context* Context_ptr; typedef class Workspace* Workspace_ptr; typedef struct XDGView* XDGView_ptr; -#if XWAYLAND +#ifdef XWAYLAND typedef struct XWaylandView* XWaylandView_ptr; #endif typedef struct View* View_ptr; @@ -34,7 +34,7 @@ typedef struct View { enum class Type { XDGShell, -#if XWAYLAND +#ifdef XWAYLAND XWayland, #endif }; @@ -48,13 +48,14 @@ typedef struct View { Output_ptr, Context_ptr, Workspace_ptr, + struct wlr_surface*, void(*)(wl_listener*, void*), void(*)(wl_listener*, void*), void(*)(wl_listener*, void*), void(*)(wl_listener*, void*), void(*)(wl_listener*, void*) ); -#if XWAYLAND +#ifdef XWAYLAND View( XWaylandView_ptr, Uid, @@ -64,6 +65,7 @@ typedef struct View { Output_ptr, Context_ptr, Workspace_ptr, + struct wlr_surface*, void(*)(wl_listener*, void*), void(*)(wl_listener*, void*), void(*)(wl_listener*, void*), @@ -74,6 +76,8 @@ typedef struct View { virtual ~View(); + static void map_view(View_ptr, struct wlr_surface*, bool, struct wlr_output*, bool); + static bool is_free(View_ptr view) { @@ -93,6 +97,7 @@ typedef struct View { Context_ptr mp_context; Workspace_ptr mp_workspace; + struct wlr_surface* mp_wlr_surface; struct wlr_scene_node* mp_scene; struct wlr_scene_node* mp_scene_surface; struct wlr_scene_rect* m_protrusions[4]; // top, bottom, left, right @@ -109,7 +114,7 @@ typedef struct View { Decoration m_free_decoration; Decoration m_active_decoration; - Region m_preferred_region; + Dim m_preferred_dim; Region m_free_region; Region m_tile_region; Region m_active_region; diff --git a/include/kranewl/tree/xwayland_view.hh b/include/kranewl/tree/xwayland_view.hh @@ -10,7 +10,7 @@ typedef class Output* Output_ptr; typedef class Context* Context_ptr; typedef class Workspace* Workspace_ptr; -#if XWAYLAND +#ifdef XWAYLAND typedef struct XWaylandView final : public View { XWaylandView( struct wlr_xwayland_surface*, diff --git a/include/version.hh b/include/version.hh @@ -1 +1 @@ -#define VERSION "master/b7cfa06+" -\ No newline at end of file +#define VERSION "master/a619f30+" +\ No newline at end of file diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc @@ -17,7 +17,6 @@ #include <kranewl/workspace.hh> #include <spdlog/spdlog.h> -#include <spdlog/fmt/bin_to_hex.h> #include <iomanip> diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc @@ -9,7 +9,9 @@ #include <kranewl/tree/output.hh> #include <kranewl/tree/view.hh> #include <kranewl/tree/xdg_view.hh> +#ifdef XWAYLAND #include <kranewl/tree/xwayland_view.hh> +#endif #include <spdlog/spdlog.h> @@ -134,6 +136,7 @@ Server::Server(Model_ptr model) ml_inhibit_deactivate({ .notify = Server::handle_inhibit_deactivate }), ml_idle_inhibitor_create({ .notify = Server::handle_idle_inhibitor_create }), ml_idle_inhibitor_destroy({ .notify = Server::handle_idle_inhibitor_destroy }), + ml_xdg_new_toplevel_decoration({ .notify = Server::handle_xdg_new_toplevel_decoration }), #ifdef XWAYLAND ml_xwayland_ready({ .notify = Server::handle_xwayland_ready }), ml_new_xwayland_surface({ .notify = Server::handle_new_xwayland_surface }), @@ -166,6 +169,7 @@ Server::Server(Model_ptr model) wl_signal_add(&mp_layer_shell->events.new_surface, &ml_new_layer_shell_surface); wl_signal_add(&mp_xdg_shell->events.new_surface, &ml_new_xdg_surface); wl_signal_add(&mp_idle_inhibit_manager->events.new_inhibitor, &ml_idle_inhibitor_create); + wl_signal_add(&mp_xdg_decoration_manager->events.new_toplevel_decoration, &ml_xdg_new_toplevel_decoration); wl_signal_add(&mp_backend->events.new_input, &ml_new_input); wl_signal_add(&mp_output_manager->events.apply, &ml_output_manager_apply); wl_signal_add(&mp_output_manager->events.test, &ml_output_manager_test); @@ -423,6 +427,20 @@ Server::handle_idle_inhibitor_destroy(struct wl_listener*, void*) } void +Server::handle_xdg_new_toplevel_decoration(struct wl_listener*, void* data) +{ + TRACE(); + + struct wlr_xdg_toplevel_decoration_v1* decoration + = reinterpret_cast<struct wlr_xdg_toplevel_decoration_v1*>(data); + + wlr_xdg_toplevel_decoration_v1_set_mode( + decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE + ); +} + +void Server::handle_xdg_toplevel_map(struct wl_listener*, void*) { TRACE(); diff --git a/src/kranewl/tree/view.cc b/src/kranewl/tree/view.cc @@ -1,5 +1,12 @@ +#include <trace.hh> + #include <kranewl/tree/view.hh> +extern "C" { +#include <sys/types.h> +#include <wlr/types/wlr_xdg_shell.h> +} + View::View( XDGView_ptr, Uid uid, @@ -9,6 +16,7 @@ View::View( Output_ptr output, Context_ptr context, Workspace_ptr workspace, + struct wlr_surface* wlr_surface, void(*handle_foreign_activate_request)(wl_listener*, void*), void(*handle_foreign_fullscreen_request)(wl_listener*, void*), void(*handle_foreign_close_request)(wl_listener*, void*), @@ -23,6 +31,32 @@ View::View( mp_output(output), mp_context(context), mp_workspace(workspace), + mp_wlr_surface(wlr_surface), + m_alpha(1.f), + m_tile_decoration(FREE_DECORATION), + m_free_decoration(FREE_DECORATION), + m_active_decoration(FREE_DECORATION), + m_preferred_dim({}), + m_free_region({}), + m_tile_region({}), + m_active_region({}), + m_previous_region({}), + m_inner_region({}), + m_focused(false), + m_mapped(false), + m_managed(true), + m_urgent(false), + m_floating(false), + m_fullscreen(false), + m_scratchpad(false), + m_contained(false), + m_invincible(false), + m_sticky(false), + m_iconifyable(true), + m_iconified(false), + m_disowned(false), + m_last_focused(std::chrono::steady_clock::now()), + m_managed_since(std::chrono::steady_clock::now()), ml_foreign_activate_request({ .notify = handle_foreign_activate_request }), ml_foreign_fullscreen_request({ .notify = handle_foreign_fullscreen_request }), ml_foreign_close_request({ .notify = handle_foreign_close_request }), @@ -32,7 +66,7 @@ View::View( wl_signal_init(&m_events.unmap); } -#if XWAYLAND +#ifdef XWAYLAND View::View( XWaylandView_ptr, Uid uid, @@ -42,6 +76,7 @@ View::View( Output_ptr output, Context_ptr context, Workspace_ptr workspace, + struct wlr_surface* wlr_surface, void(*handle_foreign_activate_request)(wl_listener*, void*), void(*handle_foreign_fullscreen_request)(wl_listener*, void*), void(*handle_foreign_close_request)(wl_listener*, void*), @@ -56,6 +91,7 @@ View::View( mp_output(output), mp_context(context), mp_workspace(workspace), + mp_wlr_surface(wlr_surface), ml_foreign_activate_request({ .notify = handle_foreign_activate_request }), ml_foreign_fullscreen_request({ .notify = handle_foreign_fullscreen_request }), ml_foreign_close_request({ .notify = handle_foreign_close_request }), @@ -67,6 +103,48 @@ View::View( View::~View() {} +static inline void +retrieve_view_pid(View_ptr view) +{ + switch (view->m_type) { + case View::Type::XDGShell: + { + pid_t pid; + struct wl_client* client + = wl_resource_get_client(view->mp_wlr_surface->resource); + + wl_client_get_credentials(client, &pid, NULL, NULL); + view->m_pid = pid; + } + break; +#if HAVE_XWAYLAND + case View::Type::XWayland: + { + struct wlr_xwayland_surface* wlr_xwayland_surface + = wlr_xwayland_surface_from_wlr_surface(view->mp_wlr_surface); + view->m_pid = wlr_xwayland_surface->pid; + } + break; +#endif + default: break; + } +} + +void +View::map_view( + View_ptr view, + struct wlr_surface* wlr_surface, + bool fullscreen, + struct wlr_output* fullscreen_output, + bool decorations +) +{ + TRACE(); + + view->mp_wlr_surface = wlr_surface; + retrieve_view_pid(view); +} + ViewChild::ViewChild(SubsurfaceViewChild_ptr) : m_type(Type::Subsurface) {} diff --git a/src/kranewl/tree/xdg_view.cc b/src/kranewl/tree/xdg_view.cc @@ -25,6 +25,7 @@ XDGView::XDGView( output, context, workspace, + wlr_xdg_surface->surface, XDGView::handle_foreign_activate_request, XDGView::handle_foreign_fullscreen_request, XDGView::handle_foreign_close_request, @@ -141,6 +142,35 @@ XDGView::handle_map(struct wl_listener* listener, void* data) { TRACE(); + XDGView_ptr view = wl_container_of(listener, view, ml_map); + struct wlr_xdg_toplevel* wlr_xdg_toplevel = view->mp_wlr_xdg_toplevel; + + view->m_mapped = true; + view->m_preferred_dim = Dim{ + .w = wlr_xdg_toplevel->base->current.geometry.width, + .h = wlr_xdg_toplevel->base->current.geometry.height, + }; + + if (!view->m_preferred_dim.w && !view->m_preferred_dim.h) { + view->m_preferred_dim.w = wlr_xdg_toplevel->base->surface->current.width; + view->m_preferred_dim.h = wlr_xdg_toplevel->base->surface->current.height; + } + + View::map_view( + view, + wlr_xdg_toplevel->base->surface, + wlr_xdg_toplevel->requested.fullscreen, + wlr_xdg_toplevel->requested.fullscreen_output, + false // TODO: determine if client has decorations + ); + + wl_signal_add(&wlr_xdg_toplevel->base->surface->events.commit, &view->ml_commit); + wl_signal_add(&wlr_xdg_toplevel->base->events.new_popup, &view->ml_new_popup); + wl_signal_add(&wlr_xdg_toplevel->events.request_fullscreen, &view->ml_request_fullscreen); + wl_signal_add(&wlr_xdg_toplevel->events.request_move, &view->ml_request_move); + wl_signal_add(&wlr_xdg_toplevel->events.request_resize, &view->ml_request_resize); + wl_signal_add(&wlr_xdg_toplevel->events.set_title, &view->ml_set_title); + wl_signal_add(&wlr_xdg_toplevel->events.set_app_id, &view->ml_set_app_id); } void diff --git a/src/kranewl/tree/xwayland_view.cc b/src/kranewl/tree/xwayland_view.cc @@ -1,9 +1,21 @@ +#ifdef XWAYLAND #include <trace.hh> #include <kranewl/tree/view.hh> #include <kranewl/tree/xwayland_view.hh> -#if XWAYLAND +// https://github.com/swaywm/wlroots/issues/682 +#include <pthread.h> +#define class class_ +#define namespace namespace_ +#define static +extern "C" { +#include <wlr/xwayland.h> +} +#undef static +#undef class +#undef namespace + XWaylandView::XWaylandView( struct wlr_xwayland_surface* wlr_xwayland_surface, Server_ptr server, @@ -22,6 +34,7 @@ XWaylandView::XWaylandView( output, context, workspace, + wlr_xwayland_surface->surface, XWaylandView::handle_foreign_activate_request, XWaylandView::handle_foreign_fullscreen_request, XWaylandView::handle_foreign_close_request,