diff --git a/meson.build b/meson.build index ebe11b8ce..a75d76409 100644 --- a/meson.build +++ b/meson.build @@ -551,7 +551,6 @@ _noctalia_sources = files( 'src/ui/controls/label.cpp', 'src/ui/controls/list_editor.cpp', 'src/ui/controls/progress_bar.cpp', - 'src/ui/controls/popup_window.cpp', 'src/ui/controls/radio_button.cpp', 'src/ui/controls/scroll_view.cpp', 'src/ui/controls/search_picker.cpp', diff --git a/src/app/application.cpp b/src/app/application.cpp index 2f414cfa0..aa070bbe8 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -30,7 +30,6 @@ #include "system/distro_info.h" #include "time/time_format.h" #include "ui/controls/input.h" -#include "ui/controls/popup_window.h" #include "ui/dialogs/color_picker_dialog.h" #include "ui/dialogs/file_dialog.h" #include "ui/dialogs/glyph_picker_dialog.h" @@ -809,11 +808,7 @@ void Application::initUi() { m_fileDialogPopup.onKeyboardEvent(event); return; } - if (PopupWindow::dispatchKeyboardEvent(m_wayland.lastKeyboardSurface(), event)) { - return; - } - if (m_settingsWindow.isOpen() && m_settingsWindow.wlSurface() != nullptr && - m_wayland.lastKeyboardSurface() == m_settingsWindow.wlSurface()) { + if (m_settingsWindow.ownsKeyboardSurface(m_wayland.lastKeyboardSurface())) { m_settingsWindow.onKeyboardEvent(event); return; } diff --git a/src/shell/settings/settings_window.cpp b/src/shell/settings/settings_window.cpp index 10f886ae1..235f10329 100644 --- a/src/shell/settings/settings_window.cpp +++ b/src/shell/settings/settings_window.cpp @@ -199,6 +199,16 @@ float SettingsWindow::uiScale() const { return std::max(0.1f, m_config->config().shell.uiScale); } +bool SettingsWindow::ownsKeyboardSurface(wl_surface* surface) const noexcept { + if (!isOpen() || surface == nullptr || m_surface == nullptr) { + return false; + } + if (surface == m_surface->wlSurface()) { + return true; + } + return m_widgetAddPopup != nullptr && m_widgetAddPopup->wlSurface() == surface; +} + void SettingsWindow::open() { if (m_wayland == nullptr || m_renderContext == nullptr || !m_wayland->hasXdgShell()) { return; @@ -483,7 +493,8 @@ void SettingsWindow::openBarWidgetAddPopup(const std::vector& laneP } if (m_widgetAddPopup == nullptr) { - m_widgetAddPopup = std::make_unique(*m_wayland, *m_renderContext); + m_widgetAddPopup = std::make_unique(); + m_widgetAddPopup->initialize(*m_wayland, *m_config, *m_renderContext); m_widgetAddPopup->setOnSelect([this](const std::vector& selectedLanePath, const std::string& value) { if (value.empty() || m_config == nullptr) { return; @@ -516,8 +527,8 @@ void SettingsWindow::openBarWidgetAddPopup(const std::vector& laneP output = m_output; } - m_widgetAddPopup->open(m_surface->xdgSurface(), output, m_wayland->lastInputSerial(), anchorButton, lanePath, - m_config->config(), uiScale(), PopupWindow::AnchorMode::CenterOnAnchor); + m_widgetAddPopup->open(m_surface->xdgSurface(), output, m_wayland->lastInputSerial(), anchorButton, + m_surface->wlSurface(), lanePath, m_config->config(), uiScale()); } void SettingsWindow::saveSupportReport() { diff --git a/src/shell/settings/settings_window.h b/src/shell/settings/settings_window.h index 573806623..79329948a 100644 --- a/src/shell/settings/settings_window.h +++ b/src/shell/settings/settings_window.h @@ -41,6 +41,7 @@ public: [[nodiscard]] wl_surface* wlSurface() const noexcept { return m_surface != nullptr ? m_surface->wlSurface() : nullptr; } + [[nodiscard]] bool ownsKeyboardSurface(wl_surface* surface) const noexcept; [[nodiscard]] bool onPointerEvent(const PointerEvent& event); void onKeyboardEvent(const KeyboardEvent& event); diff --git a/src/shell/settings/widget_add_popup.cpp b/src/shell/settings/widget_add_popup.cpp index e92724ecd..d91384f30 100644 --- a/src/shell/settings/widget_add_popup.cpp +++ b/src/shell/settings/widget_add_popup.cpp @@ -1,7 +1,10 @@ #include "shell/settings/widget_add_popup.h" #include "config/config_service.h" +#include "core/deferred_call.h" #include "i18n/i18n.h" +#include "render/render_context.h" +#include "render/scene/input_area.h" #include "render/scene/node.h" #include "shell/settings/widget_settings_registry.h" #include "ui/controls/button.h" @@ -10,9 +13,10 @@ #include "ui/palette.h" #include "ui/style.h" #include "wayland/wayland_connection.h" -#include "wayland/wayland_seat.h" +#include "xdg-shell-client-protocol.h" #include +#include #include #include #include @@ -44,31 +48,51 @@ namespace settings { return label; } + PopupSurfaceConfig makePopupConfig(std::int32_t anchorX, std::int32_t anchorY, std::int32_t anchorWidth, + std::int32_t anchorHeight, std::uint32_t width, std::uint32_t height, + std::uint32_t serial, std::int32_t offsetX = 0, std::int32_t offsetY = 0, + bool grab = true) { + PopupSurfaceConfig cfg{ + .anchorX = anchorX, + .anchorY = anchorY, + .anchorWidth = std::max(1, anchorWidth), + .anchorHeight = std::max(1, anchorHeight), + .width = std::max(1, width), + .height = std::max(1, height), + .anchor = XDG_POSITIONER_ANCHOR_BOTTOM, + .gravity = XDG_POSITIONER_GRAVITY_BOTTOM, + .constraintAdjustment = + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y | + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y, + .offsetX = offsetX, + .offsetY = offsetY, + .serial = serial, + .grab = grab, + }; + + cfg.anchorX += cfg.anchorWidth / 2; + cfg.anchorY += cfg.anchorHeight / 2; + cfg.anchorWidth = 1; + cfg.anchorHeight = 1; + return cfg; + } + } // namespace - WidgetAddPopup::WidgetAddPopup(WaylandConnection& wayland, RenderContext& renderContext) - : m_wayland(wayland), m_renderContext(renderContext), - m_popup(std::make_unique(wayland, renderContext)) { - m_popup->setOnDismissed([this]() { - m_lanePath.clear(); - m_searchPicker = nullptr; - m_focusSearchOnOpen = false; - if (m_onDismissed) { - m_onDismissed(); - } - }); - } + WidgetAddPopup::~WidgetAddPopup() { destroyPopup(); } - WidgetAddPopup::~WidgetAddPopup() = default; + void WidgetAddPopup::initialize(WaylandConnection& wayland, ConfigService& config, RenderContext& renderContext) { + initializeBase(wayland, config, renderContext); + } void WidgetAddPopup::setOnSelect(SelectCallback callback) { m_onSelect = std::move(callback); } void WidgetAddPopup::setOnDismissed(std::function callback) { m_onDismissed = std::move(callback); } void WidgetAddPopup::open(xdg_surface* parentXdgSurface, wl_output* output, std::uint32_t serial, - Button* anchorButton, const std::vector& lanePath, const Config& config, - float scale, PopupWindow::AnchorMode anchorMode) { - if (m_popup == nullptr || parentXdgSurface == nullptr || anchorButton == nullptr) { + Button* anchorButton, wl_surface* parentWlSurface, const std::vector& lanePath, + const Config& config, float scale) { + if (parentXdgSurface == nullptr || parentWlSurface == nullptr || anchorButton == nullptr) { return; } @@ -103,133 +127,131 @@ namespace settings { return; } + if (isOpen()) { + close(); + } + + m_scale = std::max(0.1f, scale); + m_options = std::move(options); m_lanePath = lanePath; m_searchPicker = nullptr; + m_root = nullptr; - const float panelPadding = Style::spaceSm * scale; - const float panelGap = Style::spaceSm * scale; - const float panelWidth = 520.0f * scale; - const float panelHeight = 420.0f * scale; - - m_popup->setContentBuilder([this, options, panelPadding, panelGap, scale](float width, float height) { - auto root = std::make_unique(); - root->setDirection(FlexDirection::Vertical); - root->setAlign(FlexAlign::Stretch); - root->setGap(panelGap); - root->setPadding(panelPadding); - root->setFill(colorSpecFromRole(ColorRole::Surface)); - root->setBorder(colorSpecFromRole(ColorRole::Outline, 0.35f), Style::borderWidth); - root->setRadius(Style::radiusLg); - root->setSize(width, height); - - auto header = std::make_unique(); - header->setDirection(FlexDirection::Horizontal); - header->setAlign(FlexAlign::Center); - header->setGap(Style::spaceSm * scale); - header->addChild(makeLabel(i18n::tr("settings.entities.widget.inspector.add-title", "lane", - laneLabel(m_lanePath.empty() ? "" : m_lanePath.back())), - Style::fontSizeBody * scale, colorSpecFromRole(ColorRole::OnSurface), true)); - - auto spacer = std::make_unique(); - spacer->setFlexGrow(1.0f); - header->addChild(std::move(spacer)); - - auto closeBtn = std::make_unique