Merge pull request 'windowSwitcher' (#2) from windowSwitcher into master

Reviewed-on: #2
This commit is contained in:
2025-10-13 19:58:12 +00:00
5 changed files with 182 additions and 43 deletions

5
Common/Shortcuts.qml Normal file
View File

@@ -0,0 +1,5 @@
import Quickshell.Hyprland
GlobalShortcut {
appid: "quickbar"
}

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
import QtQuick
import Quickshell import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Wayland import Quickshell.Wayland
@@ -70,28 +71,31 @@ Singleton {
return sortedTopLevels.map(topLevel => topLevel.workspace); return sortedTopLevels.map(topLevel => topLevel.workspace);
} }
property var sortedDesktopApplications: { property ListModel sortedDesktopApplicationsModel: ListModel {}
const sortedWayland = sortedTopLevels.map(topLevel => topLevel.wayland).filter(wayland => wayland !== null);
const desktopEntries = sortedWayland.map(topLevel => { onSortedTopLevelsChanged: updateSortedDesktopApplications()
return DesktopEntries.heuristicLookup(topLevel.appId);
});
const workspace = sortedTopLevels.map(topLevel => {
return topLevel.workspace.id;
});
const workspaceDesktopEntries = new Map();
for (let i = 0; i < workspace.length; i++) { function updateSortedDesktopApplications() {
const key = workspace[i]; sortedDesktopApplicationsModel.clear();
const value = desktopEntries[i];
if (workspaceDesktopEntries.has(key)) { for (const topLevel of sortedTopLevels) {
workspaceDesktopEntries.get(key).push(value); const entry = DesktopEntries.heuristicLookup(topLevel.wayland.appId);
} else { sortedDesktopApplicationsModel.append({
workspaceDesktopEntries.set(key, [value]); topLevel: topLevel,
} desktopEntry: entry
});
} }
return workspaceDesktopEntries; }
function workspaceApps(workspaceIndexAlign) {
const list = [];
const model = sortedDesktopApplicationsModel;
for (let i = 0; i < model.count; i++) {
const item = model.get(i);
if (item.topLevel.workspace.id === workspaceIndexAlign)
list.push(item.desktopEntry);
}
return list;
} }
Socket { Socket {

View File

@@ -62,13 +62,13 @@ Singleton {
StyledText { StyledText {
text: { text: {
if (!HoverMediator.component?.model) if (!HoverMediator.component?.model)
return ""; return "";
if (HoverMediator.component.model.tooltipTitle) if (HoverMediator.component.model.tooltipTitle)
return HoverMediator.component.model.tooltipTitle; return HoverMediator.component.model.tooltipTitle;
if (HoverMediator.component.model.title) if (HoverMediator.component.model.title)
return HoverMediator.component.model.title; return HoverMediator.component.model.title;
else else
return ""; return "";
} }
} }
} }
@@ -76,7 +76,7 @@ Singleton {
Component { Component {
id: time id: time
RowLayout{ RowLayout {
id: rowlayoutCalendar id: rowlayoutCalendar
readonly property date now: new Date() readonly property date now: new Date()
@@ -132,9 +132,7 @@ Singleton {
Repeater { Repeater {
property var modelo: HyprlandService.sortedDesktopApplications.get(parent.workspaceIndexAlign) model: HyprlandService.workspaceApps(parent.workspaceIndexAlign)
model: modelo
delegate: IconImage { delegate: IconImage {
required property var modelData required property var modelData
@@ -172,15 +170,15 @@ Singleton {
id: hoverLoader id: hoverLoader
sourceComponent: { sourceComponent: {
if (!HoverMediator.type) if (!HoverMediator.type)
return stub; return stub;
if (HoverMediator.type === "workspace") if (HoverMediator.type === "workspace")
return workspaceComponent; return workspaceComponent;
if (HoverMediator.type === "audio") if (HoverMediator.type === "audio")
return audio; return audio;
if (HoverMediator.type === "time") if (HoverMediator.type === "time")
return time; return time;
if (HoverMediator.type === "systray") if (HoverMediator.type === "systray")
return systray; return systray;
} }
} }
} }

122
Widgets/WindowSwitcher.qml Normal file
View File

@@ -0,0 +1,122 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import qs.Services
import qs.Common.Styled
import qs.Common
import Quickshell.Wayland
PanelWindow {
id: root
anchors {
left: true
bottom: true
right: true
top: true
}
implicitWidth: screen.width
// implicitWidth: 400
implicitHeight: screen.height
color: "transparent"
visible: true
signal clear
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
MouseArea {
anchors.fill: parent
onClicked: root.clear()
}
Rectangle {
id: notifWindow
anchors.centerIn:parent
implicitHeight: 300
implicitWidth: listview.contentWidth
color: "transparent"
ListView {
id: listview
anchors.fill: parent
clip: true
spacing: 5
orientation: ListView.Horizontal
focus:true
highlight: Rectangle { color: "black"; radius: 5 }
highlightFollowsCurrentItem: true
keyNavigationEnabled: false
Keys.onPressed: (event) => {
switch (event.key) {
case Qt.Key_L: // move down
case Qt.Key_D:
if (currentIndex < count - 1)
currentIndex++
event.accepted = true
break
case Qt.Key_H: // move up
case Qt.Key_A:
if (currentIndex > 0)
currentIndex--
event.accepted = true
break
case Qt.Key_Return:
currentItem.activate()
event.accepted = true
break
case Qt.Key_Escape:
root.clear()
break
}
}
model: HyprlandService.sortedDesktopApplicationsModel
delegate: Rectangle {
required property var modelData
implicitHeight: 300
implicitWidth: 300
color: "transparent"
function activate() {
modelData.topLevel.wayland.activate()
root.clear()
}
MouseArea {
anchors.fill: parent
onClicked: activate()
}
ScreencopyView {
anchors.fill: parent
live: true
captureSource: modelData.topLevel.wayland
}
IconImage {
anchors.bottom: parent.bottom
property int workspaceId: modelData.topLevel.workspace.id
property var desktopEntry: modelData.desktopEntry
width: 30
height: 30
source: (modelData && desktopEntry.icon) ? Quickshell.iconPath(desktopEntry.icon, 1) : "aaa"
}
}
}
}
}

View File

@@ -1,20 +1,13 @@
//@ pragma UseQApplication //@ pragma UseQApplication
import Quickshell import Quickshell
import qs.Widgets
import qs.Common
import qs.Services
ShellRoot { ShellRoot {
// Bar { id: root
// modelData: Quickshell.screens.values[0]
// barComponentsLeft: ["NotificationsWidget.qml"]
// barComponentsCenter: ["Workspaces.qml"]
// barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"]
// }
// Bar { property bool createWindow: false
// panelMonitor: "DP-2"
// barComponentsLeft: []
// barComponentsCenter: ["Workspaces.qml"]
// barComponentsRight: ["AudioWidget.qml", "ClockWidget.qml"]
// }
Variants { Variants {
model: Quickshell.screens model: Quickshell.screens
@@ -25,4 +18,21 @@ ShellRoot {
barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"] barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"]
} }
} }
Shortcuts {
name: "showAltTab"
onPressed: {
root.createWindow = !root.createWindow;
}
}
LazyLoader {
id: windowLoader
active: root.createWindow
component: WindowSwitcher {
onClear: root.createWindow = false
}
}
} }