Added the ability to ignore workspaces by number or regex
This commit is contained in:
3
lib/types/options.d.ts
vendored
3
lib/types/options.d.ts
vendored
@@ -215,3 +215,6 @@ export type ColorMapKey = keyof typeof defaultColorMap;
|
|||||||
export type ColorMapValue = (typeof defaultColorMap)[ColorMapKey];
|
export type ColorMapValue = (typeof defaultColorMap)[ColorMapKey];
|
||||||
|
|
||||||
export type ScalingPriority = 'gdk' | 'hyprland' | 'both';
|
export type ScalingPriority = 'gdk' | 'hyprland' | 'both';
|
||||||
|
|
||||||
|
export type IgnoredWorkspace = number | string;
|
||||||
|
export type IgnoredWorkspaces = IgnoredWorkspace[];
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const hyprland = await Service.import('hyprland');
|
const hyprland = await Service.import('hyprland');
|
||||||
|
|
||||||
|
import { IgnoredWorkspace, IgnoredWorkspaces } from 'lib/types/options';
|
||||||
import { MonitorMap, WorkspaceMap, WorkspaceRule } from 'lib/types/workspace';
|
import { MonitorMap, WorkspaceMap, WorkspaceRule } from 'lib/types/workspace';
|
||||||
import options from 'options';
|
import options from 'options';
|
||||||
import { Variable } from 'types/variable';
|
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 => {
|
export const getWorkspacesForMonitor = (curWs: number, wsRules: WorkspaceMap, monitor: number): boolean => {
|
||||||
if (!wsRules || !Object.keys(wsRules).length) {
|
if (!wsRules || !Object.keys(wsRules).length) {
|
||||||
@@ -66,63 +67,70 @@ export const getCurrentMonitorWorkspaces = (monitor: number): number[] => {
|
|||||||
return monitorWorkspaces[currentMonitorName];
|
return monitorWorkspaces[currentMonitorName];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const goToNextWS = (currentMonitorWorkspaces: Variable<number[]>, activeWorkspaces: boolean): void => {
|
type ThrottledScrollHandlers = {
|
||||||
if (activeWorkspaces === true) {
|
throttledScrollUp: () => void;
|
||||||
const activeWses = hyprland.workspaces.filter((ws) => hyprland.active.monitor.id === ws.monitorID);
|
throttledScrollDown: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
let nextIndex = hyprland.active.workspace.id + 1;
|
export const isWorkspaceIgnored = (
|
||||||
if (nextIndex > activeWses[activeWses.length - 1].id) {
|
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
|
||||||
nextIndex = activeWses[0].id;
|
workspaceNumber: number,
|
||||||
|
): boolean => {
|
||||||
|
const ignoredValues = ignoredWorkspaces.value;
|
||||||
|
|
||||||
|
return ignoredValues.some((ignore: IgnoredWorkspace) => {
|
||||||
|
if (typeof ignore === 'number') {
|
||||||
|
return ignore === workspaceNumber;
|
||||||
}
|
}
|
||||||
|
if (typeof ignore === 'string') {
|
||||||
hyprland.messageAsync(`dispatch workspace ${nextIndex}`);
|
return new RegExp(ignore).test(workspaceNumber.toString());
|
||||||
} else if (currentMonitorWorkspaces.value === undefined) {
|
|
||||||
let nextIndex = hyprland.active.workspace.id + 1;
|
|
||||||
if (nextIndex > workspaces.value) {
|
|
||||||
nextIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
hyprland.messageAsync(`dispatch workspace ${nextIndex}`);
|
const navigateWorkspace = (
|
||||||
} else {
|
direction: 'next' | 'prev',
|
||||||
const curWorkspace = hyprland.active.workspace.id;
|
currentMonitorWorkspaces: Variable<number[]>,
|
||||||
const indexOfWs = currentMonitorWorkspaces.value.indexOf(curWorkspace);
|
activeWorkspaces: boolean,
|
||||||
let nextIndex = indexOfWs + 1;
|
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
|
||||||
if (nextIndex >= currentMonitorWorkspaces.value.length) {
|
): void => {
|
||||||
nextIndex = 0;
|
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;
|
||||||
}
|
}
|
||||||
|
newIndex = (newIndex + step + workspacesList.length) % workspacesList.length;
|
||||||
hyprland.messageAsync(`dispatch workspace ${currentMonitorWorkspaces.value[nextIndex]}`);
|
attempts++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const goToPrevWS = (currentMonitorWorkspaces: Variable<number[]>, activeWorkspaces: boolean): void => {
|
export const goToNextWS = (
|
||||||
if (activeWorkspaces === true) {
|
currentMonitorWorkspaces: Variable<number[]>,
|
||||||
const activeWses = hyprland.workspaces.filter((ws) => hyprland.active.monitor.id === ws.monitorID);
|
activeWorkspaces: boolean,
|
||||||
|
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
|
||||||
|
): void => {
|
||||||
|
navigateWorkspace('next', currentMonitorWorkspaces, activeWorkspaces, ignoredWorkspaces);
|
||||||
|
};
|
||||||
|
|
||||||
let prevIndex = hyprland.active.workspace.id - 1;
|
export const goToPrevWS = (
|
||||||
if (prevIndex < activeWses[0].id) {
|
currentMonitorWorkspaces: Variable<number[]>,
|
||||||
prevIndex = activeWses[activeWses.length - 1].id;
|
activeWorkspaces: boolean,
|
||||||
}
|
ignoredWorkspaces: Variable<IgnoredWorkspaces>,
|
||||||
|
): void => {
|
||||||
hyprland.messageAsync(`dispatch workspace ${prevIndex}`);
|
navigateWorkspace('prev', currentMonitorWorkspaces, activeWorkspaces, ignoredWorkspaces);
|
||||||
} 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 function throttle<T extends (...args: unknown[]) => void>(func: T, limit: number): T {
|
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;
|
} as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThrottledScrollHandlers = {
|
|
||||||
throttledScrollUp: () => void;
|
|
||||||
throttledScrollDown: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createThrottledScrollHandlers = (
|
export const createThrottledScrollHandlers = (
|
||||||
scrollSpeed: number,
|
scrollSpeed: number,
|
||||||
currentMonitorWorkspaces: Variable<number[]>,
|
currentMonitorWorkspaces: Variable<number[]>,
|
||||||
activeWorkspaces: boolean = false,
|
activeWorkspaces: boolean = false,
|
||||||
): ThrottledScrollHandlers => {
|
): ThrottledScrollHandlers => {
|
||||||
const throttledScrollUp = throttle(() => {
|
const throttledScrollUp = throttle(() => {
|
||||||
if (reverse_scroll.value === true) {
|
if (reverse_scroll.value) {
|
||||||
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces);
|
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
|
||||||
} else {
|
} else {
|
||||||
goToNextWS(currentMonitorWorkspaces, activeWorkspaces);
|
goToNextWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
|
||||||
}
|
}
|
||||||
}, 200 / scrollSpeed);
|
}, 200 / scrollSpeed);
|
||||||
|
|
||||||
const throttledScrollDown = throttle(() => {
|
const throttledScrollDown = throttle(() => {
|
||||||
if (reverse_scroll.value === true) {
|
if (reverse_scroll.value) {
|
||||||
goToNextWS(currentMonitorWorkspaces, activeWorkspaces);
|
goToNextWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
|
||||||
} else {
|
} else {
|
||||||
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces);
|
goToPrevWS(currentMonitorWorkspaces, activeWorkspaces, ignored);
|
||||||
}
|
}
|
||||||
}, 200 / scrollSpeed);
|
}, 200 / scrollSpeed);
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
const hyprland = await Service.import('hyprland');
|
const hyprland = await Service.import('hyprland');
|
||||||
import options from 'options';
|
import options from 'options';
|
||||||
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
import { getWorkspaceRules, getWorkspacesForMonitor, isWorkspaceIgnored } from '../helpers';
|
||||||
import { range } from 'lib/utils';
|
import { range } from 'lib/utils';
|
||||||
import { BoxWidget } from 'lib/types/widget';
|
import { BoxWidget } from 'lib/types/widget';
|
||||||
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
||||||
import { WorkspaceIconMap } from 'lib/types/workspace';
|
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 => {
|
export const defaultWses = (monitor: number): BoxWidget => {
|
||||||
return Widget.Box({
|
return Widget.Box({
|
||||||
children: Utils.merge(
|
children: Utils.merge(
|
||||||
[workspaces.bind('value'), monitorSpecific.bind()],
|
[workspaces.bind('value'), monitorSpecific.bind('value'), ignored.bind('value')],
|
||||||
(workspaces: number, monitorSpecific: boolean) => {
|
(workspaces: number, monitorSpecific: boolean) => {
|
||||||
return range(workspaces || 8)
|
return range(workspaces || 8)
|
||||||
.filter((i) => {
|
.filter((workspaceNumber) => {
|
||||||
if (!monitorSpecific) {
|
if (!monitorSpecific) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const workspaceRules = getWorkspaceRules();
|
const workspaceRules = getWorkspaceRules();
|
||||||
return getWorkspacesForMonitor(i, workspaceRules, monitor);
|
return (
|
||||||
|
getWorkspacesForMonitor(workspaceNumber, workspaceRules, monitor) &&
|
||||||
|
!isWorkspaceIgnored(ignored, workspaceNumber)
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a - b;
|
return a - b;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
const hyprland = await Service.import('hyprland');
|
const hyprland = await Service.import('hyprland');
|
||||||
import options from 'options';
|
import options from 'options';
|
||||||
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
import { getWorkspaceRules, getWorkspacesForMonitor, isWorkspaceIgnored } from '../helpers';
|
||||||
import { Workspace } from 'types/service/hyprland';
|
import { Workspace } from 'types/service/hyprland';
|
||||||
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
||||||
import { range } from 'lib/utils';
|
import { range } from 'lib/utils';
|
||||||
import { BoxWidget } from 'lib/types/widget';
|
import { BoxWidget } from 'lib/types/widget';
|
||||||
import { WorkspaceIconMap } from 'lib/types/workspace';
|
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 => {
|
export const occupiedWses = (monitor: number): BoxWidget => {
|
||||||
return Widget.Box({
|
return Widget.Box({
|
||||||
@@ -28,6 +28,7 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
options.bar.workspaces.workspaceIconMap.bind('value'),
|
options.bar.workspaces.workspaceIconMap.bind('value'),
|
||||||
options.bar.workspaces.showWsIcons.bind('value'),
|
options.bar.workspaces.showWsIcons.bind('value'),
|
||||||
options.theme.matugen.bind('value'),
|
options.theme.matugen.bind('value'),
|
||||||
|
ignored.bind('value'),
|
||||||
],
|
],
|
||||||
(
|
(
|
||||||
monitorSpecific: boolean,
|
monitorSpecific: boolean,
|
||||||
@@ -61,7 +62,6 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
hyprland.monitors.find((m) => m.id === monitor) ||
|
hyprland.monitors.find((m) => m.id === monitor) ||
|
||||||
workspaceMonitorList.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) => {
|
const workspacesWithRules = Object.keys(workspaceRules).reduce((acc: number[], k: string) => {
|
||||||
return [...acc, ...workspaceRules[k]];
|
return [...acc, ...workspaceRules[k]];
|
||||||
}, [] as number[]);
|
}, [] as number[]);
|
||||||
@@ -87,6 +87,9 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return allWkspcs
|
return allWkspcs
|
||||||
|
.filter((workspaceNumber) => {
|
||||||
|
return !isWorkspaceIgnored(ignored, workspaceNumber);
|
||||||
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a - b;
|
return a - b;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
ActiveWsIndicator,
|
ActiveWsIndicator,
|
||||||
BarButtonStyles,
|
BarButtonStyles,
|
||||||
BarLocation,
|
BarLocation,
|
||||||
|
IgnoredWorkspaces,
|
||||||
NotificationAnchor,
|
NotificationAnchor,
|
||||||
OSDAnchor,
|
OSDAnchor,
|
||||||
OSDOrientation,
|
OSDOrientation,
|
||||||
@@ -861,6 +862,7 @@ const options = mkOptions(OPTIONS, {
|
|||||||
},
|
},
|
||||||
workspaces: {
|
workspaces: {
|
||||||
show_icons: opt(false),
|
show_icons: opt(false),
|
||||||
|
ignored: opt<IgnoredWorkspaces>([]),
|
||||||
show_numbered: opt(false),
|
show_numbered: opt(false),
|
||||||
showWsIcons: opt(false),
|
showWsIcons: opt(false),
|
||||||
numbered_active_indicator: opt<ActiveWsIndicator>('underline'),
|
numbered_active_indicator: opt<ActiveWsIndicator>('underline'),
|
||||||
|
|||||||
@@ -297,6 +297,11 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
|
|||||||
title: 'Scrolling Speed',
|
title: 'Scrolling Speed',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
}),
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.workspaces.ignored,
|
||||||
|
title: 'Ignored Workspaces',
|
||||||
|
type: 'object',
|
||||||
|
}),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************
|
******************************
|
||||||
|
|||||||
Reference in New Issue
Block a user