diff --git a/Modules/MainScreen/PopupMenuWindow.qml b/Modules/MainScreen/PopupMenuWindow.qml index 10d580842..ce29d0231 100644 --- a/Modules/MainScreen/PopupMenuWindow.qml +++ b/Modules/MainScreen/PopupMenuWindow.qml @@ -29,10 +29,13 @@ PanelWindow { // Use Top layer (same as MainScreen) for proper event handling WlrLayershell.layer: WlrLayer.Top - WlrLayershell.keyboardFocus: WlrKeyboardFocus.None + WlrLayershell.keyboardFocus: hasDialog ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None WlrLayershell.namespace: "noctalia-" + windowType + "-" + (screen?.name || "unknown") WlrLayershell.exclusionMode: ExclusionMode.Ignore + // Track if a dialog is currently open (needed for keyboard focus) + property bool hasDialog: false + // Register with PanelService so widgets can find this window Component.onCompleted: { objectName = "popupMenuWindow-" + (screen?.name || "unknown"); diff --git a/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml index 44ced4703..e23700d86 100644 --- a/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml @@ -29,6 +29,8 @@ Popup { if (widgetData && widgetId) { loadWidgetSettings(); } + // Request focus to ensure keyboard input works + forceActiveFocus(); } background: Rectangle { @@ -40,71 +42,108 @@ Popup { border.width: Style.borderM } - contentItem: ColumnLayout { - id: content + contentItem: FocusScope { + id: focusScope + focus: true - width: parent.width - spacing: Style.marginM - - // Title - RowLayout { - Layout.fillWidth: true - - NText { - text: I18n.tr("system.widget-settings-title", { - "widget": root.widgetId - }) - pointSize: Style.fontSizeL - font.weight: Style.fontWeightBold - color: Color.mPrimary - Layout.fillWidth: true - } - - NIconButton { - icon: "close" - tooltipText: I18n.tr("tooltips.close") - onClicked: root.close() - } - } - - // Separator - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - color: Color.mOutline - } - - // Settings based on widget type - // Will be triggered via settingsLoader.setSource() - Loader { - id: settingsLoader - Layout.fillWidth: true - } - - // Action buttons - RowLayout { - Layout.fillWidth: true - Layout.topMargin: Style.marginM + ColumnLayout { + id: content + anchors.fill: parent spacing: Style.marginM - Item { + // Title + RowLayout { Layout.fillWidth: true + + NText { + text: I18n.tr("system.widget-settings-title", { + "widget": root.widgetId + }) + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mPrimary + Layout.fillWidth: true + } + + NIconButton { + icon: "close" + tooltipText: I18n.tr("tooltips.close") + onClicked: root.close() + } } - NButton { - text: I18n.tr("bar.widget-settings.dialog.cancel") - outlined: true - onClicked: root.close() + // Separator + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline } - NButton { - text: I18n.tr("bar.widget-settings.dialog.apply") - icon: "check" - onClicked: { - if (settingsLoader.item && settingsLoader.item.saveSettings) { - var newSettings = settingsLoader.item.saveSettings(); - root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings); - root.close(); + // Settings based on widget type + // Will be triggered via settingsLoader.setSource() + Loader { + id: settingsLoader + Layout.fillWidth: true + onLoaded: { + // Try to focus the first focusable item in the loaded settings + if (item) { + Qt.callLater(() => { + var firstInput = findFirstFocusable(item); + if (firstInput) { + firstInput.forceActiveFocus(); + } else { + focusScope.forceActiveFocus(); + } + }); + } + } + + function findFirstFocusable(item) { + if (!item) + return null; + // Check if this item can accept focus + if (item.focus !== undefined && item.focus === true) + return item; + // Check children + if (item.children) { + for (var i = 0; i < item.children.length; i++) { + var child = item.children[i]; + if (child && child.focus !== undefined && child.focus === true) + return child; + var found = findFirstFocusable(child); + if (found) + return found; + } + } + return null; + } + } + + // Action buttons + RowLayout { + Layout.fillWidth: true + Layout.topMargin: Style.marginM + spacing: Style.marginM + + Item { + Layout.fillWidth: true + } + + NButton { + text: I18n.tr("bar.widget-settings.dialog.cancel") + outlined: true + onClicked: root.close() + } + + NButton { + text: I18n.tr("bar.widget-settings.dialog.apply") + icon: "check" + onClicked: { + if (settingsLoader.item && settingsLoader.item.saveSettings) { + var newSettings = settingsLoader.item.saveSettings(); + root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings); + root.close(); + } } } } diff --git a/Services/UI/BarService.qml b/Services/UI/BarService.qml index 13781c9a1..ceea242f2 100644 --- a/Services/UI/BarService.qml +++ b/Services/UI/BarService.qml @@ -330,8 +330,11 @@ Singleton { Settings.saveImmediate(); } }); + // Enable keyboard focus for the popup menu window when dialog is open + popupMenuWindow.hasDialog = true; // Close the popup menu window when dialog closes dialog.closed.connect(() => { + popupMenuWindow.hasDialog = false; popupMenuWindow.close(); dialog.destroy(); });