From e7a0fe416ffe8088956f5b8b7f20295f2f2b3e25 Mon Sep 17 00:00:00 2001
From: matt1432 <matt@nelim.org>
Date: Thu, 11 Jan 2024 10:25:53 -0500
Subject: [PATCH] fix(ags): use hover events and Gdk cursor method

---
 .../wim/config/ags/js/media-player/mpris.js   | 33 ++++++++++-
 .../config/ags/js/notifications/gesture.js    | 39 ++++++++++--
 .../ags/js/on-screen-keyboard/keyboard.js     | 40 +++++++++----
 .../config/ags/js/on-screen-keyboard/keys.js  | 48 ++++++++++++---
 .../wim/config/ags/js/overview/dragndrop.js   | 46 ++++++++++-----
 .../ags/js/quick-settings/slider-box.js       | 59 +++++++++++++++++--
 .../ags/js/quick-settings/toggle-button.js    | 47 ++++++++++-----
 7 files changed, 249 insertions(+), 63 deletions(-)

diff --git a/devices/wim/config/ags/js/media-player/mpris.js b/devices/wim/config/ags/js/media-player/mpris.js
index 8913b4a2..447c307e 100644
--- a/devices/wim/config/ags/js/media-player/mpris.js
+++ b/devices/wim/config/ags/js/media-player/mpris.js
@@ -174,13 +174,15 @@ export const PlayerIcon = (player, overlay) => {
     });
 };
 
