]> git.eshelyaron.com Git - emacs.git/commitdiff
Try really hard to make GTK 3 scroll bars fit
authorPo Lu <luangruo@yahoo.com>
Sat, 12 Mar 2022 12:33:18 +0000 (20:33 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 12 Mar 2022 12:44:35 +0000 (20:44 +0800)
* src/gtkutil.c (xg_get_widget_from_map): New argument DISPLAY.
All callers changed.
(find_scrollbar_cb): New function.
(xg_finish_scroll_bar_creation, xg_remove_scroll_bar)
(xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos)
(xg_set_toolkit_scroll_bar_thumb)
(xg_set_toolkit_horizontal_scroll_bar_thumb, xg_initialize):
Stop using id_to_widget_map on X builds with GTK 3 and set the
event box as the x_window instead.
* src/xterm.c (x_window_to_scroll_bar): Don't look for ID on GTK
3.
(handle_one_xevent): If a ConfigureNotify event is found for a
scroll bar and the dimensions are wrong, resize the X window to
the right ones.

src/gtkutil.c
src/xterm.c

index fd32dc15bf26e9da376898a4b36f37c1bf094eca..c9a3999afe7e1d8b13e65800c54b86d67dd88161 100644 (file)
@@ -142,7 +142,7 @@ struct xg_frame_tb_info
 bool xg_gtk_initialized;        /* Used to make sure xwidget calls are possible */
 #endif
 
-static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx);
+static GtkWidget *xg_get_widget_from_map (ptrdiff_t idx, Display *dpy);
 
 \f
 
@@ -2038,8 +2038,8 @@ xg_set_background_color (struct frame *f, unsigned long bg)
            !NILP (bar);
            bar = XSCROLL_BAR (bar)->next)
         {
-          GtkWidget *scrollbar =
-            xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window);
+          GtkWidget *scrollbar = xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window,
+                                                        FRAME_X_DISPLAY (f));
           GtkWidget *webox = gtk_widget_get_parent (scrollbar);
           xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
         }
@@ -4264,6 +4264,8 @@ bool xg_ignore_gtk_scrollbar;
 static int scroll_bar_width_for_theme;
 static int scroll_bar_height_for_theme;
 
+#if defined HAVE_PGTK || !defined HAVE_GTK3
+
 /* Xlib's `Window' fits in 32 bits.  But we want to store pointers, and they
    may be larger than 32 bits.  Keep a mapping from integer index to widget
    pointers to get around the 32 bit limitation.  */
@@ -4335,7 +4337,7 @@ xg_remove_widget_from_map (ptrdiff_t idx)
 /* Get the widget pointer at IDX from id_to_widget. */
 
 static GtkWidget *
-xg_get_widget_from_map (ptrdiff_t idx)
+xg_get_widget_from_map (ptrdiff_t idx, Display *dpy)
 {
   if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0)
     return id_to_widget.widgets[idx];
@@ -4343,6 +4345,42 @@ xg_get_widget_from_map (ptrdiff_t idx)
   return 0;
 }
 
+#else
+static void
+find_scrollbar_cb (GtkWidget *widget, gpointer user_data)
+{
+  GtkWidget **scroll_bar = user_data;
+
+  if (GTK_IS_SCROLLBAR (widget))
+    *scroll_bar = widget;
+}
+
+static GtkWidget *
+xg_get_widget_from_map (ptrdiff_t window, Display *dpy)
+{
+  GtkWidget *gwdesc, *scroll_bar = NULL;
+  GdkWindow *gdkwin;
+
+  gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
+                                              (Window) window);
+  if (gdkwin)
+    {
+      GdkEvent event;
+      event.any.window = gdkwin;
+      event.any.type = GDK_NOTHING;
+      gwdesc = gtk_get_event_widget (&event);
+
+      if (gwdesc && GTK_IS_EVENT_BOX (gwdesc))
+       gtk_container_forall (GTK_CONTAINER (gwdesc),
+                             find_scrollbar_cb, &scroll_bar);
+    }
+  else
+    return NULL;
+
+  return scroll_bar;
+}
+#endif
+
 static void
 update_theme_scrollbar_width (void)
 {
@@ -4402,7 +4440,7 @@ xg_get_default_scrollbar_height (struct frame *f)
   return scroll_bar_width_for_theme * xg_get_scale (f);
 }
 
-#ifndef HAVE_PGTK
+#if defined HAVE_PGTK || !defined HAVE_GTK3
 /* Return the scrollbar id for X Window WID on display DPY.
    Return -1 if WID not in id_to_widget.  */
 
@@ -4429,12 +4467,14 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid)
    DATA is the index into id_to_widget for WIDGET.
    We free pointer to last scroll bar values here and remove the index.  */
 
+#if !defined HAVE_GTK3 || defined HAVE_PGTK
 static void
 xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
 {
   intptr_t id = (intptr_t) data;
   xg_remove_widget_from_map (id);
 }
