aboutsummaryrefslogtreecommitdiffstats
path: root/src/pgtkselect.c
diff options
context:
space:
mode:
authorYuuki Harano2019-08-01 01:26:55 +0900
committerJeff Walsh2020-11-22 14:46:56 +1100
commitbc35a1e1d5dbee82391d08c4fca361c7fc77d558 (patch)
tree37d8cb8f338ca89c45be7f9642e968acfb2826d4 /src/pgtkselect.c
parent24d82638bc674d0c258ed95649fe98b22113d42f (diff)
downloademacs-bc35a1e1d5dbee82391d08c4fca361c7fc77d558.tar.gz
emacs-bc35a1e1d5dbee82391d08c4fca361c7fc77d558.zip
Make multipdisplay work by limiting selection while enabed
* src/pgtkterm.c (pgtk_mouse_position): * src/pgtkselect.c (pgtk_selection_usable): new function (Fpgtk_own_selection_internal, Fpgtk_disown_selection_internal) (Fpgtk_selection_exists_p, Fpgtk_selection_owner_p) (Fpgtk_get_selection_internal): check usable selection multi-display で落ちる理由を一つ潰した。 まだまだありそう。 multi-display 時は selection を使えないようにした。
Diffstat (limited to 'src/pgtkselect.c')
-rw-r--r--src/pgtkselect.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/pgtkselect.c b/src/pgtkselect.c
index b8854256802..4f4a43da8be 100644
--- a/src/pgtkselect.c
+++ b/src/pgtkselect.c
@@ -200,6 +200,93 @@ void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer u
200 g_object_set_qdata(G_OBJECT(widget), quark_size, 0); 200 g_object_set_qdata(G_OBJECT(widget), quark_size, 0);
201} 201}
202 202
203static bool
204pgtk_selection_usable (void)
205{
206 /*
207 * https://github.com/GNOME/gtk/blob/gtk-3-24/gdk/wayland/gdkselection-wayland.c#L1033
208 *
209 * Gdk uses gdk_display_get_default() when handling selections, so
210 * selections don't work properly on multi-display environment.
211 *
212 * ----------------
213 * #include <gtk/gtk.h>
214 *
215 * static GtkWidget *top1, *top2;
216 *
217 * int main(int argc, char **argv)
218 * {
219 * GtkWidget *w;
220 * GtkTextBuffer *buf;
221 *
222 * gtk_init(&argc, &argv);
223 *
224 * static char *text = "\
225 * It is fine today.\n\
226 * It will be fine tomorrow too.\n\
227 * It is too hot.";
228 *
229 * top1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
230 * gtk_window_set_title(GTK_WINDOW(top1), "default");
231 * gtk_widget_show(top1);
232 * w = gtk_text_view_new();
233 * gtk_container_add(GTK_CONTAINER(top1), w);
234 * gtk_widget_show(w);
235 * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
236 * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text));
237 * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY));
238 *
239 * unsetenv("GDK_BACKEND");
240 * GdkDisplay *gdpy;
241 * const char *dpyname2;
242 * if (strcmp(G_OBJECT_TYPE_NAME(gtk_widget_get_window(top1)), "GdkWaylandWindow") == 0)
243 * dpyname2 = ":0";
244 * else
245 * dpyname2 = "wayland-0";
246 * gdpy = gdk_display_open (dpyname2);
247 * top2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
248 * gtk_window_set_title(GTK_WINDOW(top2), dpyname2);
249 * gtk_window_set_screen (GTK_WINDOW (top2), gdk_display_get_default_screen(gdpy));
250 * gtk_widget_show (top2);
251 * w = gtk_text_view_new();
252 * gtk_container_add(GTK_CONTAINER(top2), w);
253 * gtk_widget_show(w);
254 * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
255 * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text));
256 * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY));
257 *
258 * gtk_main();
259 *
260 * return 0;
261 * }
262 * ----------------
263 *
264 * This code fails if
265 * GDK_BACKEND=x11 ./test
266 * and select on both of windows.
267 *
268 * ----------------
269 * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.041: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
270 *
271 * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.042: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
272 *
273 * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
274 *
275 * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
276 * ----------------
277 * (gtk-3.24.10)
278 *
279 * This function checks whether selections work by the number of displays.
280 * If you use more than 2 displays, then selection is disabled.
281 */
282
283 GdkDisplayManager *dpyman = gdk_display_manager_get ();
284 GSList *list = gdk_display_manager_list_displays (dpyman);
285 int len = g_slist_length (list);
286 g_slist_free (list);
287 return len < 2;
288}
289
203/* ========================================================================== 290/* ==========================================================================
204 291
205 Lisp Defuns 292 Lisp Defuns
@@ -228,6 +315,9 @@ nil, it defaults to the selected frame.*/)
228 315
229 check_window_system (NULL); 316 check_window_system (NULL);
230 317
318 if (!pgtk_selection_usable ())
319 return Qnil;
320
231 if (NILP (frame)) frame = selected_frame; 321 if (NILP (frame)) frame = selected_frame;
232 if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) 322 if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame)))
233 error ("pgtk selection unavailable for this frame"); 323 error ("pgtk selection unavailable for this frame");
@@ -308,6 +398,9 @@ On PGTK, the TIME-OBJECT is unused. */)
308 struct frame *f = frame_for_pgtk_selection (terminal); 398 struct frame *f = frame_for_pgtk_selection (terminal);
309 GtkClipboard *cb; 399 GtkClipboard *cb;
310 400
401 if (!pgtk_selection_usable ())
402 return Qnil;
403
311 if (!f) 404 if (!f)
312 return Qnil; 405 return Qnil;
313 406
@@ -337,6 +430,9 @@ On Nextstep, TERMINAL is unused. */)
337 struct frame *f = frame_for_pgtk_selection (terminal); 430 struct frame *f = frame_for_pgtk_selection (terminal);
338 GtkClipboard *cb; 431 GtkClipboard *cb;
339 432
433 if (!pgtk_selection_usable ())
434 return Qnil;
435
340 if (!f) 436 if (!f)
341 return Qnil; 437 return Qnil;
342 438
@@ -368,6 +464,9 @@ On Nextstep, TERMINAL is unused. */)
368 GObject *obj; 464 GObject *obj;
369 GQuark quark_data, quark_size; 465 GQuark quark_data, quark_size;
370 466
467 if (!pgtk_selection_usable ())
468 return Qnil;
469
371 cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); 470 cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection);
372 selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); 471 selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size);
373 472
@@ -406,6 +505,9 @@ On PGTK, TIME-STAMP is unused. */)
406 if (!f) 505 if (!f)
407 error ("PGTK selection unavailable for this frame"); 506 error ("PGTK selection unavailable for this frame");
408 507
508 if (!pgtk_selection_usable ())
509 return Qnil;
510
409 cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol); 511 cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol);
410 512
411 gchar *s = gtk_clipboard_wait_for_text(cb); 513 gchar *s = gtk_clipboard_wait_for_text(cb);