Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions barstyles/imi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ Ported and adapted from the Immaterial Impulse dotfiles (end-4).
- **Weather Widget** — Current conditions, hourly forecast chart, and multi-day outlook via popout card.
- **Calendar Popout** — Clock + calendar grid popout with locale-aware formatting.
- **Privacy Indicator** — Mic, camera, and screencast status chips that appear/disappear with smooth animations.
- **Submap Indicator** — Hyprland keybind submap pill (e.g. resize mode) with auto-hide.
- **Submap Indicator** — Hyprland keybind submap pill (e.g. resize mode) with auto-hide. Hidden on other compositors.
- **Autohide Bar** — Optional hover-reveal bar with Super-hold peek, overlay mode (windows ignore it) or push mode (windows make room), and popups that hold the bar out while open.
- **System Tray** — Collapsible tray icons with overflow.
- **Matugen Theming** — Full dynamic color palette from Ryoku's Matugen integration.
- **Edit Mode** — Drag-and-drop widget reordering via Bar Studio.
- **Edit Mode** — Drag-and-drop widget reordering via Bar Studio. Double-click the bar to open its own edit mode: `+` adds widgets and holds the autohide switch.
- **Multi-Monitor** — Per-output Scopes with boundary-aware popout positioning.

## Configuration
Expand All @@ -36,11 +37,26 @@ value changes apply without restarting the shell:
| `bar.layouts.left` | Widget order for the left pill | `[...]` |
| `bar.layouts.center` | Widget order for the center pill | `[...]` |
| `bar.layouts.right` | Widget order for the right pill | `[...]` |
| `bar.autoHide.enable` | Slide the bar away until the pointer hits the screen edge | `false` |
| `bar.autoHide.hoverRegionWidth` | Reveal-strip height in px at the screen edge | `2` |
| `bar.autoHide.pushWindows` | Reserve bar space when shown (`false` = bar overlays windows) | `false` |
| `bar.autoHide.dismissPopups` | Keep the bar out while a bar popup is open, closing the popup on pointer-leave | `true` |
| `bar.autoHide.showWhenPressingSuper.enable` | Peek the bar while Super is held | `true` |
| `bar.autoHide.showWhenPressingSuper.delay` | Hold delay in ms before the peek shows | `140` |

## Compositor support

Imi reads all window-manager state (workspaces, focused window, fullscreen)
through the shell's compositor-neutral facade, so it runs on **Hyprland** and
**niri** alike. Compositor-specific extras degrade gracefully elsewhere: the
keybind submap pill and scratchpad handling only appear on Hyprland, and
focus-grab dismissal of pinned popups falls back to toggle-off on other
compositors.

## Dependencies

- **Ryoku Desktop Shell** (Quickshell-based)
- **Hyprland** compositor
- **Hyprland** or **niri** compositor
- **PipeWire** (for audio visualizer)
- **Python 3** (installer only)

Expand Down
148 changes: 140 additions & 8 deletions barstyles/imi/Scene.qml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ Scope {
screen: root.modelData

color: "transparent"
exclusionMode: ExclusionMode.Normal
exclusiveZone: 48
exclusionMode: ExclusionMode.Ignore
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
WlrLayershell.namespace: "ryoku-imi"
Expand All @@ -34,14 +33,79 @@ Scope {

implicitHeight: 48

ImiBar.BarContent {
id: barContent
readonly property bool autoHide: Config.options.bar.autoHide.enable ?? false
property bool superShow: false
property bool mustShow: !win.autoHide || hoverRegion.containsMouse || win.superShow
|| GlobalStates.editMode
|| ((GlobalStates.mediaControlsOpen || GlobalStates.sysTrayOverflowOpen) && (Config.options.bar.autoHide.dismissPopups ?? true))

property QtObject barSpaceReserver: ImiBar.BarExclusiveZoneReserver {
screen: root.modelData
barNamespace: "ryoku-imi"
farEdge: false
edgeMargin: 0
zone: (!win.autoHide || (win.mustShow && (Config.options.bar.autoHide.pushWindows ?? false))) ? win.implicitHeight : 0
}

mask: Region {
item: hoverMaskRegion
}

Timer {
id: showBarTimer
interval: (Config?.options.bar.autoHide.showWhenPressingSuper.delay ?? 100)
repeat: false
onTriggered: {
win.superShow = true
}
}
Connections {
target: GlobalStates
function onSuperDownChanged() {
if (!Config?.options.bar.autoHide.showWhenPressingSuper.enable) return;
if (GlobalStates.superDown) showBarTimer.restart();
else {
showBarTimer.stop();
win.superShow = false;
}
}
}

MouseArea {
id: hoverRegion
anchors.fill: parent
hoverEnabled: true

Item {
id: hoverMaskRegion
readonly property real reveal: (Config.options.bar.autoHide.hoverRegionWidth ?? 2)
readonly property real rawTop: barContent.y - reveal
readonly property real rawBottom: barContent.y + barContent.height + reveal

x: 0
width: parent.width
y: Math.max(0, rawTop)
height: Math.max(0, Math.min(parent.height, rawBottom) - y)
}

TapHandler {
acceptedButtons: Qt.LeftButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onDoubleTapped: GlobalStates.editMode = !GlobalStates.editMode
ImiBar.BarContent {
id: barContent
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: (win.autoHide && !win.mustShow) ? -height : 0
}
height: win.implicitHeight
Behavior on anchors.topMargin {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}

TapHandler {
acceptedButtons: Qt.LeftButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onDoubleTapped: GlobalStates.editMode = !GlobalStates.editMode
}
}
}
}
Expand Down Expand Up @@ -222,6 +286,74 @@ Scope {
}
}
}

