Created
December 12, 2019 05:59
-
-
Save reusee/c8dbba4d2172352870a8e0349fd1b2f1 to your computer and use it in GitHub Desktop.
personal gnome shell extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const { Meta, Shell, GLib } = imports.gi; | |
const Main = imports.ui.main; | |
const ExtensionUtils = imports.misc.extensionUtils; | |
const Me = ExtensionUtils.getCurrentExtension(); | |
const Util = imports.misc.util; | |
class Extension { | |
constructor() { | |
} | |
enable() { | |
log(`enable ${Me.metadata.name}`); | |
// key bindings | |
const bindings = [ | |
// windows management | |
{ | |
accelerator: '<super>k', | |
// focus next | |
fn: () => { | |
this.switchWindow((windows, i) => { | |
i = i + 1 | |
if (i >= windows.length) { | |
i = 0 | |
} | |
return i | |
}) | |
}, | |
}, | |
{ | |
accelerator: '<super>j', | |
// focus prev | |
fn: () => { | |
this.switchWindow((windows, i) => { | |
i = i - 1 | |
if (i < 0) { | |
i = windows.length - 1 | |
} | |
return i | |
}) | |
}, | |
}, | |
{ | |
accelerator: '<super>z', | |
fn: () => { | |
// close | |
global.display.focus_window.delete(global.display.get_current_time()); | |
}, | |
}, | |
{ | |
accelerator: '<super>a', | |
fn: () => { | |
// minimize | |
global.display.focus_window.minimize(); | |
}, | |
}, | |
// programs | |
{ | |
accelerator: '<super>Return', | |
fn: () => { | |
// terminal emulator | |
Util.spawn(['/home/reus/bin/terminal']); | |
}, | |
}, | |
{ | |
accelerator: '<super>i', | |
fn: () => { | |
// open or switch to browser | |
this.switchWindow((windows, i) => { | |
for (const idx in windows) { | |
if (windows[idx].get_wm_class() == 'Vivaldi-stable') { | |
return idx | |
} | |
} | |
Util.spawn(['vivaldi-stable']); | |
return -1 | |
}) | |
}, | |
}, | |
] | |
const actions = {}; | |
global.display.connect( | |
'accelerator-activated', | |
function(display, action, deviceID, timestamp) { | |
const fn = actions[action]; | |
if (fn) { | |
fn() | |
} | |
}, | |
) | |
for (const binding of bindings) { | |
const action = global.display.grab_accelerator(binding.accelerator, 0); | |
if (action != Meta.KeyBindingAction.NONE) { | |
let name = Meta.external_binding_name_for_action(action); | |
Main.wm.allowKeybinding(name, Shell.ActionMode.ALL); | |
actions[action] = binding.fn; | |
} | |
} | |
// windows signals | |
global.display.connect_after('window-created', (display, win) => { | |
win.connect_after('focus', () => { | |
// unmaximize | |
win.unmaximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL); | |
}) | |
}) | |
global.display.connect_after('notify::focus-window', (display, win) => { | |
const focus = display.focus_window; | |
if (focus) { | |
this.relayout(focus.get_workspace()); | |
} | |
}) | |
// mutter shadow | |
const shadow_factory = Meta.ShadowFactory.get_default() | |
shadow_factory.set_params('normal', true, new Meta.ShadowParams({ | |
'radius': 50, | |
'opacity': 255, | |
})) | |
log(`enable ${Me.metadata.name} done`); | |
} | |
relayout(workspace) { | |
const rect = workspace.get_work_area_all_monitors(); | |
const default_height = rect.height | |
const default_width = default_height / 3 * 4 | |
const padding = rect.width - default_width | |
let windows = workspace.list_windows() | |
.filter(win => { | |
return !win.is_hidden() | |
&& win.get_window_type() == Meta.WindowType.NORMAL | |
&& win.get_transient_for() == null | |
}) | |
const focus = global.display.focus_window; | |
let focus_top = focus | |
const transient_for = focus_top.get_transient_for() | |
if (transient_for) { | |
focus_top = transient_for | |
} | |
const focus_index = windows.indexOf(focus_top); | |
if (focus_index >= 0) { | |
windows = windows.slice(focus_index + 1) | |
.concat(windows.slice(0, focus_index + 1)) | |
} | |
for (const i in windows) { | |
const width = default_width; | |
const height = default_height; | |
const x = windows.length == 1 ? | |
rect.x + padding | |
: rect.x + padding / (windows.length - 1) * i | |
const y = rect.y | |
windows[i].move_resize_frame(false, x, y, width, height); | |
windows[i].raise() | |
} | |
focus.raise() | |
} | |
switchWindow(getIndex) { | |
const workspace = global.workspace_manager.get_active_workspace(); | |
let windows = workspace.list_windows(); | |
windows = windows.filter(win => !win.is_hidden()); | |
const focus = global.display.focus_window; | |
let i = windows.indexOf(focus); | |
const idx = getIndex(windows, i); | |
if (idx >= 0 && idx != i) { | |
windows[idx].activate(global.display.get_current_time()); | |
} | |
} | |
disable() { | |
log(`disable ${Me.metadata.name}`); | |
} | |
} | |
function init() { | |
log(`init ${Me.metadata.name}`); | |
return new Extension(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment