Compare commits

..

3 commits

9 changed files with 178 additions and 103 deletions

View file

@ -32,7 +32,8 @@
"no-useless-escape": ["off"] "no-useless-escape": ["off"]
}, },
"globals": { "globals": {
"ags": "readonly", "Tablet": "readonly",
"Pointers": "readonly",
"ARGV": "readonly", "ARGV": "readonly",
"imports": "readonly", "imports": "readonly",
"print": "readonly", "print": "readonly",

View file

@ -1,39 +0,0 @@
#!/usr/bin/env bash
tablet() {
gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true
brightnessctl -d tpacpi::kbd_backlight s 0
"$HYPR_PATH"/autorotate.sh &
evtest --grab "/dev/input/by-path/platform-i8042-serio-0-event-kbd" &
evtest --grab "/dev/input/by-path/platform-i8042-serio-1-event-mouse" &
evtest --grab "/dev/input/by-path/platform-AMDI0010:02-event-mouse" &
evtest --grab "/dev/input/by-path/platform-thinkpad_acpi-event" &
evtest --grab "/dev/video-bus" &
evtest --grab "/dev/touchpad" &
}
laptop() {
gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false
brightnessctl -d tpacpi::kbd_backlight s 2
killall -r autorotate.sh
killall -r evtest
}
toggle () {
if [[ "$(gsettings get org.gnome.desktop.a11y.applications screen-keyboard-enabled)" == "false" ]]; then
echo "Tablet"
tablet > /dev/null
else
echo "Laptop"
laptop > /dev/null
fi
}
[[ $1 == "toggle" ]] && toggle
[[ $1 == "laptop" ]] && laptop
[[ $1 == "tablet" ]] && tablet

View file

@ -4,6 +4,12 @@ Array.prototype.remove = function (el) { this.splice(this.indexOf(el), 1); };
import App from 'resource:///com/github/Aylur/ags/app.js'; import App from 'resource:///com/github/Aylur/ags/app.js';
import { exec, execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { exec, execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import Tablet from './services/tablet.js';
globalThis.Tablet = Tablet;
import Pointers from './services/pointers.js';
globalThis.Pointers = Pointers;
import closeAll from './js/misc/closer.js'; import closeAll from './js/misc/closer.js';
globalThis.closeAll = closeAll; globalThis.closeAll = closeAll;

View file

@ -1,17 +1,16 @@
import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js';
import { subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js'; import EventBox from '../misc/cursorbox.js';
export default () => EventBox({ export default () => EventBox({
className: 'toggle-off', className: 'toggle-off',
onPrimaryClickRelease: self => { onPrimaryClickRelease: () => Tablet.toggleMode(),
subprocess(
['bash', '-c', '$AGS_PATH/tablet-toggle.sh toggle'], connections: [[Tablet, self => {
output => self.toggleClassName('toggle-on', output == 'Tablet'), self.toggleClassName('toggle-on', Tablet.tabletMode);
); }, 'mode-toggled']],
},
child: Box({ child: Box({
className: 'tablet-toggle', className: 'tablet-toggle',
vertical: false, vertical: false,

View file

@ -1,8 +1,5 @@
import App from 'resource:///com/github/Aylur/ags/app.js'; import App from 'resource:///com/github/Aylur/ags/app.js';
// TODO: find a way to not need this?
import Pointers from '../../services/pointers.js';
export default () => { export default () => {
Array.from(App.windows) Array.from(App.windows)

View file

@ -0,0 +1,162 @@
import Service from 'resource:///com/github/Aylur/ags/service.js';
import { execAsync, subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
import GUdev from 'gi://GUdev';
const ROTATION_MAPPING = {
'normal': 0,
'right-up': 3,
'bottom-up': 2,
'left-up': 1,
};
const SCREEN = 'desc:BOE 0x0964';
class Tablet extends Service {
static {
Service.register(this, {
'device-fetched': ['boolean'],
'autorotate-started': ['boolean'],
'autorotate-destroyed': ['boolean'],
'inputs-blocked': ['boolean'],
'inputs-unblocked': ['boolean'],
'laptop-mode': ['boolean'],
'tablet-mode': ['boolean'],
'mode-toggled': ['boolean'],
});
}
tabletMode = false;
autorotate = undefined;
blockedInputs = undefined;
udevClient = GUdev.Client.new(['input']);
get tabletMode() { return this.tabletMode; }
get autorotate() { return this.autorotate; }
constructor() {
super();
this.initUdevConnection();
}
blockInputs() {
if (this.blockedInputs)
return;
this.blockedInputs = subprocess(['libinput', 'debug-events', '--grab',
'--device', '/dev/input/by-path/platform-i8042-serio-0-event-kbd',
'--device', '/dev/input/by-path/platform-i8042-serio-1-event-mouse',
'--device', '/dev/input/by-path/platform-AMDI0010:02-event-mouse',
'--device', '/dev/input/by-path/platform-thinkpad_acpi-event',
'--device', '/dev/video-bus',
'--device', '/dev/touchpad',
],
() => {},
err => logError(err));
this.emit('inputs-blocked', true);
}
unblockInputs() {
if (this.blockedInputs) {
this.blockedInputs.force_exit();
this.blockedInputs = undefined;
this.emit('inputs-unblocked', true);
}
}
setTabletMode() {
execAsync(['gsettings', 'set', 'org.gnome.desktop.a11y.applications',
'screen-keyboard-enabled', 'true']).catch(print);
execAsync(['brightnessctl', '-d', 'tpacpi::kbd_backlight', 's', '0'])
.catch(print);
this.startAutorotate();
this.blockInputs();
this.tabletMode = true;
this.emit('tablet-mode', true);
this.emit('mode-toggled', true);
}
setLaptopMode() {
execAsync(['gsettings', 'set', 'org.gnome.desktop.a11y.applications',
'screen-keyboard-enabled', 'false']).catch(print);
execAsync(['brightnessctl', '-d', 'tpacpi::kbd_backlight', 's', '2'])
.catch(print);
this.killAutorotate();
this.unblockInputs();
this.tabletMode = false;
this.emit('laptop-mode', true);
this.emit('mode-toggled', true);
}
toggleMode() {
if (this.tabletMode)
this.setLaptopMode();
else
this.setTabletMode();
this.emit('mode-toggled', true);
}
initUdevConnection() {
this.getDevices();
this.udevClient.connect('uevent', (_, action) => {
if (action === 'add' || action === 'remove')
this.getDevices();
});
}
getDevices() {
this.devices = [];
execAsync(['hyprctl', 'devices', '-j']).then(out => {
const devices = JSON.parse(out);
devices['touch'].forEach(dev => {
this.devices.push(dev.name);
});
devices['tablets'].forEach(dev => {
this.devices.push(dev.name);
});
}).catch(print);
this.emit('device-fetched', true);
}
startAutorotate() {
if (this.autorotate)
return;
this.autorotate = subprocess(
['monitor-sensor'],
output => {
if (output.includes('orientation changed')) {
const orientation = ROTATION_MAPPING[output.split(' ').at(-1)];
execAsync(['hyprctl', 'keyword', 'monitor',
`${SCREEN},transform,${orientation}`]).catch(print);
this.devices.forEach(dev => {
execAsync(['hyprctl', 'keyword',
`device:"${dev}":transform`, String(orientation)]).catch(print);
});
}
},
err => logError(err),
);
this.emit('autorotate-started', true);
}
killAutorotate() {
if (this.autorotate) {
this.autorotate.force_exit();
this.autorotate = undefined;
this.emit('autorotate-destroyed', true);
}
}
}
const tabletService = new Tablet();
export default tabletService;

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
$AGS_PATH/tablet-toggle.sh laptop & ags -r 'Tablet.setLaptopMode()'
$LOCK_PATH/blur.sh $LOCK_PATH/blur.sh
gtklock gtklock

View file

@ -12,7 +12,7 @@ xwayland {
} }
# See https://wiki.hyprland.org/Configuring/Monitors/ x y # See https://wiki.hyprland.org/Configuring/Monitors/ x y
monitor=desc:Acer Technologies Acer K212HQL T3EAA0014201, 1920x1080@60, 840x1000, 1, transform, 3 monitor=desc:Acer Technologies Acer K212HQL T3EAA0014201, 1920x1080@60, 840x1000, 1, transform, 3
monitor=desc:BOE 0x0964, 1920x1200@60, 0x2920, 1 monitor=desc:BOE 0x0964, 1920x1200@60, 0x2920, 1
monitor=desc:Samsung Electric Company C27JG5x HTOM100586, 2560x1440@144, 1920x120, 1 monitor=desc:Samsung Electric Company C27JG5x HTOM100586, 2560x1440@144, 1920x120, 1
# Desc of monitor has comma, so force its default on everything and specify everything else # Desc of monitor has comma, so force its default on everything and specify everything else

View file

@ -1,51 +0,0 @@
#!/usr/bin/env bash
# This script was forked from https://gitlab.com/snippets/1793649 by Fishonadish
SCREEN="eDP-1"
WAYLANDINPUT=("wacom-hid-52eb-finger"
"wacom-hid-52eb-pen")
function rotate_ms {
if [[ $(hyprctl activewindow | grep Waydroid) == "" ]]; then
case $1 in
"normal")
rotate 0
;;
"right-up")
rotate 3
;;
"bottom-up")
rotate 2
;;
"left-up")
rotate 1
;;
esac
elif [[ $(hyprctl monitors | grep "transform: 0") == "" ]]; then
rotate 0
fi
}
function rotate {
TARGET_ORIENTATION=$1
echo "Rotating to" $TARGET_ORIENTATION
hyprctl keyword monitor $SCREEN,transform,$TARGET_ORIENTATION
for i in "${WAYLANDINPUT[@]}"
do
hyprctl keyword device:"$i":transform $TARGET_ORIENTATION
done
$HYPR_PATH/lisgd.sh &
}
while IFS='$\n' read -r line; do
rotation="$(echo $line | sed -En "s/^.*orientation changed: (.*)/\1/p")"
[[ ! -z $rotation ]] && rotate_ms $rotation
done < <(stdbuf -oL monitor-sensor)