c987d3d2c9
Meson is on track to replace autotools as the build system of choice, so support it in addition to autotools. If all goes well, we'll eventually be able to drop the latter ... https://bugzilla.gnome.org/show_bug.cgi?id=783229
233 lines
7.2 KiB
Plaintext
Executable File
233 lines
7.2 KiB
Plaintext
Executable File
#!@PYTHON@
|
|
# -*- mode: Python; indent-tabs-mode: nil; -*-
|
|
|
|
import os
|
|
import re
|
|
import socket
|
|
import subprocess
|
|
import sys
|
|
import optparse
|
|
import tempfile
|
|
try:
|
|
import json
|
|
except ImportError:
|
|
try:
|
|
import simplejson as json
|
|
except ImportError:
|
|
print('The Python simplejson module is required')
|
|
sys.exit(1)
|
|
|
|
from gi.repository import Gio, GLib
|
|
|
|
SAMPLE_EXTENSION_FILES = {
|
|
"extension.js": """
|
|
const St = imports.gi.St;
|
|
const Main = imports.ui.main;
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
let text, button;
|
|
|
|
function _hideHello() {
|
|
Main.uiGroup.remove_actor(text);
|
|
text = null;
|
|
}
|
|
|
|
function _showHello() {
|
|
if (!text) {
|
|
text = new St.Label({ style_class: 'helloworld-label', text: "Hello, world!" });
|
|
Main.uiGroup.add_actor(text);
|
|
}
|
|
|
|
text.opacity = 255;
|
|
|
|
let monitor = Main.layoutManager.primaryMonitor;
|
|
|
|
text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
|
|
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
|
|
|
|
Tweener.addTween(text,
|
|
{ opacity: 0,
|
|
time: 2,
|
|
transition: 'easeOutQuad',
|
|
onComplete: _hideHello });
|
|
}
|
|
|
|
function init() {
|
|
button = new St.Bin({ style_class: 'panel-button',
|
|
reactive: true,
|
|
can_focus: true,
|
|
x_fill: true,
|
|
y_fill: false,
|
|
track_hover: true });
|
|
let icon = new St.Icon({ icon_name: 'system-run-symbolic',
|
|
style_class: 'system-status-icon' });
|
|
|
|
button.set_child(icon);
|
|
button.connect('button-press-event', _showHello);
|
|
}
|
|
|
|
function enable() {
|
|
Main.panel._rightBox.insert_child_at_index(button, 0);
|
|
}
|
|
|
|
function disable() {
|
|
Main.panel._rightBox.remove_child(button);
|
|
}
|
|
""",
|
|
|
|
"stylesheet.css": """
|
|
.helloworld-label {
|
|
font-size: 36px;
|
|
font-weight: bold;
|
|
color: #ffffff;
|
|
background-color: rgba(10,10,10,0.7);
|
|
border-radius: 5px;
|
|
padding: .5em;
|
|
}
|
|
""",
|
|
}
|
|
|
|
def create_extension():
|
|
print()
|
|
print('''Name should be a very short (ideally descriptive) string.
|
|
Examples are: "Click To Focus", "Adblock", "Shell Window Shrinker".
|
|
''')
|
|
name = input('Name: ').strip()
|
|
print()
|
|
print('''Description is a single-sentence explanation of what your extension does.
|
|
Examples are: "Make windows visible on click", "Block advertisement popups"
|
|
"Animate windows shrinking on minimize"
|
|
''')
|
|
description = input('Description: ').strip()
|
|
underifier = re.compile('[^A-Za-z]')
|
|
sample_uuid = underifier.sub('_', name)
|
|
# TODO use evolution data server
|
|
hostname = socket.gethostname()
|
|
sample_uuid = sample_uuid + '@' + hostname
|
|
|
|
print()
|
|
print('''Uuid is a globally-unique identifier for your extension.
|
|
This should be in the format of an email address (foo.bar@extensions.example.com), but
|
|
need not be an actual email address, though it's a good idea to base the uuid on your
|
|
email address. For example, if your email address is janedoe@example.com, you might
|
|
use an extension title clicktofocus@janedoe.example.com.''')
|
|
uuid = input('Uuid [%s]: ' % (sample_uuid, )).strip()
|
|
if uuid == '':
|
|
uuid = sample_uuid
|
|
|
|
extension_path = os.path.join(os.path.expanduser('~/.local'), 'share', 'gnome-shell', 'extensions', uuid)
|
|
if os.path.exists(extension_path):
|
|
print("Extension path %r already exists" % (extension_path, ))
|
|
sys.exit(0)
|
|
os.makedirs(extension_path)
|
|
meta = { 'name': name,
|
|
'description': description,
|
|
'uuid': uuid,
|
|
'shell-version': ['@VERSION@'] }
|
|
f = open(os.path.join(extension_path, 'metadata.json'), 'w')
|
|
try:
|
|
json.dump(meta, f)
|
|
except AttributeError:
|
|
# For Python versions older than 2.6, try using the json-py module
|
|
f.write(json.write(meta) + '\n')
|
|
f.close()
|
|
|
|
for filename, contents in SAMPLE_EXTENSION_FILES.items():
|
|
path = os.path.join(extension_path, filename)
|
|
f = open(path, 'w')
|
|
f.write(contents)
|
|
f.close()
|
|
|
|
print("Created extension in %r" % (extension_path, ))
|
|
extensionjs_path = os.path.join(extension_path, 'extension.js')
|
|
subprocess.Popen(['xdg-open', extensionjs_path])
|
|
|
|
ENABLED_EXTENSIONS_KEY = 'enabled-extensions'
|
|
|
|
def enable_extension(uuid):
|
|
settings = Gio.Settings(schema='org.gnome.shell')
|
|
extensions = settings.get_strv(ENABLED_EXTENSIONS_KEY)
|
|
|
|
if uuid in extensions:
|
|
print("%r is already enabled." % (uuid,), file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
extensions.append(uuid)
|
|
settings.set_strv(ENABLED_EXTENSIONS_KEY, extensions)
|
|
print("%r is now enabled." % (uuid,), file=sys.stderr)
|
|
|
|
def disable_extension(uuid):
|
|
settings = Gio.Settings(schema='org.gnome.shell')
|
|
extensions = settings.get_strv(ENABLED_EXTENSIONS_KEY)
|
|
|
|
if uuid not in extensions:
|
|
print("%r is not enabled or installed." % (uuid,), file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Use a while loop here to remove *all* mentions instances
|
|
# of the extension. Some faulty tools like to append more than one.
|
|
while uuid in extensions:
|
|
extensions.remove(uuid)
|
|
|
|
settings.set_strv(ENABLED_EXTENSIONS_KEY, extensions)
|
|
print("%r is now disabled." % (uuid,), file=sys.stderr)
|
|
|
|
def reload_extension(uuid):
|
|
settings = Gio.Settings(schema='org.gnome.shell')
|
|
extensions = settings.get_strv(ENABLED_EXTENSIONS_KEY)
|
|
|
|
if uuid not in extensions:
|
|
print("%r is not enabled or installed." % (uuid,), file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
proxy = Gio.DBusProxy.new_sync(Gio.bus_get_sync(Gio.BusType.SESSION, None),
|
|
Gio.DBusProxyFlags.NONE,
|
|
None,
|
|
'org.gnome.Shell',
|
|
'/org/gnome/Shell',
|
|
'org.gnome.Shell.Extensions',
|
|
None)
|
|
proxy.call_sync('ReloadExtension',
|
|
GLib.Variant('(s)', (uuid,)),
|
|
Gio.DBusCallFlags.NONE,
|
|
-1,
|
|
None)
|
|
|
|
print("%r reloaded." % (uuid,), file=sys.stderr)
|
|
|
|
|
|
def main():
|
|
parser = optparse.OptionParser()
|
|
parser.add_option("-d", "--disable-extension", dest="disable",
|
|
help="Disable a GNOME Shell extension")
|
|
parser.add_option("-e", "--enable-extension", dest="enable",
|
|
help="Enable a GNOME Shell extension")
|
|
parser.add_option("-c", "--create-extension", dest="create", action="store_true",
|
|
help="Create a new GNOME Shell extension")
|
|
parser.add_option("-r", "--reload-extension", dest="reload",
|
|
help="Reload a GNOME Shell extension")
|
|
options, args = parser.parse_args()
|
|
|
|
if args:
|
|
parser.print_usage()
|
|
sys.exit(1)
|
|
|
|
if options.disable:
|
|
disable_extension(options.disable)
|
|
|
|
elif options.enable:
|
|
enable_extension(options.enable)
|
|
|
|
elif options.create:
|
|
create_extension()
|
|
|
|
elif options.reload:
|
|
reload_extension(options.reload)
|
|
|
|
else:
|
|
parser.print_usage()
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|