Skip to content

Commit

Permalink
OSDs are now click through and can have borders. (Jas-SinghFSU#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jas-SinghFSU authored Dec 30, 2024
1 parent d49a750 commit d2e02f5
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 165 deletions.
1 change: 1 addition & 0 deletions nix/module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ in
theme.osd.opacity = mkIntOption 100;
theme.osd.orientation = mkStrOption "vertical";
theme.osd.radius = mkStrOption "0.4em";
theme.osd.border.size = mkStrOption "0em";
theme.osd.scaling = mkIntOption 100;
theme.tooltip.scaling = mkIntOption 100;
wallpaper.enable = mkBoolOption true;
Expand Down
106 changes: 15 additions & 91 deletions src/components/osd/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Binding } from 'astal';
import { bind, timeout, Variable } from 'astal';
import { Widget } from 'astal/gtk3';
import { audioService, brightnessService, hyprlandService } from 'src/lib/constants/services';
Expand All @@ -17,85 +16,42 @@ timeout(3000, () => {
});

/**
* Handles the reveal state of a Widget.Revealer.
* Handles the reveal state of a Widget.Revealer or Widget.Window.
*
* This function sets the `reveal_child` property of the Widget.Revealer to true if the OSD is enabled and the property is 'revealChild'.
* It also manages a timeout to reset the `reveal_child` property after the specified duration.
* This function delegates the reveal handling to either `handleRevealRevealer` or `handleRevealWindow` based on the type of the widget.
*
* @param self The Widget.Revealer instance.
* @param self The Widget.Revealer or Widget.Window instance.
* @param property The property to check, either 'revealChild' or 'visible'.
*/
export const handleRevealRevealer = (self: Widget.Revealer, property: 'revealChild' | 'visible'): void => {
if (!enable.get() || property !== 'revealChild') {
export const handleReveal = (self: Widget.Revealer): void => {
if (isStartingUp) {
return;
}

self.reveal_child = true;

count++;
timeout(duration.get(), () => {
count--;

if (count === 0) {
self.reveal_child = false;
}
});
};

/**
* Handles the reveal state of a Widget.Window.
*
* This function sets the `visible` property of the Widget.Window to true if the OSD is enabled and the property is 'visible'.
* It also manages a timeout to reset the `visible` property after the specified duration.
*
* @param self The Widget.Window instance.
* @param property The property to check, either 'revealChild' or 'visible'.
*/
export const handleRevealWindow = (self: Widget.Window, property: 'revealChild' | 'visible'): void => {
if (!enable.get() || property !== 'visible') {
if (!enable.get()) {
return;
}

self.visible = true;
self.reveal_child = true;

count++;
timeout(duration.get(), () => {
count--;

if (count === 0) {
self.visible = false;
self.reveal_child = false;
}
});
};

/**
* Handles the reveal state of a Widget.Revealer or Widget.Window.
*
* This function delegates the reveal handling to either `handleRevealRevealer` or `handleRevealWindow` based on the type of the widget.
*
* @param self The Widget.Revealer or Widget.Window instance.
* @param property The property to check, either 'revealChild' or 'visible'.
*/
export const handleReveal = (self: Widget.Revealer | Widget.Window, property: 'revealChild' | 'visible'): void => {
if (isStartingUp) {
return;
}

if (self instanceof Widget.Revealer) {
handleRevealRevealer(self, property);
} else if (self instanceof Widget.Window) {
handleRevealWindow(self, property);
}
};

/**
* Retrieves the monitor index for the OSD.
*
* This function derives the monitor index for the OSD based on the focused monitor, default monitor, and active monitor settings.
*
* @returns A Binding<number> representing the monitor index for the OSD.
* @returns A Variable<number> representing the monitor index for the OSD.
*/
export const getOsdMonitor = (): Binding<number> => {
export const getOsdMonitor = (): Variable<number> => {
return Variable.derive(
[bind(hyprlandService, 'focusedMonitor'), bind(monitor), bind(active_monitor)],
(currentMonitor, defaultMonitor, followMonitor) => {
Expand All @@ -105,39 +61,7 @@ export const getOsdMonitor = (): Binding<number> => {

return defaultMonitor;
},
)();
};

/**
* Sets up the window for OSD.
*
* This function hooks various services and settings to the window to handle its visibility based on the OSD configuration.
*
* @param self The Widget.Window instance to set up.
*/
export const windowSetup = (self: Widget.Window): void => {
self.hook(enable, () => {
handleReveal(self, 'visible');
});

self.hook(brightnessService, 'notify::screen', () => {
handleReveal(self, 'visible');
});

self.hook(brightnessService, 'notify::kbd', () => {
handleReveal(self, 'visible');
});

Variable.derive(
[bind(audioService.defaultMicrophone, 'volume'), bind(audioService.defaultMicrophone, 'mute')],
() => {
handleReveal(self, 'visible');
},
);

Variable.derive([bind(audioService.defaultSpeaker, 'volume'), bind(audioService.defaultSpeaker, 'mute')], () => {
handleReveal(self, 'visible');
});
};

/**
Expand All @@ -149,25 +73,25 @@ export const windowSetup = (self: Widget.Window): void => {
*/
export const revealerSetup = (self: Widget.Revealer): void => {
self.hook(enable, () => {
handleReveal(self, 'revealChild');
handleReveal(self);
});

self.hook(brightnessService, 'notify::screen', () => {
handleReveal(self, 'revealChild');
handleReveal(self);
});

self.hook(brightnessService, 'notify::kbd', () => {
handleReveal(self, 'revealChild');
handleReveal(self);
});

Variable.derive(
[bind(audioService.defaultMicrophone, 'volume'), bind(audioService.defaultMicrophone, 'mute')],
() => {
handleReveal(self, 'revealChild');
handleReveal(self);
},
);

Variable.derive([bind(audioService.defaultSpeaker, 'volume'), bind(audioService.defaultSpeaker, 'mute')], () => {
handleReveal(self, 'revealChild');
handleReveal(self);
});
};
12 changes: 8 additions & 4 deletions src/components/osd/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ import options from 'src/options';
import { getPosition } from 'src/lib/utils';
import { bind } from 'astal';
import { Astal } from 'astal/gtk3';
import { getOsdMonitor, windowSetup } from './helpers';
import { getOsdMonitor } from './helpers';
import { OsdRevealer } from './OsdRevealer';

const { location } = options.theme.osd;

export default (): JSX.Element => {
return (
<window
monitor={getOsdMonitor()}
monitor={getOsdMonitor()()}
name={'indicator'}
namespace={'indicator'}
className={'indicator'}
visible={false}
visible={true}
layer={bind(options.tear).as((tear) => (tear ? Astal.Layer.TOP : Astal.Layer.OVERLAY))}
anchor={bind(location).as((anchorPoint) => getPosition(anchorPoint))}
setup={windowSetup}
setup={(self) => {
getOsdMonitor().subscribe(() => {
self.set_click_through(true);
});
}}
clickThrough
>
<OsdRevealer />
Expand Down
3 changes: 2 additions & 1 deletion src/components/settings/pages/config/osd/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ export const OSDSettings = (): JSX.Element => {
subtitle="OSD follows monitor of cursor"
type="boolean"
/>
<Option opt={options.theme.osd.radius} title="Radius" subtitle="Radius of the OSD" type="string" />
<Option
opt={options.theme.osd.margins}
title="Margins"
subtitle="Format: top right bottom left"
type="string"
/>
<Option opt={options.theme.osd.border.size} title="Border Size" type="string" />
<Option opt={options.theme.osd.radius} title="Radius" subtitle="Radius of the OSD" type="string" />
<Option
opt={options.theme.osd.muted_zero}
title="Mute Volume as Zero"
Expand Down
1 change: 1 addition & 0 deletions src/components/settings/pages/theme/osd/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const OsdTheme = (): JSX.Element => {
min={0}
max={100}
/>
<Option opt={options.theme.osd.border.color} title="Border" type="color" />
<Option opt={options.theme.osd.bar_color} title="Bar" type="color" />
<Option
opt={options.theme.osd.bar_overflow_color}
Expand Down
4 changes: 4 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ const options = mkOptions(CONFIG, {
enable: opt(true),
orientation: opt<OSDOrientation>('vertical'),
opacity: opt(100),
border: {
size: opt('0em'),
color: opt(colors.lavender),
},
bar_container: opt(colors.crust),
icon_container: opt(tertiary_colors.lavender),
bar_color: opt(tertiary_colors.lavender),
Expand Down
Loading

0 comments on commit d2e02f5

Please sign in to comment.