Inserting uris into Gtk.Clipboard with vala
As requested I am providing both an example for writing URIs to clipboard and getting URIs from clipboard. These examples are basically command line programs that get / set the clipboard immediately. In an actual GUI application you would probably react to a button press or, to catch CtrlC / CtrlV events, use Gtk.Widget.add_events()
and get / set the clipboard when handling the Gtk.Widget.event
signal.
Getting the clipboard
You can request URIs from the X11 clipboard using Gtk.Clipboard.request_uris ()
. This function takes a callback that will be called once the URIs are available.
Example:
public void main (string[] args) {
Gtk.init (ref args);
Gdk.Display display = Gdk.Display.get_default ();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
clipboard.request_uris (recieved_func);
Gtk.main ();
}
/* Gtk.ClipboardURIRecievedFunc */
private void recieved_func (Gtk.Clipboard clipboard, string[] uris) {
foreach (var uri in uris) {
print (uri + "\n");
}
Gtk.main_quit ();
}
To be compiled with valac clipget.vala --pkg=gtk+-3.0
Setting the clipboard
Theory:
From the Qt4 documentation:
Since there is no standard way to copy and paste files between
applications on X11, various MIME types and conventions are currently
in use. For instance, Nautilus expects files to be supplied with a
x-special/gnome-copied-files MIME type with data beginning with the
cut/copy action, a newline character, and the URL of the file.
Gtk.Clipboard
does not pre-implement setting the clipboard for copying / cutting files. As you said, there is no such Gtk.Clipboard.set_uris()
.
Instead, you should set the clipboard by providing a callback that X11 gets the clipboard contents from once requested.
These are the steps required:
Create a bunch of
Gtk.TargetEntry
s that specify what clipboard protocols your app can handle. You'll want to handle the protocolstext/uri-list
,x-special/gnome-copied-files
andUTF8_STRING
. EachTargetEntry
is identified by itsinfo
field, so that number should be unique (seeenum ClipboardProtocol
in the example below)Implement a method of the type
Gtk.ClipboardGetFunc
. This method should fill theGtk.SelectionData
object that is passed with the file paths to copy / cut. Check for theinfo
parameter to set the SelectionData argument according to the protocol specified.Register the callback and the protocols implemented to X11 using
Gtk.Clipboard.set_with_owner
orGtk.Clipboard.set_with_data
Example:
enum ClipboardProtocol {
TEXT_URI_LIST,
GNOME_COPIED_FILES,
UTF8_STRING
}
public void main (string[] args) {
Gtk.init (ref args);
Gdk.Display display = Gdk.Display.get_default ();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
var clipboard_targets = new Gtk.TargetEntry[3];
Gtk.TargetEntry target_entry = { "text/uri-list", 0, ClipboardProtocol.TEXT_URI_LIST };
clipboard_targets[0] = target_entry;
target_entry = { "x-special/gnome-copied-files", 0, ClipboardProtocol.GNOME_COPIED_FILES };
clipboard_targets[1] = target_entry;
target_entry = { "UTF8_STRING", 0, ClipboardProtocol.UTF8_STRING };
clipboard_targets[2] = target_entry;
var owner = new Object ();
var rc = clipboard.set_with_owner (
clipboard_targets,
get_func,
clear_func,
owner
);
assert (rc);
clipboard.store ();
Gtk.main ();
}
/* Gtk.ClipboardGetFunc */
private void get_func (
Gtk.Clipboard clipboard,
Gtk.SelectionData selection_data,
uint info,
void* user_data_or_owner
) {
print ("GET FUNC!\n");
File my_file = File.new_for_path ("/home/lukas/tmp/test.txt");
File my_2nd_file = File.new_for_path ("/home/lukas/tmp/test2.txt");
File[] files = { my_file, my_2nd_file };
switch (info) {
case ClipboardProtocol.TEXT_URI_LIST:
string[] uris = {};
foreach (var file in files) {
uris += file.get_uri ();
}
selection_data.set_uris (uris);
break;
case ClipboardProtocol.GNOME_COPIED_FILES:
var prefix = "copy\n";
//var prefix = "cut\n";
/* use one of the above */
var builder = new StringBuilder (prefix);
for (int i = 0; i < files.length; i++) {
builder.append (files[i].get_uri ());
/* dont put the newline if this is the last file */
if (i != files.length - 1)
builder.append_c ('\n');
}
selection_data.set (
selection_data.get_target (),
8,
builder.data
);
break;
case ClipboardProtocol.UTF8_STRING:
var builder = new StringBuilder ();
foreach (var file in files) {
builder.append (file.get_parse_name ());
}
builder.append_c ('\n');
selection_data.set_text (builder.str, -1);
break;
default:
assert_not_reached ();
}
Gtk.main_quit ();
}
/* Gtk.ClipboardClearFunc */
private void clear_func (Gtk.Clipboard clipboard, void* data) {
;
}
To be compiled with valac clipset.vala --pkg=gtk+-3.0
A couple of notes:
In my example, I could only test
x-special/gnome-copied-files
since I only have Nautilus installed at the moment. I adapted all of the protocols from the Thunar source code (see sources below) but they might still require troubleshooting*If you do not want to go through the trouble of implementing this yourself, you could also use the xclip command line tool: https://askubuntu.com/a/210428/345569 However, IMHO implementing this yourself is a little more elegant.
Sources:
- Article from the Ubuntu Forums: https://ubuntuforums.org/archive/index.php/t-2135919.html
- Thunar source code (especially thunar/thunar/thunar-clipboard-manager.c): https://github.com/xfce-mirror/thunar/blob/3de231d2dec33ca48b73391386d442231baace3e/thunar/thunar-clipboard-manager.c
- Qt4 documentation: http://doc.qt.io/archives/qt-4.8/qclipboard.html
how to use key_press_event on Gtk and Vala
Your Gtk.Widget key_press_event signal handler is correct but you missed the return value. The method expects the return of a boolean which should be:
true to stop other handlers from being invoked for the event. false to
propagate the event further.
Try adding it as:
private bool capture_kilometer (Gdk.EventKey key )
{
number_to_calc = kilometer.get_text ();
calc_kilometer_all ();
return false;
}
Alternatively you can use a lambda expression as :
kilometer.unit_entry.key_press_event.connect ((key) => {
number_to_calc = kilometer.get_text ();
calc_kilometer_all ();
return false;
});
Related Topics
Error When Bootstrapping Cmake:Log of Errors
How to Modify The Linux Kernel to Change The Version String That Uname Returns
Is There Any Difference Between '=' and '==' Operators in Bash or Sh
How to Quickly Check If Linux 'Unzip' Is Installed Using Perl
Install Opencl(Amd Sdk Kit) on Linux Without Root Privilege
How to Connect to Docker Container from Localhost
Process Scheduling from Processor Point of View
U-Boot: Cannot Boot Linux Kernel Despite Kernel Being Less Than Maximum Bootm_Len
The Most Reliable Way to Terminate a Family of Processes
Npm Install -G Grunt-Cli Failed in Linux
How to Convert a Text/Plain to Text/X.Shellscript
Tomcat 6 Log4J - Linux - Safely Remove Catalina.Out
Mod_Perl Can't See Files in /Tmp
Forcing a Context Switch from The Userland on Linux
Jmp Unexpected Behavior in Shellcode When Next(Skipped) Instruction Is a Variable Definition