API to paste from clipboard for extensions?

Is there an API that lets extensions paste from the clipboard? Barring that, is there an API to send keyboard events (so I could simulate paste with Shift + Insert)? I’m looking for a way to send a paste event so whatever is in the clipboard gets put into the currently focused input.

You could use the global.stage variable and call Clutter.Stage.get_key_focus() on it the get the currently focused element. Assuming that actor is an editable Clutter.Text or St.Entry, you can use St.Clipboard.get_text() and set the text property.

Hmmm, that doesn’t seem to work. get_key_focus almost always returns MetaStage. I also tried creating a key press event, but neither method works:

const event = Clutter.Event.new(Clutter.EventType.KEY_PRESS);
event.set_flags(Clutter.EventFlags.FLAG_SYNTHETIC);
event.set_key_code(97);

// All of gnome crashes with
// Clutter:ERROR:../clutter/clutter/clutter-seat.c:627:clutter_seat_handle_event_post: 'CLUTTER_IS_INPUT_DEVICE (device)' should be TRUE
// Bail out! Clutter:ERROR:../clutter/clutter/clutter-seat.c:627:clutter_seat_handle_event_post: 'CLUTTER_IS_INPUT_DEVICE (device)' should be TRUE
event.put();

// JS fails with JS ERROR: GLib.Error g-invoke-error-quark: Could not locate clutter_stage_event: 'clutter_stage_event': /usr/lib/x86_64-linux-gnu/mutter-8/libmutter-clutter-8.so.0: undefined symbol: clutter_stage_event
global.stage.get_key_focus().event(event, false);

You probably don’t want to make events, that’s really for the Shell to do. It also won’t do much if nothing has key focus anywhere.

For me, global.stage.get_key_focus() works if it’s something in the Shell that has focus. You can’t introspect the internal state of arbitrary applications from a GNOME Shell extension, if that’s what you’re trying to do. Those might be GTK, Qt, Windows applications being run by Wine, etc.

You can’t introspect the internal state of arbitrary applications from a GNOME Shell extension

Ah, that is what I’m trying to do (sort of). I just want to force a paste into whatever application currently has focus (I’m writing a clipboard manager). Is that not supported?

I suppose you could try simulating the keyboard events for pasting, maybe with a Clutter.VirtualDevice or there may be a way to do it with Mutter. I’ve never tried to do that before though, so I don’t know if just simulating the keypresses will engage the result.

That could work, do you know how I get an instance of the virtual keyboard?

Clutter.Seat.create_virtual_device(). You can look through js/ui/keyboard.js for hints.

1 Like

Holy freakin’ smokes, this actually works!!! Thank you!

const VirtualKeyboard = Clutter.get_default_backend()
  .get_default_seat()
  .create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);

const eventTime = Clutter.get_current_event_time() * 1000;
VirtualKeyboard.notify_keyval(
  eventTime,
  Clutter.KEY_Shift_L,
  Clutter.KeyState.PRESSED,
);
VirtualKeyboard.notify_keyval(
  eventTime,
  Clutter.KEY_Insert,
  Clutter.KeyState.PRESSED,
);
VirtualKeyboard.notify_keyval(
  eventTime,
  Clutter.KEY_Insert,
  Clutter.KeyState.RELEASED,
);
VirtualKeyboard.notify_keyval(
  eventTime,
  Clutter.KEY_Shift_L,
  Clutter.KeyState.RELEASED,
);
1 Like

I’m glad that worked out :slightly_smiling_face: