From 5936230a577fe25faf62abce625bd4c72d7ca751 Mon Sep 17 00:00:00 2001 From: wheaney <42350981+wheaney@users.noreply.github.com> Date: Fri, 17 May 2024 12:14:44 -0700 Subject: [PATCH] Add GNOME extension logging to file --- gnome/src/cursormanager.js | 16 ++- gnome/src/extension.js | 28 ++++- gnome/src/globals.js | 3 +- gnome/src/logger.js | 118 ++++++++++++++++++ gnome/src/monitormanager.js | 6 +- gnome/src/xrEffect.js | 4 +- .../com.xronlinux.BreezyDesktop.gschema.xml | 9 ++ 7 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 gnome/src/logger.js diff --git a/gnome/src/cursormanager.js b/gnome/src/cursormanager.js index 9f80ad0..545619f 100644 --- a/gnome/src/cursormanager.js +++ b/gnome/src/cursormanager.js @@ -2,6 +2,7 @@ import Clutter from 'gi://Clutter'; import Meta from 'gi://Meta'; import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js'; import { MouseSpriteContent } from './cursor.js'; +import Globals from './globals.js'; // Taken from https://github.com/jkitching/soft-brightness-plus export class CursorManager { @@ -29,19 +30,23 @@ export class CursorManager { } enable() { + Globals.logger.log_debug('CursorManager enable'); this._enableCloningMouse(); this.startCloning(); } disable() { + Globals.logger.log_debug('CursorManager disable'); this._disableCloningMouse(); } startCloning() { + Globals.logger.log_debug('CursorManager startCloning'); this._startCloningMouse(); } stopCloning() { + Globals.logger.log_debug('CursorManager stopCloning'); this._stopCloningMouse(); } @@ -53,6 +58,7 @@ export class CursorManager { // okay if _startCloningMouse is not immediately called since set_pointer_visible is bound to our replacement function // and will trigger _startCloningMouse when the cursor should be shown _enableCloningMouse() { + Globals.logger.log_debug('CursorManager _enableCloningMouse'); this._cursorTracker = Meta.CursorTracker.get_for_display(global.display); this._cursorWantedVisible = this._cursorTracker.get_pointer_visible(); this._cursorTrackerSetPointerVisible = Meta.CursorTracker.prototype.set_pointer_visible; @@ -81,6 +87,7 @@ export class CursorManager { // // completely reverts _enableCloningMouse _disableCloningMouse() { + Globals.logger.log_debug('CursorManager _disableCloningMouse'); this._stopCloningMouse(); Meta.CursorTracker.prototype.set_pointer_visible = this._cursorTrackerSetPointerVisible; this._cursorTracker.set_pointer_visible(this._cursorWantedVisible); @@ -98,6 +105,7 @@ export class CursorManager { // bound to Meta.CursorTracker.prototype.set_pointer_visible when cloning is "on" // original function available in this._cursorTrackerSetPointerVisibleBound _cursorTrackerSetPointerVisibleReplacement(visible) { + Globals.logger.log_debug('CursorManager _cursorTrackerSetPointerVisibleReplacement'); this._cursorWantedVisible = visible; if (visible) { this._startCloningMouse(); @@ -114,6 +122,7 @@ export class CursorManager { // add the clone cursor actor, watch for pointer movement and cursor changes, reflect them in the cloned cursor // prereqs: setup in _enableCloningMouse, _cursorWantedVisible is true _startCloningMouse() { + Globals.logger.log_debug('CursorManager _startCloningMouse'); if (this._cursorWatch == null) { if (Clutter.Container === undefined) { this._mainActor.add_child(this._cursorActor); @@ -137,7 +146,7 @@ export class CursorManager { } if (!this._cursorUnfocusInhibited) { - console.log('Breezy debug - inhibit_unfocus\n'); + Globals.logger.log_debug('inhibit_unfocus'); this._cursorSeat.inhibit_unfocus(); this._cursorUnfocusInhibited = true; } @@ -150,6 +159,7 @@ export class CursorManager { // // completely reverts _startCloningMouse _stopCloningMouse() { + Globals.logger.log_debug('CursorManager _stopCloningMouse'); if (this._cursorWatch != null) { this._cursorWatch.remove(); this._cursorWatch = null; @@ -175,7 +185,7 @@ export class CursorManager { } if (this._cursorUnfocusInhibited) { - console.log('Breezy debug - uninhibit_unfocus\n'); + Globals.logger.log_debug('uninhibit_unfocus'); this._cursorSeat.uninhibit_unfocus(); this._cursorUnfocusInhibited = false; } @@ -204,7 +214,7 @@ export class CursorManager { // some other processes are uninhibiting when they shouldn't, so we need to re-inhibit here if (!this._cursorSeat.is_unfocus_inhibited() && this._cursorUnfocusInhibited) { - console.log('Breezy debug - reinhibiting\n'); + Globals.logger.log_debug('reinhibiting'); this._cursorSeat.inhibit_unfocus(); } } diff --git a/gnome/src/extension.js b/gnome/src/extension.js index b31df67..44a6faa 100644 --- a/gnome/src/extension.js +++ b/gnome/src/extension.js @@ -7,6 +7,7 @@ import St from 'gi://St'; import { CursorManager } from './cursormanager.js'; import Globals from './globals.js'; +import { Logger } from './logger.js'; import MonitorManager from './monitormanager.js'; import { IPC_FILE_PATH, XREffect } from './xrEffect.js'; @@ -36,10 +37,21 @@ export default class BreezyDesktopExtension extends Extension { this._distance_binding = null; this._start_binding = null; this._end_binding = null; + + if (!Globals.logger) { + Globals.logger = new Logger({ + title: 'breezydesktop', + debug: this.settings.get_boolean('debug') + }); + Globals.logger.logVersion(); + } } enable() { + Globals.logger.log_debug('BreezyDesktopExtension enable'); Globals.extension_dir = this.path; + this.settings.bind('debug', Globals.logger, 'debug', Gio.SettingsBindFlags.DEFAULT); + this._monitor_manager = new MonitorManager(this.path); this._monitor_manager.setChangeHook(this._setup.bind(this)); this._monitor_manager.enable(); @@ -48,6 +60,7 @@ export default class BreezyDesktopExtension extends Extension { } _poll_for_ready() { + Globals.logger.log_debug('BreezyDesktopExtension _poll_for_ready'); var target_monitor = this._target_monitor; var is_effect_running = this._is_effect_running; this._running_poller_id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, (() => { @@ -55,7 +68,7 @@ export default class BreezyDesktopExtension extends Extension { const is_driver_running = this._check_driver_running(); if (is_driver_running && target_monitor) { - console.log('Driver is running, supported monitor connected. Enabling XR effect.'); + Globals.logger.log('Driver is running, supported monitor connected. Enabling XR effect.'); this._effect_enable(); return GLib.SOURCE_REMOVE; } else { @@ -65,6 +78,7 @@ export default class BreezyDesktopExtension extends Extension { } _find_supported_monitor() { + Globals.logger.log_debug('BreezyDesktopExtension _find_supported_monitor'); const target_monitor = this._monitor_manager.getMonitorPropertiesList()?.find( monitor => SUPPORTED_MONITOR_PRODUCTS.includes(monitor.product)); if (target_monitor !== undefined) { @@ -86,8 +100,9 @@ export default class BreezyDesktopExtension extends Extension { } _setup() { + Globals.logger.log_debug('BreezyDesktopExtension _setup'); if (this._is_effect_running) { - console.log('Monitors changed, disabling XR effect'); + Globals.logger.log('Monitors changed, disabling XR effect'); this._effect_disable(); } const target_monitor = this._find_supported_monitor(); @@ -98,7 +113,7 @@ export default class BreezyDesktopExtension extends Extension { this._refresh_rate = target_monitor.refreshRate; if (this._check_driver_running()) { - console.log('Ready, enabling XR effect'); + Globals.logger.log('Ready, enabling XR effect'); this._effect_enable(); } else { this._poll_for_ready(); @@ -112,6 +127,7 @@ export default class BreezyDesktopExtension extends Extension { } _effect_enable() { + Globals.logger.log_debug('BreezyDesktopExtension _effect_enable'); this._running_poller_id = undefined; if (!this._is_effect_running) { this._is_effect_running = true; @@ -159,7 +175,7 @@ export default class BreezyDesktopExtension extends Extension { this._add_settings_keybinding('toggle-display-distance-shortcut', this._xr_effect._change_distance.bind(this._xr_effect)); this._add_settings_keybinding('toggle-follow-shortcut', this._toggle_follow_mode.bind(this)); } catch (e) { - console.error(`Error enabling XR effect ${e.message}`, e.stack); + Globals.logger.log(`ERROR: Error enabling XR effect ${e.message}`, e.stack); this._effect_disable(); } } @@ -198,14 +214,17 @@ export default class BreezyDesktopExtension extends Extension { } _recenter_display() { + Globals.logger.log_debug('BreezyDesktopExtension _recenter_display'); this._write_control('recenter_screen', 'true'); } _toggle_follow_mode() { + Globals.logger.log_debug('BreezyDesktopExtension _toggle_follow_mode'); this._write_control('toggle_breezy_desktop_smooth_follow', 'true'); } _effect_disable() { + Globals.logger.log_debug('BreezyDesktopExtension _effect_disable'); this._is_effect_running = false; if (this._running_poller_id) GLib.source_remove(this._running_poller_id); @@ -246,6 +265,7 @@ export default class BreezyDesktopExtension extends Extension { } disable() { + Globals.logger.log_debug('BreezyDesktopExtension disable'); this._effect_disable(); this._target_monitor = null; if (this._monitor_manager) { diff --git a/gnome/src/globals.js b/gnome/src/globals.js index b30b510..124d2e1 100644 --- a/gnome/src/globals.js +++ b/gnome/src/globals.js @@ -1,5 +1,6 @@ const Globals = { - ipc_file: null, // Gio.File instance, file exists + logger: null, + ipc_file: null, // Gio.File instance, file exists if set extension_dir: null // string path } export default Globals; \ No newline at end of file diff --git a/gnome/src/logger.js b/gnome/src/logger.js new file mode 100644 index 0000000..8bc1881 --- /dev/null +++ b/gnome/src/logger.js @@ -0,0 +1,118 @@ +// soft-brightness-plus - Control the display's brightness via an alpha channel. +// Copyright (C) 2023 Joel Kitching (jkitching on Github) +// +// 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 . + +import * as Config from 'resource:///org/gnome/shell/misc/config.js'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import System from 'system'; + +const LOG_DIR_NAME = 'breezy_gnome/logs/gjs'; + +export const Logger = GObject.registerClass({ + GTypeName: 'Logger', + Properties: { + 'title': GObject.ParamSpec.string( + 'title', + 'Title', + 'Title to use when logging', + GObject.ParamFlags.READWRITE, + null + ), + 'debug': GObject.ParamSpec.boolean( + 'debug', + 'Log debug messages', + 'Log debug messages', + GObject.ParamFlags.READWRITE, + false + ) + } +}, class Logger extends GObject.Object { + constructor(params = {}) { + super(params); + + this._log_file_dir = `${GLib.get_user_data_dir()}/${LOG_DIR_NAME}/` + this._first_log = true; + } + + logVersion() { + const gnomeShellVersion = Config.PACKAGE_VERSION; + if (gnomeShellVersion != undefined) { + const splitVersion = gnomeShellVersion.split('.').map((x) => { + x = Number(x); + if (Number.isNaN(x)) { + return 0; + } else { + return x; + } + }); + const major = splitVersion[0]; + const minor = splitVersion.length >= 2 ? splitVersion[1] : 0; + const patch = splitVersion.length >= 3 ? splitVersion[2] : 0; + const xdgSessionType = GLib.getenv('XDG_SESSION_TYPE'); + const onWayland = xdgSessionType == 'wayland'; + this.log_debug('_logVersion(): gnome-shell version major=' + major + ', minor=' + minor + ', patch=' + patch + ', system_version=' + System.version + ', XDG_SESSION_TYPE=' + xdgSessionType); + this.log_debug('_logVersion(): onWayland=' + onWayland); + } + } + + log(text) { + if (this._first_log) { + this._first_log = false; + let msg = ''; + const gnomeShellVersion = Config.PACKAGE_VERSION; + if (gnomeShellVersion != undefined) { + msg += 'Gnome-Shell ' + gnomeShellVersion; + } + const gjsVersion = System.version; + if (gjsVersion != undefined) { + const gjsVersionMajor = Math.floor(gjsVersion / 10000); + const gjsVersionMinor = Math.floor((gjsVersion % 10000) / 100); + const gjsVersionPatch = gjsVersion % 100; + msg += (' / gjs ' + gjsVersionMajor + + '.' + gjsVersionMinor + + '.' + gjsVersionPatch + + ' (' + gjsVersion + ')' + ); + } + const sessionType = GLib.getenv('XDG_SESSION_TYPE'); + if (sessionType != undefined) { + msg += ' / ' + sessionType; + } + this.log(msg); + } + + const now = GLib.DateTime.new_now_local(); + const logFileName = `${now.format('%Y-%m-%d')}.log`; + const file = Gio.File.new_for_path(`${this._log_file_dir}/${logFileName}`); + + if (!file.query_exists(null)) { + const parentDir = file.get_parent(); + if (!parentDir.query_exists(null)) { + parentDir.make_directory_with_parents(null); + } + } + const stream = file.append_to(Gio.FileCreateFlags.NONE, null); + stream.write(`${this.title}: ${text}\n`, null); + stream.close(null); + } + + log_debug(text) { + if (this.debug) { + this.log(`\tDEBUG - ${text}`); + } + } +}); \ No newline at end of file diff --git a/gnome/src/monitormanager.js b/gnome/src/monitormanager.js index 09e4e2b..0eacea5 100644 --- a/gnome/src/monitormanager.js +++ b/gnome/src/monitormanager.js @@ -20,6 +20,8 @@ import Gio from 'gi://Gio'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import Globals from './globals.js'; + let cachedDisplayConfigProxy = null; function getDisplayConfigProxy(extPath) { @@ -32,7 +34,7 @@ function getDisplayConfigProxy(extPath) { xml = new TextDecoder().decode(bytes); } } catch (e) { - console.error('failed to load DisplayConfig interface XML'); + Globals.logger.log('ERROR: failed to load DisplayConfig interface XML'); throw e; } cachedDisplayConfigProxy = Gio.DBusProxy.makeProxyWrapper(xml); @@ -145,7 +147,7 @@ export default class MonitorManager { for (let i = 0; i < result.length; i++) { const [monitorName, connectorName, vendor, product, serial, refreshRate] = result[i]; const monitorIndex = this._backendManager.get_monitor_for_connector(connectorName); - console.log(`\n\nFound monitor ${monitorName}, vendor ${vendor}, product ${product}, serial ${serial}, connector ${connectorName}, index ${monitorIndex}\n\n`); + Globals.logger.log(`Found monitor ${monitorName}, vendor ${vendor}, product ${product}, serial ${serial}, connector ${connectorName}, index ${monitorIndex}`); if (monitorIndex >= 0) { monitorProperties[monitorIndex] = { index: monitorIndex, diff --git a/gnome/src/xrEffect.js b/gnome/src/xrEffect.js index 3f394c9..0c0b15b 100644 --- a/gnome/src/xrEffect.js +++ b/gnome/src/xrEffect.js @@ -164,7 +164,7 @@ function setIntermittentUniformVariables() { this.set_uniform_float(shaderUniformLocations['display_res'], 2, [this.target_monitor.width, this.target_monitor.height]); } else if (dataView.byteLength !== 0) { - console.error(`Invalid dataView.byteLength: ${dataView.byteLength} !== ${DATA_VIEW_LENGTH}`) + Globals.logger.log(`ERROR: Invalid dataView.byteLength: ${dataView.byteLength} !== ${DATA_VIEW_LENGTH}`) } } @@ -296,7 +296,7 @@ export const XREffect = GObject.registerClass({ setSingleFloat(this, 'look_ahead_ms', lookAheadMS(this._dataView)); setUniformMatrix(this, 'imu_quat_data', 4, this._dataView, IMU_QUAT_DATA); } else if (this._dataView.byteLength !== 0) { - console.error(`Invalid dataView.byteLength: ${this._dataView.byteLength} !== ${DATA_VIEW_LENGTH}`) + Globals.logger.log(`ERROR: Invalid dataView.byteLength: ${this._dataView.byteLength} !== ${DATA_VIEW_LENGTH}`) } // improves sampling quality for smooth text and edges diff --git a/ui/data/com.xronlinux.BreezyDesktop.gschema.xml b/ui/data/com.xronlinux.BreezyDesktop.gschema.xml index 0dc1db1..7f8c87a 100644 --- a/ui/data/com.xronlinux.BreezyDesktop.gschema.xml +++ b/ui/data/com.xronlinux.BreezyDesktop.gschema.xml @@ -63,6 +63,15 @@ Enable developer mode + + + + false + + Log debug messages + + Log debug messages +