我目前正在尝试为我的应用程序实现复制和粘贴,问题是我只能根据Gtk.Clipboard:https://valadoc.org/gtk+-3.0/Gtk.Clipboard.html set_text / set_image的文档将明文或图像写入剪贴板.
但是之后还有这个方法https://valadoc.org/gtk+-3.0/Gtk.Clipboard.set_with_data.html set_with_data,我想我可以用来添加uri或uris数组.但我无法弄清楚如何也没有找到任何好的例子.
UPDATE
使用给定的答案我可以用一个uris数组填充剪贴板,但我可以读取它们,当我尝试它只是再次调用get_func并重新填充它.
CTRL C pressed
clipboard get_func called
Received: file:///home/marcel/Downloads/.gitignore
CTRL V pressd
clipboard get_func called
Received: file:///home/marcel/Downloads
Try Pasting: file:///home/marcel/Downloads
这是我用来测试CTRL V的代码:
print ("\nCTRL V pressd\n");
clipboard.request_uris ((clipboard, uris) => {
foreach ( string content in uris ) {
print ("Try Pasting: ");
print (content);
print ("\n");
}
});
这是CTRL C的get_func的相关部分:
clipboard.set_with_owner (
clipboard_targets,
(clipboard, selection_data, info, user_data_or_owner) => {
print ("clipboard get_func called\n");
var w = user_data_or_owner as Window;
File[] files = { w.get_selected_file () };
switch ( info ) {
case ClipboardProtocol.TEXT_URI_LIST:
print ("Received: ");
string[] uris = {};
foreach ( var file in files ) {
print (file.get_uri ());
print ("\n");
uris += file.get_uri ();
}
selection_data.set_uris (uris);
break;
正如您在上面的终端输出中所看到的,它只是重新填充剪贴板,丢弃其先前的值.
解决方法:
根据要求,我提供了一个将URI写入剪贴板并从剪贴板获取URI的示例.这些示例基本上是命令行程序,可以立即获取/设置剪贴板.在实际的GUI应用程序中,您可能会对按下按钮做出反应,或者为了捕获CtrlC/C++trlV事件,使用Gtk.Widget.add_events()并在处理Gtk.Widget.event信号时获取/设置剪贴板.
获取剪贴板
您可以使用Gtk.Clipboard.request_uris()从X11剪贴板请求URI.此函数采用一旦URI可用就会调用的回调.
例:
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 ();
}
用valac clipget.vala编译–pkg = gtk -3.0
设置剪贴板
理论:
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没有预先设置剪贴板来复制/剪切文件.如你所说,没有这样的Gtk.Clipboard.set_uris().
相反,您应该通过提供X11从一次请求获取剪贴板内容的回调来设置剪贴板.
这些是所需的步骤:
>创建一堆Gtk.TargetEntrys,指定您的应用可以处理的剪贴板协议.您将需要处理protocolstext / uri-list,x-special / gnome-copied-files和UTF8_STRING.每个TargetEntry都由其信息字段标识,因此该数字应该是唯一的(请参阅下面示例中的枚举ClipboardProtocol)
>实现Gtk.ClipboardGetFunc类型的方法.此方法应填充与文件路径一起传递的Gtk.SelectionData对象以进行复制/剪切.检查info参数以根据指定的协议设置SelectionData参数.
>使用Gtk.Clipboard.set_with_owner或Gtk.Clipboard.set_with_data将回调和实现的协议注册到X11
例:
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) {
;
}
用valac clipset.vala编译–pkg = gtk -3.0
几个笔记:
>在我的例子中,我只能测试x-special / gnome-copied-files,因为我目前只安装了Nautilus.我修改了Thunar源代码中的所有协议(参见下面的来源),但它们可能仍需要排除故障*
>如果你不想自己解决这个问题,你也可以使用xclip命令行工具:https://askubuntu.com/a/210428/345569但是,恕我直言,你自己实现这个更加优雅.
资料来源:
>来自Ubuntu论坛的文章:https://ubuntuforums.org/archive/index.php/t-2135919.html
> Thunar源代码(尤其是thunar / thunar / thunar-clipboard-manager.c):https://github.com/xfce-mirror/thunar/blob/3de231d2dec33ca48b73391386d442231baace3e/thunar/thunar-clipboard-manager.c
> Qt4文档:http://doc.qt.io/archives/qt-4.8/qclipboard.html