diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a31a35b4d..b2de939f6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest container: alpine:edge steps: - - run: apk --no-cache add git gcc g++ binutils pkgconf meson ninja musl-dev wayland-dev wayland-protocols libinput-dev libevdev-dev libxkbcommon-dev pixman-dev glm-dev libdrm-dev mesa-dev cairo-dev pango-dev eudev-dev libxml2-dev libseat-dev libxcb-dev xcb-util-wm-dev xwayland doctest doctest-dev cmake hwdata + - run: apk --no-cache add git gcc g++ binutils pkgconf meson ninja musl-dev wayland-dev wayland-protocols libinput-dev libevdev-dev libxkbcommon-dev pixman-dev glm-dev libdrm-dev mesa-dev cairo-dev pango-dev eudev-dev libxml2-dev libseat-dev libxcb-dev xcb-util-wm-dev xwayland doctest doctest-dev cmake libdisplay-info-dev hwdata-dev - uses: actions/checkout@v1 - run: git config --global --add safe.directory /__w/wayfire/wayfire - run: git submodule sync --recursive && git submodule update --init --force --recursive @@ -23,7 +23,7 @@ jobs: steps: - run: sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - run: pacman --noconfirm --noprogressbar -Syyu - - run: pacman --noconfirm --noprogressbar -Sy git clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd + - run: pacman --noconfirm --noprogressbar -Sy git clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd hwdata libdisplay-info # Build Wayfire - uses: actions/checkout@v1 diff --git a/README.md b/README.md index 281604196..b0319a021 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,11 @@ These are the dependencies needed for building Wayfire. These are the dependencies needed for building wlroots, and should be installed before building it. They are relevant for cases when the system doesn't have a version of wlroots installed. +#### DRM Backend (optional, but you most likely want this) + +- [libdisplay-info-dev](https://gitlab.freedesktop.org/emersion/libdisplay-info) +- [hwdata-dev](https://github.com/vcrhonek/hwdata) + #### Session Provider (optional, recommended) - [systemd](https://systemd.io/) **or** diff --git a/meson.build b/meson.build index fa82728de..8f830069d 100644 --- a/meson.build +++ b/meson.build @@ -39,11 +39,11 @@ if get_option('use_system_wlroots').disabled() elif get_option('use_system_wlroots').enabled() use_system_wlroots = true - wlroots = dependency('wlroots', version: ['>=0.16.0', '<0.17.0'], required: true) + wlroots = dependency('wlroots', version: ['>=0.17.0', '<0.18.0'], required: true) elif get_option('use_system_wlroots').auto() message( 'SEARCHING FOR WLROOTS' ) - wlroots = dependency('wlroots', version: ['>=0.16.0', '<0.17.0'], required: false) + wlroots = dependency('wlroots', version: ['>=0.17.0', '<0.18.0'], required: false) use_system_wlroots = true if not wlroots.found() use_system_wlroots = false diff --git a/plugins/cube/cube.cpp b/plugins/cube/cube.cpp index 524428620..1efbe68fe 100644 --- a/plugins/cube/cube.cpp +++ b/plugins/cube/cube.cpp @@ -124,7 +124,6 @@ class wayfire_cube : public wf::per_output_plugin_instance_t, public wf::pointer } self->cube->render(target.translated(-wf::origin(self->get_bounding_box())), framebuffers); - wf::scene::damage_node(self, self->get_bounding_box()); } void compute_visibility(wf::output_t *output, wf::region_t& visible) override @@ -664,6 +663,7 @@ class wayfire_cube : public wf::per_output_plugin_instance_t, public wf::pointer wf::effect_hook_t pre_hook = [=] () { update_view_matrix(); + wf::scene::damage_node(render_node, render_node->get_bounding_box()); if (animation.cube_animation.running()) { output->render->schedule_redraw(); diff --git a/plugins/decor/deco-layout.cpp b/plugins/decor/deco-layout.cpp index 3681a470b..8786a4f33 100644 --- a/plugins/decor/deco-layout.cpp +++ b/plugins/decor/deco-layout.cpp @@ -186,7 +186,11 @@ wf::region_t decoration_layout_t::calculate_region() const wf::region_t r{}; for (auto& area : layout_areas) { - r |= area->get_geometry(); + auto g = area->get_geometry(); + if ((g.width > 0) && (g.height > 0)) + { + r |= g; + } } return r; diff --git a/plugins/protocols/foreign-toplevel.cpp b/plugins/protocols/foreign-toplevel.cpp index 6536c433d..d0a912363 100644 --- a/plugins/protocols/foreign-toplevel.cpp +++ b/plugins/protocols/foreign-toplevel.cpp @@ -85,9 +85,9 @@ class wayfire_foreign_toplevel } else if (app_id_mode == "full") { #if WF_HAS_XWAYLAND - if (view->get_wlr_surface() && wlr_surface_is_xwayland_surface(view->get_wlr_surface())) + if (wlr_xwayland_surface *xw_surface = + wlr_xwayland_surface_try_from_wlr_surface(view->get_wlr_surface())) { - auto xw_surface = wlr_xwayland_surface_from_wlr_surface(view->get_wlr_surface()); ev.app_id = nonull(xw_surface->instance); } diff --git a/plugins/protocols/gtk-shell.cpp b/plugins/protocols/gtk-shell.cpp index 7d0be0a02..1bf4adfb7 100644 --- a/plugins/protocols/gtk-shell.cpp +++ b/plugins/protocols/gtk-shell.cpp @@ -253,9 +253,8 @@ static void handle_gtk_shell_get_gtk_surface(wl_client *client, wl_resource *res gtk_surface, handle_gtk_surface_destroy); wlr_surface *wlr_surface = wlr_surface_from_resource(surface); - if (wlr_surface_is_xdg_surface(wlr_surface)) + if (wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface)) { - wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(wlr_surface); gtk_surface->on_configure.set_callback([=] (void*) { handle_xdg_surface_on_configure(gtk_surface); diff --git a/plugins/single_plugins/idle.cpp b/plugins/single_plugins/idle.cpp index 8ace90c87..36913fa9e 100644 --- a/plugins/single_plugins/idle.cpp +++ b/plugins/single_plugins/idle.cpp @@ -6,6 +6,7 @@ #include "wayfire/output-layout.hpp" #include "wayfire/workspace-set.hpp" #include "wayfire/signal-definitions.hpp" +#include "wayfire/seat.hpp" #include "../cube/cube-control-signal.hpp" #include @@ -36,60 +37,56 @@ class screensaver_animation_t : public duration_t class wayfire_idle { wf::option_wrapper_t dpms_timeout{"idle/dpms_timeout"}; - wf::wl_listener_wrapper on_idle_dpms, on_resume_dpms; - wlr_idle_timeout *timeout_dpms = NULL; + bool is_idle = false; public: + wf::signal::connection_t on_seat_activity; std::optional hotkey_inhibitor; + wf::wl_timer timeout_dpms; wayfire_idle() { dpms_timeout.set_callback([=] () { - create_dpms_timeout(dpms_timeout); + create_dpms_timeout(); }); - create_dpms_timeout(dpms_timeout); - } - void destroy_dpms_timeout() - { - if (timeout_dpms) + on_seat_activity = [=] (void*) { - on_idle_dpms.disconnect(); - on_resume_dpms.disconnect(); - wlr_idle_timeout_destroy(timeout_dpms); - } - - timeout_dpms = NULL; + create_dpms_timeout(); + }; + create_dpms_timeout(); + wf::get_core().connect(&on_seat_activity); } - void create_dpms_timeout(int timeout_sec) + void create_dpms_timeout() { - destroy_dpms_timeout(); - if (timeout_sec <= 0) + if (dpms_timeout <= 0) { + timeout_dpms.disconnect(); return; } - timeout_dpms = wlr_idle_timeout_create(wf::get_core().protocols.idle, - wf::get_core().get_current_seat(), 1000 * timeout_sec); - - on_idle_dpms.set_callback([&] (void*) + if (!timeout_dpms.is_connected() && is_idle) { - set_state(wf::OUTPUT_IMAGE_SOURCE_SELF, wf::OUTPUT_IMAGE_SOURCE_DPMS); - }); - on_idle_dpms.connect(&timeout_dpms->events.idle); + is_idle = false; + set_state(wf::OUTPUT_IMAGE_SOURCE_DPMS, wf::OUTPUT_IMAGE_SOURCE_SELF); + + return; + } - on_resume_dpms.set_callback([&] (void*) + timeout_dpms.disconnect(); + timeout_dpms.set_timeout(1000 * dpms_timeout, [=] () { - set_state(wf::OUTPUT_IMAGE_SOURCE_DPMS, wf::OUTPUT_IMAGE_SOURCE_SELF); + is_idle = true; + set_state(wf::OUTPUT_IMAGE_SOURCE_SELF, wf::OUTPUT_IMAGE_SOURCE_DPMS); }); - on_resume_dpms.connect(&timeout_dpms->events.resume); } ~wayfire_idle() { - destroy_dpms_timeout(); + timeout_dpms.disconnect(); + wf::get_core().disconnect(&on_seat_activity); } /* Change all outputs with state from to state to */ @@ -128,17 +125,12 @@ class wayfire_idle_plugin : public wf::per_output_plugin_instance_t bool hook_set = false; bool output_inhibited = false; uint32_t last_time; - wlr_idle_timeout *timeout_screensaver = NULL; - wf::wl_listener_wrapper on_idle_screensaver, on_resume_screensaver; + wf::wl_timer timeout_screensaver; + wf::signal::connection_t on_seat_activity; wf::shared_data::ref_ptr_t global_idle; wf::activator_callback toggle = [=] (auto) { - if (!output->can_activate_plugin(&grab_interface)) - { - return false; - } - if (global_idle->hotkey_inhibitor.has_value()) { global_idle->hotkey_inhibitor.reset(); @@ -157,6 +149,29 @@ class wayfire_idle_plugin : public wf::per_output_plugin_instance_t update_fullscreen(); }; + wf::signal::connection_t inhibit_changed = + [=] (wf::idle_inhibit_changed_signal *ev) + { + if (!ev) + { + return; + } + + if (ev->inhibit) + { + wf::get_core().disconnect(&global_idle->on_seat_activity); + wf::get_core().disconnect(&on_seat_activity); + global_idle->timeout_dpms.disconnect(); + timeout_screensaver.disconnect(); + } else + { + wf::get_core().connect(&global_idle->on_seat_activity); + wf::get_core().connect(&on_seat_activity); + global_idle->create_dpms_timeout(); + create_screensaver_timeout(); + } + }; + wf::config::option_base_t::updated_callback_t disable_on_fullscreen_changed = [=] () { @@ -207,49 +222,37 @@ class wayfire_idle_plugin : public wf::per_output_plugin_instance_t screensaver_timeout.set_callback([=] () { - create_screensaver_timeout(screensaver_timeout); + create_screensaver_timeout(); }); - create_screensaver_timeout(screensaver_timeout); - } + create_screensaver_timeout(); - void destroy_screensaver_timeout() - { - if (state == CUBE_SCREENSAVER_RUNNING) + on_seat_activity = [=] (void*) { - stop_screensaver(); - } - - if (timeout_screensaver) - { - on_idle_screensaver.disconnect(); - on_resume_screensaver.disconnect(); - wlr_idle_timeout_destroy(timeout_screensaver); - } - - timeout_screensaver = NULL; + create_screensaver_timeout(); + }; + wf::get_core().connect(&on_seat_activity); + wf::get_core().connect(&inhibit_changed); } - void create_screensaver_timeout(int timeout_sec) + void create_screensaver_timeout() { - destroy_screensaver_timeout(); - if (timeout_sec <= 0) + if (screensaver_timeout <= 0) { + timeout_screensaver.disconnect(); return; } - timeout_screensaver = wlr_idle_timeout_create(wf::get_core().protocols.idle, - wf::get_core().get_current_seat(), 1000 * timeout_sec); - on_idle_screensaver.set_callback([&] (void*) + if (!timeout_screensaver.is_connected() && (state == CUBE_SCREENSAVER_RUNNING)) { - start_screensaver(); - }); - on_idle_screensaver.connect(&timeout_screensaver->events.idle); + stop_screensaver(); + return; + } - on_resume_screensaver.set_callback([&] (void*) + timeout_screensaver.disconnect(); + timeout_screensaver.set_timeout(1000 * screensaver_timeout, [=] () { - stop_screensaver(); + start_screensaver(); }); - on_resume_screensaver.connect(&timeout_screensaver->events.resume); } void inhibit_output() @@ -351,8 +354,7 @@ class wayfire_idle_plugin : public wf::per_output_plugin_instance_t if (state == CUBE_SCREENSAVER_STOPPING) { - wlr_idle_notify_activity(wf::get_core().protocols.idle, - wf::get_core().get_current_seat()); + wf::get_core().seat->notify_activity(); } }; @@ -410,7 +412,9 @@ class wayfire_idle_plugin : public wf::per_output_plugin_instance_t void fini() override { - destroy_screensaver_timeout(); + wf::get_core().disconnect(&on_seat_activity); + wf::get_core().disconnect(&inhibit_changed); + timeout_screensaver.disconnect(); output->rem_binding(&toggle); } }; diff --git a/plugins/single_plugins/ipc-rules.cpp b/plugins/single_plugins/ipc-rules.cpp index c4f105d0a..1fb7772ee 100644 --- a/plugins/single_plugins/ipc-rules.cpp +++ b/plugins/single_plugins/ipc-rules.cpp @@ -374,7 +374,7 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker { #if WF_HAS_XWAYLAND auto surf = view->get_wlr_surface(); - if (surf && wlr_surface_is_xwayland_surface(surf)) + if (surf && wlr_xwayland_surface_try_from_wlr_surface(surf)) { return "x-or"; } diff --git a/proto/meson.build b/proto/meson.build index 4da01bf58..7167c1c50 100644 --- a/proto/meson.build +++ b/proto/meson.build @@ -22,7 +22,6 @@ wayland_scanner_client = generator( server_protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], - [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], diff --git a/src/api/wayfire/core.hpp b/src/api/wayfire/core.hpp index e5928e5d7..911d8651c 100644 --- a/src/api/wayfire/core.hpp +++ b/src/api/wayfire/core.hpp @@ -101,6 +101,7 @@ class compositor_core_t : public wf::object_base_t, public signal::provider_t * used instead of this one */ wlr_backend *backend; + wlr_session *session; wlr_renderer *renderer; wlr_allocator *allocator; @@ -127,7 +128,7 @@ class compositor_core_t : public wf::object_base_t, public signal::provider_t wlr_virtual_keyboard_manager_v1 *vkbd_manager; wlr_virtual_pointer_manager_v1 *vptr_manager; wlr_input_inhibit_manager *input_inhibit; - wlr_idle *idle; + wlr_idle_notifier_v1 *idle_notifier; wlr_idle_inhibit_manager_v1 *idle_inhibit; wlr_pointer_gestures_v1 *pointer_gestures; wlr_relative_pointer_manager_v1 *relative_pointer; diff --git a/src/api/wayfire/idle.hpp b/src/api/wayfire/idle.hpp index 77c27787e..807155450 100644 --- a/src/api/wayfire/idle.hpp +++ b/src/api/wayfire/idle.hpp @@ -19,6 +19,6 @@ class idle_inhibitor_t private: static unsigned int inhibitors; - void notify_wlroots(); + void notify_update(); }; } diff --git a/src/api/wayfire/nonstd/wlroots-full.hpp b/src/api/wayfire/nonstd/wlroots-full.hpp index ff6eae231..8dea78ab3 100644 --- a/src/api/wayfire/nonstd/wlroots-full.hpp +++ b/src/api/wayfire/nonstd/wlroots-full.hpp @@ -24,6 +24,7 @@ extern "C" #define static #include #include +#include #include #include #include @@ -32,7 +33,7 @@ extern "C" #include #include -#include +#include #include #include #include @@ -117,7 +118,6 @@ extern "C" #include #include #include -#include #include #include #include @@ -125,6 +125,7 @@ extern "C" #include #include #include +#include #include #include #define delete delete_ diff --git a/src/api/wayfire/nonstd/wlroots.hpp b/src/api/wayfire/nonstd/wlroots.hpp index 238a71d49..7c9c7fbeb 100644 --- a/src/api/wayfire/nonstd/wlroots.hpp +++ b/src/api/wayfire/nonstd/wlroots.hpp @@ -21,12 +21,12 @@ extern "C" struct wlr_xdg_output_manager_v1; struct wlr_export_dmabuf_manager_v1; struct wlr_server_decoration_manager; - struct wlr_xdg_decoration_manager_v1; struct wlr_input_inhibit_manager; + struct wlr_idle_inhibit_manager_v1; + struct wlr_xdg_decoration_manager_v1; struct wlr_virtual_keyboard_manager_v1; struct wlr_virtual_pointer_manager_v1; - struct wlr_idle; - struct wlr_idle_inhibit_manager_v1; + struct wlr_idle_notifier_v1; struct wlr_screencopy_manager_v1; struct wlr_foreign_toplevel_manager_v1; struct wlr_pointer_gestures_v1; @@ -53,7 +53,10 @@ extern "C" #include #include #include +#define static #include +#undef static +#include #include #include #include diff --git a/src/api/wayfire/plugin.hpp b/src/api/wayfire/plugin.hpp index 1355830f9..5266e8e43 100644 --- a/src/api/wayfire/plugin.hpp +++ b/src/api/wayfire/plugin.hpp @@ -108,7 +108,7 @@ class plugin_interface_t using wayfire_plugin_load_func = wf::plugin_interface_t * (*)(); /** The version of Wayfire's API/ABI */ -constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2023'10'25; +constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2023'11'23; /** * Each plugin must also provide a function which returns the Wayfire API/ABI diff --git a/src/api/wayfire/render-manager.hpp b/src/api/wayfire/render-manager.hpp index e7e02cce0..a4906259e 100644 --- a/src/api/wayfire/render-manager.hpp +++ b/src/api/wayfire/render-manager.hpp @@ -148,16 +148,17 @@ class render_manager * Same as damage_whole(), but damages only a part of the output. * * @param box The output box to be damaged, in output-local coordinates. + * @param repaint Whether to automatically schedule an output repaint. */ - void damage(const wlr_box& box); + void damage(const wlr_box& box, bool repaint = true); /** * Same as damage_whole(), but damages only a part of the output. * - * @param region The output region to be damaged, in output-local - * coordinates. + * @param region The output region to be damaged, in output-local coordinates. + * @param repaint Whether to automatically schedule an output repaint. */ - void damage(const wf::region_t& region); + void damage(const wf::region_t& region, bool repaint = true); /** * @return A box in output-local coordinates containing the given diff --git a/src/api/wayfire/seat.hpp b/src/api/wayfire/seat.hpp index 22c44390c..2e96eea1e 100644 --- a/src/api/wayfire/seat.hpp +++ b/src/api/wayfire/seat.hpp @@ -97,6 +97,11 @@ class seat_t */ wf::output_t *get_active_output(); + /** + * Notify clients and plugins of input activity on the seat + */ + void notify_activity(); + /** * Create and initialize a new seat. */ diff --git a/src/api/wayfire/signal-definitions.hpp b/src/api/wayfire/signal-definitions.hpp index e0870f738..637b6ef9c 100644 --- a/src/api/wayfire/signal-definitions.hpp +++ b/src/api/wayfire/signal-definitions.hpp @@ -160,6 +160,22 @@ struct keyboard_focus_changed_signal wf::scene::node_ptr new_focus; }; +/** + * on: core + * when: Seat activity has happened after being idle. + */ +struct seat_activity_signal +{}; + +/** + * on: core + * when: idle inhibit changed. + */ +struct idle_inhibit_changed_signal +{ + bool inhibit; +}; + /* ----------------------------------------------------------------------------/ * Output signals * -------------------------------------------------------------------------- */ diff --git a/src/core/core.cpp b/src/core/core.cpp index c4c5f8d66..c2a42c02f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -95,7 +95,7 @@ void wf::compositor_core_impl_t::init() * 3. weston toy clients expect xdg-shell before wl_seat, i.e * init_desktop_apis() should come before input. * 4. GTK expects primary selection early. */ - compositor = wlr_compositor_create(display, renderer); + compositor = wlr_compositor_create(display, 6, renderer); /* Needed for subsurfaces */ wlr_subcompositor_create(display); @@ -132,6 +132,18 @@ void wf::compositor_core_impl_t::init() }); input_inhibit_deactivated.connect(&protocols.input_inhibit->events.deactivate); + /* idle-inhibit setup */ + protocols.idle_notifier = wlr_idle_notifier_v1_create(display); + protocols.idle_inhibit = wlr_idle_inhibit_v1_create(display); + + idle_inhibitor_created.set_callback([&] (void *data) + { + auto wlri = static_cast(data); + /* will be freed by the destroy request */ + new wlr_idle_inhibitor_t(wlri); + }); + idle_inhibitor_created.connect(&protocols.idle_inhibit->events.new_inhibitor); + /* decoration_manager setup */ protocols.decorator_manager = wlr_server_decoration_manager_create(display); protocols.xdg_decorator = wlr_xdg_decoration_manager_v1_create(display); @@ -154,17 +166,6 @@ void wf::compositor_core_impl_t::init() }); vptr_created.connect(&protocols.vptr_manager->events.new_virtual_pointer); - protocols.idle_inhibit = wlr_idle_inhibit_v1_create(display); - idle_inhibitor_created.set_callback([&] (void *data) - { - auto wlri = static_cast(data); - /* will be freed by the destroy request */ - new wlr_idle_inhibitor_t(wlri); - }); - idle_inhibitor_created.connect( - &protocols.idle_inhibit->events.new_inhibitor); - - protocols.idle = wlr_idle_create(display); protocols.pointer_gestures = wlr_pointer_gestures_v1_create(display); protocols.relative_pointer = wlr_relative_pointer_manager_v1_create(display); diff --git a/src/core/idle.cpp b/src/core/idle.cpp index d21fa5960..c2595fea6 100644 --- a/src/core/idle.cpp +++ b/src/core/idle.cpp @@ -1,25 +1,30 @@ #include #include +#include "core/seat/input-manager.hpp" #include "core-impl.hpp" unsigned int wf::idle_inhibitor_t::inhibitors = 0; -void wf::idle_inhibitor_t::notify_wlroots() +void wf::idle_inhibitor_t::notify_update() { /* NOTE: inhibited -> NOT enabled */ - wlr_idle_set_enabled(wf::get_core().protocols.idle, NULL, inhibitors == 0); + wlr_idle_notifier_v1_set_inhibited(wf::get_core().protocols.idle_notifier, inhibitors == 0); + + wf::idle_inhibit_changed_signal data; + data.inhibit = (inhibitors != 0); + wf::get_core().emit(&data); } wf::idle_inhibitor_t::idle_inhibitor_t() { LOGD("creating idle inhibitor ", this, " previous count: ", inhibitors); inhibitors++; - notify_wlroots(); + notify_update(); } wf::idle_inhibitor_t::~idle_inhibitor_t() { LOGD("destroying idle inhibitor ", this, " previous count: ", inhibitors); inhibitors--; - notify_wlroots(); + notify_update(); } diff --git a/src/core/opengl.cpp b/src/core/opengl.cpp index fe7211714..e498ef2d9 100644 --- a/src/core/opengl.cpp +++ b/src/core/opengl.cpp @@ -42,7 +42,7 @@ void gl_call(const char *func, uint32_t line, const char *glfunc) } LOGE("gles2: function ", glfunc, " in ", func, " line ", line, ": ", - gl_error_string(glGetError())); + gl_error_string(err)); } namespace OpenGL diff --git a/src/core/output-layout.cpp b/src/core/output-layout.cpp index baaf4ae38..bd41f1ff1 100644 --- a/src/core/output-layout.cpp +++ b/src/core/output-layout.cpp @@ -220,9 +220,11 @@ struct output_layout_output_t wlr_output *handle; output_state_t current_state; bool is_externally_managed = false; + bool is_nested_compositor = false; + bool inhibited = false; std::unique_ptr output; - wl_listener_wrapper on_destroy, on_mode; + wl_listener_wrapper on_destroy, on_commit; std::shared_ptr config_section; wf::option_wrapper_t mode_opt; @@ -249,7 +251,7 @@ struct output_layout_output_t on_destroy.connect(&handle->events.destroy); initialize_config_options(); - bool is_nested_compositor = wlr_output_is_wl(handle); + is_nested_compositor = wlr_output_is_wl(handle); #if WLR_HAS_X11_BACKEND is_nested_compositor |= wlr_output_is_x11(handle); @@ -258,11 +260,15 @@ struct output_layout_output_t { /* Nested backends can be resized by the user. We need to handle * these cases */ - on_mode.set_callback([=] (void *data) + on_commit.set_callback([=] (void *data) { - handle_mode_changed(); + wlr_output_event_commit *ev = static_cast(data); + if (ev->state->committed & WLR_OUTPUT_STATE_MODE) + { + handle_mode_changed(); + } }); - on_mode.connect(&handle->events.mode); + on_commit.connect(&handle->events.commit); } } @@ -319,7 +325,7 @@ struct output_layout_output_t wlr_output_mode default_mode; auto width = handle->width > 0 ? handle->width : 1200; auto height = handle->height > 0 ? handle->height : 720; - auto refresh = handle->refresh > 0 ? handle->refresh : 60000; + auto refresh = handle->refresh > 0 ? handle->refresh : 0; default_mode.width = width; default_mode.height = height; @@ -678,21 +684,24 @@ struct output_layout_output_t on_mirrored_frame.set_callback([=] (void *data) { auto ev = (wlr_output_event_commit*)data; + if (!ev || !ev->state || !ev->state->buffer) + { + return; + } - if (ev->buffer) + if (ev->state->buffer) { if (source_back_buffer) { wlr_buffer_unlock(source_back_buffer); } - source_back_buffer = ev->buffer; - wlr_buffer_lock(ev->buffer); + source_back_buffer = ev->state->buffer; + wlr_buffer_lock(ev->state->buffer); } /* The mirrored output was repainted, schedule repaint * for us as well */ - wlr_output_damage_whole(handle); wlr_output_schedule_frame(handle); }); on_mirrored_frame.connect(&wo->handle->events.commit); @@ -798,6 +807,7 @@ struct output_layout_output_t set_enabled(!(state.source & OUTPUT_IMAGE_SOURCE_NONE)); apply_mode(state.mode); + if (state.source & OUTPUT_IMAGE_SOURCE_SELF) { if (handle->transform != state.transform) @@ -808,8 +818,6 @@ struct output_layout_output_t if (handle->scale != state.scale) { wlr_output_set_scale(handle, state.scale); - wf::get_core_impl().seat->priv->cursor->load_xcursor_scale( - state.scale); } wlr_output_commit(handle); @@ -1467,10 +1475,18 @@ class output_layout_t::impl return; } - config[ev->output].source = - (ev->mode == ZWLR_OUTPUT_POWER_V1_MODE_ON ? - OUTPUT_IMAGE_SOURCE_SELF : OUTPUT_IMAGE_SOURCE_DPMS); + const bool wants_dpms = (ev->mode == ZWLR_OUTPUT_POWER_V1_MODE_OFF); + config[ev->output].source = (wants_dpms ? OUTPUT_IMAGE_SOURCE_DPMS : OUTPUT_IMAGE_SOURCE_SELF); apply_configuration(config); + + auto& wo = outputs[ev->output]; + if (wo->inhibited != wants_dpms) + { + wo->inhibited = wants_dpms; + wo->output->render->add_inhibit(wants_dpms); + } + + wo->output->render->damage_whole(); } /* Public API functions */ diff --git a/src/core/seat/cursor.cpp b/src/core/seat/cursor.cpp index 4b7fec1f5..65884bcf6 100644 --- a/src/core/seat/cursor.cpp +++ b/src/core/seat/cursor.cpp @@ -45,14 +45,11 @@ void wf::cursor_t::add_new_device(wlr_input_device *dev) void wf::cursor_t::setup_listeners() { - auto& core = wf::get_core_impl(); - /* Dispatch pointer events to the pointer_t */ on_frame.set_callback([&] (void*) { seat->priv->lpointer->handle_pointer_frame(); - wlr_idle_notify_activity(core.protocols.idle, - core.get_current_seat()); + wf::get_core().seat->notify_activity(); }); on_frame.connect(&cursor->events.frame); @@ -64,7 +61,7 @@ void wf::cursor_t::setup_listeners() if (mode != wf::input_event_processing_mode_t::IGNORE) \ { \ seat->priv->lpointer->handle_pointer_ ## evname(ev, mode); \ - wlr_idle_notify_activity(core.protocols.idle, core.get_current_seat()); \ + wf::get_core().seat->notify_activity(); \ } \ emit_device_post_event_signal(ev); \ }); \ @@ -98,7 +95,7 @@ void wf::cursor_t::setup_listeners() static_cast(ev->tablet->data); \ tablet->handle_ ## evname(ev, handling_mode); \ } \ - wlr_idle_notify_activity(wf::get_core().protocols.idle, seat->seat); \ + wf::get_core().seat->notify_activity(); \ emit_device_event_signal(ev); \ }); \ on_tablet_ ## evname.connect(&cursor->events.tablet_tool_ ## evname); @@ -130,24 +127,9 @@ void wf::cursor_t::init_xcursor() } xcursor = wlr_xcursor_manager_create(theme_ptr, size); - - load_xcursor_scale(1); - for (auto& wo : wf::get_core().output_layout->get_current_configuration()) - { - if (wo.second.source & wf::OUTPUT_IMAGE_SOURCE_SELF) - { - load_xcursor_scale(wo.first->scale); - } - } - set_cursor("default"); } -void wf::cursor_t::load_xcursor_scale(float scale) -{ - wlr_xcursor_manager_load(xcursor, scale); -} - void wf::cursor_t::set_cursor(std::string name) { if (this->hide_ref_counter) @@ -167,7 +149,7 @@ void wf::cursor_t::set_cursor(std::string name) idle_set_cursor.run_once([name, this] () { - wlr_xcursor_manager_set_cursor_image(xcursor, name.c_str(), cursor); + wlr_cursor_set_xcursor(cursor, xcursor, name.c_str()); }); } diff --git a/src/core/seat/cursor.hpp b/src/core/seat/cursor.hpp index fa7701df0..cb12ca760 100644 --- a/src/core/seat/cursor.hpp +++ b/src/core/seat/cursor.hpp @@ -49,7 +49,6 @@ struct cursor_t void init_xcursor(); void setup_listeners(); - void load_xcursor_scale(float scale); // Device event listeners wf::wl_listener_wrapper on_button, on_motion, on_motion_absolute, on_axis, diff --git a/src/core/seat/drag-icon.cpp b/src/core/seat/drag-icon.cpp index 01edf4c8b..3409646e9 100644 --- a/src/core/seat/drag-icon.cpp +++ b/src/core/seat/drag-icon.cpp @@ -127,7 +127,7 @@ wf::drag_icon_t::drag_icon_t(wlr_drag_icon *ic) : icon(ic) // Sometimes, the drag surface is reused between two or more drags. // In this case, when the drag starts, the icon is already mapped. - if (!icon->mapped) + if (!icon->surface->mapped) { root_node->set_enabled(false); } @@ -147,8 +147,8 @@ wf::drag_icon_t::drag_icon_t(wlr_drag_icon *ic) : icon(ic) wf::get_core().seat->priv->drag_icon = nullptr; }); - on_map.connect(&icon->events.map); - on_unmap.connect(&icon->events.unmap); + on_map.connect(&icon->surface->events.map); + on_unmap.connect(&icon->surface->events.unmap); on_destroy.connect(&icon->events.destroy); @@ -175,8 +175,8 @@ wf::point_t wf::drag_icon_t::get_position() if (root_node->is_enabled()) { - pos.x += icon->surface->sx; - pos.y += icon->surface->sy; + pos.x += icon->surface->current.dx; + pos.y += icon->surface->current.dy; } return {(int)pos.x, (int)pos.y}; diff --git a/src/core/seat/keyboard.cpp b/src/core/seat/keyboard.cpp index cb6431faf..5f91ea3bd 100644 --- a/src/core/seat/keyboard.cpp +++ b/src/core/seat/keyboard.cpp @@ -31,7 +31,7 @@ void wf::keyboard_t::setup_listeners() if (mode == input_event_processing_mode_t::IGNORE) { - wlr_idle_notify_activity(wf::get_core().protocols.idle, seat->seat); + wf::get_core().seat->notify_activity(); emit_device_post_event_signal(ev); return; } @@ -62,7 +62,7 @@ void wf::keyboard_t::setup_listeners() } } - wlr_idle_notify_activity(wf::get_core().protocols.idle, seat->seat); + wf::get_core().seat->notify_activity(); emit_device_post_event_signal(ev); }); @@ -73,7 +73,7 @@ void wf::keyboard_t::setup_listeners() wlr_seat_set_keyboard(seat, kbd); wlr_seat_keyboard_send_modifiers(seat, &kbd->modifiers); - wlr_idle_notify_activity(wf::get_core().protocols.idle, seat); + wf::get_core().seat->notify_activity(); }); on_key.connect(&handle->events.key); @@ -294,8 +294,7 @@ bool wf::keyboard_t::handle_keyboard_key(uint32_t key, uint32_t state) if (state == WLR_KEY_PRESSED) { - auto session = wlr_backend_get_session(wf::get_core().backend); - if (check_vt_switch(session, key, get_modifiers())) + if (check_vt_switch(wf::get_core().session, key, get_modifiers())) { return true; } diff --git a/src/core/seat/seat.cpp b/src/core/seat/seat.cpp index 2fd7cf01b..103c6c343 100644 --- a/src/core/seat/seat.cpp +++ b/src/core/seat/seat.cpp @@ -231,6 +231,13 @@ xkb_state*wf::seat_t::get_xkb_state() return nullptr; } +void wf::seat_t::notify_activity() +{ + wlr_idle_notifier_v1_notify_activity(wf::get_core().protocols.idle_notifier, this->seat); + seat_activity_signal data; + wf::get_core().emit(&data); +} + std::vector wf::seat_t::get_pressed_keys() { std::vector pressed_keys{priv->pressed_keys.begin(), priv->pressed_keys.end()}; diff --git a/src/core/seat/touch.cpp b/src/core/seat/touch.cpp index 744b3d650..b4d0ef419 100644 --- a/src/core/seat/touch.cpp +++ b/src/core/seat/touch.cpp @@ -35,7 +35,7 @@ wf::touch_interface_t::touch_interface_t(wlr_cursor *cursor, wlr_seat *seat, handle_touch_down(ev->touch_id, ev->time_msec, point, mode); } - wlr_idle_notify_activity(wf::get_core().protocols.idle, wf::get_core().get_current_seat()); + wf::get_core().seat->notify_activity(); emit_device_post_event_signal(ev); }); @@ -48,8 +48,7 @@ wf::touch_interface_t::touch_interface_t(wlr_cursor *cursor, wlr_seat *seat, handle_touch_up(ev->touch_id, ev->time_msec, mode); } - wlr_idle_notify_activity(wf::get_core().protocols.idle, - wf::get_core().get_current_seat()); + wf::get_core().seat->notify_activity(); emit_device_post_event_signal(ev); }); @@ -70,7 +69,7 @@ wf::touch_interface_t::touch_interface_t(wlr_cursor *cursor, wlr_seat *seat, handle_touch_motion(ev->touch_id, ev->time_msec, point, true, mode); } - wlr_idle_notify_activity(wf::get_core().protocols.idle, wf::get_core().get_current_seat()); + wf::get_core().seat->notify_activity(); emit_device_post_event_signal(ev); }); @@ -87,8 +86,7 @@ wf::touch_interface_t::touch_interface_t(wlr_cursor *cursor, wlr_seat *seat, on_frame.set_callback([&] (void*) { wlr_seat_touch_notify_frame(wf::get_core().get_current_seat()); - wlr_idle_notify_activity(wf::get_core().protocols.idle, - wf::get_core().get_current_seat()); + wf::get_core().seat->notify_activity(); }); on_up.connect(&cursor->events.touch_up); diff --git a/src/core/view-access-interface.cpp b/src/core/view-access-interface.cpp index 4d6197025..8d2fda9b5 100644 --- a/src/core/view-access-interface.cpp +++ b/src/core/view-access-interface.cpp @@ -111,7 +111,7 @@ variant_t view_access_interface_t::get(const std::string & identifier, bool & er { #if WF_HAS_XWAYLAND auto surf = _view->get_wlr_surface(); - if (surf && wlr_surface_is_xwayland_surface(surf)) + if (surf && wlr_xwayland_surface_try_from_wlr_surface(surf)) { out = std::string("x-or"); break; diff --git a/src/main.cpp b/src/main.cpp index b8bbac0e0..d08453b6d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) /** TODO: move this to core_impl constructor */ core.display = display; core.ev_loop = wl_display_get_event_loop(core.display); - core.backend = wlr_backend_autocreate(core.display); + core.backend = wlr_backend_autocreate(core.display, &core.session); int drm_fd = wlr_backend_get_drm_fd(core.backend); if (drm_fd < 0) @@ -364,7 +364,8 @@ int main(int argc, char *argv[]) } } - core.renderer = wlr_gles2_renderer_create_with_drm_fd(drm_fd); + core.renderer = wlr_gles2_renderer_create_with_drm_fd(drm_fd); + assert(core.renderer); core.allocator = wlr_allocator_autocreate(core.backend, core.renderer); assert(core.allocator); core.egl = wlr_gles2_renderer_get_egl(core.renderer); diff --git a/src/output/render-manager.cpp b/src/output/render-manager.cpp index 5d0c894e4..76f1db70d 100644 --- a/src/output/render-manager.cpp +++ b/src/output/render-manager.cpp @@ -1,4 +1,5 @@ #include "wayfire/render-manager.hpp" +#include "pixman.h" #include "view/view-impl.hpp" #include "wayfire/core.hpp" #include "wayfire/debug.hpp" @@ -21,24 +22,31 @@ #include #include #include +#include namespace wf { /** - * output_damage_t is responsible for tracking the damage on a given output. + * swapchain_damage_manager_t is responsible for tracking the damage and managing the swapchain on the + * given output. */ -struct output_damage_t +struct swapchain_damage_manager_t { signal::connection_t root_update; std::vector render_instances; - wf::wl_listener_wrapper on_damage_destroy; + wf::wl_listener_wrapper on_needs_frame; + wf::wl_listener_wrapper on_damage; + wf::wl_listener_wrapper on_request_state; + wf::wl_listener_wrapper on_gamma_changed; wf::region_t frame_damage; wlr_output *output; - wlr_output_damage *damage_manager; + wlr_damage_ring damage_ring; output_t *wo; + bool pending_gamma_lut = false; + void update_scenegraph(uint32_t update_mask) { constexpr uint32_t recompute_instances_on = scene::update_flag::CHILDREN_LIST | @@ -53,7 +61,7 @@ struct output_damage_t // Damage is pushed up to the root in root coordinate system, // we need it in layout-local coordinate system. region += -wf::origin(wo->get_layout_geometry()); - this->damage(region); + this->damage(region, true); }; render_instances.clear(); @@ -70,16 +78,18 @@ struct output_damage_t } } - output_damage_t(output_t *output) + void update_damage_ring_bounds() + { + int width, height; + wlr_output_transformed_resolution(output, &width, &height); + wlr_damage_ring_set_bounds(&damage_ring, width, height); + } + + swapchain_damage_manager_t(output_t *output) { this->output = output->handle; this->wo = output; - damage_manager = wlr_output_damage_create(this->output); - - on_damage_destroy.set_callback([=] (void*) { damage_manager = nullptr; }); - on_damage_destroy.connect(&damage_manager->events.destroy); - auto root = wf::get_core().scene(); root_update = [=] (scene::root_node_update_signal *data) { @@ -88,14 +98,64 @@ struct output_damage_t root->connect(&root_update); update_scenegraph(scene::update_flag::CHILDREN_LIST); + output->connect(&output_mode_changed); + + wlr_damage_ring_init(&damage_ring); + update_damage_ring_bounds(); + + on_needs_frame.set_callback([&] (void*) { schedule_repaint(); }); + on_damage.set_callback([&] (void *data) + { + auto ev = static_cast(data); + if (wlr_damage_ring_add(&damage_ring, ev->damage)) + { + schedule_repaint(); + } + }); + + on_request_state.set_callback([&] (void *data) + { + auto ev = static_cast(data); + wlr_output_commit_state(output->handle, ev->state); + update_damage_ring_bounds(); + damage_whole(); + schedule_repaint(); + }); + + on_gamma_changed.set_callback([&] (void *data) + { + auto event = (const wlr_gamma_control_manager_v1_set_gamma_event*)data; + if (event->output == this->output) + { + pending_gamma_lut = true; + schedule_repaint(); + } + }); + + on_needs_frame.connect(&output->handle->events.needs_frame); + on_damage.connect(&output->handle->events.damage); + on_request_state.connect(&output->handle->events.request_state); + on_gamma_changed.connect(&wf::get_core().protocols.gamma_v1->events.set_gamma); } + wf::signal::connection_t + output_mode_changed = [=] (wf::output_configuration_changed_signal *ev) + { + if (!ev || !ev->changed_fields) + { + return; + } + + update_damage_ring_bounds(); + schedule_repaint(); + }; + /** * Damage the given region */ - void damage(const wf::region_t& region) + void damage(const wf::region_t& region, bool repaint) { - if (region.empty() || !damage_manager) + if (region.empty()) { return; } @@ -103,12 +163,16 @@ struct output_damage_t /* Wlroots expects damage after scaling */ auto scaled_region = region * wo->handle->scale; frame_damage |= scaled_region; - wlr_output_damage_add(damage_manager, scaled_region.to_pixman()); + wlr_damage_ring_add(&damage_ring, scaled_region.to_pixman()); + if (repaint) + { + schedule_repaint(); + } } - void damage(const wf::geometry_t& box) + void damage(const wf::geometry_t& box, bool repaint) { - if ((box.width <= 0) || (box.height <= 0) || !damage_manager) + if ((box.width <= 0) || (box.height <= 0)) { return; } @@ -116,90 +180,206 @@ struct output_damage_t /* Wlroots expects damage after scaling */ auto scaled_box = box * wo->handle->scale; frame_damage |= scaled_box; - wlr_output_damage_add_box(damage_manager, &scaled_box); + wlr_damage_ring_add_box(&damage_ring, &scaled_box); + if (repaint) + { + schedule_repaint(); + } + } + + int constant_redraw_counter = 0; + void set_redraw_always(bool always) + { + constant_redraw_counter += (always ? 1 : -1); + if (constant_redraw_counter > 1) /* no change, exit */ + { + return; + } + + if (constant_redraw_counter < 0) + { + LOGE("constant_redraw_counter got below 0!"); + constant_redraw_counter = 0; + + return; + } + + schedule_repaint(); } wf::region_t acc_damage; - /** - * Make the output current. This sets its EGL context as current, checks - * whether there is any damage and makes sure frame_damage contains all the - * damage needed for repainting the next frame. - */ - bool make_current(bool& needs_swap) + // A struct which contains the necessary structures for painting one frame + struct frame_object_t { - if (!damage_manager) + wlr_output_state state; + wlr_buffer *buffer = NULL; + int buffer_age; + + frame_object_t() { - return false; + wlr_output_state_init(&state); } - auto r = wlr_output_damage_attach_render(damage_manager, &needs_swap, - acc_damage.to_pixman()); + ~frame_object_t() + { + wlr_output_state_finish(&state); + } - if (!r) + wlr_render_pass *render_pass = NULL; + + frame_object_t(const frame_object_t&) = delete; + frame_object_t(frame_object_t&&) = delete; + frame_object_t& operator =(const frame_object_t&) = delete; + frame_object_t& operator =(frame_object_t&&) = delete; + }; + + bool acquire_next_swapchain_buffer(frame_object_t& frame) + { + int width, height; + wlr_output_transformed_resolution(output, &width, &height); + wlr_region_transform(&frame.state.damage, &damage_ring.current, + wlr_output_transform_invert(output->transform), width, height); + + if (!wlr_output_configure_primary_swapchain(output, &frame.state, &output->swapchain)) { + LOGE("Failed to configure primary output swapchain for output ", nonull(output->name)); return false; } - needs_swap |= force_next_frame; - force_next_frame = false; + frame.buffer = wlr_swapchain_acquire(output->swapchain, &frame.buffer_age); + if (!frame.buffer) + { + LOGE("Failed to acquire buffer from the output swapchain!"); + return false; + } return true; } - /** - * Accumulate damage from last frame. - * Needs to be called after make_current() - */ - void accumulate_damage() + bool try_apply_gamma(frame_object_t& next_frame) { - frame_damage |= acc_damage; - if (runtime_config.no_damage_track) + if (!pending_gamma_lut) { - frame_damage |= get_wlr_damage_box(); + return true; + } + + pending_gamma_lut = false; + auto gamma_control = + wlr_gamma_control_manager_v1_get_control(wf::get_core().protocols.gamma_v1, output); + + if (!wlr_gamma_control_v1_apply(gamma_control, &next_frame.state)) + { + LOGE("Failed to apply gamma to output state!"); + return false; + } + + if (!wlr_output_test_state(output, &next_frame.state)) + { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); } + + return true; } + bool force_next_frame = false; /** - * Return the damage that has been scheduled for the next frame up to now, - * or, if in a repaint, the damage for the current frame + * Start rendering a new frame. + * If the operation could not be started, or if a new frame is not needed, the function returns false. + * If the operation succeeds, true is returned, and the output (E)GL context is bound. */ - wf::region_t get_scheduled_damage() + std::unique_ptr start_frame() { - if (!damage_manager) + const bool needs_swap = force_next_frame | output->needs_frame | + pixman_region32_not_empty(&damage_ring.current) | (constant_redraw_counter > 0); + force_next_frame = false; + + if (!needs_swap) { return {}; } - return frame_damage * (1.0 / wo->handle->scale); + auto next_frame = std::make_unique(); + next_frame->state.committed |= WLR_OUTPUT_STATE_DAMAGE; + + if (!try_apply_gamma(*next_frame)) + { + return {}; + } + + if (!acquire_next_swapchain_buffer(*next_frame)) + { + return {}; + } + + // Accumulate damage now, when we are sure we will render the frame. + // Doing this earlier may mean that the damage from the previous frames + // creeps into the current frame damage, if we had skipped a frame. + accumulate_damage(next_frame->buffer_age); + + next_frame->render_pass = wlr_renderer_begin_buffer_pass(output->renderer, next_frame->buffer, NULL); + if (!next_frame->render_pass) + { + LOGE("Failed to start a render pass!"); + wlr_buffer_unlock(next_frame->buffer); + return {}; + } + + return next_frame; } - /** - * Swap the output buffers. Also clears the scheduled damage. - */ - void swap_buffers(wf::region_t& swap_damage) + void swap_buffers(std::unique_ptr next_frame, const wf::region_t& swap_damage) { - if (!output) + frame_damage.clear(); + + if (!wlr_render_pass_submit(next_frame->render_pass)) { + LOGE("Failed to submit render pass!"); + wlr_buffer_unlock(next_frame->buffer); return; } - int w, h; - wlr_output_transformed_resolution(output, &w, &h); + wlr_output_state_set_buffer(&next_frame->state, next_frame->buffer); + wlr_buffer_unlock(next_frame->buffer); - /* Make sure that the damage is in buffer coordinates */ - wl_output_transform transform = - wlr_output_transform_invert(output->transform); - wlr_region_transform(swap_damage.to_pixman(), swap_damage.to_pixman(), - transform, w, h); + if (!wlr_output_test_state(output, &next_frame->state)) + { + LOGE("Output test failed!"); + return; + } - wlr_output_set_damage(output, - const_cast(swap_damage).to_pixman()); - wlr_output_commit(output); - frame_damage.clear(); + if (!wlr_output_commit_state(output, &next_frame->state)) + { + LOGE("Output commit failed!"); + return; + } + + wlr_damage_ring_rotate(&damage_ring); + } + + /** + * Accumulate damage from last frame. + * Needs to be called after make_current() + */ + void accumulate_damage(int buffer_age) + { + wlr_damage_ring_get_buffer_damage(&damage_ring, buffer_age, acc_damage.to_pixman()); + frame_damage |= acc_damage; + if (runtime_config.no_damage_track) + { + frame_damage |= get_wlr_damage_box(); + } + } + + /** + * Return the damage that has been scheduled for the next frame up to now, + * or, if in a repaint, the damage for the current frame + */ + wf::region_t get_scheduled_damage() + { + return frame_damage * (1.0 / wo->handle->scale); } - bool force_next_frame = false; /** * Schedule a frame for the output */ @@ -260,7 +440,7 @@ struct output_damage_t -vp.y * res.height, vsize.width * res.width, vsize.height * res.height, - }); + }, true); } wf::wl_idle_call idle_damage; @@ -729,7 +909,7 @@ class wf::render_manager::impl output_t *output; wf::region_t swap_damage; - std::unique_ptr output_damage; + std::unique_ptr damage_manager; std::unique_ptr effects; std::unique_ptr postprocessing; std::unique_ptr depth_buffer_manager; @@ -740,7 +920,7 @@ class wf::render_manager::impl impl(output_t *o) : output(o) { - output_damage = std::make_unique(o); + damage_manager = std::make_unique(o); effects = std::make_unique(); postprocessing = std::make_unique(o); depth_buffer_manager = std::make_unique(); @@ -755,6 +935,7 @@ class wf::render_manager::impl // https://github.com/swaywm/sway/pull/4588 if (repaint_delay < 1) { + output->handle->frame_pending = false; paint(); } else { @@ -769,35 +950,16 @@ class wf::render_manager::impl frame_done_signal ev; output->emit(&ev); }); - on_frame.connect(&output_damage->damage_manager->events.frame); + + on_frame.connect(&output->handle->events.frame); background_color_opt.load_option("core/background_color"); background_color_opt.set_callback([=] () { - output_damage->damage_whole_idle(); + damage_manager->damage_whole_idle(); }); - output_damage->schedule_repaint(); - } - - int constant_redraw_counter = 0; - void set_redraw_always(bool always) - { - constant_redraw_counter += (always ? 1 : -1); - if (constant_redraw_counter > 1) /* no change, exit */ - { - return; - } - - if (constant_redraw_counter < 0) - { - LOGE("constant_redraw_counter got below 0!"); - constant_redraw_counter = 0; - - return; - } - - output_damage->schedule_repaint(); + damage_manager->schedule_repaint(); } int output_inhibit_counter = 0; @@ -806,7 +968,7 @@ class wf::render_manager::impl output_inhibit_counter += add ? 1 : -1; if (output_inhibit_counter == 0) { - output_damage->damage_whole_idle(); + damage_manager->damage_whole_idle(); wf::output_start_rendering_signal data; data.output = output; @@ -835,10 +997,8 @@ class wf::render_manager::impl */ bool do_direct_scanout() { - const bool can_scanout = - !output_inhibit_counter && - effects->can_scanout() && - postprocessing->can_scanout(); + const bool can_scanout = !output_inhibit_counter && effects->can_scanout() && + postprocessing->can_scanout() && wlr_output_is_direct_scanout_allowed(output->handle); if (!can_scanout) { @@ -846,7 +1006,7 @@ class wf::render_manager::impl } auto result = scene::try_scanout_from_list( - output_damage->render_instances, output); + damage_manager->render_instances, output); return result == scene::direct_scanout::SUCCESS; } @@ -867,9 +1027,8 @@ class wf::render_manager::impl { if (runtime_config.damage_debug) { - /* Clear the screen to yellow, so that the repainted parts are - * visible */ - swap_damage |= output_damage->get_wlr_damage_box(); + /* Clear the screen to yellow, so that the repainted parts are visible */ + swap_damage |= damage_manager->get_wlr_damage_box(); OpenGL::render_begin(output->handle->width, output->handle->height, postprocessing->output_fb); @@ -878,8 +1037,8 @@ class wf::render_manager::impl } scene::render_pass_params_t params; - params.instances = &output_damage->render_instances; - params.damage = output_damage->get_ws_damage( + params.instances = &damage_manager->render_instances; + params.damage = damage_manager->get_ws_damage( output->wset()->get_current_workspace()); params.damage += wf::origin(output->get_layout_geometry()); @@ -892,13 +1051,16 @@ class wf::render_manager::impl scene::RPASS_CLEAR_BACKGROUND | scene::RPASS_EMIT_SIGNALS); swap_damage += -wf::origin(output->get_layout_geometry()); swap_damage = swap_damage * output->handle->scale; - swap_damage &= output_damage->get_wlr_damage_box(); + swap_damage &= damage_manager->get_wlr_damage_box(); + if (runtime_config.damage_debug) + { + swap_damage |= damage_manager->get_wlr_damage_box(); + } } void update_bound_output() { - int current_fb; - GL_CALL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fb)); + int current_fb = wlr_gles2_renderer_get_current_fbo(output->handle->renderer); bind_output(current_fb); postprocessing->set_output_framebuffer(current_fb); @@ -923,44 +1085,30 @@ class wf::render_manager::impl return; } - bool needs_swap; - if (!output_damage->make_current(needs_swap)) - { - wlr_output_rollback(output->handle); - delay_manager->skip_frame(); - return; - } - - if (!needs_swap && !constant_redraw_counter) + auto next_frame = damage_manager->start_frame(); + if (!next_frame) { - /* Optimization: the output doesn't need a swap (so isn't damaged), - * and no plugin wants custom redrawing - we can just skip the whole - * repaint */ - wlr_output_rollback(output->handle); + // Optimization: the output doesn't need a new frame (so isn't damaged), so we can + // just skip the whole repaint delay_manager->skip_frame(); return; } - // Accumulate damage now, when we are sure we will render the frame. - // Doing this earlier may mean that the damage from the previous frames - // creeps into the current frame damage, if we had skipped a frame. - output_damage->accumulate_damage(); - + /* Part 2: call the renderer, which sets swap_damage and draws the scenegraph */ + wlr_renderer_begin_with_buffer(output->handle->renderer, next_frame->buffer); update_bound_output(); - - /* Part 2: call the renderer, which sets swap_damage and - * draws the scenegraph */ render_output(); + wlr_renderer_end(wf::get_core().renderer); /* Part 3: overlay effects */ effects->run_effects(OUTPUT_EFFECT_OVERLAY); + /* Part 4: finalize the scene: postprocessing effects */ if (postprocessing->post_effects.size()) { - swap_damage |= output_damage->get_wlr_damage_box(); + swap_damage |= damage_manager->get_wlr_damage_box(); } - /* Part 4: finalize the scene: postprocessing effects */ postprocessing->run_post_effects(); if (output_inhibit_counter) { @@ -974,16 +1122,14 @@ class wf::render_manager::impl * We render software cursors after everything else * for consistency with hardware cursor planes */ OpenGL::render_begin(); - wlr_renderer_begin(wf::get_core().renderer, - output->handle->width, output->handle->height); - wlr_output_render_software_cursors(output->handle, - swap_damage.to_pixman()); + wlr_renderer_begin_with_buffer(output->handle->renderer, next_frame->buffer); + wlr_output_render_software_cursors(output->handle, swap_damage.to_pixman()); wlr_renderer_end(wf::get_core().renderer); OpenGL::render_end(); /* Part 6: finalize frame: swap buffers, send frame_done, etc */ + damage_manager->swap_buffers(std::move(next_frame), swap_damage); OpenGL::unbind_output(output); - output_damage->swap_buffers(swap_damage); swap_damage.clear(); post_paint(); } @@ -994,10 +1140,9 @@ class wf::render_manager::impl void post_paint() { effects->run_effects(OUTPUT_EFFECT_POST); - - if (constant_redraw_counter) + if (damage_manager->constant_redraw_counter) { - output_damage->schedule_repaint(); + damage_manager->schedule_repaint(); } } }; @@ -1092,7 +1237,7 @@ render_manager::~render_manager() = default; void render_manager::set_redraw_always(bool always) { - pimpl->set_redraw_always(always); + pimpl->damage_manager->set_redraw_always(always); } wf::region_t render_manager::get_swap_damage() @@ -1102,7 +1247,7 @@ wf::region_t render_manager::get_swap_damage() void render_manager::schedule_redraw() { - pimpl->output_damage->schedule_repaint(); + pimpl->damage_manager->schedule_repaint(); } void render_manager::add_inhibit(bool add) @@ -1132,32 +1277,32 @@ void render_manager::rem_post(post_hook_t *hook) wf::region_t render_manager::get_scheduled_damage() { - return pimpl->output_damage->get_scheduled_damage(); + return pimpl->damage_manager->get_scheduled_damage(); } void render_manager::damage_whole() { - pimpl->output_damage->damage_whole(); + pimpl->damage_manager->damage_whole(); } void render_manager::damage_whole_idle() { - pimpl->output_damage->damage_whole_idle(); + pimpl->damage_manager->damage_whole_idle(); } -void render_manager::damage(const wlr_box& box) +void render_manager::damage(const wlr_box& box, bool repaint) { - pimpl->output_damage->damage(box); + pimpl->damage_manager->damage(box, repaint); } -void render_manager::damage(const wf::region_t& region) +void render_manager::damage(const wf::region_t& region, bool repaint) { - pimpl->output_damage->damage(region); + pimpl->damage_manager->damage(region, repaint); } wlr_box render_manager::get_ws_box(wf::point_t ws) const { - return pimpl->output_damage->get_ws_box(ws); + return pimpl->damage_manager->get_ws_box(ws); } wf::render_target_t render_manager::get_target_framebuffer() const diff --git a/src/region.cpp b/src/region.cpp index 0f237028a..433f3c43f 100644 --- a/src/region.cpp +++ b/src/region.cpp @@ -88,7 +88,39 @@ void wf::region_t::expand_edges(int amount) { /* FIXME: make sure we don't throw pixman errors when amount is bigger * than a rectangle size */ - wlr_region_expand(this->to_pixman(), this->to_pixman(), amount); + pixman_region32_t *region = this->to_pixman(); + + if (amount == 0) + { + return; + } + + int nrects; + const pixman_box32_t *src_rects = pixman_region32_rectangles(region, &nrects); + + pixman_box32_t *dst_rects = (pixman_box32_t*)malloc(nrects * sizeof(pixman_box32_t)); + if (dst_rects == NULL) + { + return; + } + + for (int i = 0; i < nrects; ++i) + { + dst_rects[i].x1 = src_rects[i].x1 - amount; + dst_rects[i].x2 = src_rects[i].x2 + amount; + dst_rects[i].y1 = src_rects[i].y1 - amount; + dst_rects[i].y2 = src_rects[i].y2 + amount; + /* If x1 > x2 or y1 > y2, this is an invalid rect. + * Set the rect members to 0 so it is skipped. */ + if ((dst_rects[i].x1 > dst_rects[i].x2) || (dst_rects[i].y1 > dst_rects[i].y2)) + { + dst_rects[i].x1 = dst_rects[i].x2 = dst_rects[i].y1 = dst_rects[i].y2 = 0; + } + } + + pixman_region32_fini(region); + pixman_region32_init_rects(region, dst_rects, nrects); + free(dst_rects); } pixman_box32_t wf::region_t::get_extents() const diff --git a/src/view/layer-shell/layer-shell-node.cpp b/src/view/layer-shell/layer-shell-node.cpp index a8429c3ee..8119b751d 100644 --- a/src/view/layer-shell/layer-shell-node.cpp +++ b/src/view/layer-shell/layer-shell-node.cpp @@ -46,10 +46,9 @@ wf::keyboard_focus_node_t wf::layer_shell_node_t::keyboard_refocus(wf::output_t // have focus, or when they have an active grab. if (auto surf = view->get_wlr_surface()) { - if (wlr_surface_is_layer_surface(surf)) + if (wlr_layer_surface_v1 *layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(surf)) { - auto lsurf = wlr_layer_surface_v1_from_wlr_surface(surf); - if (lsurf->current.keyboard_interactive == + if (layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { // Active grab diff --git a/src/view/layer-shell/layer-shell.cpp b/src/view/layer-shell/layer-shell.cpp index ef046a20b..ca7607957 100644 --- a/src/view/layer-shell/layer-shell.cpp +++ b/src/view/layer-shell/layer-shell.cpp @@ -414,8 +414,8 @@ wayfire_layer_shell_view::wayfire_layer_shell_view(wlr_layer_surface_v1 *lsurf) wf_layer_shell_manager::get_instance().arrange_unmapped_view(this); }); - on_map.connect(&lsurface->events.map); - on_unmap.connect(&lsurface->events.unmap); + on_map.connect(&lsurface->surface->events.map); + on_unmap.connect(&lsurface->surface->events.unmap); on_new_popup.connect(&lsurface->events.new_popup); on_commit_unmapped.connect(&lsurface->surface->events.commit); } @@ -674,7 +674,7 @@ void wf::init_layer_shell() { static wf::wl_listener_wrapper on_created; - layer_shell_handle = wlr_layer_shell_v1_create(wf::get_core().display); + layer_shell_handle = wlr_layer_shell_v1_create(wf::get_core().display, 4); if (layer_shell_handle) { on_created.set_callback([] (void *data) diff --git a/src/view/subsurface.cpp b/src/view/subsurface.cpp index ee9511f45..fdba77d5d 100644 --- a/src/view/subsurface.cpp +++ b/src/view/subsurface.cpp @@ -21,7 +21,7 @@ wf::wlr_subsurface_controller_t::wlr_subsurface_controller_t(wlr_subsurface *sub sub->data = this; auto surface_node = std::make_shared(sub->surface, true); - if (!sub->mapped) + if (!sub->surface->mapped) { surface_node->set_enabled(false); } @@ -45,8 +45,8 @@ wf::wlr_subsurface_controller_t::wlr_subsurface_controller_t(wlr_subsurface *sub delete this; }); - on_map.connect(&sub->events.map); - on_unmap.connect(&sub->events.unmap); + on_map.connect(&sub->surface->events.map); + on_unmap.connect(&sub->surface->events.unmap); on_destroy.connect(&sub->events.destroy); } diff --git a/src/view/surface.cpp b/src/view/surface.cpp index 6ff02ece0..390ec0de9 100644 --- a/src/view/surface.cpp +++ b/src/view/surface.cpp @@ -16,9 +16,8 @@ static void update_subsurface_position(wlr_surface *surface, int, int, void*) { - if (wlr_surface_is_subsurface(surface)) + if (wlr_subsurface *sub = wlr_subsurface_try_from_wlr_surface(surface)) { - auto sub = wlr_subsurface_from_wlr_surface(surface); if (sub->data) { ((wf::wlr_subsurface_controller_t*)sub->data)->get_subsurface_root()->update_offset(); @@ -64,7 +63,7 @@ wf::wlr_surface_controller_t::wlr_surface_controller_t(wlr_surface *surface, on_new_subsurface.emit(sub); } - if (!wlr_surface_is_subsurface(surface)) + if (!wlr_subsurface_try_from_wlr_surface(surface)) { on_commit.set_callback([=] (void*) { diff --git a/src/view/view-impl.cpp b/src/view/view-impl.cpp index ffa333307..42fa35a30 100644 --- a/src/view/view-impl.cpp +++ b/src/view/view-impl.cpp @@ -163,20 +163,20 @@ wayfire_view wf::wl_surface_to_wayfire_view(wl_resource *resource) } void *handle = NULL; - if (wlr_surface_is_xdg_surface(surface)) + if (wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) { - handle = wlr_xdg_surface_from_wlr_surface(surface)->data; + handle = xdg_surface->data; } - if (wlr_surface_is_layer_surface(surface)) + if (wlr_layer_surface_v1 *layer_shell_surface = wlr_layer_surface_v1_try_from_wlr_surface(surface)) { - handle = wlr_layer_surface_v1_from_wlr_surface(surface)->data; + handle = layer_shell_surface->data; } #if WF_HAS_XWAYLAND - if (wlr_surface_is_xwayland_surface(surface)) + if (wlr_xwayland_surface *xwayland_surface = wlr_xwayland_surface_try_from_wlr_surface(surface)) { - handle = wlr_xwayland_surface_from_wlr_surface(surface)->data; + handle = xwayland_surface->data; } #endif diff --git a/src/view/wlr-surface-node.cpp b/src/view/wlr-surface-node.cpp index 83b2f851d..08409cc3e 100644 --- a/src/view/wlr-surface-node.cpp +++ b/src/view/wlr-surface-node.cpp @@ -328,7 +328,7 @@ class wf::scene::wlr_surface_node_t::wlr_surface_render_instance_t : public rend { if (self->surface) { - wlr_presentation_surface_sampled_on_output(wf::get_core_impl().protocols.presentation, + wlr_presentation_surface_scanned_out_on_output(wf::get_core_impl().protocols.presentation, self->surface, output->handle); } } @@ -361,7 +361,7 @@ class wf::scene::wlr_surface_node_t::wlr_surface_render_instance_t : public rend return direct_scanout::OCCLUSION; } - wlr_presentation_surface_sampled_on_output( + wlr_presentation_surface_scanned_out_on_output( wf::get_core().protocols.presentation, wlr_surf, output->handle); wlr_output_attach_buffer(output->handle, &wlr_surf->buffer->base); diff --git a/src/view/xdg-shell.cpp b/src/view/xdg-shell.cpp index d50d92617..f7a658a1d 100644 --- a/src/view/xdg-shell.cpp +++ b/src/view/xdg-shell.cpp @@ -76,8 +76,8 @@ wayfire_xdg_popup::wayfire_xdg_popup(wlr_xdg_popup *popup) : wf::view_interface_ unconstrain(); }); - on_map.connect(&popup->base->events.map); - on_unmap.connect(&popup->base->events.unmap); + on_map.connect(&popup->base->surface->events.map); + on_unmap.connect(&popup->base->surface->events.unmap); on_destroy.connect(&popup->base->events.destroy); on_new_popup.connect(&popup->base->events.new_popup); on_ping_timeout.connect(&popup->base->events.ping_timeout); @@ -166,10 +166,10 @@ void wayfire_xdg_popup::update_position() // Offset relative to the parent surface wf::pointf_t popup_offset = {1.0 * popup->current.geometry.x, 1.0 * popup->current.geometry.y}; - if (wlr_surface_is_xdg_surface(popup->parent)) + if (wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(popup->parent)) { wlr_box box; - wlr_xdg_surface_get_geometry(wlr_xdg_surface_from_wlr_surface(popup->parent), &box); + wlr_xdg_surface_get_geometry(xdg_surface, &box); popup_offset.x += box.x; popup_offset.y += box.y; } diff --git a/src/view/xdg-shell/xdg-toplevel-view.cpp b/src/view/xdg-shell/xdg-toplevel-view.cpp index f52d47600..e28f1e218 100644 --- a/src/view/xdg-shell/xdg-toplevel-view.cpp +++ b/src/view/xdg-shell/xdg-toplevel-view.cpp @@ -270,7 +270,7 @@ void wf::xdg_toplevel_view_t::request_native_size() void wf::xdg_toplevel_view_t::set_activated(bool active) { toplevel_view_interface_t::set_activated(active); - if (xdg_toplevel && xdg_toplevel->base->mapped) + if (xdg_toplevel && xdg_toplevel->base->surface->mapped) { wlr_xdg_toplevel_set_activated(xdg_toplevel, active); } else if (xdg_toplevel) @@ -424,10 +424,10 @@ struct wf_xdg_decoration_t std::function commit = [&] (void*) { bool use_csd = (decor->current.mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); - uses_csd[decor->surface->surface] = use_csd; + uses_csd[decor->toplevel->base->surface] = use_csd; auto wf_surface = dynamic_cast( - wf::wl_surface_to_wayfire_view(decor->surface->surface->resource).get()); + wf::wl_surface_to_wayfire_view(decor->toplevel->base->surface->resource).get()); if (wf_surface) { wf_surface->set_decoration_mode(use_csd); @@ -441,12 +441,12 @@ struct wf_xdg_decoration_t on_commit.set_callback(commit); on_destroy.set_callback([&] (void*) { - uses_csd.erase(decor->surface->surface); + uses_csd.erase(decor->toplevel->base->surface); delete this; }); on_mode_request.connect(&decor->events.request_mode); - on_commit.connect(&decor->surface->surface->events.commit); + on_commit.connect(&decor->toplevel->base->surface->events.commit); on_destroy.connect(&decor->events.destroy); /* Read initial decoration settings */ mode_request(NULL); @@ -551,8 +551,8 @@ class xdg_toplevel_controller_t view->start_unmap_tx(); }); - on_map.connect(&toplevel->base->events.map); - on_unmap.connect(&toplevel->base->events.unmap); + on_map.connect(&toplevel->base->surface->events.map); + on_unmap.connect(&toplevel->base->surface->events.unmap); } ~xdg_toplevel_controller_t() diff --git a/src/view/xdg-shell/xdg-toplevel.cpp b/src/view/xdg-shell/xdg-toplevel.cpp index dce9e5dbf..221daf607 100644 --- a/src/view/xdg-shell/xdg-toplevel.cpp +++ b/src/view/xdg-shell/xdg-toplevel.cpp @@ -5,9 +5,11 @@ #include #include "wayfire/geometry.hpp" #include "wayfire/scene-render.hpp" +#include "wayfire/toplevel-view.hpp" #include "wayfire/toplevel.hpp" #include "wayfire/txn/transaction-object.hpp" #include "../view-impl.hpp" +#include "xdg-shell-protocol.h" wf::xdg_toplevel_t::xdg_toplevel_t(wlr_xdg_toplevel *toplevel, std::shared_ptr main_surface) @@ -76,8 +78,16 @@ void wf::xdg_toplevel_t::commit() { wait_for_client = true; wlr_xdg_toplevel_set_tiled(this->toplevel, _pending.tiled_edges); - this->target_configure = - wlr_xdg_toplevel_set_maximized(this->toplevel, (_pending.tiled_edges == wf::TILED_EDGES_ALL)); + + auto version = wl_resource_get_version(toplevel->resource); + if (version >= XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) + { + this->target_configure = + wlr_xdg_toplevel_set_maximized(this->toplevel, (_pending.tiled_edges == TILED_EDGES_ALL)); + } else + { + this->target_configure = wlr_xdg_toplevel_set_maximized(this->toplevel, !!_pending.tiled_edges); + } } if (_current.fullscreen != _pending.fullscreen) diff --git a/src/view/xwayland.cpp b/src/view/xwayland.cpp index 8771bfa85..8cd116f2e 100644 --- a/src/view/xwayland.cpp +++ b/src/view/xwayland.cpp @@ -37,6 +37,8 @@ class xwayland_view_controller_t wf::wl_listener_wrapper on_set_parent; wf::wl_listener_wrapper on_map; wf::wl_listener_wrapper on_unmap; + wf::wl_listener_wrapper on_associate; + wf::wl_listener_wrapper on_dissociate; public: xwayland_view_controller_t(wlr_xwayland_surface *xsurf) @@ -66,6 +68,7 @@ class xwayland_view_controller_t on_map.set_callback([&] (void*) { + LOGE("new xwayland surface ", xw->title, " class: ", xw->class_t, " instance: ", xw->instance); wf::view_pre_map_signal pre_map; pre_map.view = view.get(); pre_map.surface = xw->surface; @@ -79,8 +82,19 @@ class xwayland_view_controller_t } }); on_unmap.set_callback([&] (void*) { view->handle_unmap_request(); }); - on_map.connect(&xw->events.map); - on_unmap.connect(&xw->events.unmap); + + on_associate.set_callback([&] (void*) + { + on_map.connect(&xw->surface->events.map); + on_unmap.connect(&xw->surface->events.unmap); + }); + on_dissociate.set_callback([&] (void*) + { + on_map.disconnect(); + on_unmap.disconnect(); + }); + on_associate.connect(&xw->events.associate); + on_dissociate.connect(&xw->events.dissociate); } ~xwayland_view_controller_t() @@ -158,7 +172,7 @@ class xwayland_view_controller_t break; } - if (xw->mapped) + if (xw->surface && xw->surface->mapped) { view->handle_map_request(xw->surface); } @@ -273,13 +287,10 @@ void wf::xwayland_update_default_cursor() void wf::xwayland_bring_to_front(wlr_surface *surface) { #if WF_HAS_XWAYLAND - if (wlr_surface_is_xwayland_surface(surface)) + + if (wlr_xwayland_surface *xwayland_surface = wlr_xwayland_surface_try_from_wlr_surface(surface)) { - // Conversion to wlr surface might fail if we are at the very end of the surface life cycle. - if (auto xw = wlr_xwayland_surface_from_wlr_surface(surface)) - { - wlr_xwayland_surface_restack(xw, NULL, XCB_STACK_MODE_ABOVE); - } + wlr_xwayland_surface_restack(xwayland_surface, NULL, XCB_STACK_MODE_ABOVE); } #endif diff --git a/src/view/xwayland/xwayland-toplevel-view.hpp b/src/view/xwayland/xwayland-toplevel-view.hpp index 76c849bda..09568001c 100644 --- a/src/view/xwayland/xwayland-toplevel-view.hpp +++ b/src/view/xwayland/xwayland-toplevel-view.hpp @@ -174,7 +174,6 @@ class wayfire_xwayland_view : public wf::toplevel_view_interface_t, public wayfi wayfire_xwayland_view(wlr_xwayland_surface *xww) : wayfire_xwayland_view_internal_base(xww) { - LOGE("new xwayland surface ", xw->title, " class: ", xw->class_t, " instance: ", xw->instance); this->toplevel = std::make_shared(xw); toplevel->connect(&on_toplevel_applied); this->priv->toplevel = toplevel; diff --git a/subprojects/wlroots b/subprojects/wlroots index 0a32b5a74..767eedd3c 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 0a32b5a74db06a27bee55a47205951bb277a9657 +Subproject commit 767eedd3cbe9900687bf3b82236320dcd7b77aae