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 2fd6f353433d9c6bbee37159bc94e837ead9dae8
parent 7e52bfde60eeae43e37c66066d1fab8516912bac
Author: deurzen <m.deurzen@tum.de>
Date:   Sat, 21 May 2022 21:31:34 +0200

adds tree node handling

Diffstat:
MCMakeLists.txt | 1+
Minclude/kranewl/input/keyboard.hh | 5+++--
Minclude/kranewl/model.hh | 8+++++++-
Minclude/kranewl/server.hh | 19+++++--------------
Minclude/kranewl/tree/node.hh | 48++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/kranewl/tree/output.hh | 95+++++++++++++++++++++++++++++--------------------------------------------------
Minclude/kranewl/tree/root.hh | 40++++++++++++++++++++++++++++++++++++++++
Minclude/version.hh | 4++--
Msrc/kranewl/model.cc | 4+++-
Msrc/kranewl/server.cc | 239++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/kranewl/tree/node.cc | 46++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kranewl/tree/output.cc | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kranewl/tree/root.cc | 37+++++++++++++++++++++++++++++++++++++
13 files changed, 467 insertions(+), 216 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -35,6 +35,7 @@ add_compile_options( -O0 # debug options -g + # -DTRACING_DISABLED # -finstrument-functions -finstrument-functions-exclude-file-list=/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/include/g++-v11,/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/include/g++-v11/backward,/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/include/g++-v11/x86_64-pc-linux-gnu,/usr/local/include -ldl -Wl,--export-dynamic ) diff --git a/include/kranewl/input/keyboard.hh b/include/kranewl/input/keyboard.hh @@ -9,7 +9,8 @@ extern "C" { #include <unordered_set> typedef class Server* Server_ptr; -struct Keyboard { + +typedef struct Keyboard { Server_ptr mp_server; struct wl_list m_link; @@ -17,7 +18,7 @@ struct Keyboard { struct wl_listener ml_modifiers; struct wl_listener ml_key; -}; +}* Keyboard_ptr; struct KeyboardInput { uint32_t mod; diff --git a/include/kranewl/model.hh b/include/kranewl/model.hh @@ -25,7 +25,11 @@ public: void register_server(Server_ptr); void exit(); - Output_ptr create_output(Server_ptr, struct wlr_output*, struct wlr_scene_output*); + Keyboard_ptr create_keyboard(struct wlr_output*, struct wlr_scene_output*); + void register_keyboard(Keyboard_ptr); + void unregister_keyboard(Keyboard_ptr); + + Output_ptr create_output(struct wlr_output*, struct wlr_scene_output*); void register_output(Output_ptr); void unregister_output(Output_ptr); @@ -42,10 +46,12 @@ private: bool m_running; Cycle<Output_ptr> m_outputs; + Cycle<Keyboard_ptr> m_keyboards; Cycle<Context_ptr> m_contexts; Cycle<Workspace_ptr> m_workspaces; Output_ptr mp_output; + Output_ptr mp_fallback_output; Context_ptr mp_context; Workspace_ptr mp_workspace; diff --git a/include/kranewl/server.hh b/include/kranewl/server.hh @@ -1,6 +1,7 @@ #pragma once #include <kranewl/geometry.hh> +#include <kranewl/tree/root.hh> extern "C" { #include <wlr/backend.h> @@ -29,11 +30,9 @@ public: private: static void new_output(struct wl_listener*, void*); - static void output_destroy(struct wl_listener*, void*); static void output_layout_change(struct wl_listener*, void*); static void output_manager_apply(struct wl_listener*, void*); static void output_manager_test(struct wl_listener*, void*); - static void output_frame(struct wl_listener*, void*); static void new_xdg_surface(struct wl_listener*, void*); static void new_layer_shell_surface(struct wl_listener*, void*); @@ -89,17 +88,19 @@ private: struct wl_event_loop* mp_event_loop; struct wlr_backend* mp_backend; + struct wlr_backend* mp_headless_backend; struct wlr_renderer* mp_renderer; struct wlr_allocator* mp_allocator; struct wlr_compositor* mp_compositor; struct wlr_data_device_manager* mp_data_device_manager; + struct wlr_scene* mp_scene; + + Root m_root; #ifdef XWAYLAND struct wlr_xwayland* mp_xwayland; #endif - struct wlr_output_layout* mp_output_layout; - struct wlr_scene* mp_scene; struct wlr_xdg_shell* mp_xdg_shell; struct wlr_layer_shell_v1* mp_layer_shell; struct wlr_xdg_activation_v1* mp_xdg_activation; @@ -122,10 +123,6 @@ private: struct wlr_idle_inhibit_manager_v1* mp_idle_inhibit_manager; struct wlr_keyboard_shortcuts_inhibit_manager_v1* mp_keyboard_shortcuts_inhibit_manager; - struct wl_list m_outputs; - struct wl_list m_clients; - struct wl_list m_keyboards; - struct wl_listener ml_new_output; struct wl_listener ml_output_layout_change; struct wl_listener ml_output_manager_apply; @@ -153,12 +150,6 @@ private: struct wl_listener ml_new_xwayland_surface; #endif - CursorMode m_cursor_mode; - Client_ptr mp_grabbed_client; - double m_grab_x, m_grab_y; - struct wlr_box m_grab_geobox; - uint32_t m_resize_edges; - const std::string m_socket; }* Server_ptr; diff --git a/include/kranewl/tree/node.hh b/include/kranewl/tree/node.hh @@ -1,3 +1,51 @@ #pragma once +#include <kranewl/common.hh> +extern "C" { +#include <wayland-server-core.h> +} + +typedef class Root* Root_ptr; +typedef class Output* Output_ptr; +typedef class Context* Context_ptr; +typedef class Workspace* Workspace_ptr; +typedef class Container* Container_ptr; + +enum class NodeType { + Root, + Output, + Context, + Workspace, + Container, +}; + +typedef struct Node { +protected: + Node(Root_ptr); + Node(Output_ptr); + Node(Context_ptr); + Node(Workspace_ptr); + Node(Container_ptr); + ~Node(); + +public: + Uid m_uid; + + NodeType m_type; + union { + Root_ptr m_root; + Output_ptr m_output; + Context_ptr m_context; + Workspace_ptr m_workspace; + Container_ptr m_container; + }; + + bool m_destroying; + bool m_dirty; + + struct { + struct wl_signal destroy; + } m_events; + +}* Node_ptr; diff --git a/include/kranewl/tree/output.hh b/include/kranewl/tree/output.hh @@ -1,73 +1,36 @@ #pragma once #include <kranewl/common.hh> -#include <kranewl/geometry.hh> #include <kranewl/context.hh> -#include <kranewl/util.hh> - -#include <spdlog/spdlog.h> +#include <kranewl/geometry.hh> +#include <kranewl/tree/node.hh> extern "C" { -#include <wlr/backend.h> +#include <wayland-server-core.h> +#include <wlr/types/wlr_output.h> } typedef class Server* Server_ptr; +typedef class Model* Model_ptr; typedef class Context* Context_ptr; -typedef class Output final { -public: - Output( - Server_ptr server, - struct wlr_output* wlr_output, - struct wlr_scene_output* wlr_scene_output - ) - : mp_context(nullptr), - mp_server(server), - mp_wlr_output(wlr_output), - mp_wlr_scene_output(wlr_scene_output) - {} - - void - set_context(Context_ptr context) - { - if (!context) - spdlog::error("output must contain a valid context"); - - if (mp_context) - mp_context->set_output(nullptr); - - context->set_output(this); - mp_context = context; - } - Context_ptr - context() const - { - return mp_context; - } - - Region - full_region() const - { - return m_full_region; - } - - Region - placeable_region() const - { - return m_placeable_region; - } - - bool - contains(Pos pos) const - { - return m_full_region.contains(pos); - } - - bool - contains(Region region) const - { - return m_full_region.contains(region); - } +typedef class Output final : public Node { +public: + Output(Server_ptr, Model_ptr, struct wlr_output*, struct wlr_scene_output*); + ~Output(); + + static void handle_frame(struct wl_listener*, void*); + static void handle_destroy(struct wl_listener*, void*); + static void handle_present(struct wl_listener*, void*); + static void handle_mode(struct wl_listener*, void*); + static void handle_commit(struct wl_listener*, void*); + + void set_context(Context_ptr context); + Context_ptr context() const; + Region full_region() const; + Region placeable_region() const; + bool contains(Pos pos) const; + bool contains(Region region) const; private: Context_ptr mp_context; @@ -76,11 +39,23 @@ private: public: Server_ptr mp_server; + Model_ptr mp_model; struct wlr_output* mp_wlr_output; - struct wlr_scene_output* mp_wlr_scene_output; + struct wlr_scene_output* mp_wlr_scene_output; + + struct wlr_output_damage* mp_damage; + struct wlr_output_mode* mp_current_mode; + enum wl_output_subpixel m_subpixel; struct wl_listener ml_frame; struct wl_listener ml_destroy; + struct wl_listener ml_present; + struct wl_listener ml_mode; + struct wl_listener ml_commit; + + struct { + struct wl_signal disable; + } m_events; }* Output_ptr; diff --git a/include/kranewl/tree/root.hh b/include/kranewl/tree/root.hh @@ -1,3 +1,43 @@ #pragma once +#include <kranewl/common.hh> +#include <kranewl/cycle.hh> +#include <kranewl/geometry.hh> +#include <kranewl/tree/node.hh> +extern "C" { +#include <wayland-server-core.h> +#include <wlr/backend.h> +} + +typedef class Server* Server_ptr; +typedef class Model* Model_ptr; + +typedef class Root final : public Node { +public: + Root(Server_ptr, Model_ptr, struct wlr_output_layout*, Output_ptr); + ~Root(); + + static void handle_output_layout_change(struct wl_listener*, void*); + +public: + Server_ptr mp_server; + Model_ptr mp_model; + + struct wlr_output_layout* mp_output_layout; + + struct wl_listener ml_output_layout_change; + + struct { + struct wl_signal new_node; + } m_events; + + Region m_region; + + Cycle<Output_ptr> m_outputs; + Cycle<Container_ptr> m_scratchpad; + + Output_ptr mp_fallback_output; + Container_ptr mp_fullscreen_global; + +}* Root_ptr; diff --git a/include/version.hh b/include/version.hh @@ -1 +1 @@ -#define VERSION "master/2754909+" -\ No newline at end of file +#define VERSION "master/7e52bfd+" +\ No newline at end of file diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc @@ -23,9 +23,11 @@ Model::Model( : m_config{config}, m_running{true}, m_outputs{{}, true}, + m_keyboards{{}, false}, m_contexts{{}, true}, m_workspaces{{}, true}, mp_output{nullptr}, + mp_fallback_output{nullptr}, mp_context{nullptr}, mp_workspace{nullptr}, mp_prev_output{nullptr}, @@ -95,7 +97,6 @@ Model::register_server(Server_ptr server) Output_ptr Model::create_output( - Server_ptr server, struct wlr_output* wlr_output, struct wlr_scene_output* wlr_scene_output ) @@ -104,6 +105,7 @@ Model::create_output( Output_ptr output = new Output( mp_server, + this, wlr_output, wlr_scene_output ); diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc @@ -20,11 +20,16 @@ #define static extern "C" { #include <wlr/backend.h> +#include <wlr/backend/headless.h> +#include <wlr/backend/multi.h> #include <wlr/render/allocator.h> #include <wlr/render/wlr_renderer.h> #include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_cursor.h> +#include <wlr/types/wlr_data_control_v1.h> #include <wlr/types/wlr_data_device.h> +#include <wlr/types/wlr_export_dmabuf_v1.h> +#include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_input_device.h> @@ -41,8 +46,8 @@ extern "C" { #include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h> -#include <wlr/types/wlr_relative_pointer_v1.h> #include <wlr/types/wlr_scene.h> +#include <wlr/types/wlr_screencopy_v1.h> #include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_virtual_keyboard_v1.h> @@ -76,15 +81,57 @@ Server::Server(Model_ptr model) mp_display(wl_display_create()), mp_event_loop(wl_display_get_event_loop(mp_display)), mp_backend(wlr_backend_autocreate(mp_display)), + mp_headless_backend(wlr_headless_backend_create(mp_display)), mp_renderer([](struct wl_display* display, struct wlr_backend* backend) { - struct wlr_renderer* renderer = wlr_renderer_autocreate(backend); - wlr_renderer_init_wl_display(renderer, display); + struct wlr_renderer* renderer = wlr_renderer_autocreate(backend); + wlr_renderer_init_wl_display(renderer, display); - return renderer; + return renderer; }(mp_display, mp_backend)), mp_allocator(wlr_allocator_autocreate(mp_backend, mp_renderer)), + mp_compositor(wlr_compositor_create(mp_display, mp_renderer)), + mp_data_device_manager(wlr_data_device_manager_create(mp_display)), + mp_scene(wlr_scene_create()), + m_root([this](struct wl_display* display) { + struct wlr_output_layout* wlr_output_layout = wlr_output_layout_create(); + wlr_xdg_output_manager_v1_create(display, wlr_output_layout); + + struct wlr_output* wlr_output = + wlr_headless_add_output(mp_headless_backend, 800, 600); + + wlr_output_set_name(wlr_output, "FALLBACK"); + + return Root( + this, + mp_model, + wlr_output_layout, + mp_model->create_output( + wlr_output, + wlr_scene_output_create(mp_scene, wlr_output) + ) + ); + }(mp_display)), + mp_layer_shell(wlr_layer_shell_v1_create(mp_display)), + mp_xdg_shell(wlr_xdg_shell_create(mp_display)), + mp_cursor(wlr_cursor_create()), + mp_cursor_manager(wlr_xcursor_manager_create(NULL, 24)), + mp_seat(wlr_seat_create(mp_display, "seat0")), + mp_presentation(wlr_presentation_create(mp_display, mp_backend)), + mp_idle(wlr_idle_create(mp_display)), + mp_idle_inhibit_manager(wlr_idle_inhibit_v1_create(mp_display)), + mp_server_decoration_manager(wlr_server_decoration_manager_create(mp_display)), + mp_xdg_decoration_manager(wlr_xdg_decoration_manager_v1_create(mp_display)), + mp_output_manager(wlr_output_manager_v1_create(mp_display)), + mp_input_inhibit_manager(wlr_input_inhibit_manager_create(mp_display)), + mp_keyboard_shortcuts_inhibit_manager(wlr_keyboard_shortcuts_inhibit_v1_create(mp_display)), + mp_pointer_constraints(wlr_pointer_constraints_v1_create(mp_display)), + mp_relative_pointer_manager(wlr_relative_pointer_manager_v1_create(mp_display)), + mp_virtual_pointer_manager(wlr_virtual_pointer_manager_v1_create(mp_display)), + mp_virtual_keyboard_manager(wlr_virtual_keyboard_manager_v1_create(mp_display)), +#ifdef XWAYLAND + mp_xwayland(wlr_xwayland_create(mp_display, mp_compositor, 1)), +#endif ml_new_output({ .notify = Server::new_output }), - ml_output_layout_change({ .notify = Server::output_layout_change }), ml_output_manager_apply({ .notify = Server::output_manager_apply }), ml_output_manager_test({ .notify = Server::output_manager_test }), ml_new_xdg_surface({ .notify = Server::new_xdg_surface }), @@ -113,112 +160,72 @@ Server::Server(Model_ptr model) { TRACE(); - mp_compositor = wlr_compositor_create(mp_display, mp_renderer); - mp_data_device_manager = wlr_data_device_manager_create(mp_display); - - mp_output_layout = wlr_output_layout_create(); - - wl_list_init(&m_outputs); - wl_signal_add(&mp_backend->events.new_output, &ml_new_output); - - mp_scene = wlr_scene_create(); - wlr_scene_attach_output_layout(mp_scene, mp_output_layout); - - wl_list_init(&m_clients); - - mp_layer_shell = wlr_layer_shell_v1_create(mp_display); - wl_signal_add(&mp_layer_shell->events.new_surface, &ml_new_layer_shell_surface); - - mp_xdg_shell = wlr_xdg_shell_create(mp_display); - wl_signal_add(&mp_xdg_shell->events.new_surface, &ml_new_xdg_surface); - - mp_cursor = wlr_cursor_create(); - wlr_cursor_attach_output_layout(mp_cursor, mp_output_layout); - - mp_cursor_manager = wlr_xcursor_manager_create(NULL, 24); - wlr_xcursor_manager_load(mp_cursor_manager, 1); - - mp_seat = wlr_seat_create(mp_display, "seat0"); - mp_presentation = wlr_presentation_create(mp_display, mp_backend); - mp_idle = wlr_idle_create(mp_display); - - mp_idle_inhibit_manager = wlr_idle_inhibit_v1_create(mp_display); - wl_signal_add(&mp_idle_inhibit_manager->events.new_inhibitor, &ml_idle_inhibitor_create); - - { // set up cursor handling - wl_signal_add(&mp_cursor->events.motion, &ml_cursor_motion); - wl_signal_add(&mp_cursor->events.motion_absolute, &ml_cursor_motion_absolute); - wl_signal_add(&mp_cursor->events.button, &ml_cursor_button); - wl_signal_add(&mp_cursor->events.axis, &ml_cursor_axis); - wl_signal_add(&mp_cursor->events.frame, &ml_cursor_frame); + if (m_socket.empty()) { + wlr_backend_destroy(mp_backend); + wlr_backend_destroy(mp_headless_backend); + wl_display_destroy(mp_display); + std::exit(1); + spdlog::critical("Could not set up server socket"); + return; } - { // set up keyboard handling - wl_list_init(&m_keyboards); - wl_signal_add(&mp_backend->events.new_input, &ml_new_input); - wl_signal_add(&mp_seat->events.request_set_cursor, &ml_request_set_cursor); - wl_signal_add(&mp_seat->events.request_set_selection, &ml_request_set_selection); - wl_signal_add(&mp_seat->events.request_set_primary_selection, &ml_request_set_primary_selection); - } + wlr_multi_backend_add(mp_backend, mp_headless_backend); - mp_server_decoration_manager = wlr_server_decoration_manager_create(mp_display); - mp_xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(mp_display); + wlr_export_dmabuf_manager_v1_create(mp_display); + wlr_screencopy_manager_v1_create(mp_display); + wlr_data_control_manager_v1_create(mp_display); + wlr_gamma_control_manager_v1_create(mp_display); + wlr_primary_selection_v1_device_manager_create(mp_display); + wlr_scene_attach_output_layout(mp_scene, m_root.mp_output_layout); + wlr_cursor_attach_output_layout(mp_cursor, m_root.mp_output_layout); + wlr_xcursor_manager_load(mp_cursor_manager, 1); + wlr_scene_set_presentation(mp_scene, wlr_presentation_create(mp_display, mp_backend)); wlr_server_decoration_manager_set_default_mode( mp_server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER ); - wlr_xdg_output_manager_v1_create(mp_display, mp_output_layout); - wl_signal_add(&mp_output_layout->events.change, &ml_output_layout_change); - - mp_output_manager = wlr_output_manager_v1_create(mp_display); + wl_signal_add(&mp_backend->events.new_output, &ml_new_output); + 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_cursor->events.motion, &ml_cursor_motion); + wl_signal_add(&mp_cursor->events.motion_absolute, &ml_cursor_motion_absolute); + wl_signal_add(&mp_cursor->events.button, &ml_cursor_button); + wl_signal_add(&mp_cursor->events.axis, &ml_cursor_axis); + wl_signal_add(&mp_cursor->events.frame, &ml_cursor_frame); + wl_signal_add(&mp_backend->events.new_input, &ml_new_input); + wl_signal_add(&mp_seat->events.request_set_cursor, &ml_request_set_cursor); + wl_signal_add(&mp_seat->events.request_set_selection, &ml_request_set_selection); + wl_signal_add(&mp_seat->events.request_set_primary_selection, &ml_request_set_primary_selection); wl_signal_add(&mp_output_manager->events.apply, &ml_output_manager_apply); wl_signal_add(&mp_output_manager->events.test, &ml_output_manager_test); - - wlr_scene_set_presentation(mp_scene, wlr_presentation_create(mp_display, mp_backend)); - -#ifdef XWAYLAND - mp_xwayland = wlr_xwayland_create(mp_display, mp_compositor, 1); - - if (mp_xwayland) { - wl_signal_add(&mp_xwayland->events.ready, &ml_xwayland_ready); - wl_signal_add(&mp_xwayland->events.new_surface, &ml_new_xwayland_surface); - - setenv("DISPLAY", mp_xwayland->display_name, 1); - } else - spdlog::error("Failed to initiate XWayland"); - spdlog::warn("Continuing without XWayland functionality"); -#endif - - mp_input_inhibit_manager = wlr_input_inhibit_manager_create(mp_display); wl_signal_add(&mp_input_inhibit_manager->events.activate, &ml_inhibit_activate); wl_signal_add(&mp_input_inhibit_manager->events.deactivate, &ml_inhibit_deactivate); - mp_keyboard_shortcuts_inhibit_manager = wlr_keyboard_shortcuts_inhibit_v1_create(mp_display); // TODO: mp_keyboard_shortcuts_inhibit_manager signals - - mp_pointer_constraints = wlr_pointer_constraints_v1_create(mp_display); // TODO: mp_pointer_constraints signals - - mp_relative_pointer_manager = wlr_relative_pointer_manager_v1_create(mp_display); // TODO: mp_relative_pointer_manager signals - - mp_virtual_pointer_manager = wlr_virtual_pointer_manager_v1_create(mp_display); // TODO: mp_virtual_pointer_manager signals - - mp_virtual_keyboard_manager = wlr_virtual_keyboard_manager_v1_create(mp_display); // TODO: mp_virtual_keyboard_manager signals - if (m_socket.empty()) { - wlr_backend_destroy(mp_backend); - std::exit(1); - return; +#ifdef XWAYLAND + if (mp_xwayland) { + wl_signal_add(&mp_xwayland->events.ready, &ml_xwayland_ready); + wl_signal_add(&mp_xwayland->events.new_surface, &ml_new_xwayland_surface); + setenv("DISPLAY", mp_xwayland->display_name, 1); + } else { + spdlog::error("Failed to initiate XWayland"); + spdlog::warn("Continuing without XWayland functionality"); } +#endif if (!wlr_backend_start(mp_backend)) { wlr_backend_destroy(mp_backend); + wlr_backend_destroy(mp_headless_backend); wl_display_destroy(mp_display); + spdlog::critical("Could not start backend"); std::exit(1); return; } @@ -226,9 +233,6 @@ Server::Server(Model_ptr model) setenv("WAYLAND_DISPLAY", m_socket.c_str(), true); setenv("XDG_CURRENT_DESKTOP", "kranewl", true); - setenv("QT_QPA_PLATFORM", "wayland", true); - setenv("MOZ_ENABLE_WAYLAND", "1", true); - spdlog::info("Server initiated on WAYLAND_DISPLAY=" + m_socket); } @@ -254,9 +258,16 @@ Server::new_output(struct wl_listener* listener, void* data) TRACE(); Server_ptr server = wl_container_of(listener, server, ml_new_output); - struct wlr_output* wlr_output = reinterpret_cast<struct wlr_output*>(data); - wlr_output_init_render(wlr_output, server->mp_allocator, server->mp_renderer); + + if (wlr_output == server->m_root.mp_fallback_output->mp_wlr_output) + return; + + if (!wlr_output_init_render(wlr_output, server->mp_allocator, server->mp_renderer)) { + spdlog::error("Could not initialize rendering to output"); + spdlog::warn("Ignoring output " + std::string(wlr_output->name)); + return; + } if (!wl_list_empty(&wlr_output->modes)) { wlr_output_set_mode(wlr_output, wlr_output_preferred_mode(wlr_output)); @@ -268,42 +279,12 @@ Server::new_output(struct wl_listener* listener, void* data) } Output_ptr output = server->mp_model->create_output( - server, wlr_output, wlr_scene_output_create(server->mp_scene, wlr_output) ); wlr_output->data = output; - output->ml_frame.notify = Server::output_frame; - output->ml_destroy.notify = Server::output_destroy; - wl_signal_add(&wlr_output->events.frame, &output->ml_frame); - wl_signal_add(&wlr_output->events.destroy, &output->ml_destroy); - - wlr_output_layout_add_auto(server->mp_output_layout, wlr_output); -} - -void -Server::output_destroy(struct wl_listener* listener, void* data) -{ - TRACE(); - - struct wlr_output* wlr_output = reinterpret_cast<struct wlr_output*>(data); - Output_ptr output = reinterpret_cast<Output_ptr>(wlr_output->data); - Server_ptr server = output->mp_server; - - wl_list_remove(&output->ml_destroy.link); - wl_list_remove(&output->ml_frame.link); - - wlr_scene_output_destroy(output->mp_wlr_scene_output); - wlr_output_layout_remove(server->mp_output_layout, output->mp_wlr_output); - - server->mp_model->unregister_output(output); -} - -void -Server::output_layout_change(struct wl_listener* listener, void* data) -{ - // TODO + wlr_output_layout_add_auto(server->m_root.mp_output_layout, wlr_output); } void @@ -319,20 +300,6 @@ Server::output_manager_test(struct wl_listener* listener, void* data) } void -Server::output_frame(struct wl_listener* listener, void* data) -{ - TRACE(); - - Output_ptr output = wl_container_of(listener, output, ml_frame); - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - wlr_scene_output_commit(output->mp_wlr_scene_output); - wlr_scene_output_send_frame_done(output->mp_wlr_scene_output, &now); -} - -void Server::new_xdg_surface(struct wl_listener* listener, void* data) { /* Server_ptr server = wl_container_of(listener, server, ml_new_xdg_surface); */ diff --git a/src/kranewl/tree/node.cc b/src/kranewl/tree/node.cc @@ -1,3 +1,49 @@ #include <kranewl/tree/node.hh> +Node::Node(Root_ptr root) + : m_uid(reinterpret_cast<Uid>(root)), + m_type(NodeType::Root), + m_root(root), + m_destroying(false), + m_dirty(false), + m_events{ .destroy = {} } +{} +Node::Node(Output_ptr output) + : m_uid(reinterpret_cast<Uid>(output)), + m_type(NodeType::Output), + m_output(output), + m_destroying(false), + m_dirty(false), + m_events{ .destroy = {} } +{} + +Node::Node(Context_ptr context) + : m_uid(reinterpret_cast<Uid>(context)), + m_type(NodeType::Context), + m_context(context), + m_destroying(false), + m_dirty(false), + m_events{ .destroy = {} } +{} + +Node::Node(Workspace_ptr workspace) + : m_uid(reinterpret_cast<Uid>(workspace)), + m_type(NodeType::Workspace), + m_workspace(workspace), + m_destroying(false), + m_dirty(false), + m_events{ .destroy = {} } +{} + +Node::Node(Container_ptr container) + : m_uid(reinterpret_cast<Uid>(container)), + m_type(NodeType::Container), + m_container(container), + m_destroying(false), + m_dirty(false), + m_events{ .destroy = {} } +{} + +Node::~Node() +{} diff --git a/src/kranewl/tree/output.cc b/src/kranewl/tree/output.cc @@ -1,3 +1,140 @@ +#include <trace.hh> + #include <kranewl/tree/output.hh> +#include <kranewl/server.hh> + +extern "C" { +#include <wlr/types/wlr_output_damage.h> +} + +Output::Output( + Server_ptr server, + Model_ptr model, + struct wlr_output* wlr_output, + struct wlr_scene_output* wlr_scene_output +) + : Node(this), + mp_context(nullptr), + mp_server(server), + mp_model(model), + mp_wlr_output(wlr_output), + mp_wlr_scene_output(wlr_scene_output), + m_subpixel(wlr_output->subpixel) +{ + TRACE(); + + ml_frame.notify = Output::handle_frame; + ml_destroy.notify = Output::handle_destroy; + ml_present.notify = Output::handle_present; + ml_mode.notify = Output::handle_mode; + ml_commit.notify = Output::handle_commit; + + wl_signal_add(&mp_wlr_output->events.frame, &ml_frame); + wl_signal_add(&mp_wlr_output->events.destroy, &ml_destroy); + wl_signal_add(&mp_wlr_output->events.present, &ml_present); + wl_signal_add(&mp_wlr_output->events.mode, &ml_mode); + wl_signal_add(&mp_wlr_output->events.commit, &ml_commit); + + wl_signal_init(&m_events.disable); +} + +Output::~Output() +{} + +void +Output::handle_frame(struct wl_listener* listener, void*) +{ + TRACE(); + + /* Output_ptr output = wl_container_of(listener, output, ml_frame); */ + + /* struct timespec now; */ + /* clock_gettime(CLOCK_MONOTONIC, &now); */ + + /* wlr_scene_output_commit(output->mp_wlr_scene_output); */ + /* wlr_scene_output_send_frame_done(output->mp_wlr_scene_output, &now); */ +} + +void +Output::handle_destroy(struct wl_listener*, void*) +{ + TRACE(); + + /* struct wlr_output* wlr_output = reinterpret_cast<struct wlr_output*>(data); */ + /* Output_ptr output = reinterpret_cast<Output_ptr>(wlr_output->data); */ + /* Server_ptr server = output->mp_server; */ + + /* wl_list_remove(&output->ml_destroy.link); */ + /* wl_list_remove(&output->ml_frame.link); */ + + /* wlr_scene_output_destroy(output->mp_wlr_scene_output); */ + /* wlr_output_layout_remove(server->mp_output_layout, output->mp_wlr_output); */ + + /* server->mp_model->unregister_output(output); */ +} + +void +Output::handle_present(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Output::handle_mode(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Output::handle_commit(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Output::set_context(Context_ptr context) +{ + TRACE(); + + if (!context) + spdlog::error("output must contain a valid context"); + + if (mp_context) + mp_context->set_output(nullptr); + + context->set_output(this); + mp_context = context; +} + +Context_ptr +Output::context() const +{ + return mp_context; +} + +Region +Output::full_region() const +{ + return m_full_region; +} + +Region +Output::placeable_region() const +{ + return m_placeable_region; +} +bool +Output::contains(Pos pos) const +{ + return m_full_region.contains(pos); +} +bool +Output::contains(Region region) const +{ + return m_full_region.contains(region); +} diff --git a/src/kranewl/tree/root.cc b/src/kranewl/tree/root.cc @@ -1,3 +1,40 @@ +#include <trace.hh> + #include <kranewl/tree/root.hh> +#include <kranewl/cycle.t.hh> + +extern "C" { +#include <wlr/types/wlr_output_layout.h> +} + +Root::Root( + Server_ptr server, + Model_ptr model, + struct wlr_output_layout* wlr_output_layout, + Output_ptr fallback_output +) + : Node(this), + mp_server(server), + mp_model(model), + mp_output_layout(wlr_output_layout), + m_outputs({}, true), + m_scratchpad({}, true), + mp_fallback_output(fallback_output) +{ + TRACE(); + + ml_output_layout_change.notify = Root::handle_output_layout_change; + wl_signal_add(&mp_output_layout->events.change, &ml_output_layout_change); + + wl_signal_init(&m_events.new_node); +} + +Root::~Root() +{} +void +Root::handle_output_layout_change(struct wl_listener*, void*) +{ + TRACE(); +}