fix(controls): popup_window now inherits keyboard focus

This commit is contained in:
Ly-sec
2026-05-07 12:21:11 +02:00
parent 730bea8d53
commit 25fc1eabff
3 changed files with 47 additions and 1 deletions
+4
View File
@@ -30,6 +30,7 @@
#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"
@@ -808,6 +809,9 @@ 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()) {
m_settingsWindow.onKeyboardEvent(event);
+37 -1
View File
@@ -18,6 +18,11 @@ namespace {
} // namespace
std::vector<PopupWindow*>& PopupWindow::openPopups() {
static std::vector<PopupWindow*> popups;
return popups;
}
PopupWindow::PopupWindow(WaylandConnection& wayland, RenderContext& renderContext)
: m_wayland(wayland), m_renderContext(renderContext) {}
@@ -64,9 +69,17 @@ void PopupWindow::openCommon(PopupSurfaceConfig config, zwlr_layer_surface_v1* p
const bool needsSceneBuild = self->m_sceneRoot == nullptr ||
static_cast<std::uint32_t>(std::round(self->m_sceneRoot->width())) != width ||
static_cast<std::uint32_t>(std::round(self->m_sceneRoot->height())) != height;
if (needsSceneBuild || needsLayout) {
if (needsSceneBuild) {
UiPhaseScope layoutPhase(UiPhase::Layout);
self->buildScene(width, height);
return;
}
if (needsLayout && self->m_sceneRoot != nullptr) {
UiPhaseScope layoutPhase(UiPhase::Layout);
self->m_sceneRoot->setSize(static_cast<float>(width), static_cast<float>(height));
self->m_sceneRoot->layout(self->m_renderContext);
self->m_surface->setSceneRoot(self->m_sceneRoot.get());
}
});
@@ -81,6 +94,7 @@ void PopupWindow::openCommon(PopupSurfaceConfig config, zwlr_layer_surface_v1* p
}
m_wlSurface = m_surface->wlSurface();
openPopups().push_back(this);
}
void PopupWindow::buildScene(std::uint32_t width, std::uint32_t height) {
@@ -109,6 +123,8 @@ void PopupWindow::buildScene(std::uint32_t width, std::uint32_t height) {
void PopupWindow::close() {
const bool wasOpen = m_surface != nullptr;
auto& popups = openPopups();
popups.erase(std::remove(popups.begin(), popups.end(), this), popups.end());
m_sceneRoot.reset();
m_surface.reset();
m_inputDispatcher.setSceneRoot(nullptr);
@@ -209,6 +225,26 @@ void PopupWindow::requestRedraw() {
}
}
bool PopupWindow::dispatchKeyboardEvent(wl_surface* keyboardSurface, const KeyboardEvent& event) {
if (keyboardSurface == nullptr) {
return false;
}
auto& popups = openPopups();
for (auto it = popups.rbegin(); it != popups.rend(); ++it) {
auto* popup = *it;
if (popup == nullptr || !popup->isOpen()) {
continue;
}
if (popup->wlSurface() == keyboardSurface) {
popup->onKeyboardEvent(event);
return true;
}
}
return false;
}
PopupSurfaceConfig PopupWindow::makeConfig(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, AnchorMode mode, std::int32_t offsetX,
+6
View File
@@ -5,6 +5,7 @@
#include <functional>
#include <memory>
#include <vector>
class Node;
class PopupSurface;
@@ -47,6 +48,9 @@ public:
void requestLayout();
void requestRedraw();
// Dispatch keyboard events to the popup that currently owns the provided Wayland keyboard surface.
[[nodiscard]] static bool dispatchKeyboardEvent(wl_surface* keyboardSurface, const KeyboardEvent& event);
[[nodiscard]] static PopupSurfaceConfig makeConfig(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,
@@ -69,4 +73,6 @@ private:
ContentBuilder m_contentBuilder;
SceneReadyCallback m_sceneReadyCallback;
std::function<void()> m_onDismissed;
static std::vector<PopupWindow*>& openPopups();
};