[gnome] Upgrade gjsosk
This commit is contained in:
@ -6,7 +6,6 @@ import St from 'gi://St';
|
||||
import Shell from 'gi://Shell';
|
||||
|
||||
|
||||
import * as EdgeDragAction from 'resource:///org/gnome/shell/ui/edgeDragAction.js';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
|
||||
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
|
||||
@ -17,7 +16,13 @@ import * as InputSourceManager from 'resource:///org/gnome/shell/ui/status/keybo
|
||||
import * as Config from 'resource:///org/gnome/shell/misc/config.js'
|
||||
const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s));
|
||||
import { Dialog } from 'resource:///org/gnome/shell/ui/dialog.js';
|
||||
|
||||
let EdgeDragAction = null;
|
||||
if (major < 49) {
|
||||
try {
|
||||
const edgedragimport = await import('resource:///org/gnome/shell/ui/edgeDragAction.js')
|
||||
EdgeDragAction = edgedragimport ?? null
|
||||
} catch { }
|
||||
}
|
||||
import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';
|
||||
|
||||
const State = {
|
||||
@ -82,12 +87,14 @@ export default class GjsOskExtension extends Extension {
|
||||
_openKeyboard(instant) {
|
||||
if (this.Keyboard.state == State.CLOSED) {
|
||||
this.Keyboard.open(null, !instant ? null : true);
|
||||
this.openBit.set_boolean('keyboard-visible', true);
|
||||
}
|
||||
}
|
||||
|
||||
_closeKeyboard(instant) {
|
||||
if (this.Keyboard.state == State.OPENED) {
|
||||
this.Keyboard.close(!instant ? null : true);
|
||||
this.openBit.set_boolean('keyboard-visible', false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +111,7 @@ export default class GjsOskExtension extends Extension {
|
||||
}
|
||||
|
||||
open_interval() {
|
||||
if (this.tapConnect && GObject.signal_handler_is_connected(global.stage, this.tapConnect))
|
||||
global.stage.disconnect(this.tapConnect)
|
||||
if (this.openInterval !== null) {
|
||||
clearInterval(this.openInterval);
|
||||
@ -130,13 +138,26 @@ export default class GjsOskExtension extends Extension {
|
||||
}, 300);
|
||||
this.tapConnect = global.stage.connect("event", (_actor, event) => {
|
||||
if (event.type() !== 4 && event.type() !== 5) {
|
||||
this.lastInputMethod = [false, event.type() >= 9 && event.type() <= 12, true][this.settings.get_int("enable-tap-gesture")]
|
||||
this.lastInputMethod = [false, event.type() >= 9 && event.type() <= 12, true][this.settings.get_boolean("indicator-enabled") ? this.settings.get_int("enable-tap-gesture") : 0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fail(error, method = null, instance = null) {
|
||||
Main.notifyError("Error with extension GJS-OSK"
|
||||
+ (instance != null || method != null ? " in " : "")
|
||||
+ (instance != null ? instance + "." : "")
|
||||
+ (method != null ? method + "\n" : ""),
|
||||
error.message
|
||||
+ "\n" + error.stack);
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.settings = this.getSettings();
|
||||
if (this.settings == null) {
|
||||
return;
|
||||
}
|
||||
this.disableEdgeSwipeSettings = this.settings.get_boolean("disable-edge-swipe");
|
||||
this.darkSchemeSettings = this.getSettings("org.gnome.desktop.interface");
|
||||
this.inputLanguageSettings = InputSourceManager.getInputSourceManager();
|
||||
this.gnomeKeyboardSettings = this.getSettings('org.gnome.desktop.a11y.applications');
|
||||
@ -158,10 +179,19 @@ export default class GjsOskExtension extends Extension {
|
||||
}
|
||||
|
||||
let refresh = () => {
|
||||
(async () => {
|
||||
// [insert handwriting 2]
|
||||
let prevOpenState = false;
|
||||
if (this.Keyboard != null) {
|
||||
prevOpenState = this.Keyboard.opened;
|
||||
}
|
||||
let currentMonitors = this.settings.get_string("default-monitor").split(";")
|
||||
let currentMonitorMap = {};
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
if (Main.layoutManager.primaryMonitor == null) {
|
||||
this.waitRefresh = setTimeout(refresh, 1000)
|
||||
return;
|
||||
}
|
||||
for (var i of currentMonitors) {
|
||||
let tmp = i.split(":");
|
||||
currentMonitorMap[tmp[0]] = tmp[1] + "";
|
||||
@ -178,24 +208,174 @@ export default class GjsOskExtension extends Extension {
|
||||
} catch {
|
||||
currentMonitorId = 0;
|
||||
}
|
||||
if (!Gio.File.new_for_path(extract_dir).query_exists(null)) {
|
||||
Gio.File.new_for_path(extract_dir).make_directory(null);
|
||||
Gio.File.new_for_path(extract_dir + "/keycodes").make_directory(null);
|
||||
let [status, out, err, code] = GLib.spawn_command_line_sync("tar -Jxf " + this.path + "/keycodes.tar.xz -C " + extract_dir + "/keycodes")
|
||||
if (err != "" || code != 0) {
|
||||
throw new Error(err);
|
||||
const fileExists = async (file) => {
|
||||
try {
|
||||
return await new Promise((resolve) => {
|
||||
file.query_info_async(
|
||||
'*',
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
(source, res) => {
|
||||
try {
|
||||
source.query_info_finish(res);
|
||||
resolve(true);
|
||||
} catch (e) {
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
if (this.Keyboard != null) {
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const ensureDirectory = async (dir) => {
|
||||
try {
|
||||
if (!(await fileExists(dir))) {
|
||||
await new Promise((resolve, reject) => {
|
||||
dir.make_directory_async(GLib.PRIORITY_DEFAULT, null, (source, res) => {
|
||||
try {
|
||||
source.make_directory_finish(res);
|
||||
resolve();
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
|
||||
reject(e);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`Failed to create directory ${dir.get_path()}: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const runCommand = (argv) => {
|
||||
return new Promise((resolve) => {
|
||||
const proc = Gio.Subprocess.new(
|
||||
argv,
|
||||
Gio.SubprocessFlags.STDOUT_PIPE |
|
||||
Gio.SubprocessFlags.STDERR_PIPE
|
||||
);
|
||||
proc.wait_check_async(null, (source, res) => {
|
||||
try {
|
||||
const success = source.wait_check_finish(res);
|
||||
resolve(success);
|
||||
} catch (e) {
|
||||
console.error(`Command failed: ${argv.join(' ')}`);
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const extractKeycodes = async () => {
|
||||
const baseDir = Gio.File.new_for_path(extract_dir);
|
||||
const keycodesDir = Gio.File.new_for_path(extract_dir + "/keycodes");
|
||||
const layoutId = KeyboardManager.getKeyboardManager().currentLayout?.id || "us";
|
||||
const targetFile = Gio.File.new_for_path(`${extract_dir}/keycodes/${layoutId}.json`);
|
||||
|
||||
if (await fileExists(targetFile)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(await ensureDirectory(baseDir))) {
|
||||
console.error("Failed to create base directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(await ensureDirectory(keycodesDir))) {
|
||||
console.error("Failed to create keycodes directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const success = await runCommand([
|
||||
"tar",
|
||||
"-Jxf",
|
||||
this.path + "/keycodes.tar.xz",
|
||||
"-C",
|
||||
keycodesDir.get_path(),
|
||||
"--strip-components=1"
|
||||
]);
|
||||
|
||||
if (!success) {
|
||||
throw new Error("Failed to extract keycodes archive");
|
||||
}
|
||||
|
||||
if (!(await fileExists(targetFile))) {
|
||||
throw new Error("Keycodes file not found after extraction");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error extracting keycodes: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const initializeKeyboard = async () => {
|
||||
const layoutId = KeyboardManager.getKeyboardManager().currentLayout?.id || "us";
|
||||
const keycodesPath = GLib.build_filenamev([
|
||||
extract_dir,
|
||||
"keycodes",
|
||||
`${layoutId}.json`
|
||||
]);
|
||||
|
||||
const [ok, contents] = GLib.file_get_contents(keycodesPath);
|
||||
if (!ok) {
|
||||
throw new Error(`Failed to read keycodes from ${keycodesPath}`);
|
||||
}
|
||||
|
||||
keycodes = JSON.parse(contents);
|
||||
|
||||
if (this.Keyboard) {
|
||||
this.Keyboard.destroy();
|
||||
this.Keyboard = null;
|
||||
}
|
||||
let [ok, contents] = GLib.file_get_contents(extract_dir + "/keycodes/" + KeyboardManager.getKeyboardManager().currentLayout.id + '.json');
|
||||
if (ok) {
|
||||
keycodes = JSON.parse(contents);
|
||||
|
||||
if (this.settings == null) {
|
||||
return;
|
||||
}
|
||||
this.Keyboard = new Keyboard(this.settings, this);
|
||||
this.Keyboard.refresh = refresh
|
||||
|
||||
function withErrorHandler(TargetClass, handler) {
|
||||
return new Proxy(TargetClass, {
|
||||
construct(Target, args) {
|
||||
const instance = new Target(...args);
|
||||
for (const key of Object.getOwnPropertyNames(Target.prototype)) {
|
||||
const fn = instance[key];
|
||||
if (typeof fn === "function" && key !== "constructor") {
|
||||
instance[key] = async (...fnArgs) => {
|
||||
try {
|
||||
return await fn.apply(instance, fnArgs);
|
||||
} catch (err) {
|
||||
handler(err, key, instance);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
});
|
||||
}
|
||||
const SafeKeyboard = withErrorHandler(Keyboard, this.fail);
|
||||
this.Keyboard = new SafeKeyboard(this.settings, this);
|
||||
this.Keyboard.refresh = refresh;
|
||||
if (prevOpenState) {
|
||||
this.Keyboard.open(null, true);
|
||||
this.openBit.set_boolean('keyboard-visible', true);
|
||||
}
|
||||
};
|
||||
await extractKeycodes();
|
||||
await initializeKeyboard();
|
||||
})().catch(this.fail)
|
||||
}
|
||||
refresh()
|
||||
|
||||
@ -226,21 +406,29 @@ export default class GjsOskExtension extends Extension {
|
||||
this._quick_settings_indicator.quickSettingsItems.push(this._toggle);
|
||||
Main.panel.statusArea.quickSettings.addExternalIndicator(this._quick_settings_indicator);
|
||||
this.open_interval();
|
||||
this.openFromCommandHandler = this.openBit.connect("changed", () => {
|
||||
this.openBit.set_boolean("opened", false)
|
||||
|
||||
this.keyboardVisibilityHandler = this.openBit.connect('changed::keyboard-visible', () => {
|
||||
const shouldBeVisible = this.openBit.get_boolean('keyboard-visible');
|
||||
if (shouldBeVisible !== this.Keyboard?.opened) {
|
||||
this._toggleKeyboard(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.openFromCommandHandler = this.openBit.connect("changed::opened", () => {
|
||||
if (this.openBit.get_boolean("opened")) {
|
||||
this.openBit.set_boolean("opened", false);
|
||||
this._toggleKeyboard();
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
if (this.openBit.get_boolean('keyboard-visible') && this.Keyboard) {
|
||||
this._openKeyboard(true);
|
||||
}
|
||||
let settingsChanged = () => {
|
||||
let opened;
|
||||
if (this.Keyboard != null)
|
||||
opened = this.Keyboard.opened
|
||||
else
|
||||
opened = false
|
||||
if (this.darkSchemeSettings.get_string("color-scheme") == "prefer-dark")
|
||||
this.settings.scheme = "-dark"
|
||||
else
|
||||
this.settings.scheme = ""
|
||||
this.Keyboard.openedFromButton = false;
|
||||
refresh()
|
||||
this._toggle._refresh();
|
||||
if (this.settings.get_boolean("indicator-enabled")) {
|
||||
@ -274,8 +462,24 @@ export default class GjsOskExtension extends Extension {
|
||||
this.openInterval = null;
|
||||
}
|
||||
this.open_interval();
|
||||
if (opened) {
|
||||
this._toggleKeyboard(true);
|
||||
let disableEdgeSwipe = this.settings.get_boolean("disable-edge-swipe");
|
||||
if (this.disableEdgeSwipeSettings !== disableEdgeSwipe) {
|
||||
this.disableEdgeSwipeSettings = disableEdgeSwipe;
|
||||
if (disableEdgeSwipe) {
|
||||
if (EdgeDragAction != null) {
|
||||
global.stage.remove_action_by_name('osk');
|
||||
} else {
|
||||
global.stage.remove_action_by_name('GJS-OSK Edge Drag Action');
|
||||
}
|
||||
} else {
|
||||
if (this.keyboard != null && this.keyboard.bottomDragAction != null) {
|
||||
if (EdgeDragAction != null) {
|
||||
global.stage.add_action_full('osk', Clutter.EventPhase.CAPTURE, this.keyboard.bottomDragAction);
|
||||
} else {
|
||||
global.stage.add_action(this.keyboard.bottomDragAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.settingsHandlers = [
|
||||
@ -306,15 +510,24 @@ export default class GjsOskExtension extends Extension {
|
||||
this.darkSchemeSettings = null;
|
||||
this.inputLanguageSettings = null;
|
||||
this.gnomeKeyboardSettings = null;
|
||||
if (this.keyboardVisibilityHandler) {
|
||||
this.openBit.disconnect(this.keyboardVisibilityHandler);
|
||||
this.keyboardVisibilityHandler = null;
|
||||
}
|
||||
if (this.openFromCommandHandler) {
|
||||
this.openBit.disconnect(this.openFromCommandHandler);
|
||||
this.openFromCommandHandler = null;
|
||||
}
|
||||
this.openBit = null;
|
||||
global.stage.disconnect(this.tapConnect)
|
||||
if (this.openInterval !== null) {
|
||||
clearInterval(this.openInterval);
|
||||
this.openInterval = null;
|
||||
}
|
||||
if (this._toggle !== null) {
|
||||
this._toggle.destroy()
|
||||
this._toggle = null
|
||||
}
|
||||
this.settings = null
|
||||
this.Keyboard = null
|
||||
keycodes = null
|
||||
@ -341,14 +554,15 @@ class Keyboard extends Dialog {
|
||||
this.settingsOpenFunction = extensionObject.openPrefs
|
||||
this.inputDevice = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
|
||||
this.settings = settings;
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId];
|
||||
super._init(Main.layoutManager.modalDialogGroup, 'db-keyboard-content');
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor;
|
||||
super._init(Main.uiGroup, 'db-keyboard-content');
|
||||
this.box = new St.Widget({
|
||||
reactive: true,
|
||||
layout_manager: new Clutter.GridLayout({
|
||||
orientation: Clutter.Orientation.HORIZONTAL,
|
||||
})
|
||||
});
|
||||
this.box.clear_actions();
|
||||
this.widthPercent = (monitor.width > monitor.height) ? settings.get_int("landscape-width-percent") / 100 : settings.get_int("portrait-width-percent") / 100;
|
||||
this.heightPercent = (monitor.width > monitor.height) ? settings.get_int("landscape-height-percent") / 100 : settings.get_int("portrait-height-percent") / 100;
|
||||
this.nonDragBlocker = new Clutter.Actor();
|
||||
@ -367,7 +581,9 @@ class Keyboard extends Dialog {
|
||||
this.state = State.CLOSED;
|
||||
this.delta = [];
|
||||
this.monitorChecker = global.backend.get_monitor_manager().connect('monitors-changed', () => {
|
||||
this.refresh()
|
||||
if (Main.layoutManager.monitors.length > 0) {
|
||||
this.refresh();
|
||||
}
|
||||
});
|
||||
this._dragging = false;
|
||||
let side = null;
|
||||
@ -389,25 +605,21 @@ class Keyboard extends Dialog {
|
||||
side = St.Side.BOTTOM;
|
||||
break;
|
||||
}
|
||||
this.oldBottomDragAction = global.stage.get_action('osk');
|
||||
this.oldBottomDragAction = global.stage.get_action(EdgeDragAction == null ? 'OSK show bottom drag' : 'osk');
|
||||
if (this.oldBottomDragAction !== null && this.oldBottomDragAction instanceof Clutter.Action)
|
||||
global.stage.remove_action(this.oldBottomDragAction);
|
||||
if (side != null) {
|
||||
const mode = Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN;
|
||||
const bottomDragAction = new EdgeDragAction.EdgeDragAction(side, mode);
|
||||
bottomDragAction.connect('activated', () => {
|
||||
let oskEdgeDragAction;
|
||||
if (EdgeDragAction != null) {
|
||||
oskEdgeDragAction = new EdgeDragAction.EdgeDragAction(side, mode);
|
||||
oskEdgeDragAction.connect('activated', () => {
|
||||
this.open(true);
|
||||
this.openedFromButton = true;
|
||||
this.closedFromButton = false;
|
||||
this.gestureInProgress = false;
|
||||
});
|
||||
bottomDragAction.connect('progress', (_action, progress) => {
|
||||
if (!this.gestureInProgress)
|
||||
this.open(false)
|
||||
this.setOpenState(Math.min(Math.max(0, (progress / (side % 2 == 0 ? this.box.height : this.box.width)) * 100), 100))
|
||||
this.gestureInProgress = true;
|
||||
});
|
||||
bottomDragAction.connect('gesture-cancel', () => {
|
||||
oskEdgeDragAction.connect('gesture-cancel', () => {
|
||||
if (this.gestureInProgress) {
|
||||
this.close()
|
||||
this.openedFromButton = false;
|
||||
@ -416,14 +628,56 @@ class Keyboard extends Dialog {
|
||||
this.gestureInProgress = false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
global.stage.add_action_full('osk', Clutter.EventPhase.CAPTURE, bottomDragAction);
|
||||
this.bottomDragAction = bottomDragAction;
|
||||
oskEdgeDragAction.connect('progress', (_action, progress) => {
|
||||
if (!this.gestureInProgress)
|
||||
this.open(false)
|
||||
this.setOpenState(Math.min(Math.max(0, (progress / (side % 2 == 0 ? this.box.height : this.box.width)) * 100), 100))
|
||||
this.gestureInProgress = true;
|
||||
});
|
||||
if (!this.settings.get_boolean("disable-edge-swipe")) {
|
||||
global.stage.add_action_full('osk', Clutter.EventPhase.CAPTURE, oskEdgeDragAction);
|
||||
}
|
||||
this.bottomDragAction = oskEdgeDragAction;
|
||||
} else {
|
||||
oskEdgeDragAction = new Shell.EdgeDragGesture({
|
||||
name: 'GJS-OSK Edge Drag Action',
|
||||
side
|
||||
})
|
||||
oskEdgeDragAction.connect('may-recognize', () => {
|
||||
return Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN & Main.actionMode;
|
||||
})
|
||||
oskEdgeDragAction.connect('end', () => {
|
||||
this.open(true);
|
||||
this.openedFromButton = true;
|
||||
this.closedFromButton = false;
|
||||
this.gestureInProgress = false;
|
||||
});
|
||||
oskEdgeDragAction.connect('cancel', () => {
|
||||
if (this.gestureInProgress) {
|
||||
this.close()
|
||||
this.openedFromButton = false;
|
||||
this.closedFromButton = true;
|
||||
}
|
||||
this.gestureInProgress = false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
oskEdgeDragAction.connect('progress', (_action, progress) => {
|
||||
if (!this.gestureInProgress)
|
||||
this.open(false)
|
||||
this.setOpenState(Math.min(Math.max(0, (progress / (side % 2 == 0 ? this.box.height : this.box.width)) * 100), 100))
|
||||
this.gestureInProgress = true;
|
||||
});
|
||||
if (!this.settings.get_boolean("disable-edge-swipe")) {
|
||||
global.stage.add_action(oskEdgeDragAction);
|
||||
}
|
||||
this.bottomDragAction = oskEdgeDragAction;
|
||||
}
|
||||
} else {
|
||||
this.bottomDragAction = null;
|
||||
}
|
||||
this._oldMaybeHandleEvent = Main.keyboard.maybeHandleEvent
|
||||
Main.keyboard.maybeHandleEvent = (e) => {
|
||||
let lastInputMethod = [e.type() == 11, e.type() == 11, e.type() == 7 || e.type() == 11][this.settings.get_int("enable-tap-gesture")]
|
||||
let lastInputMethod = [e.type() == 11, e.type() == 11, e.type() == 7 || e.type() == 11][this.settings.get_boolean("indicator-enabled") ? this.settings.get_int("enable-tap-gesture") : 0]
|
||||
let ac = global.stage.get_event_actor(e)
|
||||
if (this.contains(ac)) {
|
||||
ac.event(e, true);
|
||||
@ -438,9 +692,14 @@ class Keyboard extends Dialog {
|
||||
|
||||
destroy() {
|
||||
Main.keyboard.maybeHandleEvent = this._oldMaybeHandleEvent
|
||||
if (this.oldBottomDragAction !== null && this.oldBottomDragAction instanceof Clutter.Action && EdgeDragAction != null) {
|
||||
global.stage.remove_action_by_name('osk')
|
||||
if (this.oldBottomDragAction !== null && this.oldBottomDragAction instanceof Clutter.Action)
|
||||
global.stage.add_action_full('osk', Clutter.EventPhase.CAPTURE, this.oldBottomDragAction)
|
||||
}
|
||||
else if (this.oldBottomDragAction != null) {
|
||||
global.stage.remove_action_by_name('GJS-OSK Edge Drag Action')
|
||||
global.stage.add_action(this.oldBottomDragAction)
|
||||
}
|
||||
if (this.textboxChecker !== null) {
|
||||
clearInterval(this.textboxChecker);
|
||||
this.textboxChecker = null;
|
||||
@ -451,9 +710,15 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
if (this.keyTimeout !== null) {
|
||||
clearTimeout(this.keyTimeout);
|
||||
this.keyTimeout = null;
|
||||
if (typeof this.keyTimeoutFunc === 'function') {
|
||||
this.keyTimeoutFunc();
|
||||
}
|
||||
this.keymap.disconnect(this.capslockConnect);
|
||||
this.keyTimeout = null;
|
||||
this.keyTimeoutFunc = null;
|
||||
}
|
||||
if (this.capsLockConnect && GObject.signal_handler_is_connected(this.keymap, this.capsLockConnect))
|
||||
this.keymap.disconnect(this.capsLockConnect);
|
||||
if (this.numLockConnect && GObject.signal_handler_is_connected(this.keymap, this.numLockConnect))
|
||||
this.keymap.disconnect(this.numLockConnect);
|
||||
global.backend.get_monitor_manager().disconnect(this.monitorChecker)
|
||||
super.destroy();
|
||||
@ -474,10 +739,8 @@ class Keyboard extends Dialog {
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
onComplete: () => { }
|
||||
});
|
||||
let device = event.get_device();
|
||||
let sequence = event.get_event_sequence();
|
||||
this._grab = global.stage.grab(this);
|
||||
this._grabbedDevice = device;
|
||||
this._grabbedSequence = sequence;
|
||||
this.emit('drag-begin');
|
||||
let [absX, absY] = event.get_coords();
|
||||
@ -508,7 +771,6 @@ class Keyboard extends Dialog {
|
||||
onComplete: () => { }
|
||||
});
|
||||
this._grabbedSequence = null;
|
||||
this._grabbedDevice = null;
|
||||
this._dragging = false;
|
||||
this.delta = [];
|
||||
this.emit('drag-end');
|
||||
@ -532,7 +794,7 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
|
||||
snapMovement(xPos, yPos) {
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId]
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor
|
||||
if (xPos < monitor.x || yPos < monitor.y || xPos > monitor.x + monitor.width || yPos > monitor.y + monitor.width) {
|
||||
this.set_translation(xPos, yPos, 0);
|
||||
return;
|
||||
@ -558,7 +820,7 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
|
||||
setOpenState(percent) {
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId];
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor;
|
||||
let posX = [this.settings.get_int("snap-spacing-px"), ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - this.settings.get_int("snap-spacing-px")][(this.settings.get_int("default-snap") % 3)];
|
||||
let posY = [this.settings.get_int("snap-spacing-px"), ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - this.settings.get_int("snap-spacing-px")][Math.floor((this.settings.get_int("default-snap") / 3))];
|
||||
let mX = [-this.box.width, 0, this.box.width][(this.settings.get_int("default-snap") % 3)];
|
||||
@ -579,7 +841,7 @@ class Keyboard extends Dialog {
|
||||
this.show();
|
||||
}
|
||||
if (noPrep == null || noPrep) {
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId];
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor;
|
||||
let posX = [this.settings.get_int("snap-spacing-px"), ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - this.settings.get_int("snap-spacing-px")][(this.settings.get_int("default-snap") % 3)];
|
||||
let posY = [this.settings.get_int("snap-spacing-px"), ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - this.settings.get_int("snap-spacing-px")][Math.floor((this.settings.get_int("default-snap") / 3))];
|
||||
if (noPrep == null) {
|
||||
@ -620,7 +882,7 @@ class Keyboard extends Dialog {
|
||||
|
||||
close(instant = null) {
|
||||
this.prevKeyFocus = null;
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId];
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor;
|
||||
let posX = [this.settings.get_int("snap-spacing-px"), ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - this.settings.get_int("snap-spacing-px")][(this.settings.get_int("default-snap") % 3)];
|
||||
let posY = [this.settings.get_int("snap-spacing-px"), ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - this.settings.get_int("snap-spacing-px")][Math.floor((this.settings.get_int("default-snap") / 3))];
|
||||
let mX = [-this.box.width, 0, this.box.width][(this.settings.get_int("default-snap") % 3)];
|
||||
@ -679,6 +941,14 @@ class Keyboard extends Dialog {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
vfunc_key_press_event() {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
vfunc_key_release_event() {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
vfunc_touch_event() {
|
||||
let event = Clutter.get_current_event();
|
||||
let sequence = event.get_event_sequence();
|
||||
@ -701,9 +971,17 @@ class Keyboard extends Dialog {
|
||||
buildUI() {
|
||||
this.box.set_opacity(0);
|
||||
this.keys = [];
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId]
|
||||
let layoutName = Object.keys(layouts)[(monitor.width > monitor.height) ? this.settings.get_int("layout-landscape") : this.settings.get_int("layout-portrait")];
|
||||
this.box.width = Math.round((monitor.width - this.settings.get_int("snap-spacing-px") * 2) * (layoutName.includes("Split") ? 1 : this.widthPercent))
|
||||
let monitor = Main.layoutManager.monitors[currentMonitorId] ?? Main.layoutManager.primaryMonitor
|
||||
let layoutIdx = (monitor.width > monitor.height) ? this.settings.get_int("layout-landscape") : this.settings.get_int("layout-portrait")
|
||||
let currentLayout;
|
||||
if (layoutIdx < 10) {
|
||||
let layoutName = Object.keys(layouts)[layoutIdx];
|
||||
currentLayout = layouts[layoutName];
|
||||
}
|
||||
else {
|
||||
currentLayout = JSON.parse(this.settings.get_string("custom-layout"))
|
||||
}
|
||||
this.box.width = Math.round((monitor.width - this.settings.get_int("snap-spacing-px") * 2) * (currentLayout[currentLayout.length - 1].split ? 1 : this.widthPercent))
|
||||
this.box.height = Math.round((monitor.height - this.settings.get_int("snap-spacing-px") * 2) * this.heightPercent)
|
||||
|
||||
if (!this.settings.get_boolean("enable-drag")) {
|
||||
@ -749,7 +1027,7 @@ class Keyboard extends Dialog {
|
||||
|
||||
const grid = this.box.layout_manager
|
||||
grid.set_row_homogeneous(true)
|
||||
grid.set_column_homogeneous(!layoutName.includes("Split"))
|
||||
grid.set_column_homogeneous(!currentLayout[currentLayout.length - 1].split)
|
||||
|
||||
let gridLeft;
|
||||
let gridRight;
|
||||
@ -758,7 +1036,7 @@ class Keyboard extends Dialog {
|
||||
let right;
|
||||
let topBtnWidth;
|
||||
|
||||
if (layoutName.includes("Split")) {
|
||||
if (currentLayout[currentLayout.length - 1].split) {
|
||||
this.box.reactive = false;
|
||||
left = new St.Widget({
|
||||
reactive: true,
|
||||
@ -792,17 +1070,16 @@ class Keyboard extends Dialog {
|
||||
this.shiftButtons = [];
|
||||
// [insert handwriting 7]
|
||||
|
||||
let currentLayout = layouts[layoutName];
|
||||
let width = 0;
|
||||
for (const c of currentLayout[0]) {
|
||||
width += (Object.hasOwn(c, "width") ? c.width : 1)
|
||||
width += (("width" in c) ? c.width : 1)
|
||||
}
|
||||
let rowSize;
|
||||
let halfSize;
|
||||
let r = 0;
|
||||
let c;
|
||||
const doAddKey = (keydef) => {
|
||||
const i = Object.hasOwn(keydef, "key") ? keycodes[keydef.key] : Object.hasOwn(keydef, "split") ? "split" : "empty space";
|
||||
const i = ("key" in keydef) ? keycodes[keydef.key] : ("split" in keydef) ? "split" : "empty space";
|
||||
if (i != null && typeof i !== 'string') {
|
||||
if (i.layers.default == null) {
|
||||
for (var key of Object.keys(i.layers)) {
|
||||
@ -816,7 +1093,7 @@ class Keyboard extends Dialog {
|
||||
|
||||
let iconKeys = ["left", "up", "right", "down", "space"]
|
||||
if (this.settings.get_boolean("show-icons")) {
|
||||
iconKeys = ["left", "up", "right", "down", "backspace", "tab", "capslock", "shift", "enter", "ctrl", "super", "alt", "space"]
|
||||
iconKeys = ["left", "up", "right", "down", "backspace", "tab", "capslock", "shift", "enter", "ctrl", "super", "alt", "space", "menu"]
|
||||
}
|
||||
// [insert handwriting 8]
|
||||
if (iconKeys.some(j => { return i.layers.default.toLowerCase() == j })) {
|
||||
@ -829,7 +1106,7 @@ class Keyboard extends Dialog {
|
||||
params.label = i.layers.default
|
||||
}
|
||||
i.isMod = false
|
||||
if ([42, 54, 29, 125, 56, 100, 97, 58, 69].some(j => { return i.code == j })) {
|
||||
if ([42, 54, 29, 125, 126, 56, 100, 97, 58, 69].some(j => { return i.code == j })) {
|
||||
i.isMod = true;
|
||||
}
|
||||
const keyBtn = new St.Button(params)
|
||||
@ -837,7 +1114,7 @@ class Keyboard extends Dialog {
|
||||
keyBtn.char = i
|
||||
if (i.code == 58) {
|
||||
this.keymap = Clutter.get_default_backend().get_default_seat().get_keymap()
|
||||
this.capslockConnect = this.keymap.connect("state-changed", (a, e) => {
|
||||
this.capsLockConnect = this.keymap.connect("state-changed", (a, e) => {
|
||||
this.setCapsLock(keyBtn, this.keymap.get_caps_lock_state())
|
||||
})
|
||||
this.updateCapsLock = () => this.setCapsLock(keyBtn, this.keymap.get_caps_lock_state())
|
||||
@ -850,13 +1127,13 @@ class Keyboard extends Dialog {
|
||||
} else if (i.code == 42 || i.code == 54) {
|
||||
this.shiftButtons.push(keyBtn)
|
||||
}
|
||||
currentGrid.attach(keyBtn, c, 5 + r, (Object.hasOwn(keydef, "width") ? keydef.width : 1) * 2, r == 0 ? 3 : (Object.hasOwn(keydef, "height") ? keydef.height : 1) * 4)
|
||||
currentGrid.attach(keyBtn, c, 5 + r, (("width" in keydef) ? keydef.width : 1) * 2, r == 0 ? 3 : (("height" in keydef) ? keydef.height : 1) * 4)
|
||||
keyBtn.visible = true
|
||||
c += (Object.hasOwn(keydef, "width") ? keydef.width : 1) * 2
|
||||
c += (("width" in keydef) ? keydef.width : 1) * 2
|
||||
this.keys.push(keyBtn)
|
||||
// [insert handwriting 9]
|
||||
} else if (i == "empty space") {
|
||||
c += (Object.hasOwn(keydef, "width") ? keydef.width : 1) * 2
|
||||
c += (("width" in keydef) ? keydef.width : 1) * 2
|
||||
} else if (i == "split") {
|
||||
currentGrid = gridRight
|
||||
const size = c
|
||||
@ -864,21 +1141,21 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
for (const kRow of currentLayout) {
|
||||
for (const kRow of currentLayout.slice(0, -1)) {
|
||||
c = 0;
|
||||
if (layoutName.includes("Split")) {
|
||||
if (currentLayout[currentLayout.length - 1].split) {
|
||||
currentGrid = gridLeft;
|
||||
}
|
||||
for (const keydef of kRow) {
|
||||
if (keydef instanceof Array) {
|
||||
keydef.forEach(i => { doAddKey(i); r += 2; c -= (Object.hasOwn(i, "width") ? i.width : 1) * 2 });
|
||||
c += (Object.hasOwn(keydef[0], "width") ? keydef[0].width : 1) * 2;
|
||||
keydef.forEach(i => { doAddKey(i); r += 2; c -= (("width" in i) ? i.width : 1) * 2 });
|
||||
c += (("width" in keydef[0]) ? keydef[0].width : 1) * 2;
|
||||
r -= 4;
|
||||
} else {
|
||||
doAddKey(keydef)
|
||||
}
|
||||
}
|
||||
if (!topBtnWidth) topBtnWidth = ((Object.hasOwn(kRow[kRow.length - 1], "width") && (Object.hasOwn(kRow[kRow.length - 1], "key"))) ? kRow[kRow.length - 1].width : 1)
|
||||
if (!topBtnWidth) topBtnWidth = ((("width" in kRow[kRow.length - 1]) && ("key" in kRow[kRow.length - 1])) ? kRow[kRow.length - 1].width : 1)
|
||||
const size = c;
|
||||
if (!rowSize) rowSize = size;
|
||||
r += r == 0 ? 3 : 4
|
||||
@ -907,37 +1184,60 @@ class Keyboard extends Dialog {
|
||||
left.add_style_class_name("regular");
|
||||
right.add_style_class_name("regular");
|
||||
}
|
||||
|
||||
let mvBtnStartLeft = 2 * topBtnWidth
|
||||
let mvBtnEndRight = 2 * topBtnWidth
|
||||
|
||||
if (currentLayout[currentLayout.length - 1].settings) {
|
||||
const settingsBtn = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
settingsBtn.add_style_class_name("settings_btn")
|
||||
settingsBtn.add_style_class_name("key")
|
||||
settingsBtn.connect("clicked", () => {
|
||||
settingsBtn.connect("button-press-event", () => {
|
||||
this.settingsOpenFunction();
|
||||
})
|
||||
settingsBtn.connect("touch-event", () => {
|
||||
if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_BEGIN)
|
||||
this.settingsOpenFunction();
|
||||
})
|
||||
gridLeft.attach(settingsBtn, 0, 0, 2 * topBtnWidth, 3)
|
||||
this.keys.push(settingsBtn)
|
||||
gridLeft.attach(settingsBtn, 0, 0, 2 * topBtnWidth, 3)
|
||||
} else {
|
||||
mvBtnStartLeft = 0
|
||||
}
|
||||
|
||||
if (currentLayout[currentLayout.length - 1].close) {
|
||||
const closeBtn = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
closeBtn.add_style_class_name("close_btn")
|
||||
closeBtn.add_style_class_name("key")
|
||||
closeBtn.connect("clicked", () => {
|
||||
closeBtn.connect("button-press-event", () => {
|
||||
this.close();
|
||||
this.closedFromButton = true;
|
||||
})
|
||||
closeBtn.connect("touch-event", () => {
|
||||
if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_BEGIN) {
|
||||
this.close();
|
||||
this.closedFromButton = true;
|
||||
}
|
||||
})
|
||||
gridRight.attach(closeBtn, (rowSize - 2 * topBtnWidth), 0, 2 * topBtnWidth, 3)
|
||||
this.keys.push(closeBtn)
|
||||
} else {
|
||||
mvBtnEndRight = 0
|
||||
}
|
||||
|
||||
let moveHandleLeft = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
moveHandleLeft.clear_actions()
|
||||
moveHandleLeft.add_style_class_name("moveHandle")
|
||||
moveHandleLeft.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
moveHandleLeft.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px" : "0") + "; background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
if (this.lightOrDark()) {
|
||||
moveHandleLeft.add_style_class_name("inverted");
|
||||
} else {
|
||||
@ -950,14 +1250,15 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
this.event(event, false)
|
||||
})
|
||||
gridLeft.attach(moveHandleLeft, 2 * topBtnWidth, 0, (halfSize - 2 * topBtnWidth), 3)
|
||||
gridLeft.attach(moveHandleLeft, mvBtnStartLeft, 0, (halfSize - mvBtnStartLeft), 3)
|
||||
|
||||
let moveHandleRight = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
moveHandleRight.clear_actions()
|
||||
moveHandleRight.add_style_class_name("moveHandle")
|
||||
moveHandleRight.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
moveHandleRight.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px" : "0") + "; background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
if (this.lightOrDark()) {
|
||||
moveHandleRight.add_style_class_name("inverted");
|
||||
} else {
|
||||
@ -970,7 +1271,7 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
this.event(event, false)
|
||||
})
|
||||
gridRight.attach(moveHandleRight, halfSize, 0, (rowSize - halfSize - 2 * topBtnWidth), 3)
|
||||
gridRight.attach(moveHandleRight, halfSize, 0, (rowSize - halfSize - mvBtnEndRight), 3)
|
||||
gridLeft.attach(new St.Widget({ x_expand: true, y_expand: true }), 0, 3, halfSize, 1)
|
||||
gridRight.attach(new St.Widget({ x_expand: true, y_expand: true }), halfSize, 3, (rowSize - halfSize), 1)
|
||||
} else {
|
||||
@ -990,30 +1291,50 @@ class Keyboard extends Dialog {
|
||||
this.box.add_style_class_name("regular");
|
||||
}
|
||||
|
||||
let mvBtnStartLeft = 2 * topBtnWidth
|
||||
let mvBtnEndRight = 2 * topBtnWidth
|
||||
|
||||
if (currentLayout[currentLayout.length - 1].settings) {
|
||||
const settingsBtn = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
settingsBtn.add_style_class_name("settings_btn")
|
||||
settingsBtn.add_style_class_name("key")
|
||||
settingsBtn.connect("clicked", () => {
|
||||
settingsBtn.connect("button-press-event", () => {
|
||||
this.settingsOpenFunction();
|
||||
})
|
||||
settingsBtn.connect("touch-event", () => {
|
||||
if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_BEGIN)
|
||||
this.settingsOpenFunction();
|
||||
})
|
||||
grid.attach(settingsBtn, 0, 0, 2 * topBtnWidth, 3)
|
||||
this.keys.push(settingsBtn)
|
||||
|
||||
grid.attach(settingsBtn, 0, 0, 2 * topBtnWidth, 3)
|
||||
} else {
|
||||
mvBtnStartLeft = 0
|
||||
}
|
||||
if (currentLayout[currentLayout.length - 1].close) {
|
||||
const closeBtn = new St.Button({
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
closeBtn.add_style_class_name("close_btn")
|
||||
closeBtn.add_style_class_name("key")
|
||||
closeBtn.connect("clicked", () => {
|
||||
closeBtn.connect("button-press-event", () => {
|
||||
this.close();
|
||||
this.closedFromButton = true;
|
||||
})
|
||||
closeBtn.connect("touch-event", () => {
|
||||
if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_BEGIN) {
|
||||
this.close();
|
||||
this.closedFromButton = true;
|
||||
}
|
||||
})
|
||||
grid.attach(closeBtn, (rowSize - 2 * topBtnWidth), 0, 2 * topBtnWidth, 3)
|
||||
this.keys.push(closeBtn)
|
||||
} else {
|
||||
mvBtnEndRight = 0;
|
||||
}
|
||||
|
||||
// [insert handwriting 10]
|
||||
|
||||
@ -1021,8 +1342,9 @@ class Keyboard extends Dialog {
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
})
|
||||
moveHandle.clear_actions();
|
||||
moveHandle.add_style_class_name("moveHandle")
|
||||
moveHandle.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
moveHandle.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px" : "0") + "; background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
if (this.lightOrDark()) {
|
||||
moveHandle.add_style_class_name("inverted");
|
||||
} else {
|
||||
@ -1035,12 +1357,12 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
this.event(event, false)
|
||||
})
|
||||
grid.attach(moveHandle, 2 * topBtnWidth, 0, (rowSize - 4 * topBtnWidth), 3) // [insert handwriting 11]
|
||||
grid.attach(moveHandle, mvBtnStartLeft, 0, (rowSize - mvBtnStartLeft - mvBtnEndRight), 3) // [insert handwriting 11]
|
||||
grid.attach(new St.Widget({ x_expand: true, y_expand: true }), 0, 3, rowSize, 1)
|
||||
}
|
||||
|
||||
this.keys.forEach(item => {
|
||||
item.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? (this.settings.get_int("border-spacing-px") + 5) + "px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
item.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? (this.settings.get_int("border-spacing-px") + 5) + "px" : "0") + "; background-size: " + this.settings.get_int("font-size-px") + "px; font-weight: " + (this.settings.get_boolean("font-bold") ? "bold" : "normal") + "; border: " + this.settings.get_int("border-spacing-px") + "px solid transparent;");
|
||||
if (this.lightOrDark()) {
|
||||
item.add_style_class_name("inverted");
|
||||
} else {
|
||||
@ -1070,18 +1392,27 @@ class Keyboard extends Dialog {
|
||||
item.space_motion_handler = null
|
||||
item.set_scale(1.2, 1.2)
|
||||
item.add_style_pseudo_class("pressed")
|
||||
let player
|
||||
let player = global.display.get_sound_player();
|
||||
if (this.settings.get_boolean("play-sound")) {
|
||||
player = global.display.get_sound_player();
|
||||
if (this.settings.get_string("sound-file") != "") {
|
||||
const sound_file = Gio.File.new_for_path(this.settings.get_string("sound-file"))
|
||||
player.play_from_file(sound_file, "tap", null)
|
||||
} else {
|
||||
player.play_from_theme("dialog-information", "tap", null)
|
||||
}
|
||||
}
|
||||
if (["delete_btn", "backspace_btn", "up_btn", "down_btn", "left_btn", "right_btn"].some(e => item.has_style_class_name(e))) {
|
||||
item.button_pressed = setTimeout(() => {
|
||||
const oldModBtns = this.modBtns
|
||||
item.button_repeat = setInterval(() => {
|
||||
if (this.settings.get_boolean("play-sound")) {
|
||||
if (this.settings.get_string("sound-file") != "") {
|
||||
const sound_file = Gio.File.new_for_path(this.settings.get_string("sound-file"))
|
||||
player.play_from_file(sound_file, "tap", null)
|
||||
} else {
|
||||
player.play_from_theme("dialog-information", "tap", null)
|
||||
}
|
||||
}
|
||||
this.decideMod(item.char)
|
||||
|
||||
for (var i of oldModBtns) {
|
||||
@ -1159,6 +1490,7 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
item.key_pressed = false;
|
||||
}
|
||||
item.clear_actions();
|
||||
item.connect("button-press-event", () => pressEv("mouse"))
|
||||
item.connect("button-release-event", releaseEv)
|
||||
item.connect("touch-event", () => {
|
||||
@ -1189,25 +1521,6 @@ class Keyboard extends Dialog {
|
||||
return hsp > 127.5
|
||||
}
|
||||
releaseAllKeys() {
|
||||
let instances = [];
|
||||
|
||||
function traverse(obj) {
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (key === "code") {
|
||||
instances.push(obj[key]);
|
||||
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
traverse(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(keycodes);
|
||||
instances.forEach(i => {
|
||||
this.inputDevice.notify_key(Clutter.get_current_event_time(), i, Clutter.KeyState.RELEASED);
|
||||
})
|
||||
|
||||
this.keys.forEach(item => {
|
||||
item.key_pressed = false;
|
||||
if (item.button_pressed !== null) {
|
||||
@ -1218,7 +1531,7 @@ class Keyboard extends Dialog {
|
||||
clearInterval(item.button_repeat)
|
||||
item.button_repeat == null
|
||||
}
|
||||
if (item.space_motion_handler !== null) {
|
||||
if (item.space_motion_handler !== null && GObject.signal_handler_is_connected(item, item.space_motion_handler)) {
|
||||
item.disconnect(item.space_motion_handler)
|
||||
item.space_motion_handler = null;
|
||||
}
|
||||
@ -1226,25 +1539,38 @@ class Keyboard extends Dialog {
|
||||
}
|
||||
sendKey(keys) {
|
||||
try {
|
||||
if (this.keyInProgress) {
|
||||
return;
|
||||
}
|
||||
this.keyInProgress = true;
|
||||
let event_time = Clutter.get_current_event_time() * 1000;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
this.inputDevice.notify_key(Clutter.get_current_event_time(), keys[i], Clutter.KeyState.PRESSED);
|
||||
this.inputDevice.notify_key(event_time, keys[i], Clutter.KeyState.PRESSED);
|
||||
}
|
||||
if (this.keyTimeout !== null) {
|
||||
clearTimeout(this.keyTimeout);
|
||||
if (typeof this.keyTimeoutFunc === 'function') {
|
||||
this.keyTimeoutFunc();
|
||||
}
|
||||
this.keyTimeout = null;
|
||||
this.keyTimeoutFunc = null;
|
||||
}
|
||||
this.keyTimeout = setTimeout(() => {
|
||||
for (var j = keys.length - 1; j >= 0; j--) {
|
||||
this.inputDevice.notify_key(Clutter.get_current_event_time(), keys[j], Clutter.KeyState.RELEASED);
|
||||
this.keyTimeoutFunc = () => {
|
||||
const currKeys = keys
|
||||
for (var j = currKeys.length - 1; j >= 0; j--) {
|
||||
this.inputDevice.notify_key(event_time, currKeys[j], Clutter.KeyState.RELEASED);
|
||||
}
|
||||
}, 100);
|
||||
this.keyInProgress = false;
|
||||
}
|
||||
this.keyTimeout = setTimeout(this.keyTimeoutFunc, 100);
|
||||
} catch (err) {
|
||||
this.keyInProgress = false;
|
||||
throw new Error("GJS-OSK: An unknown error occured. Please report this bug to the Issues page (https://github.com/Vishram1123/gjs-osk/issues):\n\n" + err + "\n\nKeys Pressed: " + keys);
|
||||
}
|
||||
}
|
||||
|
||||
decideMod(i, mBtn) {
|
||||
if (i.code == 29 || i.code == 56 || i.code == 97 || i.code == 125) {
|
||||
if (i.code == 29 || i.code == 56 || i.code == 97 || i.code == 125 || i.code == 126) {
|
||||
this.setNormMod(mBtn);
|
||||
} else if (i.code == 100) {
|
||||
this.setAlt(mBtn);
|
||||
@ -1326,6 +1652,7 @@ class Keyboard extends Dialog {
|
||||
button.remove_style_class_name("selected");
|
||||
this.modBtns.splice(this.modBtns.indexOf(button), this.modBtns.indexOf(button) + 1);
|
||||
this.inputDevice.notify_key(Clutter.get_current_event_time(), button.char.code, Clutter.KeyState.RELEASED);
|
||||
this.sendKey([button.char.code])
|
||||
} else {
|
||||
if (!(button.char.code == 42) && !(button.char.code == 54))
|
||||
button.add_style_class_name("selected");
|
||||
|
||||
Binary file not shown.
@ -7,7 +7,8 @@
|
||||
"45",
|
||||
"46",
|
||||
"47",
|
||||
"48"
|
||||
"48",
|
||||
"49"
|
||||
],
|
||||
"url": "https://github.com/Vishram1123/gjs-osk",
|
||||
"uuid": "gjsosk@vishram1123.com",
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"RTRN", "width":1.5, "height":2}, {"key":"DELE"}, {"key":"END"}, {"key":"PGDN"}, {"key":"KP7"}, {"key":"KP8"}, {"key":"KP9"}, {"key":"KPAD", "width":1, "height":2}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key":"BKSL", "width":0.5}, {"width":1.5}, {"width":3}, {"key":"KP4"}, {"key":"KP5"}, {"key":"KP6"}, {"width":1}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width":2}, {"width":1}, {"key":"UP"}, {"width":1}, {"key":"KP1"}, {"key":"KP2"}, {"key":"KP3"}, {"key":"KPEN", "height":2}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}, {"key":"KP0", "width":2}, {"key":"KPDL"}, {"width":1}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}, {"key":"KP0", "width":2}, {"key":"KPDL"}, {"width":1}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Full Sized US":[
|
||||
@ -14,7 +15,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"BKSL", "width":1.5}, {"key":"DELE"}, {"key":"END"}, {"key":"PGDN"}, {"key":"KP7"}, {"key":"KP8"}, {"key":"KP9"}, {"key":"KPAD", "width":1, "height":2}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key": "RTRN", "width": 2}, {"width":3}, {"key":"KP4"}, {"key":"KP5"}, {"key":"KP6"}, {"width":1}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width":2}, {"width":1}, {"key":"UP"}, {"width":1}, {"key":"KP1"}, {"key":"KP2"}, {"key":"KP3"}, {"key":"KPEN", "height":2}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}, {"key":"KP0", "width":2}, {"key":"KPDL"}, {"width":1}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}, {"key":"KP0", "width":2}, {"key":"KPDL"}, {"width":1}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Tenkeyless International":[
|
||||
@ -23,7 +25,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"RTRN", "width":1.5, "height":2}, {"key":"DELE"}, {"key":"END"}, {"key":"PGDN"}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key":"BKSL", "width":0.5}, {"width":1.5}, {"width":3}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width":2}, {"width":1}, {"key":"UP"}, {"width":1}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Tenkeyless US":[
|
||||
@ -32,7 +35,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"BKSL", "width":1.5}, {"key":"DELE"}, {"key":"END"}, {"key":"PGDN"}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key": "RTRN", "width": 2}, {"width":3}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width":2}, {"width":1}, {"key":"UP"}, {"width":1}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":10}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, {"key":"DOWN"}, {"key":"RGHT"}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Compact International":[
|
||||
@ -41,7 +45,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"RTRN", "width":1.5, "height":2}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key":"BKSL", "width":0.5}, {"width":1.5}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width": 2}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":7}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":7}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Compact US":[
|
||||
@ -50,7 +55,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"BKSL", "width":1.5}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key": "RTRN", "width": 2}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width": 2}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":7}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":7}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Split International":[
|
||||
@ -59,7 +65,8 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"split":true}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"RTRN", "height":2}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"split":true}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key":"BKSL", "width":0.5}, {"width":1}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"split":true}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width": 1.5}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":4}, {"split":true}, {"key":"SPCE", "width":2.5}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":4}, {"split":true}, {"key":"SPCE", "width":2.5}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}],
|
||||
{ "split": true, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Split US":[
|
||||
@ -68,24 +75,27 @@
|
||||
[{"key":"TAB", "width":1.5}, {"key":"AD01"}, {"key":"AD02"}, {"key":"AD03"}, {"key":"AD04"}, {"key":"AD05"}, {"key":"AD06"}, {"split":true}, {"key":"AD07"}, {"key":"AD08"}, {"key":"AD09"}, {"key":"AD10"}, {"key":"AD11"}, {"key":"AD12"}, {"key":"BKSL"}],
|
||||
[{"key":"CAPS", "width":2}, {"key":"AC01"}, {"key":"AC02"}, {"key":"AC03"}, {"key":"AC04"}, {"key":"AC05"}, {"split":true}, {"key":"AC06"}, {"key":"AC07"}, {"key":"AC08"}, {"key":"AC09"}, {"key":"AC10"}, {"key":"AC11"}, {"key": "RTRN", "width": 1.5}],
|
||||
[{"key":"LFSH", "width":2}, {"key":"LSGT"}, {"key":"AB01"}, {"key":"AB02"}, {"key":"AB03"}, {"key":"AB04"}, {"split":true}, {"key":"AB05"}, {"key":"AB06"}, {"key":"AB07"}, {"key":"AB08"}, {"key":"AB09"}, {"key":"AB10"}, {"key":"RTSH", "width": 1.5}],
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":4}, {"split":true}, {"key":"SPCE", "width":2.5}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}]
|
||||
[{"key":"LCTL"}, {"key":"LWIN"}, {"key":"LALT"}, {"key":"SPCE", "width":4}, {"split":true}, {"key":"SPCE", "width":2.5}, {"key":"RALT"}, {"key":"RCTL"}, {"key":"LEFT"}, [{"key":"UP", "height": 0.5}, {"key":"DOWN", "height": 0.5}], {"key":"RGHT"}],
|
||||
{ "split": true, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Mobile": [
|
||||
[{"key":"TLDE", "width": 2}, {"key":"TAB", "width": 2}, {"key":"ESC", "width": 2}, {"key":"FK01", "width": 2}, {"key":"FK02", "width": 2}, {"key":"FK03", "width": 2}, {"key":"FK04", "width": 2}, {"key":"FK05", "width": 2}, {"key":"FK06", "width": 2}, {"key":"FK07", "width": 2}, {"key":"FK08", "width": 2}, {"key":"FK09", "width": 2}, {"key":"FK10", "width": 2}, {"key":"FK11", "width": 2}, {"key":"FK12", "width": 2}, {"key":"PRSC", "width": 2}, {"key":"DELE", "width": 2}, {"key":"BKSL", "width": 2}],
|
||||
[{"key":"AE11", "width": 3}, {"key":"AE01", "width": 3}, {"key":"AE02", "width": 3}, {"key":"AE03", "width": 3}, {"key":"AE04", "width": 3}, {"key":"AE05", "width": 3}, {"key":"AE06", "width": 3}, {"key":"AE07", "width": 3}, {"key":"AE08", "width": 3}, {"key":"AE09", "width": 3}, {"key":"AE10", "width": 3}, {"key":"AE12", "width": 3}],
|
||||
[{"key":"AD11", "width": 3}, {"key":"AD01", "width": 3}, {"key":"AD02", "width": 3}, {"key":"AD03", "width": 3}, {"key":"AD04", "width": 3}, {"key":"AD05", "width": 3}, {"key":"AD06", "width": 3}, {"key":"AD07", "width": 3}, {"key":"AD08", "width": 3}, {"key":"AD09", "width": 3}, {"key":"AD10", "width": 3}, {"key":"AD12", "width": 3}],
|
||||
[{"width": 1.5}, {"key":"AC10", "width": 3}, {"key":"AC01", "width": 3}, {"key":"AC02", "width": 3}, {"key":"AC03", "width": 3}, {"key":"AC04", "width": 3}, {"key":"AC05", "width": 3}, {"key":"AC06", "width": 3}, {"key":"AC07", "width": 3}, {"key":"AC08", "width": 3}, {"key":"AC09", "width": 3}, {"key":"AC11", "width": 3}],
|
||||
[{"width": 1.5}, {"key":"AC11", "width": 3}, {"key":"AC01", "width": 3}, {"key":"AC02", "width": 3}, {"key":"AC03", "width": 3}, {"key":"AC04", "width": 3}, {"key":"AC05", "width": 3}, {"key":"AC06", "width": 3}, {"key":"AC07", "width": 3}, {"key":"AC08", "width": 3}, {"key":"AC09", "width": 3}, {"key":"AC10", "width": 3}],
|
||||
[{"key":"LFSH", "width": 2.5}, {"key":"LSGT", "width": 2}, {"key":"AB08", "width": 3}, {"key":"AB01", "width": 3}, {"key":"AB02", "width": 3}, {"key":"AB03", "width": 3}, {"key":"AB04", "width": 3}, {"key":"AB05", "width": 3}, {"key":"AB06", "width": 3}, {"key":"AB07", "width": 3}, {"key":"AB09", "width": 3}, {"key":"AB10", "width": 2}, {"key": "BKSP", "width": 2.5}],
|
||||
[{"key":"CAPS", "width": 2.5}, {"key":"LCTL", "width": 2.5}, {"key":"LWIN", "width": 2.5}, {"key":"LALT", "width": 2.5}, {"key":"SPCE", "width":10}, {"key":"RALT", "width": 2.5}, {"key":"RCTL", "width": 2.5}, {"key":"LEFT", "width": 2.5}, [{"key":"UP", "width": 2.5, "height": 0.5}, {"key":"DOWN", "width": 2.5, "height": 0.5}], {"key":"RGHT", "width": 2.5}, {"key":"RTRN", "width": 3.5}]
|
||||
[{"key":"CAPS", "width": 2.5}, {"key":"LCTL", "width": 2.5}, {"key":"LWIN", "width": 2.5}, {"key":"LALT", "width": 2.5}, {"key":"SPCE", "width":10}, {"key":"RALT", "width": 2.5}, {"key":"RCTL", "width": 2.5}, {"key":"LEFT", "width": 2.5}, [{"key":"UP", "width": 2.5, "height": 0.5}, {"key":"DOWN", "width": 2.5, "height": 0.5}], {"key":"RGHT", "width": 2.5}, {"key":"RTRN", "width": 3.5}],
|
||||
{ "split": false, "settings": true, "close": true }
|
||||
],
|
||||
|
||||
"Split Mobile": [
|
||||
[{"key":"TLDE", "width": 2}, {"key":"TAB", "width": 2}, {"key":"ESC", "width": 2}, {"key":"FK01", "width": 2}, {"key":"FK02", "width": 2}, {"key":"FK03", "width": 2}, {"key":"FK04", "width": 2}, {"key":"FK05", "width": 2}, {"key":"FK06", "width": 2}, {"split":true}, {"key":"FK07", "width": 2}, {"key":"FK08", "width": 2}, {"key":"FK09", "width": 2}, {"key":"FK10", "width": 2}, {"key":"FK11", "width": 2}, {"key":"FK12", "width": 2}, {"key":"PRSC", "width": 2}, {"key":"DELE", "width": 3}, {"key":"BKSL", "width": 2.5}],
|
||||
[{"key":"AE11", "width": 3}, {"key":"AE01", "width": 3}, {"key":"AE02", "width": 3}, {"key":"AE03", "width": 3}, {"key":"AE04", "width": 3}, {"key":"AE05", "width": 3}, {"split":true}, {"key":"AE06", "width": 3}, {"key":"AE07", "width": 3}, {"key":"AE08", "width": 3}, {"key":"AE09", "width": 3}, {"key":"AE10", "width": 3}, {"key":"AE12", "width": 4.5}],
|
||||
[{"key":"AD11", "width": 3}, {"key":"AD01", "width": 3}, {"key":"AD02", "width": 3}, {"key":"AD03", "width": 3}, {"key":"AD04", "width": 3}, {"key":"AD05", "width": 3}, {"split":true}, {"key":"AD06", "width": 3}, {"key":"AD07", "width": 3}, {"key":"AD08", "width": 3}, {"key":"AD09", "width": 3}, {"key":"AD10", "width": 3}, {"key":"AD12", "width": 4.5}],
|
||||
[{"key":"AC10", "width": 3}, {"key":"AC01", "width": 3}, {"key":"AC02", "width": 3}, {"key":"AC03", "width": 3}, {"key":"AC04", "width": 3}, {"key":"AC05", "width": 3}, {"split":true}, {"key":"AC05", "width": 3}, {"key":"AC06", "width": 3}, {"key":"AC07", "width": 3}, {"key":"AC08", "width": 3}, {"key":"AC09", "width": 3}, {"key":"AC11", "width": 4.5}],
|
||||
[{"key":"AC11", "width": 3}, {"key":"AC01", "width": 3}, {"key":"AC02", "width": 3}, {"key":"AC03", "width": 3}, {"key":"AC04", "width": 3}, {"key":"AC05", "width": 3}, {"split":true}, {"key":"AC05", "width": 3}, {"key":"AC06", "width": 3}, {"key":"AC07", "width": 3}, {"key":"AC08", "width": 3}, {"key":"AC09", "width": 3}, {"key":"AC10", "width": 3}, {"width": 1.5}],
|
||||
[{"key":"LFSH", "width": 2}, {"key":"LSGT", "width": 2}, {"key":"AB08", "width": 2}, {"key":"AB01", "width": 3}, {"key":"AB02", "width": 3}, {"key":"AB03", "width": 3}, {"key":"AB04", "width": 3}, {"split":true}, {"key":"AB04", "width": 3}, {"key":"AB05", "width": 3}, {"key":"AB06", "width": 3}, {"key":"AB07", "width": 3}, {"key":"AB09", "width": 3}, {"key":"AB10", "width": 2}, {"key": "BKSP", "width": 2.5}],
|
||||
[{"key":"CAPS", "width": 2.5}, {"key":"LCTL", "width": 2.5}, {"key":"LWIN", "width": 2.5}, {"key":"LALT", "width": 2.5}, {"key":"SPCE", "width":8}, {"split":true}, {"key":"SPCE", "width":4}, {"key":"RALT", "width": 2.5}, {"key":"RCTL", "width": 2.5}, {"key":"LEFT", "width": 2.5}, [{"key":"UP", "width": 2.5, "height": 0.5}, {"key":"DOWN", "width": 2.5, "height": 0.5}], {"key":"RGHT", "width": 2.5}, {"key":"RTRN", "width": 3}]
|
||||
[{"key":"CAPS", "width": 2.5}, {"key":"LCTL", "width": 2.5}, {"key":"LWIN", "width": 2.5}, {"key":"LALT", "width": 2.5}, {"key":"SPCE", "width":8}, {"split":true}, {"key":"SPCE", "width":4}, {"key":"RALT", "width": 2.5}, {"key":"RCTL", "width": 2.5}, {"key":"LEFT", "width": 2.5}, [{"key":"UP", "width": 2.5, "height": 0.5}, {"key":"DOWN", "width": 2.5, "height": 0.5}], {"key":"RGHT", "width": 2.5}, {"key":"RTRN", "width": 3}],
|
||||
{ "split": true, "settings": true, "close": true }
|
||||
]
|
||||
}
|
||||
@ -44,6 +44,7 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
}
|
||||
|
||||
let layoutList = Object.keys(layouts);
|
||||
layoutList.push("Custom")
|
||||
let layoutLandscapeDrop = Gtk.DropDown.new_from_strings(layoutList);
|
||||
layoutLandscapeDrop.valign = Gtk.Align.CENTER;
|
||||
layoutLandscapeDrop.selected = settings.get_int("layout-landscape");
|
||||
@ -63,6 +64,40 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
layoutPortraitRow.add_suffix(layoutPortraitDrop);
|
||||
layoutPortraitRow.activatable_widget = layoutPortraitDrop;
|
||||
|
||||
const customLayoutRow = new Adw.EntryRow({
|
||||
title: _('Custom Layout')
|
||||
});
|
||||
layoutRow.add_row(customLayoutRow);
|
||||
|
||||
customLayoutRow.set_text(settings.get_string("custom-layout"));
|
||||
customLayoutRow.set_show_apply_button(true);
|
||||
|
||||
const createKeyboardLayoutRow = new Adw.ActionRow({
|
||||
title: _('Create/edit a custom keyboard layout')
|
||||
})
|
||||
layoutRow.add_row(createKeyboardLayoutRow)
|
||||
|
||||
const layoutLink = new Gtk.LinkButton({
|
||||
label: 'Keyboard Layout Editor',
|
||||
uri: 'https://vishram1123.github.io/gjs-osk'
|
||||
})
|
||||
|
||||
createKeyboardLayoutRow.add_suffix(layoutLink)
|
||||
createKeyboardLayoutRow.activatable_widget = layoutLink
|
||||
|
||||
const disableEdgeSwipeRow = new Adw.ActionRow({
|
||||
title: _('Disable Edge Swipe')
|
||||
});
|
||||
behaviorGroup.add(disableEdgeSwipeRow);
|
||||
|
||||
const disableEdgeSwipeDT = new Gtk.Switch({
|
||||
active: settings.get_boolean('disable-edge-swipe'),
|
||||
valign: Gtk.Align.CENTER,
|
||||
});
|
||||
|
||||
disableEdgeSwipeRow.add_suffix(disableEdgeSwipeDT);
|
||||
disableEdgeSwipeRow.activatable_widget = disableEdgeSwipeDT;
|
||||
|
||||
const enableDragRow = new Adw.ActionRow({
|
||||
title: _('Enable Dragging')
|
||||
});
|
||||
@ -217,18 +252,73 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
defaultPosition.add_suffix(snapDrop);
|
||||
defaultPosition.activatable_widget = snapDrop;
|
||||
|
||||
const soundPlayRow = new Adw.ActionRow({
|
||||
title: _('Play sound')
|
||||
const soundPlayRow = new Adw.ExpanderRow({
|
||||
title: _('Play sound'),
|
||||
show_enable_switch: true
|
||||
});
|
||||
behaviorGroup.add(soundPlayRow);
|
||||
soundPlayRow.enable_expansion = settings.get_boolean('play-sound')
|
||||
|
||||
const soundPlayDT = new Gtk.Switch({
|
||||
active: settings.get_boolean('play-sound'),
|
||||
const fileRow = new Adw.ActionRow({
|
||||
title: _('Sound file'),
|
||||
subtitle: settings.get_string('sound-file') || _('No file selected'),
|
||||
activatable: false, // prevent clicking the whole row
|
||||
});
|
||||
|
||||
const fileButton = new Gtk.Button({
|
||||
label: settings.get_string('sound-file') ? _('Clear') : _('Choose'),
|
||||
valign: Gtk.Align.CENTER,
|
||||
});
|
||||
|
||||
soundPlayRow.add_suffix(soundPlayDT);
|
||||
soundPlayRow.activatable_widget = soundPlayDT;
|
||||
fileRow.add_suffix(fileButton);
|
||||
fileRow.activatable_widget = fileButton;
|
||||
|
||||
fileButton.connect('clicked', () => {
|
||||
const currentPath = settings.get_string('sound-file');
|
||||
if (currentPath) {
|
||||
settings.set_string('sound-file', '');
|
||||
fileRow.subtitle = _('No file selected');
|
||||
fileButton.label = _('Choose');
|
||||
} else {
|
||||
const fileChooser = new Gtk.FileChooserNative({
|
||||
title: _('Select OGG File'),
|
||||
transient_for: window,
|
||||
action: Gtk.FileChooserAction.OPEN,
|
||||
accept_label: _('Open'),
|
||||
cancel_label: _('Cancel'),
|
||||
});
|
||||
|
||||
const filter = new Gtk.FileFilter();
|
||||
filter.add_mime_type('audio/ogg');
|
||||
filter.set_name(_('OGG files'));
|
||||
fileChooser.add_filter(filter);
|
||||
|
||||
fileChooser.connect('response', (dlg, response) => {
|
||||
if (response === Gtk.ResponseType.ACCEPT) {
|
||||
const file = dlg.get_file();
|
||||
if (file) {
|
||||
const path = file.get_path();
|
||||
settings.set_string('sound-file', path);
|
||||
fileRow.subtitle = path;
|
||||
fileButton.label = _('Clear');
|
||||
|
||||
// Optionally play the file immediately
|
||||
try {
|
||||
let player = global.display.get_sound_player();
|
||||
player.play_from_file(path, null);
|
||||
} catch (e) {
|
||||
logError(e, 'Failed to play sound file');
|
||||
}
|
||||
}
|
||||
}
|
||||
dlg.destroy();
|
||||
});
|
||||
|
||||
fileChooser.show();
|
||||
}
|
||||
});
|
||||
|
||||
soundPlayRow.add_row(fileRow);
|
||||
|
||||
const appearanceGroup = new Adw.PreferencesGroup({
|
||||
title: _("Appearance")
|
||||
@ -405,7 +495,7 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
context.add_class("title-1");
|
||||
|
||||
let another_label = new Gtk.Label({
|
||||
label: _("Autorelease ") + `776e35f`
|
||||
label: _("Autorelease ") + `3f0ef02`
|
||||
});
|
||||
|
||||
let links_pref_group = new Adw.PreferencesGroup();
|
||||
@ -447,6 +537,10 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
|
||||
settings.bind("layout-landscape", layoutLandscapeDrop, "selected", 0);
|
||||
settings.bind("layout-portrait", layoutPortraitDrop, "selected", 0);
|
||||
customLayoutRow.connect("apply", () => {
|
||||
settings.set_string("custom-layout", customLayoutRow.get_text());
|
||||
});
|
||||
settings.bind("disable-edge-swipe", disableEdgeSwipeDT, "active", 0);
|
||||
settings.bind("enable-drag", dragEnableDT, "active", 0);
|
||||
settings.bind("enable-tap-gesture", dragOpt, "selected", 0);
|
||||
settings.bind("indicator-enabled", indEnabled, "active", 0);
|
||||
@ -472,7 +566,7 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
settings.bind("outer-spacing-px", numChanger_outer, "value", 0);
|
||||
settings.bind("snap-spacing-px", numChanger_snap, "value", 0)
|
||||
settings.bind("round-key-corners", roundKeyCDT, "active", 0);
|
||||
settings.bind("play-sound", soundPlayDT, "active", 0);
|
||||
settings.bind("play-sound", soundPlayRow, "enable-expansion", 0);
|
||||
settings.bind("show-icons", showIconDT, "active", 0)
|
||||
settings.bind("default-snap", snapDrop, "selected", 0);
|
||||
monitorDrop.connect("notify::selected", () => {
|
||||
@ -492,6 +586,8 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
window.connect("close-request", () => {
|
||||
settings.set_int("layout-landscape", layoutLandscapeDrop.selected);
|
||||
settings.set_int("layout-portrait", layoutPortraitDrop.selected);
|
||||
settings.set_string("custom-layout", customLayoutRow.get_text());
|
||||
settings.set_boolean("disable-edge-swipe", disableEdgeSwipeDT.active);
|
||||
settings.set_boolean("enable-drag", dragEnableDT.active);
|
||||
settings.set_int("enable-tap-gesture", dragOpt.selected);
|
||||
settings.set_boolean("indicator-enabled", indEnabled.active);
|
||||
@ -513,7 +609,7 @@ export default class GjsOskPreferences extends ExtensionPreferences {
|
||||
settings.set_int("outer-spacing-px", numChanger_outer.value);
|
||||
settings.set_int("snap-spacing-px", numChanger_snap.value)
|
||||
settings.set_boolean("round-key-corners", roundKeyCDT.active);
|
||||
settings.set_boolean("play-sound", soundPlayDT.active);
|
||||
settings.set_boolean("play-sound", soundPlayRow.enable_expansion);
|
||||
settings.set_boolean("show-icons", showIconDT.active)
|
||||
settings.set_int("default-snap", snapDrop.selected);
|
||||
currentMonitorMap[monitors.length + ""] = monitors.map(m => { return m.get_connector() })[monitorDrop.selected];
|
||||
|
||||
Binary file not shown.
@ -7,6 +7,9 @@
|
||||
<key name="layout-portrait" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="custom-layout" type="s">
|
||||
<default>""</default>
|
||||
</key>
|
||||
<key name="portrait-width-percent" type="i">
|
||||
<default>100</default>
|
||||
</key>
|
||||
@ -19,6 +22,9 @@
|
||||
<key name="landscape-height-percent" type="i">
|
||||
<default>30</default>
|
||||
</key>
|
||||
<key name="disable-edge-swipe" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="enable-drag" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
@ -82,6 +88,9 @@
|
||||
<key name="play-sound" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="sound-file" type="s">
|
||||
<default>""</default>
|
||||
</key>
|
||||
<key name="show-icons" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
@ -92,5 +101,8 @@
|
||||
<key name="opened" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="keyboard-visible" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
box-sizing: border-box;
|
||||
background-image: url(ui/icons/hicolor/scalable/actions/transparent.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.dr-b {
|
||||
@ -55,7 +54,6 @@
|
||||
.down_btn,
|
||||
.right_btn {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.close_btn.regular,
|
||||
@ -158,6 +156,16 @@
|
||||
background-image: url(ui/icons/hicolor/scalable/actions/alt-dark.svg);
|
||||
}
|
||||
|
||||
.menu_btn.regular,
|
||||
.menu_btn.selected.inverted {
|
||||
background-image: url(ui/icons/hicolor/scalable/actions/menu.svg);
|
||||
}
|
||||
|
||||
.menu_btn.inverted,
|
||||
.menu_btn.selected.regular {
|
||||
background-image: url(ui/icons/hicolor/scalable/actions/menu-dark.svg);
|
||||
}
|
||||
|
||||
.space_btn.regular,
|
||||
.space_btn.selected.inverted {
|
||||
background-image: url(ui/icons/hicolor/scalable/actions/space.svg);
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="menu-dark.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="23.459667"
|
||||
inkscape:cx="8.3547647"
|
||||
inkscape:cy="14.919223"
|
||||
inkscape:window-width="1856"
|
||||
inkscape:window-height="1067"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
transform="matrix(1,0,0,1.3750001,0,-4.4092509)">
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:0.948849"
|
||||
id="rect1"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="10.885887" />
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:0.948849"
|
||||
id="rect1-5"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="13.837102" />
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:0.948849"
|
||||
id="rect1-5-2"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="7.934" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="menu.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="23.459667"
|
||||
inkscape:cx="8.3547647"
|
||||
inkscape:cy="14.919223"
|
||||
inkscape:window-width="1856"
|
||||
inkscape:window-height="1067"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
transform="matrix(1,0,0,1.3750001,0,-4.4092509)"
|
||||
style="fill:#ffffff">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.948849"
|
||||
id="rect1"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="10.885887" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.948849"
|
||||
id="rect1-5"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="13.837102" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.948849"
|
||||
id="rect1-5-2"
|
||||
width="11"
|
||||
height="2.0968976"
|
||||
x="6.5"
|
||||
y="7.934" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
Reference in New Issue
Block a user