Implemented the ability to change workspaces by scrolling or clicking on the workspace module. (#12)

* Updated README to add instructions on Notifications.

* Resolves #8 - Implemented scrolling and clicking to change workspaces.

* Remove the hover effect on workspaces as its no longer applicable.
This commit is contained in:
Jas Singh
2024-07-27 20:07:00 -07:00
committed by GitHub
parent 1ad30f4ffe
commit bb6597fe01
8 changed files with 176 additions and 75 deletions

View File

@@ -65,6 +65,10 @@ ags
``` ```
Or you can add it to your Hyprland config (hyprland.conf) to auto-start with: Or you can add it to your Hyprland config (hyprland.conf) to auto-start with:
### Notifications
HyprPanel handles notifications through the AGS built-in notification service. If you're already using a notification daemon such as Dunst or Mako, you may have to stop them to prevent conflicts with HyprPanel.
```bash ```bash
exec-once = ags exec-once = ags
``` ```

View File

@@ -2,7 +2,7 @@ const hyprland = await Service.import("hyprland");
import { WorkspaceRule, WorkspaceMap } from "lib/types/workspace"; import { WorkspaceRule, WorkspaceMap } from "lib/types/workspace";
import options from "options"; import options from "options";
const { workspaces, monitorSpecific } = options.bar.workspaces; const { workspaces, monitorSpecific, reverse_scroll } = options.bar.workspaces;
function range(length: number, start = 1) { function range(length: number, start = 1) {
return Array.from({ length }, (_, i) => i + start); return Array.from({ length }, (_, i) => i + start);
@@ -42,6 +42,43 @@ const Workspaces = (monitor = -1, ws = 8) => {
} }
}; };
const getCurrentMonitorWorkspaces = () => {
const monitorWorkspaces = getWorkspaceRules();
const monitorMap = {};
hyprland.monitors.forEach((m) => (monitorMap[m.id] = m.name));
const currentMonitorName = monitorMap[monitor];
return monitorWorkspaces[currentMonitorName];
}
const currentMonitorWorkspaces = Variable(getCurrentMonitorWorkspaces());
workspaces.connect("changed", () => {
currentMonitorWorkspaces.value = getCurrentMonitorWorkspaces()
})
const goToNextWS = () => {
const curWorkspace = hyprland.active.workspace.id;
const indexOfWs = currentMonitorWorkspaces.value.indexOf(curWorkspace);
let nextIndex = indexOfWs + 1;
if (nextIndex >= currentMonitorWorkspaces.value.length) {
nextIndex = 0;
}
hyprland.messageAsync(`dispatch workspace ${currentMonitorWorkspaces.value[nextIndex]}`)
}
const goToPrevWS = () => {
const curWorkspace = hyprland.active.workspace.id;
const indexOfWs = currentMonitorWorkspaces.value.indexOf(curWorkspace);
let prevIndex = indexOfWs - 1;
if (prevIndex < 0) {
prevIndex = currentMonitorWorkspaces.value.length - 1;
}
hyprland.messageAsync(`dispatch workspace ${currentMonitorWorkspaces.value[prevIndex]}`)
}
return { return {
component: Widget.Box({ component: Widget.Box({
class_name: "workspaces", class_name: "workspaces",
@@ -57,7 +94,12 @@ const Workspaces = (monitor = -1, ws = 8) => {
return getWorkspacesForMonitor(i, workspaceRules); return getWorkspacesForMonitor(i, workspaceRules);
}) })
.map((i) => { .map((i) => {
return Widget.Label({ return Widget.Button({
on_primary_click: () => {
hyprland.messageAsync(`dispatch workspace ${i}`)
},
child: Widget.Label({
attribute: i, attribute: i,
vpack: "center", vpack: "center",
class_name: Utils.merge( class_name: Utils.merge(
@@ -112,6 +154,7 @@ const Workspaces = (monitor = -1, ws = 8) => {
); );
}); });
}, },
})
}); });
}); });
}, },
@@ -130,6 +173,24 @@ const Workspaces = (monitor = -1, ws = 8) => {
}), }),
isVisible: true, isVisible: true,
boxClass: "workspaces", boxClass: "workspaces",
useBox: true,
props: {
on_scroll_up: () => {
if (reverse_scroll.value === true) {
goToPrevWS();
} else {
goToNextWS();
}
},
on_scroll_down: () => {
if (reverse_scroll.value === true) {
goToNextWS();
} else {
goToPrevWS();
}
},
}
}; };
}; };
export { Workspaces }; export { Workspaces };

View File

