quickshell: seamless switching between dropdowns
Remove grabFocus from BarDropdown. Centralized toggleDropdown() closes the active dropdown before opening a new one, so clicking between network/battery/calendar/tray is instant — no double-click. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2b9edcb589
commit
98d1e6249c
1 changed files with 33 additions and 44 deletions
|
|
@ -458,6 +458,25 @@ in
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
color: "#D1${c.base00}"
|
color: "#D1${c.base00}"
|
||||||
|
|
||||||
|
property var activeDropdown: null
|
||||||
|
function closeAllDropdowns() {
|
||||||
|
if (activeDropdown && activeDropdown.visible) {
|
||||||
|
activeDropdown.visible = false;
|
||||||
|
}
|
||||||
|
activeDropdown = null;
|
||||||
|
}
|
||||||
|
function toggleDropdown(dd, setupFn) {
|
||||||
|
if (dd.visible) {
|
||||||
|
dd.visible = false;
|
||||||
|
activeDropdown = null;
|
||||||
|
} else {
|
||||||
|
closeAllDropdowns();
|
||||||
|
if (setupFn) setupFn();
|
||||||
|
dd.visible = true;
|
||||||
|
activeDropdown = dd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Left — workspaces
|
// Left — workspaces
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
@ -519,21 +538,9 @@ in
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (calPopup.justDismissed) return;
|
bar.toggleDropdown(calPopup);
|
||||||
if (calPopup.visible) {
|
|
||||||
calPopup.open = false;
|
|
||||||
calCloseTimer.start();
|
|
||||||
} else {
|
|
||||||
calPopup.visible = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: calCloseTimer
|
|
||||||
interval: 230
|
|
||||||
onTriggered: calPopup.visible = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right — network, battery, tray
|
// Right — network, battery, tray
|
||||||
|
|
@ -653,16 +660,12 @@ in
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (netDropdown.justDismissed) return;
|
bar.toggleDropdown(netDropdown, function() {
|
||||||
if (netDropdown.visible) {
|
|
||||||
netDropdown.visible = false;
|
|
||||||
} else {
|
|
||||||
netWidget.wifiNetworks = [];
|
netWidget.wifiNetworks = [];
|
||||||
wifiScanProc.running = true;
|
wifiScanProc.running = true;
|
||||||
let pos = netWidget.mapToItem(bar.contentItem, netWidget.width / 2, 0);
|
let pos = netWidget.mapToItem(bar.contentItem, netWidget.width / 2, 0);
|
||||||
netDropdown.dropdownX = pos.x;
|
netDropdown.dropdownX = pos.x;
|
||||||
netDropdown.visible = true;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -765,16 +768,12 @@ in
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (batteryDropdown.justDismissed) return;
|
bar.toggleDropdown(batteryDropdown, function() {
|
||||||
if (batteryDropdown.visible) {
|
|
||||||
batteryDropdown.visible = false;
|
|
||||||
} else {
|
|
||||||
batteryProc.running = true;
|
batteryProc.running = true;
|
||||||
profileProc.running = true;
|
profileProc.running = true;
|
||||||
let pos = batteryWidget.mapToItem(bar.contentItem, batteryWidget.width / 2, 0);
|
let pos = batteryWidget.mapToItem(bar.contentItem, batteryWidget.width / 2, 0);
|
||||||
batteryDropdown.dropdownX = pos.x;
|
batteryDropdown.dropdownX = pos.x;
|
||||||
batteryDropdown.visible = true;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -815,13 +814,13 @@ in
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
onClicked: (event) => {
|
onClicked: (event) => {
|
||||||
if (contextMenu.justDismissed) return;
|
|
||||||
if (event.button === Qt.RightButton && modelData.hasMenu) {
|
if (event.button === Qt.RightButton && modelData.hasMenu) {
|
||||||
let pos = parent.mapToItem(bar.contentItem, parent.width / 2, 0);
|
bar.toggleDropdown(contextMenu, function() {
|
||||||
contextMenu.dropdownX = pos.x;
|
let pos = parent.mapToItem(bar.contentItem, parent.width / 2, 0);
|
||||||
contextMenu.trayItem = modelData;
|
contextMenu.dropdownX = pos.x;
|
||||||
menuOpener.menu = modelData.menu;
|
contextMenu.trayItem = modelData;
|
||||||
contextMenu.visible = true;
|
menuOpener.menu = modelData.menu;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
modelData.activate();
|
modelData.activate();
|
||||||
}
|
}
|
||||||
|
|
@ -836,7 +835,6 @@ in
|
||||||
component BarDropdown: PopupWindow {
|
component BarDropdown: PopupWindow {
|
||||||
id: dropdown
|
id: dropdown
|
||||||
property bool open: false
|
property bool open: false
|
||||||
property bool justDismissed: false
|
|
||||||
property real dropdownX: 0
|
property real dropdownX: 0
|
||||||
property real fullWidth: 200
|
property real fullWidth: 200
|
||||||
property real fullHeight: 200
|
property real fullHeight: 200
|
||||||
|
|
@ -848,7 +846,6 @@ in
|
||||||
anchor.edges: Edges.Top | Edges.Left
|
anchor.edges: Edges.Top | Edges.Left
|
||||||
anchor.gravity: Edges.Bottom | Edges.Right
|
anchor.gravity: Edges.Bottom | Edges.Right
|
||||||
anchor.adjustment: PopupAdjustment.Slide
|
anchor.adjustment: PopupAdjustment.Slide
|
||||||
grabFocus: true
|
|
||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
implicitWidth: fullWidth + 16
|
implicitWidth: fullWidth + 16
|
||||||
|
|
@ -859,17 +856,9 @@ in
|
||||||
open = true;
|
open = true;
|
||||||
} else {
|
} else {
|
||||||
open = false;
|
open = false;
|
||||||
justDismissed = true;
|
|
||||||
_dismissGuard.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: _dismissGuard
|
|
||||||
interval: 100
|
|
||||||
onTriggered: dropdown.justDismissed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.right: _dropdownRect.left
|
anchors.right: _dropdownRect.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
@ -1010,7 +999,7 @@ in
|
||||||
enabled: !modelData.isSeparator && modelData.enabled
|
enabled: !modelData.isSeparator && modelData.enabled
|
||||||
onClicked: {
|
onClicked: {
|
||||||
modelData.triggered();
|
modelData.triggered();
|
||||||
contextMenu.visible = false;
|
bar.closeAllDropdowns();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1071,7 +1060,7 @@ in
|
||||||
netWidget.netState = "disconnected";
|
netWidget.netState = "disconnected";
|
||||||
netWidget.netConn = "";
|
netWidget.netConn = "";
|
||||||
netWidget.netIcon = "\u{f05aa}";
|
netWidget.netIcon = "\u{f05aa}";
|
||||||
netDropdown.visible = false;
|
bar.closeAllDropdowns();
|
||||||
netRefreshDelay.start();
|
netRefreshDelay.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1160,7 +1149,7 @@ in
|
||||||
wifiConnectProc.running = true;
|
wifiConnectProc.running = true;
|
||||||
netRefreshDelay.start();
|
netRefreshDelay.start();
|
||||||
}
|
}
|
||||||
netDropdown.visible = false;
|
bar.closeAllDropdowns();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue