Added the ability to ignore workspaces by number or regex

This commit is contained in:
Jas Singh
2024-09-25 00:49:08 -07:00
parent d60d3db401
commit c01ddce201
6 changed files with 87 additions and 68 deletions

View File

@@ -215,3 +215,6 @@ export type ColorMapKey = keyof typeof defaultColorMap;
export type ColorMapValue = (typeof defaultColorMap)[ColorMapKey];
export type ScalingPriority = 'gdk' | 'hyprland' | 'both';
export type IgnoredWorkspace = number | string;
export type IgnoredWorkspaces = IgnoredWorkspace[];

View File

@@ -1,10 +1,11 @@
const hyprland = await Service.import('hyprland');
import { IgnoredWorkspace, IgnoredWorkspaces } from 'lib/types/options';
import { MonitorMap, WorkspaceMap, WorkspaceRule } from 'lib/types/workspace';
import options from 'options';
import { Variable } from 'types/variable';
const { workspaces, reverse_scroll } = options.bar.workspaces;
const { workspaces, reverse_scroll, ignored } = options.bar.workspaces;
export const getWorkspacesForMonitor = (curWs: number, wsRules: WorkspaceMap, monitor: number): boolean => {
if (!wsRules || !Object.keys(wsRules).length) {
@@ -66,63 +67,70 @@ export const getCurrentMonitorWorkspaces = (monitor: number): number[] => {
return monitorWorkspaces[currentMonitorName];
};
export const goToNextWS = (currentMonitorWorkspaces: Variable<number[]>, activeWorkspaces: boolean): void => {
if (activeWorkspaces === true) {
const activeWses = hyprland.workspaces.filter((ws) => hyprland.active.monitor.id === ws.monitorID);
type ThrottledScrollHandlers = {
throttledScrollUp: () => void;
throttledScrollDown: () => void;
};
let nextIndex = hyprland.active.workspace.id + 1;
if (nextIndex > activeWses[activeWses.length - 1].id) {
nextIndex = activeWses[0].id;
export const isWorkspaceIgnored = (
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
workspaceNumber: number,
): boolean => {
const ignoredValues = ignoredWorkspaces.value;
return ignoredValues.some((ignore: IgnoredWorkspace) => {
if (typeof ignore === 'number') {
return ignore === workspaceNumber;
}
hyprland.messageAsync(`dispatch workspace ${nextIndex}`);
} else if (currentMonitorWorkspaces.value === undefined) {
let nextIndex = hyprland.active.workspace.id + 1;
if (nextIndex > workspaces.value) {
nextIndex = 0;
if (typeof ignore === 'string') {
return new RegExp(ignore).test(workspaceNumber.toString());
}
return true;
});
};
hyprland.messageAsync(`dispatch workspace ${nextIndex}`);
} else {
const curWorkspace = hyprland.active.workspace.id;
const indexOfWs = currentMonitorWorkspaces.value.indexOf(curWorkspace);
let nextIndex = indexOfWs + 1;
if (nextIndex >= currentMonitorWorkspaces.value.length) {
nextIndex = 0;
const navigateWorkspace = (
direction: 'next' | 'prev',
currentMonitorWorkspaces: Variable<number[]>,
activeWorkspaces: boolean,
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
): void => {
const workspacesList = activeWorkspaces
? hyprland.workspaces.filter((ws) => hyprland.active.monitor.id === ws.monitorID).map((ws) => ws.id)
: currentMonitorWorkspaces.value || Array.from({ length: workspaces.value }, (_, i) => i + 1);
if (workspacesList.length === 0) return;
const currentIndex = workspacesList.indexOf(hyprland.active.workspace.id);
const step = direction === 'next' ? 1 : -1;
let newIndex = (currentIndex + step + workspacesList.length) % workspacesList.length;
let attempts = 0;
while (attempts < workspacesList.length) {
const targetWS = workspacesList[newIndex];
if (!isWorkspaceIgnored(ignoredWorkspaces, targetWS)) {
hyprland.messageAsync(`dispatch workspace ${targetWS}`);
return;
}
hyprland.messageAsync(`dispatch workspace ${currentMonitorWorkspaces.value[nextIndex]}`);
newIndex = (newIndex + step + workspacesList.length) % workspacesList.length;
attempts++;
}
};
export const goToPrevWS = (currentMonitorWorkspaces: Variable<number[]>, activeWorkspaces: boolean): void => {
if (activeWorkspaces === true) {
const activeWses = hyprland.workspaces.filter((ws) => hyprland.active.monitor.id === ws.monitorID);
export const goToNextWS = (
currentMonitorWorkspaces: Variable<number[]>,
activeWorkspaces: boolean,
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
): void => {
navigateWorkspace('next', currentMonitorWorkspaces, activeWorkspaces, ignoredWorkspaces);
};
let prevIndex = hyprland.active.workspace.id - 1;
if (prevIndex < activeWses[0].id) {
prevIndex = activeWses[activeWses.length - 1].id;
}
hyprland.messageAsync(`dispatch workspace ${prevIndex}`);
} else if (currentMonitorWorkspaces.value === undefined) {
let prevIndex = hyprland.active.workspace.id - 1;
if (prevIndex <= 0) {
prevIndex = workspaces.value;
}
hyprland.messageAsync(`dispatch workspace ${prevIndex}`);
} else {
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]}`);
}
export const goToPrevWS = (
currentMonitorWorkspaces: Variable<number[]>,
activeWorkspaces: boolean,
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
): void => {
navigateWorkspace('prev', currentMonitorWorkspaces, activeWorkspaces, ignoredWorkspaces);
};
export function throttle<T extends (...args: unknown[]) => void>(func: T, limit: number): T {
@@ -138,29 +146,24 @@ export function throttle<T extends (...args: unknown[]) => void>(func: T, limit:
} as T;
}
type ThrottledScrollHandlers = {
throttledScrollUp: () => void;
throttledScrollDown: () => void;
};
export const createThrottledScrollHandlers = (
scrollSpeed: number,
currentMonitorWorkspaces: Variable<number[]>,
activeWorkspaces: boolean = false,
): ThrottledScrollHandlers => {
const throttledScrollUp = throttle(() => {
if (reverse_scroll.value === true) {
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces);
if (reverse_scroll.value) {
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
} else {
goToNextWS(currentMonitorWorkspaces, activeWorkspaces);
goToNextWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
}
}, 200 / scrollSpeed);
const throttledScrollDown = throttle(() => {
if (reverse_scroll.value === true) {
goToNextWS(currentMonitorWorkspaces, activeWorkspaces);
if (reverse_scroll.value) {
goToNextWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
} else {
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces);
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
}
}, 200 / scrollSpeed);

View File

@@ -1,24 +1,27 @@
const hyprland = await Service.import('hyprland');
import options from 'options';
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
import { getWorkspaceRules, getWorkspacesForMonitor, isWorkspaceIgnored } from '../helpers';
import { range } from 'lib/utils';
import { BoxWidget } from 'lib/types/widget';
import { getWsColor, renderClassnames, renderLabel } from '../utils';
import { WorkspaceIconMap } from 'lib/types/workspace';
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
const { workspaces, monitorSpecific, workspaceMask, spacing, ignored } = options.bar.workspaces;
export const defaultWses = (monitor: number): BoxWidget => {
return Widget.Box({
children: Utils.merge(
[workspaces.bind('value'), monitorSpecific.bind()],
[workspaces.bind('value'), monitorSpecific.bind('value'), ignored.bind('value')],
(workspaces: number, monitorSpecific: boolean) => {
return range(workspaces || 8)
.filter((i) => {
.filter((workspaceNumber) => {
if (!monitorSpecific) {
return true;
}
const workspaceRules = getWorkspaceRules();
return getWorkspacesForMonitor(i, workspaceRules, monitor);
return (
getWorkspacesForMonitor(workspaceNumber, workspaceRules, monitor) &&
!isWorkspaceIgnored(ignored, workspaceNumber)
);
})
.sort((a, b) => {
return a - b;

View File

@@ -1,13 +1,13 @@
const hyprland = await Service.import('hyprland');
import options from 'options';
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
import { getWorkspaceRules, getWorkspacesForMonitor, isWorkspaceIgnored } from '../helpers';
import { Workspace } from 'types/service/hyprland';
import { getWsColor, renderClassnames, renderLabel } from '../utils';
import { range } from 'lib/utils';
import { BoxWidget } from 'lib/types/widget';
import { WorkspaceIconMap } from 'lib/types/workspace';
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
const { workspaces, monitorSpecific, workspaceMask, spacing, ignored } = options.bar.workspaces;
export const occupiedWses = (monitor: number): BoxWidget => {
return Widget.Box({
@@ -28,6 +28,7 @@ export const occupiedWses = (monitor: number): BoxWidget => {
options.bar.workspaces.workspaceIconMap.bind('value'),
options.bar.workspaces.showWsIcons.bind('value'),
options.theme.matugen.bind('value'),
ignored.bind('value'),
],
(
monitorSpecific: boolean,
@@ -61,7 +62,6 @@ export const occupiedWses = (monitor: number): BoxWidget => {
hyprland.monitors.find((m) => m.id === monitor) ||
workspaceMonitorList.find((m) => m.id === monitor);
// go through each key in workspaceRules and flatten the array
const workspacesWithRules = Object.keys(workspaceRules).reduce((acc: number[], k: string) => {
return [...acc, ...workspaceRules[k]];
}, [] as number[]);
@@ -87,6 +87,9 @@ export const occupiedWses = (monitor: number): BoxWidget => {
}
return allWkspcs
.filter((workspaceNumber) => {
return !isWorkspaceIgnored(ignored, workspaceNumber);
})
.sort((a, b) => {
return a - b;
})

View File

@@ -13,6 +13,7 @@ import {
ActiveWsIndicator,
BarButtonStyles,
BarLocation,
IgnoredWorkspaces,
NotificationAnchor,
OSDAnchor,
OSDOrientation,
@@ -861,6 +862,7 @@ const options = mkOptions(OPTIONS, {
},
workspaces: {
show_icons: opt(false),
ignored: opt<IgnoredWorkspaces>([]),
show_numbered: opt(false),
showWsIcons: opt(false),
numbered_active_indicator: opt<ActiveWsIndicator>('underline'),

View File

@@ -297,6 +297,11 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
title: 'Scrolling Speed',
type: 'number',
}),
Option({
opt: options.bar.workspaces.ignored,
title: 'Ignored Workspaces',
type: 'object',
}),
/*
******************************