refactor(ags): typecheck popupwins and make cursorbox its own thing

This commit is contained in:
matt1432 2023-12-18 23:20:32 -05:00
parent 065cb0ce5f
commit e1e38fc18f
27 changed files with 215 additions and 176 deletions

View file

@ -4,7 +4,7 @@ import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
import { Box, Icon, Label } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Icon, Label } from 'resource:///com/github/Aylur/ags/widget.js';
import { lookUpIcon } from 'resource:///com/github/Aylur/ags/utils.js'; import { lookUpIcon } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
/** /**
@ -50,14 +50,13 @@ export default (app) => {
], ],
}); });
return CursorBox({
return EventBox({
hexpand: true, hexpand: true,
class_name: 'app', class_name: 'app',
attribute: { app }, attribute: { app },
onPrimaryClickRelease: (self) => { on_primary_click_release: (self) => {
App.closeWindow('applauncher'); App.closeWindow('applauncher');
Hyprland.sendMessage(`dispatch exec sh -c Hyprland.sendMessage(`dispatch exec sh -c
${self.attribute.app.executable}`); ${self.attribute.app.executable}`);

View file

@ -78,10 +78,9 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
}, },
on_change: ({ text }) => { on_change: ({ text }) => {
if (!text) { if (text === null) {
return; return;
} }
setSort(text); setSort(text);
let visibleApps = 0; let visibleApps = 0;

View file

@ -4,13 +4,13 @@ import { Label } from 'resource:///com/github/Aylur/ags/widget.js';
const { DateTime } = imports.gi.GLib; const { DateTime } = imports.gi.GLib;
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
export default () => EventBox({ export default () => CursorBox({
className: 'toggle-off', class_name: 'toggle-off',
onPrimaryClickRelease: () => App.toggleWindow('calendar'), on_primary_click_release: () => App.toggleWindow('calendar'),
setup: (self) => { setup: (self) => {
self.hook(App, (_, windowName, visible) => { self.hook(App, (_, windowName, visible) => {

View file

@ -2,7 +2,7 @@ import { Label } from 'resource:///com/github/Aylur/ags/widget.js';
import Variable from 'resource:///com/github/Aylur/ags/variable.js'; import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
import Persist from '../../misc/persist.js'; import Persist from '../../misc/persist.js';
const HeartState = Variable(''); const HeartState = Variable('');
@ -16,8 +16,8 @@ Persist({
}); });
export default () => EventBox({ export default () => CursorBox({
onPrimaryClickRelease: () => { on_primary_click_release: () => {
HeartState.value = HeartState.value === '' ? '󰣐' : ''; HeartState.value = HeartState.value === '' ? '󰣐' : '';
}, },

View file

@ -3,18 +3,18 @@ import Notifications from 'resource:///com/github/Aylur/ags/service/notification
import { Box, CenterBox, Icon, Label } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, CenterBox, Icon, Label } from 'resource:///com/github/Aylur/ags/widget.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
import Separator from '../../misc/separator.js'; import Separator from '../../misc/separator.js';
const SPACING = 4; const SPACING = 4;
export default () => EventBox({ export default () => CursorBox({
className: 'toggle-off', class_name: 'toggle-off',
onPrimaryClickRelease: (self) => { on_primary_click_release: (self) => {
// @ts-expect-error // @ts-expect-error
App.getWindow('notification-center')?.setXPos( App.getWindow('notification-center')?.attribute.set_x_pos(
self.get_allocation(), self.get_allocation(),
'right', 'right',
); );

View file

@ -1,13 +1,13 @@
import { Label } from 'resource:///com/github/Aylur/ags/widget.js'; import { Label } from 'resource:///com/github/Aylur/ags/widget.js';
import Tablet from '../../../services/tablet.js'; import Tablet from '../../../services/tablet.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
export default () => EventBox({ export default () => CursorBox({
className: 'toggle-off', class_name: 'toggle-off',
onPrimaryClickRelease: () => Tablet.toggleOsk(), on_primary_click_release: () => Tablet.toggleOsk(),
child: Label({ child: Label({
class_name: 'osk-toggle', class_name: 'osk-toggle',

View file

@ -8,20 +8,18 @@ import Brightness from './brightness.js';
import KeyboardLayout from './keyboard-layout.js'; import KeyboardLayout from './keyboard-layout.js';
import Network from './network.js'; import Network from './network.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
import Separator from '../../misc/separator.js'; import Separator from '../../misc/separator.js';
const SPACING = 4; const SPACING = 4;
export default () => EventBox({ export default () => CursorBox({
className: 'toggle-off', class_name: 'toggle-off',
onHoverLost: () => { /**/ }, on_primary_click_release: (self) => {
onPrimaryClickRelease: (self) => {
// @ts-expect-error // @ts-expect-error
App.getWindow('notification-center').setXPos( App.getWindow('notification-center').attribute.set_x_pos(
self.get_allocation(), self.get_allocation(),
'right', 'right',
); );

View file

@ -1,13 +1,13 @@
import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js';
import Tablet from '../../../services/tablet.js'; import Tablet from '../../../services/tablet.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
export default () => EventBox({ export default () => CursorBox({
class_name: 'toggle-off', class_name: 'toggle-off',
onPrimaryClickRelease: () => Tablet.toggleMode(), on_primary_click_release: () => Tablet.toggleMode(),
child: Box({ child: Box({
class_name: 'tablet-toggle', class_name: 'tablet-toggle',

View file

@ -3,7 +3,7 @@ import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
import { timeout } from 'resource:///com/github/Aylur/ags/utils.js'; import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
import { Box, Overlay, Revealer } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Overlay, Revealer } from 'resource:///com/github/Aylur/ags/widget.js';
import EventBox from '../../misc/cursorbox.js'; import CursorBox from '../../misc/cursorbox.js';
const URGENT_DURATION = 1000; const URGENT_DURATION = 1000;
@ -16,10 +16,10 @@ const Workspace = ({ id }) => {
transition: 'slide_right', transition: 'slide_right',
attribute: { id }, attribute: { id },
child: EventBox({ child: CursorBox({
tooltipText: `${id}`, tooltipText: `${id}`,
onPrimaryClickRelease: () => { on_primary_click_release: () => {
Hyprland.sendMessage(`dispatch workspace ${id}`); Hyprland.sendMessage(`dispatch workspace ${id}`);
}, },
@ -84,7 +84,7 @@ export default () => {
const updateHighlight = (self) => { const updateHighlight = (self) => {
const currentId = Hyprland.active.workspace.id; const currentId = Hyprland.active.workspace.id;
// @ts-expect-error // @ts-expect-error
const indicators = self.get_parent().get_children()[0].child.children; const indicators = self.get_parent().get_children()[0].child.child.children;
const currentIndex = Array.from(indicators) const currentIndex = Array.from(indicators)
.findIndex((w) => w.attribute.id === currentId); .findIndex((w) => w.attribute.id === currentId);
@ -105,7 +105,7 @@ export default () => {
const widget = Overlay({ const widget = Overlay({
pass_through: true, pass_through: true,
overlays: [highlight], overlays: [highlight],
child: EventBox({ child: CursorBox({
child: Box({ child: Box({
class_name: 'workspaces', class_name: 'workspaces',

View file

@ -1,7 +1,7 @@
import { timeout } from 'resource:///com/github/Aylur/ags/utils.js'; import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
import { Box, EventBox, Overlay } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, EventBox, Overlay } from 'resource:///com/github/Aylur/ags/widget.js';
import Gtk from 'gi://Gtk'; const { Gtk } = imports.gi;
const MAX_OFFSET = 200; const MAX_OFFSET = 200;
const OFFSCREEN = 500; const OFFSCREEN = 500;
@ -61,10 +61,9 @@ export default ({
setup(self); setup(self);
self self
// @ts-expect-error
.hook(gesture, (overlay, realGesture) => { .hook(gesture, (overlay, realGesture) => {
if (realGesture) { if (realGesture) {
overlay.attribute.list().forEach((over) => { Array.from(overlay.attribute.list()).forEach((over) => {
over.visible = true; over.visible = true;
}); });
} }

View file

@ -4,7 +4,7 @@ import { Button, Icon, Label, Stack, Slider, CenterBox, Box } from 'resource:///
import { execAsync, lookUpIcon, readFileAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { execAsync, lookUpIcon, readFileAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import Separator from '../misc/separator.js'; import Separator from '../misc/separator.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
/** /**
* @typedef {import('types/service/mpris').MprisPlayer} Player * @typedef {import('types/service/mpris').MprisPlayer} Player
@ -137,10 +137,10 @@ export const PlayerIcon = (player, overlay) => {
* @param {Overlay=} widget * @param {Overlay=} widget
* @param {Overlay=} over * @param {Overlay=} over
*/ */
const playerIcon = (p, widget, over) => EventBox({ const playerIcon = (p, widget, over) => CursorBox({
tooltip_text: p.identity || '', tooltip_text: p.identity || '',
onPrimaryClickRelease: () => { on_primary_click_release: () => {
widget?.attribute.moveToTop(over); widget?.attribute.moveToTop(over);
}, },
@ -223,7 +223,13 @@ export const PositionSlider = (player, colors) => Slider({
}, },
}); });
const PlayerButton = ({ player, colors, items, onClick, prop }) => EventBox({ const PlayerButton = ({
player,
colors,
items,
onClick,
prop,
}) => CursorBox({
child: Button({ child: Button({
attribute: { hovered: false }, attribute: { hovered: false },
child: Stack({ items }), child: Stack({ items }),

View file

@ -17,13 +17,13 @@ const micIcons = {
}; };
export const SpeakerIcon = Variable(); export const SpeakerIcon = Variable('');
Audio.connect('speaker-changed', () => { Audio.connect('speaker-changed', () => {
if (!Audio.speaker) { if (!Audio.speaker) {
return; return;
} }
if (Audio.speaker.stream.isMuted) { if (Audio.speaker.stream.is_muted) {
SpeakerIcon.value = speakerIcons[0]; SpeakerIcon.value = speakerIcons[0];
} }
else { else {
@ -37,13 +37,13 @@ Audio.connect('speaker-changed', () => {
} }
}); });
export const MicIcon = Variable(); export const MicIcon = Variable('');
Audio.connect('microphone-changed', () => { Audio.connect('microphone-changed', () => {
if (!Audio.microphone) { if (!Audio.microphone) {
return; return;
} }
if (Audio.microphone.stream.isMuted) { if (Audio.microphone.stream.is_muted) {
MicIcon.value = micIcons[0]; MicIcon.value = micIcons[0];
} }
else { else {

View file

@ -3,7 +3,10 @@ import App from 'resource:///com/github/Aylur/ags/app.js';
export default () => { export default () => {
Array.from(App.windows) Array.from(App.windows)
.filter((w) => w[1].closeOnUnfocus && w[1].closeOnUnfocus !== 'stay') // @ts-expect-error
.filter((w) => w[1].attribute?.close_on_unfocus &&
// @ts-expect-error
w[1].attribute?.close_on_unfocus !== 'stay')
.forEach((w) => { .forEach((w) => {
App.closeWindow(w[0]); App.closeWindow(w[0]);
}); });

View file

@ -1,49 +1,38 @@
import Variable from 'resource:///com/github/Aylur/ags/variable.js'; import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import { Button, EventBox } from 'resource:///com/github/Aylur/ags/widget.js'; import { EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
import Gtk from 'gi://Gtk'; const { Gtk } = imports.gi;
// TODO: wrap in another EventBox for disabled cursor // TODO: wrap in another EventBox for disabled cursor
/** /**
* @typedef {import('types/widget.js').Widget} Widget * @typedef {import('types/widgets/eventbox').EventBoxProps} EventBox
* @typedef {Widget & Object} CursorProps
* @property {boolean=} isButton
* @property {function(Widget):void=} onPrimaryClickRelease
* *
* @param {CursorProps} obj * @param {EventBox & {
* on_primary_click_release?: function(EventBox):void
* }} o
*/ */
export default ({ export default ({
isButton = false, attribute,
on_primary_click_release = () => {/**/},
onPrimaryClickRelease = (self) => {
self;
},
...props ...props
}) => { }) => {
// Make this variable to know if the function should // Make this variable to know if the function should
// be executed depending on where the click is released // be executed depending on where the click is released
const CanRun = Variable(true); const CanRun = Variable(true);
const Disabled = Variable(false);
let widgetFunc; const widget = EventBox({
if (isButton) {
widgetFunc = Button;
}
else {
widgetFunc = EventBox;
}
const widget = widgetFunc({
...props, ...props,
cursor: 'pointer', sensitive: Disabled.bind().transform((v) => !v),
on_primary_click_release: (self) => { on_primary_click_release: (self) => {
// Every click, do a one shot connect to // Every click, do a one shot connect to
// CanRun to wait for location of click // CanRun to wait for location of click
const id = CanRun.connect('changed', () => { const id = CanRun.connect('changed', () => {
if (CanRun.value) { if (CanRun.value) {
onPrimaryClickRelease(self); on_primary_click_release(self);
} }
CanRun.disconnect(id); CanRun.disconnect(id);
@ -51,9 +40,31 @@ export default ({
}, },
}); });
const wrapper = EventBox({
cursor: 'pointer',
attribute: {
...attribute,
disabled: Disabled,
get_child: () => widget.child,
set_child: (new_child) => {
widget.child = new_child;
},
},
child: widget,
}).hook(Disabled, (self) => {
self.cursor = Disabled.value ?
'not-allowed' :
'pointer';
});
const gesture = Gtk.GestureLongPress.new(widget); const gesture = Gtk.GestureLongPress.new(widget);
// @ts-expect-error
widget.hook(gesture, () => { widget.hook(gesture, () => {
const pointer = gesture.get_point(null); const pointer = gesture.get_point(null);
const x = pointer[1]; const x = pointer[1];
@ -69,5 +80,5 @@ export default ({
); );
}, 'end'); }, 'end');
return widget; return wrapper;
}; };

View file

@ -4,24 +4,35 @@ import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
import { Revealer, Box, Window } from 'resource:///com/github/Aylur/ags/widget.js'; import { Revealer, Box, Window } from 'resource:///com/github/Aylur/ags/widget.js';
import { timeout } from 'resource:///com/github/Aylur/ags/utils.js'; import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
/**
* @typedef {import('types/widgets/revealer').RevealerProps} RevProp
* @typedef {import('types/widgets/window').WindowProps} WinProp
*/
/**
* @param {WinProp & {
* transition?: RevProp['transition']
* transition_duration?: RevProp['transition_duration']
* onOpen?: function
* onClose?: function
* blur?: boolean
* close_on_unfocus?: 'none'|'stay'|'released'|'clicked'
* }} o
*/
export default ({ export default ({
// Revealer props
transition = 'slide_down', transition = 'slide_down',
transitionDuration = 500, transition_duration = 500,
// Optional: execute a function whenever
// the window pops up or goes away
onOpen = () => { /**/ }, onOpen = () => { /**/ },
onClose = () => { /**/ }, onClose = () => { /**/ },
// Window props // Window props
name, name,
child, child,
blur = false,
closeOnUnfocus = 'released',
visible = false, visible = false,
layer = 'overlay', layer = 'overlay',
blur = false,
close_on_unfocus = 'released',
...props ...props
}) => { }) => {
const window = Window({ const window = Window({
@ -30,11 +41,49 @@ export default ({
visible: false, visible: false,
...props, ...props,
attribute: {
set_x_pos: (
alloc = {},
side = 'right',
) => {
const width = window.get_display()
.get_monitor_at_point(alloc.x, alloc.y)
.get_geometry().width;
window.margins = [
window.margins[0],
side === 'right' ?
(width - alloc.x - alloc.width) :
window.margins[1],
window.margins[2],
side === 'right' ?
window.margins[3] :
(alloc.x - alloc.width),
];
},
// @ts-expect-error
get_child: () => window.child.children[0].child,
set_child: (newChild) => {
// @ts-expect-error
window.child.children[0].child = newChild;
// @ts-expect-error
window.child.children[0].show_all();
},
// This is for my custom pointers.js
close_on_unfocus,
},
setup: () => { setup: () => {
// Add way to make window open on startup // Add way to make window open on startup
const id = App.connect('config-parsed', () => { const id = App.connect('config-parsed', () => {
if (visible) { if (visible) {
App.openWindow(name); App.openWindow(String(name));
} }
App.disconnect(id); App.disconnect(id);
}); });
@ -56,18 +105,18 @@ export default ({
`, `,
child: Revealer({ child: Revealer({
transition, transition,
transitionDuration, transition_duration,
setup: (self) => { setup: (self) => {
self.hook(App, (_, currentName, isOpen) => { self.hook(App, (_, currentName, isOpen) => {
if (currentName === name) { if (currentName === name) {
self.revealChild = isOpen; self.reveal_child = isOpen;
if (isOpen) { if (isOpen) {
onOpen(window); onOpen(window);
} }
else { else {
timeout(transitionDuration, () => { timeout(Number(transition_duration), () => {
onClose(window); onClose(window);
}); });
} }
@ -80,39 +129,5 @@ export default ({
}), }),
}); });
window.setXPos = (
alloc,
side = 'right',
) => {
const width = window.get_display()
.get_monitor_at_point(alloc.x, alloc.y)
.get_geometry().width;
window.margins = [
window.margins[0],
side === 'right' ?
(width - alloc.x - alloc.width) :
window.margins[1],
window.margins[2],
side === 'right' ?
window.margins[3] :
(alloc.x - alloc.width),
];
};
// Make getting the original child passed in this
// function easier when making more code for the widget
window.getChild = () => window.child.children[0].child;
window.setChild = (newChild) => {
window.child.children[0].child = newChild;
window.child.children[0].show_all();
};
// This is for my custom pointers.js
window.closeOnUnfocus = closeOnUnfocus;
return window; return window;
}; };

View file

@ -1,6 +1,14 @@
import { Box } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box } from 'resource:///com/github/Aylur/ags/widget.js';
/**
* @param {number} size
* @param {{
* vertical?: boolean
* css?: string
* props?: import('types/widgets/box').BoxProps
* }} o
*/
export default (size, { export default (size, {
vertical = false, vertical = false,
css = '', css = '',

View file

@ -18,7 +18,7 @@ const getDragState = (box) => box.get_parent().get_parent()
.get_parent().get_parent().get_parent()._dragging; .get_parent().get_parent().get_parent()._dragging;
import Gesture from './gesture.js'; import Gesture from './gesture.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
const NotificationIcon = (notif) => { const NotificationIcon = (notif) => {
@ -75,8 +75,8 @@ const NotificationIcon = (notif) => {
} }
if (notif.image) { if (notif.image) {
return EventBox({ return CursorBox({
onPrimaryClickRelease: iconCmd, on_primary_click_release: iconCmd,
child: Box({ child: Box({
vpack: 'start', vpack: 'start',
@ -106,8 +106,8 @@ const NotificationIcon = (notif) => {
} }
return EventBox({ return CursorBox({
onPrimaryClickRelease: iconCmd, on_primary_click_release: iconCmd,
child: Box({ child: Box({
vpack: 'start', vpack: 'start',
@ -205,7 +205,7 @@ export const Notification = ({
}), }),
// Close button // Close button
EventBox({ CursorBox({
child: Button({ child: Button({
className: 'close-button', className: 'close-button',
vpack: 'start', vpack: 'start',

View file

@ -5,7 +5,7 @@ import { Button, Label, Box, Icon, Scrollable, Revealer } from 'resource:///com/
import { timeout } from 'resource:///com/github/Aylur/ags/utils.js'; import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
import { Notification, HasNotifs } from './base.js'; import { Notification, HasNotifs } from './base.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
const addNotif = (box, notif) => { const addNotif = (box, notif) => {
@ -55,7 +55,7 @@ const NotificationList = () => Box({
}); });
// Needs to be wrapped to still have onHover when disabled // Needs to be wrapped to still have onHover when disabled
const ClearButton = () => EventBox({ const ClearButton = () => CursorBox({
child: Button({ child: Button({
onPrimaryClickRelease: () => { onPrimaryClickRelease: () => {
Notifications.clear(); Notifications.clear();

View file

@ -8,7 +8,7 @@ export const NotifPopups = () => PopupWindow({
anchor: ['top', 'left'], anchor: ['top', 'left'],
visible: true, visible: true,
transition: 'none', transition: 'none',
closeOnUnfocus: 'stay', close_on_unfocus: 'stay',
child: PopUpsWidget(), child: PopUpsWidget(),
}); });

View file

@ -53,8 +53,8 @@ export default () => PopupWindow({
name: 'osd', name: 'osd',
anchor: ['bottom'], anchor: ['bottom'],
exclusivity: 'ignore', exclusivity: 'ignore',
closeOnUnfocus: 'stay', close_on_unfocus: 'stay',
transition: 'slide_up', transition: 'slide_up',
transitionDuration: 200, transition_duration: 200,
child: OSDs(), child: OSDs(),
}); });

View file

@ -1,12 +1,10 @@
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
import { EventBox } from 'resource:///com/github/Aylur/ags/widget.js'; import { Button, EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
import Gtk from 'gi://Gtk';
import Gdk from 'gi://Gdk';
import Cairo from 'cairo'; import Cairo from 'cairo';
const { Gtk, Gdk } = imports.gi;
import Button from '../misc/cursorbox.js';
import { updateClients } from './clients.js'; import { updateClients } from './clients.js';
const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)];
@ -58,10 +56,15 @@ export const WorkspaceDrop = (props) => EventBox({
}, },
}); });
export const WindowButton = ({ address, mainBox, ...props } = {}) => Button({ export const WindowButton = ({
isButton: true, address,
mainBox,
...props
} = {}) => Button({
...props, ...props,
cursor: 'pointer',
setup: (self) => { setup: (self) => {
self.drag_source_set( self.drag_source_set(
Gdk.ModifierType.BUTTON1_MASK, Gdk.ModifierType.BUTTON1_MASK,

View file

@ -93,15 +93,15 @@ export const Overview = () => {
}; };
export default () => { export default () => {
const window = PopupWindow({ const win = PopupWindow({
name: 'overview', name: 'overview',
blur: true, blur: true,
closeOnUnfocus: 'none', close_on_unfocus: 'none',
onOpen: (win) => { onOpen: () => {
win.setChild(Overview()); win.attribute.set_child(Overview());
win.getChild().getChild().update(); win.attribute.get_child().getChild().update();
}, },
}); });
return window; return win;
}; };

View file

@ -4,17 +4,17 @@ import { CenterBox, Label } from 'resource:///com/github/Aylur/ags/widget.js';
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import PopupWindow from './misc/popup.js'; import PopupWindow from './misc/popup.js';
import Button from './misc/cursorbox.js'; import CursorBox from './misc/cursorbox.js';
const PowermenuWidget = () => CenterBox({ const PowermenuWidget = () => CenterBox({
className: 'powermenu', class_name: 'powermenu',
// @ts-expect-error
vertical: false, vertical: false,
startWidget: Button({ startWidget: CursorBox({
isButton: true, class_name: 'shutdown',
className: 'shutdown', on_primary_click_release: () => execAsync(['systemctl', 'poweroff'])
onPrimaryClickRelease: () => execAsync(['systemctl', 'poweroff'])
.catch(print), .catch(print),
child: Label({ child: Label({
@ -22,10 +22,9 @@ const PowermenuWidget = () => CenterBox({
}), }),
}), }),
centerWidget: Button({ centerWidget: CursorBox({
isButton: true, class_name: 'reboot',
className: 'reboot', on_primary_click_release: () => execAsync(['systemctl', 'reboot'])
onPrimaryClickRelease: () => execAsync(['systemctl', 'reboot'])
.catch(print), .catch(print),
child: Label({ child: Label({
@ -33,10 +32,9 @@ const PowermenuWidget = () => CenterBox({
}), }),
}), }),
endWidget: Button({ endWidget: CursorBox({
isButton: true, class_name: 'logout',
className: 'logout', on_primary_click_release: () => Hyprland.sendMessage('dispatch exit')
onPrimaryClickRelease: () => Hyprland.sendMessage('dispatch exit')
.catch(print), .catch(print),
child: Label({ child: Label({

View file

@ -3,7 +3,7 @@ import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
const SCROLL_THRESH_H = 200; const SCROLL_THRESH_H = 200;
const SCROLL_THRESH_N = 7; const SCROLL_THRESH_N = 7;
@ -42,8 +42,8 @@ const BluetoothDevice = (dev) => {
widget.add(Revealer({ widget.add(Revealer({
revealChild: true, revealChild: true,
transition: 'slide_down', transition: 'slide_down',
child: EventBox({ child: CursorBox({
onPrimaryClickRelease: () => dev.setConnection(true), on_primary_click_release: () => dev.setConnection(true),
child, child,
}), }),
})); }));

View file

@ -7,7 +7,7 @@ import { Box, Icon, Label, Revealer } from 'resource:///com/github/Aylur/ags/wid
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import { SpeakerIcon, MicIcon } from '../misc/audio-icons.js'; import { SpeakerIcon, MicIcon } from '../misc/audio-icons.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
import Separator from '../misc/separator.js'; import Separator from '../misc/separator.js';
import { NetworkMenu } from './network.js'; import { NetworkMenu } from './network.js';
@ -85,10 +85,10 @@ const GridButton = ({
className: 'grid-button', className: 'grid-button',
children: [ children: [
EventBox({ CursorBox({
className: 'left-part', className: 'left-part',
onPrimaryClickRelease: () => { on_primary_click_release: () => {
if (Activated.value) { if (Activated.value) {
secondaryCommand(); secondaryCommand();
} }
@ -100,10 +100,10 @@ const GridButton = ({
child: icon, child: icon,
}), }),
EventBox({ CursorBox({
className: 'right-part', className: 'right-part',
onPrimaryClickRelease: () => { on_primary_click_release: () => {
ButtonStates.forEach((state) => { ButtonStates.forEach((state) => {
if (state !== Activated) { if (state !== Activated) {
state.value = false; state.value = false;

View file

@ -5,7 +5,7 @@ import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js'; import CursorBox from '../misc/cursorbox.js';
const SCROLL_THRESH_H = 200; const SCROLL_THRESH_H = 200;
const SCROLL_THRESH_N = 7; const SCROLL_THRESH_N = 7;
@ -60,8 +60,8 @@ const AccessPoint = (ap) => {
widget.add(Revealer({ widget.add(Revealer({
revealChild: true, revealChild: true,
transition: 'slide_down', transition: 'slide_down',
child: EventBox({ child: CursorBox({
onPrimaryClickRelease: () => { on_primary_click_release: () => {
execAsync(`nmcli device wifi connect execAsync(`nmcli device wifi connect
${widget.ap.value.bssid}`).catch(print); ${widget.ap.value.bssid}`).catch(print);
}, },

View file

@ -62,7 +62,7 @@ class Pointers extends Service {
this.#getDevices(); this.#getDevices();
this.#udevClient.connect('uevent', (_, action) => { this.#udevClient.connect('uevent', (_, action) => {
if (action === 'add' || action === 'remove') { if (action === 'add' || action === 'remove') {
this.getDevices(); this.#getDevices();
if (this.#process) { if (this.#process) {
this.killProc(); this.killProc();
this.startProc(); this.startProc();
@ -139,9 +139,9 @@ class Pointers extends Service {
#initAppConnection() { #initAppConnection() {
App.connect('window-toggled', () => { App.connect('window-toggled', () => {
const anyVisibleAndClosable = Array.from(App.windows).some((w) => { const anyVisibleAndClosable = Array.from(App.windows).some((w) => {
const closable = w[1].closeOnUnfocus && const closable = w[1].attribute?.close_on_unfocus &&
!(w[1].closeOnUnfocus === 'none' || !(w[1].attribute?.close_on_unfocus === 'none' ||
w[1].closeOnUnfocus === 'stay'); w[1].attribute?.close_on_unfocus === 'stay');
return w[1].visible && closable; return w[1].visible && closable;
}); });
@ -158,8 +158,8 @@ class Pointers extends Service {
static detectClickedOutside(clickStage) { static detectClickedOutside(clickStage) {
const toClose = Array.from(App.windows).some((w) => { const toClose = Array.from(App.windows).some((w) => {
const closable = (w[1].closeOnUnfocus && const closable = (w[1].attribute?.close_on_unfocus &&
w[1].closeOnUnfocus === clickStage); w[1].attribute?.close_on_unfocus === clickStage);
return w[1].visible && closable; return w[1].visible && closable;
}); });
@ -181,8 +181,8 @@ class Pointers extends Service {
const widgets = key.levels['3'].filter((n) => { const widgets = key.levels['3'].filter((n) => {
const window = App.getWindow(n.namespace); const window = App.getWindow(n.namespace);
return window?.closeOnUnfocus && return window?.attribute?.close_on_unfocus &&
window?.closeOnUnfocus === clickStage; window?.attribute?.close_on_unfocus === clickStage;
}); });
if (pos.x > bar?.x && pos.x < bar?.x + bar?.w && if (pos.x > bar?.x && pos.x < bar?.x + bar?.w &&