emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk bc35a1e 032/100: Make multipdisplay work by limiting select


From: Yuuki Harano
Subject: feature/pgtk bc35a1e 032/100: Make multipdisplay work by limiting selection while enabed
Date: Tue, 24 Nov 2020 08:02:31 -0500 (EST)

branch: feature/pgtk
commit bc35a1e1d5dbee82391d08c4fca361c7fc77d558
Author: Yuuki Harano <masm+github@masm11.me>
Commit: Jeff Walsh <fejfighter@gmail.com>

    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 を使えないようにした。
---
 src/pgtkselect.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pgtkterm.c   |  35 ++++++++++---------
 2 files changed, 121 insertions(+), 16 deletions(-)

diff --git a/src/pgtkselect.c b/src/pgtkselect.c
index b885425..4f4a43d 100644
--- a/src/pgtkselect.c
+++ b/src/pgtkselect.c
@@ -200,6 +200,93 @@ void pgtk_selection_lost(GtkWidget *widget, 
GdkEventSelection *event, gpointer u
   g_object_set_qdata(G_OBJECT(widget), quark_size, 0);
 }
 
+static bool
+pgtk_selection_usable (void)
+{
+  /*
+   * 
https://github.com/GNOME/gtk/blob/gtk-3-24/gdk/wayland/gdkselection-wayland.c#L1033
+   *
+   * Gdk uses gdk_display_get_default() when handling selections, so
+   * selections don't work properly on multi-display environment.
+   *
+   * ----------------
+   * #include <gtk/gtk.h>
+   *
+   * static GtkWidget *top1, *top2;
+   *
+   * int main(int argc, char **argv)
+   * {
+   *     GtkWidget *w;
+   *     GtkTextBuffer *buf;
+   *
+   *     gtk_init(&argc, &argv);
+   *
+   *     static char *text = "\
+   * It is fine today.\n\
+   * It will be fine tomorrow too.\n\
+   * It is too hot.";
+   *
+   *     top1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+   *     gtk_window_set_title(GTK_WINDOW(top1), "default");
+   *     gtk_widget_show(top1);
+   *     w = gtk_text_view_new();
+   *     gtk_container_add(GTK_CONTAINER(top1), w);
+   *     gtk_widget_show(w);
+   *     buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
+   *     gtk_text_buffer_insert_at_cursor(buf, text, strlen(text));
+   *     gtk_text_buffer_add_selection_clipboard(buf, 
gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY));
+   *
+   *     unsetenv("GDK_BACKEND");
+   *     GdkDisplay *gdpy;
+   *     const char *dpyname2;
+   *     if (strcmp(G_OBJECT_TYPE_NAME(gtk_widget_get_window(top1)), 
"GdkWaylandWindow") == 0)
+   *         dpyname2 = ":0";
+   *     else
+   *         dpyname2 = "wayland-0";
+   *     gdpy = gdk_display_open (dpyname2);
+   *     top2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+   *     gtk_window_set_title(GTK_WINDOW(top2), dpyname2);
+   *     gtk_window_set_screen (GTK_WINDOW (top2), 
gdk_display_get_default_screen(gdpy));
+   *     gtk_widget_show (top2);
+   *     w = gtk_text_view_new();
+   *     gtk_container_add(GTK_CONTAINER(top2), w);
+   *     gtk_widget_show(w);
+   *     buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
+   *     gtk_text_buffer_insert_at_cursor(buf, text, strlen(text));
+   *     gtk_text_buffer_add_selection_clipboard(buf, 
gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY));
+   *
+   *     gtk_main();
+   *
+   *     return 0;
+   * }
+   * ----------------
+   *
+   * This code fails if
+   *   GDK_BACKEND=x11 ./test
+   * and select on both of windows.
+   *
+   * ----------------
+   * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.041: g_object_ref: 
assertion 'G_IS_OBJECT (object)' failed
+   *
+   * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.042: g_object_ref: 
assertion 'G_IS_OBJECT (object)' failed
+   *
+   * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: 
assertion 'G_IS_OBJECT (object)' failed
+   *
+   * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: 
assertion 'G_IS_OBJECT (object)' failed
+   * ----------------
+   * (gtk-3.24.10)
+   *
+   * This function checks whether selections work by the number of displays.
+   * If you use more than 2 displays, then selection is disabled.
+   */
+
+  GdkDisplayManager *dpyman = gdk_display_manager_get ();
+  GSList *list = gdk_display_manager_list_displays (dpyman);
+  int len = g_slist_length (list);
+  g_slist_free (list);
+  return len < 2;
+}
+
 /* ==========================================================================
 
     Lisp Defuns
@@ -228,6 +315,9 @@ nil, it defaults to the selected frame.*/)
 
   check_window_system (NULL);
 
