123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
- //
- // SPDX-License-Identifier: GPL-2.0-or-later
- 'use strict';
- const Gdk = imports.gi.Gdk;
- const GLib = imports.gi.GLib;
- const Gtk = imports.gi.Gtk;
- const Gio = imports.gi.Gio;
- const GObject = imports.gi.GObject;
- const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard';
- const DBUS_PATH = '/org/gnome/Shell/Extensions/GSConnect/Clipboard';
- var Clipboard = GObject.registerClass({
- GTypeName: 'GSConnectClipboard',
- Properties: {
- 'text': GObject.ParamSpec.string(
- 'text',
- 'Text Content',
- 'The current text content of the clipboard',
- GObject.ParamFlags.READWRITE,
- ''
- ),
- },
- }, class Clipboard extends GObject.Object {
- _init() {
- super._init();
- this._cancellable = new Gio.Cancellable();
- this._clipboard = null;
- this._ownerChangeId = 0;
- this._nameWatcherId = Gio.bus_watch_name(
- Gio.BusType.SESSION,
- DBUS_NAME,
- Gio.BusNameWatcherFlags.NONE,
- this._onNameAppeared.bind(this),
- this._onNameVanished.bind(this)
- );
- }
- get text() {
- if (this._text === undefined)
- this._text = '';
- return this._text;
- }
- set text(content) {
- if (this.text === content)
- return;
- this._text = content;
- this.notify('text');
- if (typeof content !== 'string')
- return;
- if (this._clipboard instanceof Gtk.Clipboard)
- this._clipboard.set_text(content, -1);
- if (this._clipboard instanceof Gio.DBusProxy) {
- this._clipboard.call('SetText', new GLib.Variant('(s)', [content]),
- Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable)
- .catch(debug);
- }
- }
- async _onNameAppeared(connection, name, name_owner) {
- try {
- // Cleanup the GtkClipboard
- if (this._clipboard && this._ownerChangeId > 0) {
- this._clipboard.disconnect(this._ownerChangeId);
- this._ownerChangeId = 0;
- }
- // Create a proxy for the remote clipboard
- this._clipboard = new Gio.DBusProxy({
- g_bus_type: Gio.BusType.SESSION,
- g_name: DBUS_NAME,
- g_object_path: DBUS_PATH,
- g_interface_name: DBUS_NAME,
- g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES,
- });
- await this._clipboard.init_async(GLib.PRIORITY_DEFAULT,
- this._cancellable);
- this._ownerChangeId = this._clipboard.connect('g-signal',
- this._onOwnerChange.bind(this));
- this._onOwnerChange();
- if (!globalThis.HAVE_GNOME) {
- // Directly subscrible signal
- this.signalHandler = Gio.DBus.session.signal_subscribe(
- DBUS_NAME,
- DBUS_NAME,
- 'OwnerChange',
- DBUS_PATH,
- null,
- Gio.DBusSignalFlags.NONE,
- this._onOwnerChange.bind(this)
- );
- }
- } catch (e) {
- if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
- debug(e);
- this._onNameVanished(null, null);
- }
- }
- }
- _onNameVanished(connection, name) {
- if (this._clipboard && this._ownerChangeId > 0) {
- this._clipboard.disconnect(this._ownerChangeId);
- this._clipboardChangedId = 0;
- }
- const display = Gdk.Display.get_default();
- this._clipboard = Gtk.Clipboard.get_default(display);
- this._ownerChangeId = this._clipboard.connect('owner-change',
- this._onOwnerChange.bind(this));
- this._onOwnerChange();
- }
- async _onOwnerChange() {
- try {
- if (this._clipboard instanceof Gtk.Clipboard)
- await this._gtkUpdateText();
- else if (this._clipboard instanceof Gio.DBusProxy)
- await this._proxyUpdateText();
- } catch (e) {
- if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
- debug(e);
- }
- }
- _applyUpdate(text) {
- if (typeof text !== 'string' || this.text === text)
- return;
- this._text = text;
- this.notify('text');
- }
- /*
- * Proxy Clipboard
- */
- async _proxyUpdateText() {
- let reply = await this._clipboard.call('GetMimetypes', null,
- Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable);
- const mimetypes = reply.deepUnpack()[0];
- // Special case for a cleared clipboard
- if (mimetypes.length === 0)
- return this._applyUpdate('');
- // Special case to ignore copied files
- if (mimetypes.includes('text/uri-list'))
- return;
- reply = await this._clipboard.call('GetText', null,
- Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable);
- const text = reply.deepUnpack()[0];
- this._applyUpdate(text);
- }
- /*
- * GtkClipboard
- */
- async _gtkUpdateText() {
- const mimetypes = await new Promise((resolve, reject) => {
- this._clipboard.request_targets((clipboard, atoms) => resolve(atoms));
- });
- // Special case for a cleared clipboard
- if (mimetypes.length === 0)
- return this._applyUpdate('');
- // Special case to ignore copied files
- if (mimetypes.includes('text/uri-list'))
- return;
- const text = await new Promise((resolve, reject) => {
- this._clipboard.request_text((clipboard, text) => resolve(text));
- });
- this._applyUpdate(text);
- }
- destroy() {
- if (this._cancellable.is_cancelled())
- return;
- this._cancellable.cancel();
- if (this._clipboard && this._ownerChangeId > 0) {
- this._clipboard.disconnect(this._ownerChangeId);
- this._ownerChangedId = 0;
- }
- if (this._nameWatcherId > 0) {
- Gio.bus_unwatch_name(this._nameWatcherId);
- this._nameWatcherId = 0;
- }
- if (!globalThis.HAVE_GNOME && this.signalHandler)
- Gio.DBus.session.signal_unsubscribe(this.signalHandler);
- }
- });
- /**
- * The service class for this component
- */
- var Component = Clipboard;
- // vim:tabstop=2:shiftwidth=2:expandtab
|