diff --git a/smile-autopaste@turtl.cc/README.md b/smile-autopaste@turtl.cc/README.md new file mode 100644 index 00000000..20ae05aa --- /dev/null +++ b/smile-autopaste@turtl.cc/README.md @@ -0,0 +1,17 @@ +# Smile Autopaste + +A Cinnamon extension that automatically pastes emojis selected in [Smile](https://github.com/mijorus/smile) into the previously focused window. + +![Screenshot of the Smile Autopaste plugin](./screenshot.png) + +## How it works + +When you pick an emoji in Smile, Smile copies it to the clipboard and emits a D-Bus signal. This extension listens for that signal and replays `Ctrl+V` into the previously focused window after a short delay, so the emoji lands where the user's cursor was. + +## Requirements + +- [Smile](https://github.com/mijorus/smile) emoji picker must be installed and running. + +## Installation + +Clone this repository and copy `files/smile-autopaste@turtl.cc` into `~/.local/share/cinnamon/extensions/`. diff --git a/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/extension.js b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/extension.js new file mode 100644 index 00000000..9617fbad --- /dev/null +++ b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/extension.js @@ -0,0 +1,69 @@ +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const Clutter = imports.gi.Clutter; +const Settings = imports.ui.settings; + +const SMILE_DBUS_INTERFACE = 'it.mijorus.smile'; +const SMILE_DBUS_PATH = '/it/mijorus/smile/actions'; +const SMILE_SIGNAL = 'CopiedEmojiBroadcast'; + +let dbusSignalId = null; +let pendingTimeouts = []; +let settings = null; +let pasteDelay = 100; + +function getVirtualKeyboard() { + return Clutter.get_default_backend() + .get_default_seat() + .create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE); +} + +function sendCtrlV(keyboard) { + const time = Clutter.get_current_event_time(); + keyboard.notify_keyval(time, Clutter.KEY_Control_L, Clutter.KeyState.PRESSED); + keyboard.notify_keyval(time, Clutter.KEY_v, Clutter.KeyState.PRESSED); + keyboard.notify_keyval(time, Clutter.KEY_v, Clutter.KeyState.RELEASED); + keyboard.notify_keyval(time, Clutter.KEY_Control_L, Clutter.KeyState.RELEASED); +} + +function clearTimeouts() { + for (let id of pendingTimeouts) { + GLib.Source.remove(id); + } + pendingTimeouts = []; +} + +function init(metadata) { + settings = new Settings.ExtensionSettings(this, metadata.uuid); + settings.bind('paste-delay', 'pasteDelay', null); +} + +function enable() { + dbusSignalId = Gio.DBus.session.signal_subscribe( + null, + SMILE_DBUS_INTERFACE, + SMILE_SIGNAL, + SMILE_DBUS_PATH, + null, + Gio.DBusSignalFlags.NONE, + function() { + const keyboard = getVirtualKeyboard(); + const id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, pasteDelay, function() { + sendCtrlV(keyboard); + return GLib.SOURCE_REMOVE; + }); + pendingTimeouts.push(id); + } + ); +} + +function disable() { + clearTimeouts(); + + if (dbusSignalId !== null) { + Gio.DBus.session.signal_unsubscribe(dbusSignalId); + dbusSignalId = null; + } + + settings = null; +} diff --git a/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/icon.png b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/icon.png new file mode 100644 index 00000000..86dfda9e Binary files /dev/null and b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/icon.png differ diff --git a/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/metadata.json b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/metadata.json new file mode 100644 index 00000000..f83c7967 --- /dev/null +++ b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/metadata.json @@ -0,0 +1,10 @@ +{ + "uuid": "smile-autopaste@turtl.cc", + "name": "Smile Autopaste", + "description": "Automatically pastes emojis selected in Smile into the previously focused window.", + "version": "1.0", + "cinnamon-version": ["6.6"], + "author": "megaturtl", + "website": "https://turtl.cc", + "url": "https://github.com/megaturtl/smile-autopaste" +} diff --git a/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/settings-schema.json b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/settings-schema.json new file mode 100644 index 00000000..cedc6491 --- /dev/null +++ b/smile-autopaste@turtl.cc/files/smile-autopaste@turtl.cc/settings-schema.json @@ -0,0 +1,12 @@ +{ + "paste-delay": { + "type": "spinbutton", + "default": 100, + "min": 50, + "max": 500, + "step": 50, + "units": "ms", + "description": "Paste delay", + "tooltip": "How long to wait after Smile closes before sending Ctrl+V. Increase this if the paste is not landing your target window." + } +} diff --git a/smile-autopaste@turtl.cc/info.json b/smile-autopaste@turtl.cc/info.json new file mode 100644 index 00000000..1aa6ea10 --- /dev/null +++ b/smile-autopaste@turtl.cc/info.json @@ -0,0 +1,4 @@ +{ + "author": "megaturtl", + "license": "GPL-3.0" +} diff --git a/smile-autopaste@turtl.cc/screenshot.png b/smile-autopaste@turtl.cc/screenshot.png new file mode 100644 index 00000000..e9ae2817 Binary files /dev/null and b/smile-autopaste@turtl.cc/screenshot.png differ