diff --git a/modules/bar/workspaces/index.ts b/modules/bar/workspaces/index.ts index fb0987f..5a66166 100644 --- a/modules/bar/workspaces/index.ts +++ b/modules/bar/workspaces/index.ts @@ -2,7 +2,7 @@ const hyprland = await Service.import("hyprland"); import { WorkspaceRule, WorkspaceMap } from "lib/types/workspace"; import options from "options"; -const { workspaces, monitorSpecific, reverse_scroll } = options.bar.workspaces; +const { workspaces, monitorSpecific, reverse_scroll, scroll_speed, spacing } = options.bar.workspaces; function range(length: number, start = 1) { return Array.from({ length }, (_, i) => i + start); @@ -43,6 +43,10 @@ const Workspaces = (monitor = -1, ws = 8) => { }; const getCurrentMonitorWorkspaces = () => { + if (hyprland.monitors.length === 1) { + return Array.from({ length: workspaces.value }, (_, i) => i + 1); + } + const monitorWorkspaces = getWorkspaceRules(); const monitorMap = {}; hyprland.monitors.forEach((m) => (monitorMap[m.id] = m.name)); @@ -79,6 +83,39 @@ const Workspaces = (monitor = -1, ws = 8) => { hyprland.messageAsync(`dispatch workspace ${currentMonitorWorkspaces.value[prevIndex]}`) } + function throttle void>(func: T, limit: number): T { + let inThrottle: boolean; + return function (this: ThisParameterType, ...args: Parameters) { + if (!inThrottle) { + func.apply(this, args); + inThrottle = true; + setTimeout(() => { + inThrottle = false; + }, limit); + } + } as T; + } + + const createThrottledScrollHandlers = (scrollSpeed: number) => { + const throttledScrollUp = throttle(() => { + if (reverse_scroll.value === true) { + goToPrevWS(); + } else { + goToNextWS(); + } + }, 200 / scrollSpeed); + + const throttledScrollDown = throttle(() => { + if (reverse_scroll.value === true) { + goToNextWS(); + } else { + goToPrevWS(); + } + }, 200 / scrollSpeed); + + return { throttledScrollUp, throttledScrollDown }; + } + return { component: Widget.Box({ class_name: "workspaces", @@ -95,6 +132,7 @@ const Workspaces = (monitor = -1, ws = 8) => { }) .map((i) => { return Widget.Button({ + class_name: "workspace-button", on_primary_click: () => { hyprland.messageAsync(`dispatch workspace ${i}`) @@ -102,6 +140,7 @@ const Workspaces = (monitor = -1, ws = 8) => { child: Widget.Label({ attribute: i, vpack: "center", + css: spacing.bind("value").as(sp => `margin: 0rem ${0.375 * sp}rem;`), class_name: Utils.merge( [ options.bar.workspaces.show_icons.bind("value"), @@ -173,23 +212,14 @@ const Workspaces = (monitor = -1, ws = 8) => { }), isVisible: true, 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(); - } - }, + setup: (self: any) => { + self.hook(scroll_speed, () => { + const { throttledScrollUp, throttledScrollDown } = createThrottledScrollHandlers(scroll_speed.value); + self.on_scroll_up = throttledScrollUp; + self.on_scroll_down = throttledScrollDown; + }); + } } }; }; diff --git a/modules/shared/barItemBox.ts b/modules/shared/barItemBox.ts index a5a2ff5..fb25c6b 100644 --- a/modules/shared/barItemBox.ts +++ b/modules/shared/barItemBox.ts @@ -6,18 +6,6 @@ export const BarItemBox = (child) => { 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({ class_name: `bar_item_box_visible ${Object.hasOwnProperty.call(child, "boxClass") ? child.boxClass : ""}`, child: child.component, diff --git a/options.ts b/options.ts index 92f4714..5dfb67d 100644 --- a/options.ts +++ b/options.ts @@ -577,8 +577,10 @@ const options = mkOptions(OPTIONS, { occupied: opt(""), }, workspaces: opt(10), + spacing: opt(1), monitorSpecific: opt(true), reverse_scroll: opt(false), + scroll_speed: opt(5), }, volume: { label: opt(true), diff --git a/scss/style/bar/workspace.scss b/scss/style/bar/workspace.scss index 9d46cf5..09e90d9 100644 --- a/scss/style/bar/workspace.scss +++ b/scss/style/bar/workspace.scss @@ -2,14 +2,6 @@ @import '../../variables'; .workspaces { - button { - margin: 0rem 0.5rem * .5; - - &:not(:first-child) { - margin-left: 0.7em; - } - } - label { font-size: 0.2em; min-width: 4em; @@ -38,8 +30,8 @@ min-width: 0em; min-height: 0em; border-radius: 0em; - font-size: 1.1em; + transition: 300ms * .5; + font-size: 1em; } } - } diff --git a/widget/settings/pages/config/bar/index.ts b/widget/settings/pages/config/bar/index.ts index 907927a..b48bb03 100644 --- a/widget/settings/pages/config/bar/index.ts +++ b/widget/settings/pages/config/bar/index.ts @@ -22,9 +22,11 @@ export const BarSettings = () => { Option({ opt: options.bar.workspaces.icons.available, title: 'Workspace Available', type: 'string' }), Option({ opt: options.bar.workspaces.icons.active, title: 'Workspace Active', type: 'string' }), Option({ opt: options.bar.workspaces.icons.occupied, title: 'Workspace Occupied', type: 'string' }), + Option({ opt: options.bar.workspaces.spacing, title: 'Spacing', subtitle: 'Spacing between workspace icons', type: 'float' }), 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.reverse_scroll, title: 'Invert Scroll', subtitle: 'Scrolling up will go to the previous workspace rather than the next.', type: 'boolean' }), + Option({ opt: options.bar.workspaces.scroll_speed, title: 'Scrolling Speed', type: 'number' }), Header('Volume'), Option({ opt: options.bar.volume.label, title: 'Show Volume Percentage', type: 'boolean' }),