+#endif
 
 static void
 xg_finish_scroll_bar_creation (struct frame *f,
@@ -4456,12 +4496,15 @@ xg_finish_scroll_bar_creation (struct frame *f,
 #endif
   g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
 
+#if defined HAVE_PGTK || !defined HAVE_GTK3
   ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll);
 
   g_signal_connect (G_OBJECT (wscroll),
                     "destroy",
                     G_CALLBACK (xg_gtk_scroll_destroy),
                     (gpointer) scroll_id);
+#endif
+
   g_signal_connect (G_OBJECT (wscroll),
                     "change-value",
                     scroll_callback,
@@ -4489,8 +4532,9 @@ xg_finish_scroll_bar_creation (struct frame *f,
   gtk_widget_realize (webox);
 #ifdef HAVE_PGTK
   gtk_widget_show_all (webox);
-#endif
-#ifndef HAVE_PGTK
+#elif defined HAVE_GTK3
+  bar->x_window = GTK_WIDGET_TO_X_WIN (webox);
+#else
   GTK_WIDGET_TO_X_WIN (webox);
 #endif
 
@@ -4506,9 +4550,15 @@ xg_finish_scroll_bar_creation (struct frame *f,
                                  GTK_STYLE_PROVIDER_PRIORITY_USER);
   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (background_provider),
                                  GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+#ifndef HAVE_PGTK
+  gtk_widget_add_events (webox, GDK_STRUCTURE_MASK);
+#endif
 #endif
 
+#if !defined HAVE_GTK3 || !defined HAVE_GTK3
   bar->x_window = scroll_id;
+#endif
 }
 
 /* Create a scroll bar widget for frame F.  Store the scroll bar
@@ -4582,7 +4632,8 @@ xg_create_horizontal_scroll_bar (struct frame *f,
 void
 xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id)
 {
-  GtkWidget *w = xg_get_widget_from_map (scrollbar_id);
+  GtkWidget *w = xg_get_widget_from_map (scrollbar_id,
+                                        FRAME_X_DISPLAY (f));
   if (w)
     {
       GtkWidget *wparent = gtk_widget_get_parent (w);
@@ -4605,7 +4656,8 @@ xg_update_scrollbar_pos (struct frame *f,
                          int width,
                          int height)
 {
-  GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+  GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id,
+                                              FRAME_X_DISPLAY (f));
   if (wscroll)
     {
       GtkWidget *wfixed = f->output_data.xp->edit_widget;
@@ -4658,7 +4710,8 @@ xg_update_scrollbar_pos (struct frame *f,
 
       if (!hidden)
        {
-         GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id);
+         GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id,
+                                                        FRAME_X_DISPLAY (f));
          GtkWidget *webox = gtk_widget_get_parent (scrollbar);
 
 #ifndef HAVE_PGTK
@@ -4697,7 +4750,8 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
                                    int width,
                                    int height)
 {
-  GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+  GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id,
+                                              FRAME_X_DISPLAY (f));
 
   if (wscroll)
     {
@@ -4749,7 +4803,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
 
       {
        GtkWidget *scrollbar =
-         xg_get_widget_from_map (scrollbar_id);
+         xg_get_widget_from_map (scrollbar_id, FRAME_X_DISPLAY (f));
        GtkWidget *webox = gtk_widget_get_parent (scrollbar);
 
 #ifndef HAVE_PGTK
@@ -4789,9 +4843,10 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
                                  int position,
                                  int whole)
 {
-  GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
-
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window,
+                                              FRAME_X_DISPLAY (f));
+
 
   if (wscroll && bar->dragging == -1)
     {
@@ -4876,7 +4931,9 @@ xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
                                            int position,
                                            int whole)
 {
-  GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window,
+                                              FRAME_X_DISPLAY (f));
 
   if (wscroll && bar->dragging == -1)
     {
@@ -6055,8 +6112,10 @@ xg_initialize (void)
   xg_menu_cb_list.prev = xg_menu_cb_list.next =
     xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0;
 
+#if defined HAVE_PGTK || !defined HAVE_GTK3
   id_to_widget.max_size = id_to_widget.used = 0;
   id_to_widget.widgets = 0;
+#endif
 
   settings = gtk_settings_get_for_screen (gdk_display_get_default_screen
                                           (gdk_display_get_default ()));
index d8311828116ba34e4ef60417216803c15df152e4..46f9364abecda00ed9f95f0e382cd437ed7e247e 100644 (file)
@@ -7238,9 +7238,9 @@ x_window_to_scroll_bar (Display *display, Window window_id, int type)
 {
   Lisp_Object tail, frame;
 
-#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
+#if defined (USE_GTK) && !defined (HAVE_GTK3) && defined (USE_TOOLKIT_SCROLL_BARS)
   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
+#endif /* USE_GTK && !HAVE_GTK3  && USE_TOOLKIT_SCROLL_BARS */
 
   FOR_EACH_FRAME (tail, frame)
     {
@@ -11294,6 +11294,41 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            configureEvent = next_event;
         }
 
+#if defined HAVE_GTK3 && defined USE_TOOLKIT_SCROLL_BARS
+         struct scroll_bar *bar = x_window_to_scroll_bar (dpyinfo->display,
+                                                          configureEvent.xconfigure.window, 2);
+
+         /* There is really no other way to make GTK scroll bars fit
+            in the dimensions we want them to.  */
+         if (bar)
+           {
+             /* Skip all the pending configure events, not just the
+                ones where window motion occurred.  */
+             while (XPending (dpyinfo->display))
+               {
+                 XNextEvent (dpyinfo->display, &next_event);
+                 if (next_event.type != ConfigureNotify
+                     || next_event.xconfigure.window != event->xconfigure.window)
+                   {
+                     XPutBackEvent (dpyinfo->display, &next_event);
+                     break;
+                   }
+                 else
+                   configureEvent = next_event;
+               }
+
+             if (configureEvent.xconfigure.width != max (bar->width, 1)
+                 || configureEvent.xconfigure.height != max (bar->height, 1))
+               XResizeWindow (dpyinfo->display, bar->x_window,
+                              max (bar->width, 1), max (bar->height, 1));
+
+             if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
+               x_drop_xrender_surfaces (f);
+
+             goto OTHER;
+           }
+#endif
+
       f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
       /* Unfortunately, we need to call x_drop_xrender_surfaces for
          _all_ ConfigureNotify events, otherwise we miss some and