I've implemented custom clipboard handling in my program that allows me
to push to clipboard more than one clipboard format in parallel (plain
text format plus "text/html" plus "HTML Format" on windows etc).
My issue is that from time to time I get report from users that they can
not paste plain text into some text editor, and when they check the
clipboard contents it is indeed the case that only HTML formats are
present at the time (although the code always tries to push at least
plain text format). The issue appears randomly, I myself have managed to
reproduce it only once a long time ago.
The logs always show the following issue:
16:37:02.616 GTK [16]: gdkproperty-win32.c:200: OpenClipboard failed:
Access is denied.
16:37:02.626 GTK [8]: inner_clipboard_window_procedure: assertion
`success' failed
I've attached the example of the code quite similar to what I use.
It appears as if something is locking the clipboard, but not everything,
HTML always seems to pass through.
Additionally, the code to block the default signal handler
(g_signal_stop_emission_by_name part) seems to cause crash in my bigger
program so I commented it in there.
Can anyone spot the possible issue in my code?
I am using GTK 2.24.10 for Windows here (from www.gtk.org). Compiler is
Visual Studio 2008.
Does anyone know of any relevant fixes in the newer GTK in this regards.
Also any tips on what GTK 2.24.x build for Windows you use are welcome.
TIA,
Miroslav
#include <gtk/gtk.h>
#include <string>
GtkWidget *window1;
GtkWidget *textview1;
GdkAtom atomString = GDK_NONE;
GdkAtom atomTextHtml = GDK_NONE;
#ifdef _WIN32
GdkAtom atomTextHtmlWin= GDK_NONE;
#endif
std::string g_strClipTxt;
std::string g_strClipHtml;
std::string g_strClipHtmlWin;
void SuppressDefaultSignal(GtkWidget *widget, const char *szSignalName)
{
//FIX: this version throws a warning in console if the signal was not
fired
g_signal_stop_emission_by_name(widget, szSignalName);
GSignalInvocationHint* hint = g_signal_get_invocation_hint(widget);
if(hint) //has the code actually been invoked by a signal
{
gint signal_id = g_signal_lookup(szSignalName, G_OBJECT_TYPE
(widget));
if (signal_id > 0){
gulong nSignal = g_signal_handler_find(widget,
G_SIGNAL_MATCH_ID, signal_id, 0, 0, 0, 0);
if(nSignal != 0){
if(g_signal_has_handler_pending(widget,
signal_id, 0, true))
g_signal_stop_emission (widget,
signal_id, 0);
}
}
}
}
extern "C" void MyGtkClipboardGetFunc(GtkClipboard *clipboard, GtkSelectionData
*selection_data, guint info, gpointer user_data_or_owner)
{
GdkAtom atSelTarget = gtk_selection_data_get_target(selection_data);
if(atSelTarget == atomTextHtml)
{
gtk_selection_data_set (selection_data, atomTextHtml, 8,
(guchar *)g_strClipHtml.c_str(), g_strClipHtml.size());
}
#ifdef _WIN32
else if(atSelTarget == atomTextHtmlWin)
{
gtk_selection_data_set (selection_data, atomTextHtmlWin, 8,
(guchar *)g_strClipHtmlWin.c_str(), g_strClipHtmlWin.size());
}
#endif
else
{
gtk_selection_data_set_text (selection_data,
g_strClipTxt.c_str(), -1);
}
}
void on_copy1_activate (GtkMenuItem *menuitem, gpointer user_data)
{
//suppress default handler (copies plain text only)
SuppressDefaultSignal(textview1, "copy_clipboard");
//init data to be pushed
g_strClipTxt = "Some text";
g_strClipHtml = "Some <b>text</b>";
//g_strClipHtmlWin = "";
//initiate clipboard transfer
GtkTargetList *list = gtk_target_list_new (NULL, 0);
if(!g_strClipTxt.empty()){
gtk_target_list_add(list, gdk_atom_intern("TEXT", FALSE), 0, 0);
gtk_target_list_add(list, gdk_atom_intern("UTF8_STRING",
FALSE), 0, 0);
gtk_target_list_add(list, gdk_atom_intern("STRING", FALSE), 0,
0);
}
if(!g_strClipHtml.empty()){
gtk_target_list_add(list, atomTextHtml, 0, 0);
}
#ifdef _WIN32
if(!g_strClipHtmlWin.empty()){
gtk_target_list_add(list, atomTextHtmlWin, 0, 0);
}
#endif
int nTargetCnt = 0;
GtkTargetEntry *targets = gtk_target_table_new_from_list(list,
&nTargetCnt);
if(nTargetCnt < 1){
gtk_target_table_free(targets, nTargetCnt);
gtk_target_list_unref (list);
return; //nothing to export
}
GdkDisplay *display = gtk_widget_get_display (textview1);
GtkClipboard *clipboard = gtk_clipboard_get_for_display (display,
GDK_SELECTION_CLIPBOARD);
gboolean bOK = gtk_clipboard_set_with_data(clipboard, targets,
nTargetCnt, MyGtkClipboardGetFunc, NULL, 0);
if(bOK){
gtk_clipboard_set_can_store (clipboard, NULL, 0);
}
gtk_target_table_free(targets, nTargetCnt);
gtk_target_list_unref (list);
}
void create_gui()
{
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window1), "Clipboard test");
gtk_window_set_default_size (GTK_WINDOW (window1), 500, 350);
gtk_widget_show (window1);
GtkWidget *vbox1 = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (window1), vbox1);
GtkWidget *scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (scrolledwindow1);
gtk_container_add (GTK_CONTAINER (vbox1), scrolledwindow1);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
GtkTextBuffer *buffer = gtk_text_buffer_new (NULL);
textview1 = gtk_text_view_new_with_buffer (buffer);
gtk_widget_show (textview1);
gtk_container_add (GTK_CONTAINER (scrolledwindow1), textview1);
g_signal_connect (textview1, "copy-clipboard", G_CALLBACK
(on_copy1_activate), NULL);
g_signal_connect (window1, "destroy", G_CALLBACK (gtk_main_quit), NULL);
atomString = gdk_atom_intern("STRING", FALSE);
atomTextHtml = gdk_atom_intern_static_string("text/html");
#ifdef _WIN32
atomTextHtmlWin = gdk_atom_intern_static_string("HTML Format");
#endif
}
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
create_gui();
gtk_main ();
return 0;
}
#ifdef _WIN32
#include <windows.h>
int APIENTRY WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
return main( __argc, __argv );
}
#endif
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list