123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /* extension.js
- * Copyright (C) 2023 kosmospredanie, shyzus, Shinigaminai
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
- import Gio from 'gi://Gio';
- import * as SystemActions from 'resource:///org/gnome/shell/misc/systemActions.js';
- import * as Rotator from './rotator.js'
- const ORIENTATION_LOCK_SCHEMA = 'org.gnome.settings-daemon.peripherals.touchscreen';
- const ORIENTATION_LOCK_KEY = 'orientation-lock';
- // Orientation names must match those provided by net.hadess.SensorProxy
- const Orientation = Object.freeze({
- 'normal': 0,
- 'left-up': 1,
- 'bottom-up': 2,
- 'right-up': 3
- });
- class SensorProxy {
- constructor(rotate_cb) {
- this._rotate_cb = rotate_cb;
- this._proxy = null;
- this._enabled = false;
- this._watcher_id = Gio.bus_watch_name(
- Gio.BusType.SYSTEM,
- 'net.hadess.SensorProxy',
- Gio.BusNameWatcherFlags.NONE,
- this.appeared.bind(this),
- this.vanished.bind(this)
- );
- }
- destroy() {
- Gio.bus_unwatch_name(this._watcher_id);
- if (this._enabled) this.disable();
- this._proxy = null;
- }
- enable() {
- this._enabled = true;
- if (this._proxy === null) return;
- this._proxy.call_sync('ClaimAccelerometer', null, Gio.DBusCallFlags.NONE, -1, null);
- }
- disable() {
- this._enabled = false;
- if (this._proxy === null) return;
- this._proxy.call_sync('ReleaseAccelerometer', null, Gio.DBusCallFlags.NONE, -1, null);
- }
- appeared(connection, name, name_owner) {
- this._proxy = Gio.DBusProxy.new_for_bus_sync(
- Gio.BusType.SYSTEM, Gio.DBusProxyFlags.NONE, null,
- 'net.hadess.SensorProxy', '/net/hadess/SensorProxy', 'net.hadess.SensorProxy',
- null);
- this._proxy.connect('g-properties-changed', this.properties_changed.bind(this));
- if (this._enabled) {
- this._proxy.call_sync('ClaimAccelerometer', null, Gio.DBusCallFlags.NONE, -1, null);
- }
- }
- vanished(connection, name) {
- this._proxy = null;
- }
- properties_changed(proxy, changed, invalidated) {
- if (!this._enabled) return;
- let properties = changed.deep_unpack();
- for (let [name, value] of Object.entries(properties)) {
- if (name != 'AccelerometerOrientation') continue;
- let target = value.unpack();
- this._rotate_cb(target);
- }
- }
- }
- class ScreenAutorotate {
- constructor(settings) {
- this._system_actions = SystemActions.getDefault();
- this._settings = settings;
- this._system_actions_backup = null;
- this._override_system_actions();
- this._orientation_settings = new Gio.Settings({ schema_id: ORIENTATION_LOCK_SCHEMA });
- this._orientation_settings.connect('changed::' + ORIENTATION_LOCK_KEY, this._orientation_lock_changed.bind(this));
- this._sensor_proxy = new SensorProxy(this.rotate_to.bind(this));
- this._state = false; // enabled or not
- let locked = this._orientation_settings.get_boolean(ORIENTATION_LOCK_KEY);
- if (!locked) this.enable();
- }
- _override_system_actions() {
- this._system_actions_backup = {
- '_updateOrientationLock': this._system_actions._updateOrientationLock
- };
- this._system_actions._updateOrientationLock = function() {
- this._actions.get('lock-orientation').available = true;
- this.notify('can-lock-orientation');
- };
- this._system_actions._updateOrientationLock();
- }
- _restore_system_actions() {
- if (this._system_actions_backup === null) return;
- this._system_actions._updateOrientationLock = this._system_actions_backup['_updateOrientationLock'];
- this._system_actions._updateOrientationLock();
- this._system_actions_backup = null;
- }
- _orientation_lock_changed() {
- let locked = this._orientation_settings.get_boolean(ORIENTATION_LOCK_KEY);
- if (this._state == locked) {
- this.toggle();
- }
- }
- destroy() {
- this._sensor_proxy.destroy();
- this._orientation_settings = null;
- this._restore_system_actions();
- }
- toggle() {
- if (this._state) {
- this.disable();
- } else {
- this.enable();
- }
- }
- enable() {
- this._sensor_proxy.enable();
- this._state = true;
- }
- disable() {
- this._sensor_proxy.disable();
- this._state = false;
- }
- rotate_to(orientation) {
- const sensor = Orientation[orientation];
- const invert_horizontal_direction = this._settings.get_boolean('invert-horizontal-rotation-direction');
- const invert_vertical_direction = this._settings.get_boolean('invert-vertical-rotation-direction');
- const offset = this._settings.get_int('orientation-offset');
- let target = sensor; // Default to sensor output.
- switch (sensor) {
- case 0:
- // sensor reports landscape
- if (invert_horizontal_direction) {
- target = 2;
- }
- break;
- case 1:
- // sensor reports portrait
- if (invert_vertical_direction) {
- target = 3;
- }
- break;
- case 2:
- // sensor reports landscape-inverted
- if (invert_horizontal_direction) {
- target = 0;
- }
- break;
- case 3:
- // sensor reports portrait-inverted
- if (invert_vertical_direction) {
- target = 1;
- }
- break;
- }
- target = (target + offset) % 4;
- if (this._settings.get_boolean('debug-logging')) {
- console.debug(`sensor=${Orientation[orientation]}`);
- console.debug(`offset=${offset}`);
- console.debug(`target=${target}`);
- }
- Rotator.rotate_to(target);
- }
- }
- export default class ScreenAutoRotateExtension extends Extension {
- enable() {
- this._settings = this.getSettings();
- this._ext = new ScreenAutorotate(this._settings);
- }
- disable() {
- /*
- Comment for unlock-dialog usage:
- The unlock-dialog sesson-mode is usefull for this extension as it allows
- the user to rotate their screen or lock rotation after their device may
- have auto-locked. This provides the ability to log back in regardless of
- the orientation of the device in tablet mode.
- */
- this._settings = null;
- this._ext.destroy();
- this._ext = null;
- }
- }
|