+const { Gdk } = imports.gi;
+const display = Gdk.Display.get_default();
+
 /**
  * @param {Player} player
  * @param {Variable} colors
  */
 export const PositionSlider = (player, colors) => Slider({
     class_name: 'position-slider',
-    cursor: 'pointer',
     vpack: 'center',
     hexpand: true,
     draw_value: false,
@@ -214,11 +216,36 @@ export const PositionSlider = (player, colors) => Slider({
                     `);
                 }
             })
+
+            // OnClick
             .on('button-press-event', () => {
-                self.cursor = 'grabbing';
+                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                    display,
+                    'grabbing',
+                ));
             })
+
+            // OnRelease
             .on('button-release-event', () => {
-                self.cursor = 'pointer';
+                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                    display,
+                    'pointer',
+                ));
+            })
+
+            // OnHover
+            .on('enter-notify-event', () => {
+                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                    display,
+                    'pointer',
+                ));
+                self.toggleClassName('hover', true);
+            })
+
+            // OnHoverLost
+            .on('leave-notify-event', () => {
+                self.window.set_cursor(null);
+                self.toggleClassName('hover', false);
             });
     },
 });
diff --git a/devices/wim/config/ags/js/notifications/gesture.js b/devices/wim/config/ags/js/notifications/gesture.js
index f0d7e6d2..7b5e67bc 100644
--- a/devices/wim/config/ags/js/notifications/gesture.js
+++ b/devices/wim/config/ags/js/notifications/gesture.js
@@ -5,7 +5,8 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
 
 import { HasNotifs } from './base.js';
 
-const { Gtk } = imports.gi;
+const { Gdk, Gtk } = imports.gi;
+const display = Gdk.Display.get_default();
 
 const MAX_OFFSET = 200;
 const OFFSCREEN = 300;
@@ -45,19 +46,45 @@ export default ({
 }) => {
     const widget = EventBox({
         ...props,
-        cursor: 'grab',
 
         setup: (self) => {
             self
-                .on('leave-notify-event', () => {
-                    if (self.attribute.hovered) {
-                        self.attribute.hovered = false;
-                    }
+                // OnClick
+                .on('button-press-event', () => {
+                    self.window.set_cursor(Gdk.Cursor.new_from_name(
+                        display,
+                        'grabbing',
+                    ));
                 })
+
+                // OnRelease
+                .on('button-release-event', () => {
+                    self.window.set_cursor(Gdk.Cursor.new_from_name(
+                        display,
+                        'grab',
+                    ));
+                })
+
+                // OnHover
                 .on('enter-notify-event', () => {
+                    self.window.set_cursor(Gdk.Cursor.new_from_name(
+                        display,
+                        'grab',
+                    ));
+                    self.toggleClassName('hover', true);
                     if (!self.attribute.hovered) {
                         self.attribute.hovered = true;
                     }
+                })
+
+                // OnHoverLost
+                .on('leave-notify-event', () => {
+                    self.window.set_cursor(null);
+                    self.toggleClassName('hover', false);
+
+                    if (self.attribute.hovered) {
+                        self.attribute.hovered = false;
+                    }
                 });
         },
 
diff --git a/devices/wim/config/ags/js/on-screen-keyboard/keyboard.js b/devices/wim/config/ags/js/on-screen-keyboard/keyboard.js
index 88eb8a9e..a1947f48 100644
--- a/devices/wim/config/ags/js/on-screen-keyboard/keyboard.js
+++ b/devices/wim/config/ags/js/on-screen-keyboard/keyboard.js
@@ -1,5 +1,8 @@
 import { Box, CenterBox, Label, ToggleButton } from 'resource:///com/github/Aylur/ags/widget.js';
 
+const { Gdk } = imports.gi;
+const display = Gdk.Display.get_default();
+
 import Separator from '../misc/separator.js';
 import RoundedCorner from '../corners/screen-corners.js';
 import Key from './keys.js';
@@ -34,21 +37,38 @@ export default (window) => Box({
 
                     children: [
                         ToggleButton({
-                            cursor: 'pointer',
                             class_name: 'button',
                             active: true,
                             vpack: 'center',
 
                             setup: (self) => {
-                                self.on('toggled', () => {
-                                    self.toggleClassName(
-                                        'toggled',
-                                        self.get_active(),
-                                    );
-                                    window.exclusivity = self.get_active() ?
-                                        'exclusive' :
-                                        'normal';
-                                });
+                                self
+                                    .on('toggled', () => {
+                                        self.toggleClassName(
+                                            'toggled',
+                                            self.get_active(),
+                                        );
+                                        window.exclusivity = self.get_active() ?
+                                            'exclusive' :
+                                            'normal';
+                                    })
+
+                                    // OnHover
+                                    .on('enter-notify-event', () => {
+                                        self.window.set_cursor(
+                                            Gdk.Cursor.new_from_name(
+                                                display,
+                                                'pointer',
+                                            ),
+                                        );
+                                        self.toggleClassName('hover', true);
+                                    })
+
+                                    // OnHoverLost
+                                    .on('leave-notify-event', () => {
+                                        self.window.set_cursor(null);
+                                        self.toggleClassName('hover', false);
+                                    });
                             },
 
                             child: Label('Exclusive'),
diff --git a/devices/wim/config/ags/js/on-screen-keyboard/keys.js b/devices/wim/config/ags/js/on-screen-keyboard/keys.js
index a210a43d..f8e28593 100644
--- a/devices/wim/config/ags/js/on-screen-keyboard/keys.js
+++ b/devices/wim/config/ags/js/on-screen-keyboard/keys.js
@@ -4,7 +4,8 @@ import Brightness from '../../services/brightness.js';
 import { Box, EventBox, Label } from 'resource:///com/github/Aylur/ags/widget.js';
 import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
 
-const { Gtk } = imports.gi;
+const { Gdk, Gtk } = imports.gi;
+const display = Gdk.Display.get_default();
 
 import Separator from '../misc/separator.js';
 
@@ -78,7 +79,6 @@ const ModKey = (key) => {
     }
 
     const button = EventBox({
-        cursor: 'pointer',
         class_name: 'key',
 
         on_primary_click_release: (self) => {
@@ -92,13 +92,29 @@ const ModKey = (key) => {
         },
 
         setup: (self) => {
-            self.hook(NormalClick, () => {
-                Mod.value = false;
+            self
+                .hook(NormalClick, () => {
+                    Mod.value = false;
 
-                // @ts-expect-error
-                self.child.toggleClassName('active', false);
-                execAsync(`ydotool key ${key.keycode}:0`);
-            });
+                    // @ts-expect-error
+                    self.child.toggleClassName('active', false);
+                    execAsync(`ydotool key ${key.keycode}:0`);
+                })
+
+                // OnHover
+                .on('enter-notify-event', () => {
+                    self.window.set_cursor(Gdk.Cursor.new_from_name(
+                        display,
+                        'pointer',
+                    ));
+                    self.toggleClassName('hover', true);
+                })
+
+                // OnHoverLost
+                .on('leave-notify-event', () => {
+                    self.window.set_cursor(null);
+                    self.toggleClassName('hover', false);
+                });
         },
         child: Label({
             class_name: `mod ${key.label}`,
@@ -117,7 +133,6 @@ const ModKey = (key) => {
 /** @param {Object} key */
 const RegularKey = (key) => {
     const widget = EventBox({
-        cursor: 'pointer',
         class_name: 'key',
 
         child: Label({
@@ -157,6 +172,21 @@ const RegularKey = (key) => {
 
                         self.toggleClassName('altgr', AltGr.value);
                         self.label = AltGr.value ? key.labelAltGr : key.label;
+                    })
+
+                    // OnHover
+                    .on('enter-notify-event', () => {
+                        self.window.set_cursor(Gdk.Cursor.new_from_name(
+                            display,
+                            'pointer',
+                        ));
+                        self.toggleClassName('hover', true);
+                    })
+
+                    // OnHoverLost
+                    .on('leave-notify-event', () => {
+                        self.window.set_cursor(null);
+                        self.toggleClassName('hover', false);
                     });
             },
         }),
diff --git a/devices/wim/config/ags/js/overview/dragndrop.js b/devices/wim/config/ags/js/overview/dragndrop.js
index e841c6d5..e7399446 100644
--- a/devices/wim/config/ags/js/overview/dragndrop.js
+++ b/devices/wim/config/ags/js/overview/dragndrop.js
@@ -8,6 +8,7 @@ const { Gtk, Gdk } = imports.gi;
 import { updateClients } from './clients.js';
 
 const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)];
+const display = Gdk.Display.get_default();
 
 /**
  * @typedef {import('types/widgets/button').default} Button
@@ -80,8 +81,6 @@ export const WindowButton = ({
 }) => Button({
     ...props,
 
-    cursor: 'pointer',
-
     setup: (self) => {
         self.drag_source_set(
             Gdk.ModifierType.BUTTON1_MASK,
@@ -89,20 +88,39 @@ export const WindowButton = ({
             Gdk.DragAction.COPY,
         );
 
-        self.on('drag-data-get', (_w, _c, data) => {
-            data.set_text(address, address.length);
-        });
+        self
+            .on('drag-data-get', (_w, _c, data) => {
+                data.set_text(address, address.length);
+            })
 
-        self.on('drag-begin', (_, context) => {
-            Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self));
-            // @ts-expect-error
-            self.get_parent()?.set_reveal_child(false);
-        });
+            .on('drag-begin', (_, context) => {
+                Gtk.drag_set_icon_surface(
+                    context,
+                    createSurfaceFromWidget(self),
+                );
+                // @ts-expect-error
+                self.get_parent()?.set_reveal_child(false);
+            })
 
-        self.on('drag-end', () => {
-            self.get_parent()?.destroy();
+            .on('drag-end', () => {
+                self.get_parent()?.destroy();
 
-            updateClients(mainBox);
-        });
+                updateClients(mainBox);
+            })
+
+            // OnHover
+            .on('enter-notify-event', () => {
+                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                    display,
+                    'pointer',
+                ));
+                self.toggleClassName('hover', true);
+            })
+
+            // OnHoverLost
+            .on('leave-notify-event', () => {
+                self.window.set_cursor(null);
+                self.toggleClassName('hover', false);
+            });
     },
 });
diff --git a/devices/wim/config/ags/js/quick-settings/slider-box.js b/devices/wim/config/ags/js/quick-settings/slider-box.js
index 88a07688..f6896a07 100644
--- a/devices/wim/config/ags/js/quick-settings/slider-box.js
+++ b/devices/wim/config/ags/js/quick-settings/slider-box.js
@@ -2,6 +2,9 @@ import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
 
 import { Box, Slider, Icon } from 'resource:///com/github/Aylur/ags/widget.js';
 
+const { Gdk } = imports.gi;
+const display = Gdk.Display.get_default();
+
 import Brightness from '../../services/brightness.js';
 import { SpeakerIcon } from '../misc/audio-icons.js';
 
@@ -25,7 +28,6 @@ export default () => Box({
                 }),
 
                 Slider({
-                    cursor: 'pointer',
                     vpack: 'center',
                     max: 0.999,
                     draw_value: false,
@@ -42,12 +44,35 @@ export default () => Box({
                                 self.value = Audio.speaker?.volume || 0;
                             }, 'speaker-changed')
 
+                            // OnClick
                             .on('button-press-event', () => {
-                                self.cursor = 'grabbing';
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'grabbing',
+                                ));
                             })
 
+                            // OnRelease
                             .on('button-release-event', () => {
-                                self.cursor = 'pointer';
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'pointer',
+                                ));
+                            })
+
+                            // OnHover
+                            .on('enter-notify-event', () => {
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'pointer',
+                                ));
+                                self.toggleClassName('hover', true);
+                            })
+
+                            // OnHoverLost
+                            .on('leave-notify-event', () => {
+                                self.window.set_cursor(null);
+                                self.toggleClassName('hover', false);
                             });
                     },
                 }),
@@ -66,7 +91,6 @@ export default () => Box({
                 }),
 
                 Slider({
-                    cursor: 'pointer',
                     vpack: 'center',
                     draw_value: false,
 
@@ -80,12 +104,35 @@ export default () => Box({
                                 self.value = Brightness.screen;
                             }, 'screen')
 
+                            // OnClick
                             .on('button-press-event', () => {
-                                self.cursor = 'grabbing';
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'grabbing',
+                                ));
                             })
 
+                            // OnRelease
                             .on('button-release-event', () => {
-                                self.cursor = 'pointer';
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'pointer',
+                                ));
+                            })
+
+                            // OnHover
+                            .on('enter-notify-event', () => {
+                                self.window.set_cursor(Gdk.Cursor.new_from_name(
+                                    display,
+                                    'pointer',
+                                ));
+                                self.toggleClassName('hover', true);
+                            })
+
+                            // OnHoverLost
+                            .on('leave-notify-event', () => {
+                                self.window.set_cursor(null);
+                                self.toggleClassName('hover', false);
                             });
                     },
                 }),
diff --git a/devices/wim/config/ags/js/quick-settings/toggle-button.js b/devices/wim/config/ags/js/quick-settings/toggle-button.js
index d22b8532..991b2051 100644
--- a/devices/wim/config/ags/js/quick-settings/toggle-button.js
+++ b/devices/wim/config/ags/js/quick-settings/toggle-button.js
@@ -3,12 +3,13 @@ import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
 
 import { CenterBox, Icon, ToggleButton } from 'resource:///com/github/Aylur/ags/widget.js';
 
+const { Gdk } = imports.gi;
+const display = Gdk.Display.get_default();
+
 
 /** @param {import('types/widgets/revealer').default} rev */
 export default (rev) => CenterBox({
     center_widget: ToggleButton({
-        cursor: 'pointer',
-
         setup: (self) => {
             // Open at startup if there are players
             const id = Mpris.connect('changed', () => {
@@ -16,24 +17,40 @@ export default (rev) => CenterBox({
                 Mpris.disconnect(id);
             });
 
-            self.on('toggled', () => {
-                if (self.get_active()) {
-                    self.child
+            self
+                .on('toggled', () => {
+                    if (self.get_active()) {
+                        self.child
                         // @ts-expect-error
-                        ?.setCss('-gtk-icon-transform: rotate(0deg);');
-                    rev.reveal_child = true;
-                }
-                else {
-                    self.child
+                            ?.setCss('-gtk-icon-transform: rotate(0deg);');
+                        rev.reveal_child = true;
+                    }
+                    else {
+                        self.child
                         // @ts-expect-error
-                        ?.setCss('-gtk-icon-transform: rotate(180deg);');
-                    rev.reveal_child = false;
-                }
-            });
+                            ?.setCss('-gtk-icon-transform: rotate(180deg);');
+                        rev.reveal_child = false;
+                    }
+                })
+
+                // OnHover
+                .on('enter-notify-event', () => {
+                    self.window.set_cursor(Gdk.Cursor.new_from_name(
+                        display,
+                        'pointer',
+                    ));
+                    self.toggleClassName('hover', true);
+                })
+
+                // OnHoverLost
+                .on('leave-notify-event', () => {
+                    self.window.set_cursor(null);
+                    self.toggleClassName('hover', false);
+                });
         },
 
         child: Icon({
-            icon: `${App.configDir }/icons/down-large.svg`,
+            icon: `${App.configDir}/icons/down-large.svg`,
             class_name: 'arrow',
             css: '-gtk-icon-transform: rotate(180deg);',
         }),