├── .gitignore ├── README.md ├── extension.js ├── img ├── img1.png ├── img2.png ├── img3.png └── img4.png ├── metadata.json ├── prefs.js ├── schemas ├── gschemas.compiled └── org.gnome.shell.extensions.emoji-selector.gschema.xml └── stylesheet.css /.gitignore: -------------------------------------------------------------------------------- 1 | better-osd.zip 2 | better-osd 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Better OSD (GNOME 41 Extension) 2 | 3 | A GNOME Shell extension allowing the user to set the position, size, transparency and delay of the OSD popup. 4 | 5 | ## Installation 6 | 7 | Install from [GNOME Extensions](https://extensions.gnome.org/extension/4231/better-osd-gnome-40/). 8 | 9 | > How to manually install the extension ? 10 | 11 | ``` 12 | git clone https://github.com/hllvc/better-osd.git \ 13 | ~/.local/share/gnome-shell/extensions/better-osd 14 | ``` 15 | 16 | You may need to restart the gnome shell environnment 17 | 18 | - logout and login again _or_ 19 | - `alt+f2` then type `r` and `enter` 20 | 21 | ## What's new 22 | 23 | #### 1.0 24 | - move OSD popup with horizontal and vertical percentage 25 | - set size percentage 26 | - set delay of OSD popup 27 | 28 | #### 2.0 29 | - added transparency toggle 30 | 31 | ## Upcoming 32 | 33 | - transparency slider for custom opacity 34 | - refined preference window 35 | 36 | ## Screenshots 37 | 38 | ![Screenshot](img/img1.png) 39 | ![Screenshot](img/img2.png) 40 | 41 | > without transparency 42 | ![Screenshot](img/img3.png) 43 | 44 | > with transparency 45 | ![Screenshot](img/img4.png) 46 | 47 | ## Details 48 | 49 | This is forked version modified to work with GNOME 40 from [here](https://extensions.gnome.org/extension/1345/better-osd/). 50 | -------------------------------------------------------------------------------- /extension.js: -------------------------------------------------------------------------------- 1 | const Main = imports.ui.main; 2 | const OsdWindow = imports.ui.osdWindow; 3 | const OsdWindowManager = Main.osdWindowManager; 4 | 5 | const ExtensionUtils = imports.misc.extensionUtils; 6 | const Me = ExtensionUtils.getCurrentExtension(); 7 | 8 | //------------------------------------------------ 9 | 10 | function init() { 11 | ExtensionUtils.initTranslations(); 12 | } 13 | 14 | //------------------------------------------------ 15 | 16 | function style() { 17 | for ( 18 | let monitorIndex = 0; 19 | monitorIndex < OsdWindowManager._osdWindows.length; 20 | monitorIndex++ 21 | ) { 22 | OsdWindowManager._osdWindows[monitorIndex]._box.add_style_class_name( 23 | "osd-transparency" 24 | ); 25 | } 26 | } 27 | 28 | function unstyle() { 29 | for ( 30 | let monitorIndex = 0; 31 | monitorIndex < OsdWindowManager._osdWindows.length; 32 | monitorIndex++ 33 | ) { 34 | OsdWindowManager._osdWindows[monitorIndex]._box.remove_style_class_name( 35 | "osd-transparency" 36 | ); 37 | } 38 | } 39 | 40 | //------------------------------------------------ 41 | 42 | function injectToFunction(parent, name, func) { 43 | let origin = parent[name]; 44 | parent[name] = function () { 45 | let ret; 46 | ret = origin.apply(this, arguments); 47 | if (ret === undefined) ret = func.apply(this, arguments); 48 | return ret; 49 | }; 50 | return origin; 51 | } 52 | 53 | function removeInjection(object, injection, name) { 54 | if (injection[name] === undefined) delete object[name]; 55 | else object[name] = injection[name]; 56 | } 57 | 58 | let injections = []; 59 | let _id; 60 | 61 | //--------------------------------------------- 62 | 63 | function enable() { 64 | let _settings = ExtensionUtils.getSettings( 65 | "org.gnome.shell.extensions.better-osd" 66 | ); 67 | 68 | style(); 69 | _id = Main.layoutManager.connect("monitors-changed", this.style.bind(this)); 70 | 71 | injections["show"] = injectToFunction( 72 | OsdWindow.OsdWindow.prototype, 73 | "show", 74 | function () { 75 | let monitor = Main.layoutManager.monitors[this._monitorIndex]; 76 | let h_percent = _settings.get_int("horizontal"); 77 | let v_percent = _settings.get_int("vertical"); 78 | let osd_size = _settings.get_int("size"); 79 | let hide_delay = _settings.get_int("delay"); 80 | let transparency = _settings.get_boolean("transparency"); 81 | transparency ? style() : unstyle(); 82 | 83 | this._box.translation_x = (h_percent * monitor.width) / 100; 84 | this._box.translation_y = (v_percent * monitor.height) / 100; 85 | 86 | this._icon.icon_size = (osd_size * monitor.height) / 100 / 2; 87 | this._boxConstraint._minSize = (osd_size * monitor.height) / 100; 88 | 89 | imports.ui.osdWindow.HIDE_TIMEOUT = hide_delay; 90 | } 91 | ); 92 | } 93 | 94 | function disable() { 95 | unstyle(); 96 | Main.layoutManager.disconnect(_id); 97 | 98 | let arrayOSD = Main.osdWindowManager._osdWindows; 99 | for (let i = 0; i < arrayOSD.length; i++) { 100 | arrayOSD[i]._relayout(); 101 | arrayOSD[i]._box.translation_x = 0; 102 | imports.ui.osdWindow.HIDE_TIMEOUT = 1500; 103 | } 104 | 105 | removeInjection(OsdWindow.OsdWindow.prototype, injections, "show"); 106 | } 107 | -------------------------------------------------------------------------------- /img/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hllvc/better-osd/44c9d721dd3e54628c1f8bb691cde2f0d6858933/img/img1.png -------------------------------------------------------------------------------- /img/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hllvc/better-osd/44c9d721dd3e54628c1f8bb691cde2f0d6858933/img/img2.png -------------------------------------------------------------------------------- /img/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hllvc/better-osd/44c9d721dd3e54628c1f8bb691cde2f0d6858933/img/img3.png -------------------------------------------------------------------------------- /img/img4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hllvc/better-osd/44c9d721dd3e54628c1f8bb691cde2f0d6858933/img/img4.png -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Better OSD - Gnome 40", 3 | "gettext-domain": "better-osd", 4 | "description": "Customize your OSD popups. Move, resize, set delay and transparency!", 5 | "uuid": "better-osd@hllvc", 6 | "url": "https://github.com/hllvc/better-osd", 7 | "shell-version": ["40", "41", "41.1"], 8 | "version": 2.1 9 | } 10 | -------------------------------------------------------------------------------- /prefs.js: -------------------------------------------------------------------------------- 1 | const GObject = imports.gi.GObject; 2 | const Gtk = imports.gi.Gtk; 3 | 4 | const Gettext = imports.gettext.domain("better-osd"); 5 | const _ = Gettext.gettext; 6 | 7 | const ExtensionUtils = imports.misc.extensionUtils; 8 | const Me = ExtensionUtils.getCurrentExtension(); 9 | 10 | //----------------------------------------------- 11 | 12 | function init() { 13 | ExtensionUtils.initTranslations(); 14 | } 15 | 16 | //----------------------------------------------- 17 | 18 | const OSDSettingsWidget = new GObject.registerClass( 19 | { 20 | GTypeName: "OSDPrefsWidget", 21 | }, 22 | class OSDSettingsWidget extends Gtk.Box { 23 | _init(params) { 24 | super._init(params); 25 | this.margin = 30; 26 | this.spacing = 25; 27 | this.fill = true; 28 | this.orientation = Gtk.Orientation.VERTICAL; 29 | 30 | this._settings = ExtensionUtils.getSettings( 31 | "org.gnome.shell.extensions.better-osd" 32 | ); 33 | 34 | let labelHorizontalPercentage = _("Horizontal position (percentage) :"); 35 | 36 | let horizontalPercentage = new Gtk.SpinButton(); 37 | horizontalPercentage.set_sensitive(true); 38 | horizontalPercentage.set_range(-60, 60); 39 | horizontalPercentage.set_value(0); 40 | horizontalPercentage.set_value(this._settings.get_int("horizontal")); 41 | horizontalPercentage.set_increments(1, 2); 42 | 43 | horizontalPercentage.connect( 44 | "value-changed", 45 | function (w) { 46 | var value = w.get_value_as_int(); 47 | this._settings.set_int("horizontal", value); 48 | }.bind(this) 49 | ); 50 | 51 | let hBox = new Gtk.Box({ 52 | orientation: Gtk.Orientation.HORIZONTAL, 53 | spacing: 15, 54 | }); 55 | hBox.prepend( 56 | new Gtk.Label({ 57 | label: labelHorizontalPercentage, 58 | use_markup: true, 59 | halign: Gtk.Align.START, 60 | }) 61 | ); 62 | hBox.append(horizontalPercentage); 63 | this.append(hBox); 64 | 65 | //------------------------------------------------------- 66 | 67 | let labelVerticalPercentage = _("Vertical position (percentage) :"); 68 | 69 | let verticalPercentage = new Gtk.SpinButton(); 70 | verticalPercentage.set_sensitive(true); 71 | verticalPercentage.set_range(-110, 110); 72 | verticalPercentage.set_value(70); 73 | verticalPercentage.set_value(this._settings.get_int("vertical")); 74 | verticalPercentage.set_increments(1, 2); 75 | 76 | verticalPercentage.connect( 77 | "value-changed", 78 | function (w) { 79 | var value = w.get_value_as_int(); 80 | this._settings.set_int("vertical", value); 81 | }.bind(this) 82 | ); 83 | 84 | let vBox = new Gtk.Box({ 85 | orientation: Gtk.Orientation.HORIZONTAL, 86 | spacing: 15, 87 | }); 88 | vBox.prepend( 89 | new Gtk.Label({ 90 | label: labelVerticalPercentage, 91 | use_markup: true, 92 | halign: Gtk.Align.START, 93 | }) 94 | ); 95 | vBox.append(verticalPercentage); 96 | this.append(vBox); 97 | 98 | //------------------------------------------------------- 99 | 100 | let labelSizePercentage = _("Size (percentage) :"); 101 | 102 | let sizePercentage = new Gtk.SpinButton(); 103 | sizePercentage.set_sensitive(true); 104 | sizePercentage.set_range(0, 100); 105 | sizePercentage.set_value(20); 106 | sizePercentage.set_value(this._settings.get_int("size")); 107 | sizePercentage.set_increments(1, 2); 108 | 109 | sizePercentage.connect( 110 | "value-changed", 111 | function (w) { 112 | var value = w.get_value_as_int(); 113 | this._settings.set_int("size", value); 114 | }.bind(this) 115 | ); 116 | 117 | let sizeBox = new Gtk.Box({ 118 | orientation: Gtk.Orientation.HORIZONTAL, 119 | spacing: 15, 120 | }); 121 | sizeBox.prepend( 122 | new Gtk.Label({ 123 | label: labelSizePercentage, 124 | use_markup: true, 125 | halign: Gtk.Align.START, 126 | }) 127 | ); 128 | sizeBox.append(sizePercentage); 129 | this.append(sizeBox); 130 | 131 | //------------------------------------------------------- 132 | 133 | let labelDelay = _("Hide Delay (ms) :"); 134 | 135 | let hideDelay = new Gtk.SpinButton(); 136 | hideDelay.set_sensitive(true); 137 | hideDelay.set_range(0, 5000); 138 | hideDelay.set_value(1500); 139 | hideDelay.set_value(this._settings.get_int("delay")); 140 | hideDelay.set_increments(1, 2); 141 | 142 | hideDelay.connect( 143 | "value-changed", 144 | function (w) { 145 | var value = w.get_value_as_int(); 146 | this._settings.set_int("delay", value); 147 | }.bind(this) 148 | ); 149 | 150 | let delayBox = new Gtk.Box({ 151 | orientation: Gtk.Orientation.HORIZONTAL, 152 | spacing: 15, 153 | }); 154 | delayBox.prepend( 155 | new Gtk.Label({ 156 | label: labelDelay, 157 | use_markup: true, 158 | halign: Gtk.Align.START, 159 | }) 160 | ); 161 | delayBox.append(hideDelay); 162 | this.append(delayBox); 163 | 164 | //------------------------------------------------------- 165 | 166 | let labelTransparency = _("Transparency:"); 167 | 168 | let switchTransparency = new Gtk.Switch(); 169 | switchTransparency.set_active(this._settings.get_boolean("transparency")); 170 | 171 | switchTransparency.connect( 172 | "state-set", 173 | function (w) { 174 | var value = w.get_active(); 175 | this._settings.set_boolean("transparency", value); 176 | }.bind(this) 177 | ); 178 | 179 | let transparencyBox = new Gtk.Box({ 180 | orientation: Gtk.Orientation.HORIZONTAL, 181 | spacing: 15, 182 | }); 183 | transparencyBox.prepend( 184 | new Gtk.Label({ 185 | label: labelTransparency, 186 | use_markup: true, 187 | halign: Gtk.Align.START, 188 | }) 189 | ); 190 | transparencyBox.append(switchTransparency); 191 | this.append(transparencyBox); 192 | } 193 | } 194 | ); 195 | 196 | //----------------------------------------------- 197 | 198 | //I guess this is like the "enable" in extension.js : something called each 199 | //time he user try to access the settings' window 200 | function buildPrefsWidget() { 201 | return new OSDSettingsWidget(); 202 | } 203 | -------------------------------------------------------------------------------- /schemas/gschemas.compiled: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hllvc/better-osd/44c9d721dd3e54628c1f8bb691cde2f0d6858933/schemas/gschemas.compiled -------------------------------------------------------------------------------- /schemas/org.gnome.shell.extensions.emoji-selector.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0 6 | Horizontal shifting (%) 7 | The percentage of the screen width (from the center of the screen) at which the OSD will be displayed. 8 | 9 | 10 | 0 11 | Vertical shifting (%) 12 | The percentage of the screen height (from the center of the screen) at which the OSD will be displayed. 13 | 14 | 15 | 15 16 | OSD size (screen %) 17 | Relative OSD size. 18 | 19 | 20 | 1000 21 | Hide delay (ms) 22 | How long the OSD will be displayed. 23 | 24 | 25 | false 26 | Transparency toggle 27 | Toggle OSD transparency to on/off. 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /stylesheet.css: -------------------------------------------------------------------------------- 1 | .osd-transparency { 2 | background-color: rgba(0,0,0,0.25); 3 | } 4 | --------------------------------------------------------------------------------