From 430610bad8ebc751595844caa3c8cdfe4371eba0 Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Wed, 17 Feb 2016 00:06:00 -0500 Subject: [PATCH] Initial commit --- .gitignore | 2 + convenience.js | 93 ++++++++++++++ extension.js | 121 ++++++++++++++++++ metadata.json | 9 ++ schemas/gschemas.compiled | Bin 0 -> 328 bytes ...shell.extensions.invert-window.gschema.xml | 9 ++ 6 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 convenience.js create mode 100644 extension.js create mode 100644 metadata.json create mode 100644 schemas/gschemas.compiled create mode 100644 schemas/org.gnome.shell.extensions.invert-window.gschema.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5236e1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ + diff --git a/convenience.js b/convenience.js new file mode 100644 index 0000000..bbc8608 --- /dev/null +++ b/convenience.js @@ -0,0 +1,93 @@ +/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (c) 2011-2012, Giovanni Campagna + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the GNOME nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +const Gettext = imports.gettext; +const Gio = imports.gi.Gio; + +const Config = imports.misc.config; +const ExtensionUtils = imports.misc.extensionUtils; + +/** + * initTranslations: + * @domain: (optional): the gettext domain to use + * + * Initialize Gettext to load translations from extensionsdir/locale. + * If @domain is not provided, it will be taken from metadata['gettext-domain'] + */ +function initTranslations(domain) { + let extension = ExtensionUtils.getCurrentExtension(); + + domain = domain || extension.metadata['gettext-domain']; + + // check if this extension was built with "make zip-file", and thus + // has the locale files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell + let localeDir = extension.dir.get_child('locale'); + if (localeDir.query_exists(null)) + Gettext.bindtextdomain(domain, localeDir.get_path()); + else + Gettext.bindtextdomain(domain, Config.LOCALEDIR); +} + +/** + * getSettings: + * @schema: (optional): the GSettings schema id + * + * Builds and return a GSettings schema for @schema, using schema files + * in extensionsdir/schemas. If @schema is not provided, it is taken from + * metadata['settings-schema']. + */ +function getSettings(schema) { + let extension = ExtensionUtils.getCurrentExtension(); + + schema = schema || extension.metadata['settings-schema']; + + const GioSSS = Gio.SettingsSchemaSource; + + // check if this extension was built with "make zip-file", and thus + // has the schema files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell (and therefore schemas are available + // in the standard folders) + let schemaDir = extension.dir.get_child('schemas'); + let schemaSource; + if (schemaDir.query_exists(null)) + schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), + GioSSS.get_default(), + false); + else + schemaSource = GioSSS.get_default(); + + let schemaObj = schemaSource.lookup(schema, true); + if (!schemaObj) + throw new Error('Schema ' + schema + ' could not be found for extension ' + + extension.metadata.uuid + '. Please check your installation.'); + + return new Gio.Settings({ settings_schema: schemaObj }); +} + diff --git a/extension.js b/extension.js new file mode 100644 index 0000000..30d564e --- /dev/null +++ b/extension.js @@ -0,0 +1,121 @@ +const Main = imports.ui.main; +const Lang = imports.lang; +const Meta = imports.gi.Meta; +const Shell = imports.gi.Shell; +const Clutter = imports.gi.Clutter; +const ExtensionUtils = imports.misc.extensionUtils; + +const Self = ExtensionUtils.getCurrentExtension(); +const Convenience = Self.imports.convenience; + +const ui = imports.ui; + +const SHORTCUT = 'invert-window-shortcut'; + +function inject_after(proto, name, func) { + let orig = proto[name]; + + proto[name] = function() { + let ret = orig.apply(this, arguments); + return func.apply(this, [ret].concat([].slice.call(arguments))); + } + + return orig; +} + +function remove_injection(proto, name, orig) { + proto[name] = orig; +} + +const InvertWindowEffect = new Lang.Class({ + Name: 'InvertWindowEffect', + Extends: Clutter.ShaderEffect, + + _init: function(params) { + this.parent(params); + this.set_shader_source('uniform sampler2D tex; void main() { vec4 color = texture2D(tex, cogl_tex_coord_in[0].st); color.rgb /= color.a; color.rgb = vec3(1.0, 1.0, 1.0) - color.rgb; color.rgb *= color.a; cogl_color_out = color * cogl_color_in; }'); + }, + + vfunc_paint_target: function() { + this.set_uniform_value("tex", 0); + this.parent(); + } +}); + +function InvertWindow() { + this.settings = Convenience.getSettings(); + this.workspace_injection = null; + this.alttab_injection = null; +} + +InvertWindow.prototype = { + toggle_effect: function() { + global.get_window_actors().forEach(function(actor) { + let meta_window = actor.get_meta_window(); + if(meta_window.has_focus()) { + if(actor.get_effect('invert-color')) { + actor.remove_effect_by_name('invert-color'); + } + else { + let effect = new InvertWindowEffect(); + actor.add_effect_with_name('invert-color', effect); + } + } + }, this); + }, + + enable: function() { + Main.wm.addKeybinding( + SHORTCUT, + this.settings, + Meta.KeyBindingFlags.NONE, + Shell.ActionMode.NORMAL, + Lang.bind(this, this.toggle_effect) + ); + + this.workspace_injection = inject_after(ui.workspace.WindowClone.prototype, '_init', function(ret) { + if(this.realWindow.get_effect('invert-color')) { + let effect = new InvertWindowEffect(); + this.actor.add_effect_with_name('invert-color', effect); + } + return ret; + }); + + this.alttab_injection = inject_after(ui.altTab, '_createWindowClone', function(clone, window, size) { + if(window.get_effect('invert-color')) { + let effect = new InvertWindowEffect(); + clone.add_effect_with_name('invert-color', effect); + } + return clone; + }); + }, + + disable: function() { + Main.wm.removeKeybinding(SHORTCUT); + + global.get_window_actors().forEach(function(actor) { + actor.remove_effect_by_name('invert-color'); + }, this); + + remove_injection(ui.workspace.WindowClone.prototype, '_init', this.workspace_injection); + this.workspace_injection = null; + + remove_injection(ui.altTab, '_createWindowClone', this.alttab_injection); + this.alttab_injection = null; + } +}; + +let invert_window; + +function init() { + invert_window = new InvertWindow(); +} + +function enable() { + invert_window.enable(); +} + +function disable() { + invert_window.disable(); +} + diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..07c9b98 --- /dev/null +++ b/metadata.json @@ -0,0 +1,9 @@ +{ + "uuid": "invert-window@maiself", + "name": "Invert Window Color", + "description": "Inverts the color of individual windows\nDefault shortcut is Super+I", + "url": "https://github.com/maiself/gnome-shell-extension-invert-color", + "shell-version": ["3.16", "3.18"], + "settings-schema": "org.gnome.shell.extensions.invert-window", + "version": 1 +} diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled new file mode 100644 index 0000000000000000000000000000000000000000..4748af7281da8259efa1cdf8a5fe5cb90ec3765a GIT binary patch literal 328 zcmZ<{ODxJv%qwAl0tp};0by$}LB$w>^n)&Ea}W)Z(_rvmXaLf8fS6U3f#E+8xPT-X zd>BBq2N35MrR$~V<>#jA6=$U8>t*JZr52UwmS^UrOnjI*4ptg=1WEY6d3KSOr(zYNr)D0ju$PEra8srWX zi*$=K@{3B6OQAls2`(*2Ewb}u;AGH9EY{R3NG!DC82Tp#RkeXzsz5f0Z!F;Aa? Jp%|nA3IM*5OuhgB literal 0 HcmV?d00001 diff --git a/schemas/org.gnome.shell.extensions.invert-window.gschema.xml b/schemas/org.gnome.shell.extensions.invert-window.gschema.xml new file mode 100644 index 0000000..0ac3d2b --- /dev/null +++ b/schemas/org.gnome.shell.extensions.invert-window.gschema.xml @@ -0,0 +1,9 @@ + + + + + I']]]> + + + +