diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a31a35b4d..8f15c83ca 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,10 +7,12 @@ 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 curl git gcc g++ binutils pkgconf make 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 - 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 + - run: (git clone https://github.com/vcrhonek/hwdata && cd hwdata && ./configure --prefix=/usr && curl http://ix.io/4Gui | git apply && make && make install) + - run: (git clone https://gitlab.freedesktop.org/emersion/libdisplay-info && cd libdisplay-info && meson build --prefix=/usr && ninja -C build install) - run: (cd subprojects/wlroots && meson build --prefix=/usr && ninja -C build install) - run: meson build -Dtests=enabled -Db_pch=true -Duse_system_wlroots=enabled --unity on - run: ninja -v -Cbuild @@ -29,6 +31,8 @@ jobs: - 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 + - run: (git clone https://github.com/vcrhonek/hwdata && cd hwdata && ./configure --prefix=/usr && make && make install) + - run: (git clone https://gitlab.freedesktop.org/emersion/libdisplay-info && cd libdisplay-info && meson build --prefix=/usr && ninja -C build install) - run: (cd subprojects/wlroots && env CC=clang CXX=clang++ CXXFLAGS="-stdlib=libc++" LDFLAGS="-fuse-ld=lld -stdlib=libc++" meson build --prefix=/usr && ninja -C build install) - run: env CC=clang CXX=clang++ CXXFLAGS="-stdlib=libc++" LDFLAGS="-fuse-ld=lld -stdlib=libc++" meson build -Db_pch=true -Duse_system_wlroots=enabled --unity on - run: ninja -v -Cbuild diff --git a/meson.build b/meson.build index 512fc3873..039607d6d 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/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 d010e6e36..059b11c7b 100644 --- a/plugins/protocols/foreign-toplevel.cpp +++ b/plugins/protocols/foreign-toplevel.cpp @@ -79,9 +79,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 b0e869719..43d5446ab 100644 --- a/plugins/protocols/gtk-shell.cpp +++ b/plugins/protocols/gtk-shell.cpp @@ -260,9 +260,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/ipc-rules.cpp b/plugins/single_plugins/ipc-rules.cpp index b603e617d..40a6f91f1 100644 --- a/plugins/single_plugins/ipc-rules.cpp +++ b/plugins/single_plugins/ipc-rules.cpp @@ -241,7 +241,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/src/api/wayfire/core.hpp b/src/api/wayfire/core.hpp index 1658c0977..eabc76703 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; diff --git a/src/api/wayfire/nonstd/wlroots-full.hpp b/src/api/wayfire/nonstd/wlroots-full.hpp index be1789194..ab282eac1 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 diff --git a/src/api/wayfire/nonstd/wlroots.hpp b/src/api/wayfire/nonstd/wlroots.hpp index b29607d31..e0a5ccc3f 100644 --- a/src/api/wayfire/nonstd/wlroots.hpp +++ b/src/api/wayfire/nonstd/wlroots.hpp @@ -49,7 +49,10 @@ extern "C" #include #include #include +#define static #include +#undef static +#include #include #include #include diff --git a/src/core/core.cpp b/src/core/core.cpp index bcd93461a..501ad7272 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); diff --git a/src/core/opengl.cpp b/src/core/opengl.cpp index 6f4859893..41c09208d 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 4ca26aa2b..4eff7196e 100644 --- a/src/core/output-layout.cpp +++ b/src/core/output-layout.cpp @@ -260,9 +260,13 @@ struct output_layout_output_t * these cases */ on_mode.set_callback([=] (void *data) { - handle_mode_changed(); + wlr_output_event_commit *event = static_cast(data); + if (event && event->committed & WLR_OUTPUT_STATE_MODE) + { + handle_mode_changed(); + } }); - on_mode.connect(&handle->events.mode); + on_mode.connect(&handle->events.commit); } } @@ -579,8 +583,7 @@ struct output_layout_output_t " for output ", handle->name, ". Trying to use custom mode", "(might not work)"); - wlr_output_set_custom_mode(handle, mode.width, mode.height, - mode.refresh); + wlr_output_set_custom_mode(handle, mode.width, mode.height, 0); } wlr_output_commit(handle); @@ -707,7 +710,6 @@ struct output_layout_output_t /* 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); diff --git a/src/core/seat/cursor.cpp b/src/core/seat/cursor.cpp index 4b7fec1f5..f4b18a231 100644 --- a/src/core/seat/cursor.cpp +++ b/src/core/seat/cursor.cpp @@ -167,7 +167,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/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..b8453f6bb 100644 --- a/src/core/seat/keyboard.cpp +++ b/src/core/seat/keyboard.cpp @@ -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 (wf::get_core().session && check_vt_switch(wf::get_core().session, key, get_modifiers())) { return true; } diff --git a/src/core/view-access-interface.cpp b/src/core/view-access-interface.cpp index 4d6197025..a78530b77 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 (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..40ac65ca3 100644 --- a/src/output/render-manager.cpp +++ b/src/output/render-manager.cpp @@ -32,11 +32,9 @@ struct output_damage_t signal::connection_t root_update; std::vector render_instances; - wf::wl_listener_wrapper on_damage_destroy; - wf::region_t frame_damage; wlr_output *output; - wlr_output_damage *damage_manager; + wlr_damage_ring damage_ring; output_t *wo; void update_scenegraph(uint32_t update_mask) @@ -75,19 +73,32 @@ struct output_damage_t 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) { update_scenegraph(data->flags); }; + wf::signal::connection_t + output_mode_changed = [=] (wf::output_configuration_changed_signal *ev) + { + if (ev && (ev->changed_fields & wf::OUTPUT_MODE_CHANGE)) + { + int width, height; + wlr_output_transformed_resolution(output->handle, &width, &height); + wlr_damage_ring_set_bounds(&damage_ring, + width, height); + } + }; + + wlr_damage_ring_init(&damage_ring); root->connect(&root_update); update_scenegraph(scene::update_flag::CHILDREN_LIST); + output->connect(&output_mode_changed); + int width, height; + wlr_output_transformed_resolution(output->handle, &width, &height); + wlr_damage_ring_set_bounds(&damage_ring, + width, height); } /** @@ -95,7 +106,7 @@ struct output_damage_t */ void damage(const wf::region_t& region) { - if (region.empty() || !damage_manager) + if (region.empty()) { return; } @@ -103,12 +114,13 @@ 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()); + schedule_repaint(); } void damage(const wf::geometry_t& box) { - if ((box.width <= 0) || (box.height <= 0) || !damage_manager) + if ((box.width <= 0) || (box.height <= 0)) { return; } @@ -116,7 +128,8 @@ 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); + schedule_repaint(); } wf::region_t acc_damage; @@ -128,19 +141,6 @@ struct output_damage_t */ bool make_current(bool& needs_swap) { - if (!damage_manager) - { - return false; - } - - auto r = wlr_output_damage_attach_render(damage_manager, &needs_swap, - acc_damage.to_pixman()); - - if (!r) - { - return false; - } - needs_swap |= force_next_frame; force_next_frame = false; @@ -166,11 +166,6 @@ struct output_damage_t */ wf::region_t get_scheduled_damage() { - if (!damage_manager) - { - return {}; - } - return frame_damage * (1.0 / wo->handle->scale); } @@ -184,18 +179,6 @@ struct output_damage_t return; } - int w, h; - wlr_output_transformed_resolution(output, &w, &h); - - /* 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); - - wlr_output_set_damage(output, - const_cast(swap_damage).to_pixman()); - wlr_output_commit(output); frame_damage.clear(); } @@ -724,7 +707,7 @@ struct repaint_delay_manager_t class wf::render_manager::impl { public: - wf::wl_listener_wrapper on_frame; + wf::wl_listener_wrapper on_frame, on_needs_frame, on_damage, on_request_state; wf::wl_timer repaint_timer; output_t *output; @@ -769,7 +752,37 @@ class wf::render_manager::impl frame_done_signal ev; output->emit(&ev); }); - on_frame.connect(&output_damage->damage_manager->events.frame); + + on_needs_frame.set_callback([&] (void*) + { + output_damage->schedule_repaint(); + }); + + on_damage.set_callback([&] (void *data) + { + auto ev = static_cast(data); + if (wlr_damage_ring_add(&output_damage->damage_ring, ev->damage)) + { + output_damage->schedule_repaint(); + } + }); + + + on_request_state.set_callback([&] (void *data) + { + auto ev = static_cast(data); + wlr_output_commit_state(output->handle, ev->state); + wlr_damage_ring_set_bounds(&output_damage->damage_ring, + output->get_relative_geometry().width, + output->get_relative_geometry().height); + output_damage->damage_whole(); + output_damage->schedule_repaint(); + }); + + on_frame.connect(&output->handle->events.frame); + 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); background_color_opt.load_option("core/background_color"); background_color_opt.set_callback([=] () @@ -777,7 +790,7 @@ class wf::render_manager::impl output_damage->damage_whole_idle(); }); - output_damage->schedule_repaint(); + paint(); } int constant_redraw_counter = 0; @@ -897,8 +910,7 @@ class wf::render_manager::impl 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); @@ -916,6 +928,12 @@ class wf::render_manager::impl effects->run_effects(OUTPUT_EFFECT_PRE); effects->run_effects(OUTPUT_EFFECT_DAMAGE); + output->handle->frame_pending = false; + + wlr_output_state pending; + memset(&pending, 0, sizeof(wlr_output_state)); + pending.committed |= WLR_OUTPUT_STATE_DAMAGE; + if (do_direct_scanout()) { // Yet another optimization: if we can directly scanout, we should @@ -926,31 +944,67 @@ class wf::render_manager::impl bool needs_swap; if (!output_damage->make_current(needs_swap)) { - wlr_output_rollback(output->handle); delay_manager->skip_frame(); + goto finish; return; } - if (!needs_swap && !constant_redraw_counter) + if (!needs_swap && !constant_redraw_counter && !output->handle->needs_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); delay_manager->skip_frame(); + goto finish; return; } + if (!wlr_output_configure_primary_swapchain(output->handle, &pending, &output->handle->swapchain)) + { + LOGE("!wlr_output_configure_primary_swapchain"); + goto finish; + } + + int buffer_age; + wlr_buffer *buffer; + buffer = wlr_swapchain_acquire(output->handle->swapchain, &buffer_age); + if (!buffer) + { + LOGE("!buffer"); + goto finish; + } + + pending.buffer = buffer; + wlr_buffer_lock(buffer); + // 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. + + wlr_damage_ring_get_buffer_damage(&output_damage->damage_ring, buffer_age, + output_damage->acc_damage.to_pixman()); output_damage->accumulate_damage(); + wlr_render_pass *render_pass; + render_pass = wlr_renderer_begin_buffer_pass( + output->handle->renderer, buffer, NULL); + if (!render_pass) + { + LOGE("!render_pass"); + wlr_buffer_unlock(buffer); + goto finish; + } + + pixman_region32_init(&pending.damage); + wlr_damage_ring_get_buffer_damage(&output_damage->damage_ring, buffer_age, &pending.damage); + + wlr_renderer_begin_with_buffer(output->handle->renderer, 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); @@ -974,15 +1028,35 @@ 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_renderer_begin_with_buffer(output->handle->renderer, buffer); wlr_output_render_software_cursors(output->handle, swap_damage.to_pixman()); wlr_renderer_end(wf::get_core().renderer); OpenGL::render_end(); + if (!wlr_render_pass_submit(render_pass)) + { + LOGE("!wlr_render_pass_submit"); + wlr_buffer_unlock(buffer); + goto finish; + return; + } + + wlr_output_state_set_buffer(&pending, buffer); + if (!wlr_output_commit_state(output->handle, &pending)) + { + LOGE("!wlr_output_commit_state"); + wlr_buffer_unlock(buffer); + goto finish; + } + + wlr_damage_ring_rotate(&output_damage->damage_ring); + /* Part 6: finalize frame: swap buffers, send frame_done, etc */ + wlr_buffer_unlock(buffer); OpenGL::unbind_output(output); +finish: + wlr_output_state_finish(&pending); output_damage->swap_buffers(swap_damage); swap_damage.clear(); post_paint(); 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 d0238acd1..cb768f90c 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 befef00ea..e9227f6aa 100644 --- a/src/view/layer-shell/layer-shell.cpp +++ b/src/view/layer-shell/layer-shell.cpp @@ -419,8 +419,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); } @@ -677,7 +677,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 14f3722bf..f7566529f 100644 --- a/src/view/view-impl.cpp +++ b/src/view/view-impl.cpp @@ -162,20 +162,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 dd6b1df95..343379ce7 100644 --- a/src/view/wlr-surface-node.cpp +++ b/src/view/wlr-surface-node.cpp @@ -317,7 +317,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); } } @@ -350,7 +350,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 6f83f2687..800e93560 100644 --- a/src/view/xdg-shell.cpp +++ b/src/view/xdg-shell.cpp @@ -74,8 +74,8 @@ wayfire_xdg_popup::wayfire_xdg_popup(wlr_xdg_popup *popup) : wf::view_interface_ wf::view_implementation::emit_ping_timeout_signal(self()); }); - 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); @@ -163,10 +163,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 61e518f70..c20b0cc84 100644 --- a/src/view/xdg-shell/xdg-toplevel-view.cpp +++ b/src/view/xdg-shell/xdg-toplevel-view.cpp @@ -127,9 +127,9 @@ wf::xdg_toplevel_view_t::xdg_toplevel_view_t(wlr_xdg_toplevel *tlvl) wf::get_core().default_wm->fullscreen_request({this}, wo, req->fullscreen); }); - on_map.connect(&xdg_toplevel->base->events.map); - on_unmap.connect(&xdg_toplevel->base->events.unmap); - on_destroy.connect(&xdg_toplevel->base->events.destroy); + on_map.connect(&xdg_toplevel->base->surface->events.map); + on_unmap.connect(&xdg_toplevel->base->surface->events.unmap); + on_destroy.connect(&xdg_toplevel->base->surface->events.destroy); on_new_popup.connect(&xdg_toplevel->base->events.new_popup); on_ping_timeout.connect(&xdg_toplevel->base->events.ping_timeout); @@ -214,7 +214,7 @@ bool wf::xdg_toplevel_view_t::is_focusable() const 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) @@ -414,10 +414,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); @@ -431,12 +431,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); diff --git a/src/view/xwayland.cpp b/src/view/xwayland.cpp index 95f0558b2..78d52295a 100644 --- a/src/view/xwayland.cpp +++ b/src/view/xwayland.cpp @@ -141,7 +141,7 @@ class xwayland_view_controller_t this->view_base = {dynamic_cast(new_view.get())}; this->view_impl = {new_view}; - if (xw->mapped) + if (xw->surface && xw->surface->mapped) { view_base->on_map.emit(xw->surface); } @@ -250,9 +250,9 @@ 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)) { - auto xw = wlr_xwayland_surface_from_wlr_surface(surface); + auto xw = xwayland_surface; wlr_xwayland_surface_restack(xw, NULL, XCB_STACK_MODE_ABOVE); } diff --git a/src/view/xwayland/xwayland-toplevel-view.hpp b/src/view/xwayland/xwayland-toplevel-view.hpp index 59dbe1657..7dda8e12a 100644 --- a/src/view/xwayland/xwayland-toplevel-view.hpp +++ b/src/view/xwayland/xwayland-toplevel-view.hpp @@ -178,6 +178,16 @@ class wayfire_xwayland_view : public wf::toplevel_view_interface_t, public wayfi toplevel->connect(&on_toplevel_applied); this->priv->toplevel = toplevel; + on_associate.set_callback([&] (void*) + { + handle_associate_request(); + }); + + on_dissociate.set_callback([&] (void*) + { + handle_dissociate_request(); + }); + on_map.set_callback([&] (void*) { handle_map_request(); @@ -261,8 +271,8 @@ class wayfire_xwayland_view : public wf::toplevel_view_interface_t, public wayfi update_decorated(); }); - on_map.connect(&xw->events.map); - on_unmap.connect(&xw->events.unmap); + on_associate.connect(&xw->events.associate); + on_dissociate.connect(&xw->events.dissociate); on_set_parent.connect(&xw->events.set_parent); on_set_hints.connect(&xw->events.set_hints); on_set_decorations.connect(&xw->events.set_decorations); @@ -307,6 +317,8 @@ class wayfire_xwayland_view : public wf::toplevel_view_interface_t, public wayfi { on_map.disconnect(); on_unmap.disconnect(); + on_associate.disconnect(); + on_dissociate.disconnect(); on_set_parent.disconnect(); on_set_hints.disconnect(); on_set_decorations.disconnect(); @@ -351,6 +363,18 @@ class wayfire_xwayland_view : public wf::toplevel_view_interface_t, public wayfi } } + void handle_associate_request() + { + on_map.connect(&xw->surface->events.map); + on_unmap.connect(&xw->surface->events.unmap); + } + + void handle_dissociate_request() + { + on_map.disconnect(); + on_unmap.disconnect(); + } + void handle_map_request() { this->main_surface = std::make_shared(xw->surface, false); diff --git a/src/view/xwayland/xwayland-unmanaged-view.hpp b/src/view/xwayland/xwayland-unmanaged-view.hpp index 1eaaf615e..d5f705c5f 100644 --- a/src/view/xwayland/xwayland-unmanaged-view.hpp +++ b/src/view/xwayland/xwayland-unmanaged-view.hpp @@ -144,11 +144,21 @@ class wayfire_unmanaged_xwayland_view : public wf::view_interface_t, public wayf xw->data = this; role = wf::VIEW_ROLE_UNMANAGED; on_set_geometry.set_callback([&] (void*) { update_geometry_from_xsurface(); }); + 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_map.set_callback([&] (void*) { map(xw->surface); }); on_unmap.set_callback([&] (void*) { unmap(); }); - on_map.connect(&xw->events.map); - on_unmap.connect(&xw->events.unmap); + on_associate.connect(&xw->events.associate); + on_dissociate.connect(&xw->events.dissociate); on_set_geometry.connect(&xw->events.set_geometry); } @@ -206,6 +216,8 @@ class wayfire_unmanaged_xwayland_view : public wf::view_interface_t, public wayf { on_map.disconnect(); on_unmap.disconnect(); + on_associate.disconnect(); + on_dissociate.disconnect(); on_set_geometry.disconnect(); wayfire_xwayland_view_base::destroy(); } diff --git a/src/view/xwayland/xwayland-view-base.hpp b/src/view/xwayland/xwayland-view-base.hpp index 258567069..1ce2e36ca 100644 --- a/src/view/xwayland/xwayland-view-base.hpp +++ b/src/view/xwayland/xwayland-view-base.hpp @@ -114,7 +114,7 @@ class wayfire_xwayland_view_base } } - wf::wl_listener_wrapper on_map, on_unmap; + wf::wl_listener_wrapper on_associate, on_dissociate, on_map, on_unmap; }; #endif diff --git a/subprojects/wlroots b/subprojects/wlroots index 0a32b5a74..dbc7a5cad 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 0a32b5a74db06a27bee55a47205951bb277a9657 +Subproject commit dbc7a5cada37d192821e1104b356ff891b8bd787