summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-03-12 20:33:18 +0800
committerPo Lu <luangruo@yahoo.com>2022-03-12 20:44:35 +0800
commit82a454915ca2f162794812c5d9d668ec15b50372 (patch)
tree8b1e0ea1594d451e6a5b18b8bbec1ca9579678c6
parent3af12cb8f20d93a3fdbebe2e3b987948e8228f03 (diff)
downloademacs-82a454915ca2f162794812c5d9d668ec15b50372.tar.gz
Try really hard to make GTK 3 scroll bars fit
* 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.
-rw-r--r--src/gtkutil.c89
-rw-r--r--src/xterm.c39
2 files changed, 111 insertions, 17 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c
index fd32dc15bf2..c9a3999afe7 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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);
@@ -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 ()));
diff --git a/src/xterm.c b/src/xterm.c
index d8311828116..46f9364abec 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -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