+  if (!pgtk_selection_usable ())
+    return Qnil;
+
   if (NILP (frame)) frame = selected_frame;
   if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame)))
     error ("pgtk selection unavailable for this frame");
@@ -308,6 +398,9 @@ On PGTK, the TIME-OBJECT is unused.  */)
   struct frame *f = frame_for_pgtk_selection (terminal);
   GtkClipboard *cb;
 
+  if (!pgtk_selection_usable ())
+    return Qnil;
+
   if (!f)
     return Qnil;
 
@@ -337,6 +430,9 @@ On Nextstep, TERMINAL is unused.  */)
   struct frame *f = frame_for_pgtk_selection (terminal);
   GtkClipboard *cb;
 
+  if (!pgtk_selection_usable ())
+    return Qnil;
+
   if (!f)
     return Qnil;
 
@@ -368,6 +464,9 @@ On Nextstep, TERMINAL is unused.  */)
   GObject *obj;
   GQuark quark_data, quark_size;
 
+  if (!pgtk_selection_usable ())
+    return Qnil;
+
   cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection);
   selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, 
&quark_size);
 
@@ -406,6 +505,9 @@ On PGTK, TIME-STAMP is unused.  */)
   if (!f)
     error ("PGTK selection unavailable for this frame");
 
+  if (!pgtk_selection_usable ())
+    return Qnil;
+
   cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol);
 
   gchar *s = gtk_clipboard_wait_for_text(cb);
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 50ee31e..92f1409 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -2975,6 +2975,8 @@ pgtk_mouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
   int win_x, win_y;
   GdkSeat *seat;
   GdkDevice *device;
+  GdkModifierType mask;
+  GdkWindow *win;
 
   block_input ();
 
@@ -2988,32 +2990,33 @@ pgtk_mouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
 
   dpyinfo->last_mouse_scroll_bar = NULL;
 
-  seat = gdk_display_get_default_seat(dpyinfo->gdpy);
-  device = gdk_seat_get_pointer(seat);
-
   if (gui_mouse_grabbed (dpyinfo)) {
-    GdkWindow *win;
-    GdkModifierType mask;
-    /* get x, y relative to edit window of f1. */
+    /* 1.1. use last_mouse_frame as frame where the pointer is on. */
     f1 = dpyinfo->last_mouse_frame;
-    win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1));
-    win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask);
   } else {
-    GdkWindow *win;
-    GdkModifierType mask;
-    /* 1. get frame where the pointer is on. */
+    f1 = *fp;
+    /* 1.2. get frame where the pointer is on. */
     win = gtk_widget_get_window(FRAME_GTK_WIDGET(*fp));
+    seat = gdk_display_get_default_seat(dpyinfo->gdpy);
+    device = gdk_seat_get_pointer(seat);
     win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask);
     if (win != NULL)
       f1 = pgtk_any_window_to_frame(win);
-    else
+    else {
+      // crossing display server?
       f1 = SELECTED_FRAME();
-
-    /* 2. get x, y relative to edit window of the frame. */
-    win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1));
-    win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask);
+    }
   }
 
+  /* 2. get the display and the device. */
+  win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1));
+  GdkDisplay *gdpy = gdk_window_get_display (win);
+  seat = gdk_display_get_default_seat(gdpy);
+  device = gdk_seat_get_pointer(seat);
+
+  /* 3. get x, y relative to edit window of the frame. */
+  win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask);
+
   if (f1 != NULL) {
     dpyinfo = FRAME_DISPLAY_INFO (f1);
     remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]