@@ -6,6 +6,18 @@ export const BarItemBox = (child) => {
return child.isVisible; return child.isVisible;
}; };
if (Object.hasOwnProperty.call(child, "useBox") && child.useBox === true) {
return Widget.Box({
class_name: `bar_item_box_visible ${Object.hasOwnProperty.call(child, "boxClass") ? child.boxClass : ""}`,
child: Widget.EventBox({
class_name: `bar-event-box`,
child: child.component,
...child.props,
}),
visible: computeVisible(),
});
}
return Widget.Button({ return Widget.Button({
class_name: `bar_item_box_visible ${Object.hasOwnProperty.call(child, "boxClass") ? child.boxClass : ""}`, class_name: `bar_item_box_visible ${Object.hasOwnProperty.call(child, "boxClass") ? child.boxClass : ""}`,
child: child.component, child: child.component,

View File

@@ -578,6 +578,7 @@ const options = mkOptions(OPTIONS, {
}, },
workspaces: opt(10), workspaces: opt(10),
monitorSpecific: opt(true), monitorSpecific: opt(true),
reverse_scroll: opt(false),
}, },
volume: { volume: {
label: opt(true), label: opt(true),

View File

@@ -3,6 +3,7 @@
.bar { .bar {
background: if($bar-transparent, transparent, $bar-background); background: if($bar-transparent, transparent, $bar-background);
.transparent { .transparent {
background: transparent; background: transparent;
} }
@@ -20,66 +21,87 @@
&.battery { &.battery {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-battery-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-battery-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-battery-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-battery-hover);
} }
} }
&.bluetooth { &.bluetooth {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-bluetooth-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-bluetooth-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-bluetooth-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-bluetooth-hover);
} }
} }
&.clock { &.clock {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-clock-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-clock-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-clock-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-clock-hover);
} }
} }
&.media { &.media {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-media-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-media-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-media-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-media-hover);
} }
} }
&.dashboard { &.dashboard {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-dashboard-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-dashboard-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-dashboard-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-dashboard-hover);
} }
} }
&.network { &.network {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-network-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-network-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-network-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-network-hover);
} }
} }
&.notifications { &.notifications {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-notifications-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-notifications-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-notifications-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-notifications-hover);
} }
} }
&.systray { &.systray {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-systray-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-systray-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-systray-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-systray-hover);
} }
} }
&.volume { &.volume {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-volume-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-volume-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-volume-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-volume-hover);
} }
} }
&.windowtitle { &.windowtitle {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-windowtitle-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-windowtitle-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-windowtitle-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-windowtitle-hover);
} }
} }
&.workspaces { &.workspaces {
background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-workspaces-background); background-color: if($bar-buttons-monochrome, $bar-buttons-background, $bar-buttons-workspaces-background);
&:hover { &:hover {
background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-workspaces-hover); background: if($bar-buttons-monochrome, $bar-buttons-hover, $bar-buttons-workspaces-hover);
} }

View File

@@ -2,20 +2,23 @@
@import '../../variables'; @import '../../variables';
.workspaces { .workspaces {
button {
margin: 0rem 0.5rem * .5;
&:not(:first-child) {
margin-left: 0.7em;
}
}
label { label {
font-size: 0.2em; font-size: 0.2em;
min-width: 4em; min-width: 4em;
min-height: 4em; min-height: 4em;
border-radius: 1.9rem * .6; border-radius: 1.9rem * .6;
margin: 0rem 0.5rem * .5;
transition: 300ms * .5; transition: 300ms * .5;
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available); background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available); color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
&:not(:first-child) {
margin-left: 4.5em;
}
&.occupied { &.occupied {
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied); background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied); color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
@@ -35,8 +38,6 @@
min-width: 0em; min-width: 0em;
min-height: 0em; min-height: 0em;
border-radius: 0em; border-radius: 0em;
margin: 0rem 1rem * .5;
transition: 300ms * .5;
font-size: 1.1em; font-size: 1.1em;
} }
} }

View File

@@ -24,6 +24,7 @@ export const BarSettings = () => {
Option({ opt: options.bar.workspaces.icons.occupied, title: 'Workspace Occupied', type: 'string' }), Option({ opt: options.bar.workspaces.icons.occupied, title: 'Workspace Occupied', type: 'string' }),
Option({ opt: options.bar.workspaces.workspaces, title: 'Total Workspaces', type: 'number' }), Option({ opt: options.bar.workspaces.workspaces, title: 'Total Workspaces', type: 'number' }),
Option({ opt: options.bar.workspaces.monitorSpecific, title: 'Monitor Specific', subtitle: 'Only workspaces applicable to the monitor will be displayed', type: 'boolean' }), Option({ opt: options.bar.workspaces.monitorSpecific, title: 'Monitor Specific', subtitle: 'Only workspaces applicable to the monitor will be displayed', type: 'boolean' }),
Option({ opt: options.bar.workspaces.reverse_scroll, title: 'Invert Scroll', subtitle: 'Scrolling up will go to the previous workspace rather than the next.', type: 'boolean' }),
Header('Volume'), Header('Volume'),
Option({ opt: options.bar.volume.label, title: 'Show Volume Percentage', type: 'boolean' }), Option({ opt: options.bar.volume.label, title: 'Show Volume Percentage', type: 'boolean' }),

View File

@@ -29,7 +29,6 @@ export const BarTheme = () => {
Header('Workspaces'), Header('Workspaces'),
Option({ opt: options.theme.bar.buttons.workspaces.background, title: 'Background', type: 'color' }), Option({ opt: options.theme.bar.buttons.workspaces.background, title: 'Background', type: 'color' }),
Option({ opt: options.theme.bar.buttons.workspaces.hover, title: 'Hover', type: 'color' }),
Option({ opt: options.theme.bar.buttons.workspaces.available, title: 'Workspace Available Color', type: 'color' }), Option({ opt: options.theme.bar.buttons.workspaces.available, title: 'Workspace Available Color', type: 'color' }),
Option({ opt: options.theme.bar.buttons.workspaces.occupied, title: 'Workspace Occupied Color', type: 'color' }), Option({ opt: options.theme.bar.buttons.workspaces.occupied, title: 'Workspace Occupied Color', type: 'color' }),
Option({ opt: options.theme.bar.buttons.workspaces.active, title: 'Workspace Active Color', type: 'color' }), Option({ opt: options.theme.bar.buttons.workspaces.active, title: 'Workspace Active Color', type: 'color' }),