Rectangle {
width: pickerColumn.width
height: 1
color: Appearance.m3colors.m3outlineVariant
opacity: 0.5
}

Rectangle {
id: autoHideRow
width: pickerColumn.width
height: 36
radius: 8
color: autoHideHover.hovered ? Appearance.m3colors.m3surfaceContainerHigh : "transparent"

HoverHandler { id: autoHideHover }

readonly property bool autoHideOn: Config.options.bar.autoHide.enable ?? false

RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
spacing: 8

Text {
text: "visibility_off"
font.family: "Material Symbols Rounded"
font.pixelSize: 18
color: Appearance.m3colors.m3onSurfaceVariant
Layout.alignment: Qt.AlignVCenter
}
Text {
text: "Autohide bar"
color: Appearance.m3colors.m3onSurface
font.pixelSize: 13
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: 34
height: 20
radius: 10
color: autoHideRow.autoHideOn ? Appearance.m3colors.m3primary : Appearance.m3colors.m3surfaceContainerHigh
border.width: autoHideRow.autoHideOn ? 0 : 1
border.color: Appearance.m3colors.m3outline

Rectangle {
width: 14
height: 14
radius: 7
anchors.verticalCenter: parent.verticalCenter
x: autoHideRow.autoHideOn ? parent.width - width - 3 : 3
color: autoHideRow.autoHideOn ? Appearance.m3colors.m3onPrimary : Appearance.m3colors.m3onSurfaceVariant
Behavior on x {
NumberAnimation { duration: 150 }
}
}
}
}

MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: Config.options.bar.autoHide.enable = !autoHideRow.autoHideOn
}
}
}
}
}
Expand Down
49 changes: 25 additions & 24 deletions barstyles/imi/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"schema": 1,
"id": "imi",
"category": "barstyles",
"version": "1.0.1",
"version": "1.1.0",
"destination": "ryoku/barstyles/imi",
"files": [
{
Expand Down Expand Up @@ -41,16 +41,16 @@
"source": "README.md",
"destination": "README.md",
"mode": "0644",
"size": 4156,
"sha256": "93a025e3621c181c89afa1d4353c76db193753736c6571603f54f55033d8e3a3",
"size": 5490,
"sha256": "e8f8a84493ea13d7dd4e01a1685643a79a6f2a26051e28162798a46da46dfa4a",
"install": true
},
{
"source": "Scene.qml",
"destination": "Scene.qml",
"mode": "0644",
"size": 8019,
"sha256": "ceea20306e1dbbebc0ab550a704f9619e9813af9b39f958b114a92355951a78a",
"size": 13552,
"sha256": "6b518b3f576236d4ee86b4302c47d862c5fb22223c3e6e54ae8d5b39e83a967c",
"install": true
},
{
Expand Down Expand Up @@ -409,8 +409,8 @@
"source": "modules/common/models/WorkspaceModel.qml",
"destination": "modules/common/models/WorkspaceModel.qml",
"mode": "0644",
"size": 2892,
"sha256": "51f454f46980ee60ad843a7eb52aa4c6414ddc0bccd1123836fbcdf6aa3e0432",
"size": 5094,
"sha256": "e4369db17058a2f761a4e2911098d085dcd470400fb0496b4cce050c886488ae",
"install": true
},
{
Expand Down Expand Up @@ -729,8 +729,8 @@
"source": "modules/common/widgets/DockContextMenu.qml",
"destination": "modules/common/widgets/DockContextMenu.qml",
"mode": "0644",
"size": 13668,
"sha256": "5b0a0da7e3ca350f9cae52b70e8c44f8bdd9a532007f01badba3d91af1adbc80",
"size": 13718,
"sha256": "fdd323c4b322eb194fecdf012771d802f048d22dd80bd55ab75b4c8f21ceec8c",
"install": true
},
{
Expand Down Expand Up @@ -1385,16 +1385,16 @@
"source": "modules/imi/bar/ActiveWindow.qml",
"destination": "modules/imi/bar/ActiveWindow.qml",
"mode": "0644",
"size": 3257,
"sha256": "64702e867ff34018fdbe4a6866fa6c5a8542e43551f2b32f206ea512d8dc4736",
"size": 3533,
"sha256": "5db493446b315bded584bb84411a04cac5c1a92a9cd6176fe5c3e7d85bfbe166",
"install": true
},
{
"source": "modules/imi/bar/Bar.qml",
"destination": "modules/imi/bar/Bar.qml",
"mode": "0644",
"size": 25837,
"sha256": "83c8539f3669d1270bc2490e03573299d46fb3227f7338de872d3f4a0713937a",
"size": 25844,
"sha256": "6312f4faf6563207e2ac47e08a47e5228195633af241edfb93977739acec797e",
"install": true
},
{
Expand Down Expand Up @@ -1449,8 +1449,8 @@
"source": "modules/imi/bar/BarPopupOverlay.qml",
"destination": "modules/imi/bar/BarPopupOverlay.qml",
"mode": "0644",
"size": 32916,
"sha256": "147ccd2872c67f5dd1d974c6625dc5f42f0fc5ca1f12ffc22ad7f400888580a7",
"size": 32960,
"sha256": "072a09e6c9385ef26bca6b0bae2809d622a4da6eae9aeb561cb0e2bfa990cfd2",
"install": true
},
{
Expand Down Expand Up @@ -1777,8 +1777,8 @@
"source": "modules/imi/bar/Workspaces.qml",
"destination": "modules/imi/bar/Workspaces.qml",
"mode": "0644",
"size": 17846,
"sha256": "8e83f1aa4c6d805a78d8e72fee52d3afc711040cb267fe2dda15530b872bdc40",
"size": 17946,
"sha256": "93546b1fa78f67eff6a25f22702c77e03206ef8f64159c67b0835d8dbfd1844f",
"install": true
},
{
Expand Down Expand Up @@ -1817,8 +1817,8 @@
"source": "modules/imi/editMode/EditModeChrome.qml",
"destination": "modules/imi/editMode/EditModeChrome.qml",
"mode": "0644",
"size": 4919,
"sha256": "9084da67ea5e0712b1e95489178ac47abfc30687b7bf044eb549c389b7bb096f",
"size": 4914,
"sha256": "e0fff46bddb4d075cdf4b359831b4bbe3b08a21334585515facf61a6f7881a7a",
"install": true
},
{
Expand Down Expand Up @@ -2089,8 +2089,8 @@
"source": "services/HyprlandData.qml",
"destination": "services/HyprlandData.qml",
"mode": "0644",
"size": 2375,
"sha256": "efd2f8c55320763b4bcb91ad56ab5d9b0a66ff3b6b5826cc909389caabd4dcb5",
"size": 2640,
"sha256": "c202a4da04e6dd3a3db3009e06d64a6a1ee918016ebc52ce88fd5b0e497182f3",
"install": true
},
{
Expand Down Expand Up @@ -2321,8 +2321,8 @@
"source": "services/WM.qml",
"destination": "services/WM.qml",
"mode": "0644",
"size": 1785,
"sha256": "f90c21dbd4524f1dd04252c9fc6467bd437748bf6f7f2fe8ddadd083e2904192",
"size": 4437,
"sha256": "ddf66fb7fc7817f093b2220c792dd99e2ee284d745a6e83a1de047b5c5bb2668",
"install": true
},
{
Expand Down Expand Up @@ -2357,5 +2357,6 @@
"sha256": "b91a53f73089e76988abe0c8c5731ac6302025466ef7761f824b6602416104b0",
"install": true
}
]
],
"license": "GPL-3.0-only"
}
Loading