From 7ad1df5e1684532efeec435be4ac7fc76affc814 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 11 Mar 2022 20:07:52 +0800 Subject: [PATCH] Implement customization of scroll bar colors on GTK 3 * src/gtkutil.c (xg_create_frame_widgets): Create CSS providers for scroll bars. (xg_finish_scroll_bar_creation): Attach created CSS providers. * src/xfns.c (x_set_scroll_bar_foreground): (x_set_scroll_bar_background): Put appropriate content into CSS providers. * src/xterm.c (x_free_frame_resources): Free CSS providers. * src/xterm.h (struct x_output): New fields for scroll bar stylesheet providers. --- src/gtkutil.c | 30 +++++++++++++++++++----------- src/xfns.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/xterm.c | 8 ++++++++ src/xterm.h | 7 +++++++ 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/gtkutil.c b/src/gtkutil.c index 1b4ecaf9492..f488b0ff752 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1612,10 +1612,7 @@ xg_create_frame_widgets (struct frame *f) with regular X drawing primitives, so from a GTK/GDK point of view, the widget is totally blank. When an expose comes, this will make the widget blank, and then Emacs redraws it. This flickers - a lot, so we turn off double buffering. - FIXME: gtk_widget_set_double_buffered is deprecated and might stop - working in the future. We need to migrate away from combining - X and GTK+ drawing to a pure GTK+ build. */ + a lot, so we turn off double buffering. */ #ifndef HAVE_PGTK gtk_widget_set_double_buffered (wfixed, FALSE); @@ -1634,6 +1631,14 @@ xg_create_frame_widgets (struct frame *f) G_CALLBACK (delete_cb), f); #endif +#if defined HAVE_GTK3 && !defined HAVE_PGTK + /* On PGTK this is done in Fx_create_frame. */ + FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider + = gtk_css_provider_new (); + FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider + = gtk_css_provider_new (); +#endif + /* Convert our geometry parameters into a geometry string and specify it. GTK will itself handle calculating the real position this way. */ @@ -4448,6 +4453,10 @@ xg_finish_scroll_bar_creation (struct frame *f, const char *scroll_bar_name) { GtkWidget *webox = gtk_event_box_new (); +#ifdef HAVE_GTK3 + GtkCssProvider *foreground_provider; + GtkCssProvider *background_provider; +#endif gtk_widget_set_name (wscroll, scroll_bar_name); #ifndef HAVE_GTK3 @@ -4496,15 +4505,14 @@ xg_finish_scroll_bar_creation (struct frame *f, /* Set the cursor to an arrow. */ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); -#ifdef HAVE_PGTK +#ifdef HAVE_GTK3 GtkStyleContext *ctxt = gtk_widget_get_style_context (wscroll); - gtk_style_context_add_provider (ctxt, - GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)-> - scrollbar_foreground_css_provider), + foreground_provider = FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider; + background_provider = FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider; + + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (foreground_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - gtk_style_context_add_provider (ctxt, - GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)-> - scrollbar_background_css_provider), + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (background_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); #endif diff --git a/src/xfns.c b/src/xfns.c index a3236efbcc6..65f3b5097c3 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1943,6 +1943,10 @@ static void x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval) { unsigned long pixel; +#ifdef HAVE_GTK3 + XColor color; + char css[64]; +#endif if (STRINGP (value)) pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f)); @@ -1964,6 +1968,25 @@ x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object old update_face_from_frame_parameter (f, Qscroll_bar_foreground, value); redraw_frame (f); } + +#ifdef HAVE_GTK3 + if (pixel != -1) + { + color.pixel = pixel; + + XQueryColor (FRAME_X_DISPLAY (f), + FRAME_X_COLORMAP (f), + &color); + + sprintf (css, "scrollbar slider { background-color: #%02x%02x%02x; }", + color.red >> 8, color.green >> 8, color.blue >> 8); + gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider, + css, -1, NULL); + } + else + gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider, + "", -1, NULL); +#endif } @@ -1976,6 +1999,10 @@ static void x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval) { unsigned long pixel; +#ifdef HAVE_GTK3 + XColor color; + char css[64]; +#endif if (STRINGP (value)) pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f)); @@ -2011,6 +2038,25 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old update_face_from_frame_parameter (f, Qscroll_bar_background, value); redraw_frame (f); } + +#ifdef HAVE_GTK3 + if (pixel != -1) + { + color.pixel = pixel; + + XQueryColor (FRAME_X_DISPLAY (f), + FRAME_X_COLORMAP (f), + &color); + + sprintf (css, "scrollbar trough { background-color: #%02x%02x%02x; }", + color.red >> 8, color.green >> 8, color.blue >> 8); + gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider, + css, -1, NULL); + } + else + gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider, + "", -1, NULL); +#endif } diff --git a/src/xterm.c b/src/xterm.c index 2adf70b829d..cf79135497c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16579,6 +16579,14 @@ x_free_frame_resources (struct frame *f) XFlush (FRAME_X_DISPLAY (f)); } +#ifdef HAVE_GTK3 + if (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider) + g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider); + + if (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider) + g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider); +#endif + xfree (f->output_data.x->saved_menu_event); xfree (f->output_data.x); f->output_data.x = NULL; diff --git a/src/xterm.h b/src/xterm.h index 4875eabafe6..5b199cab6b6 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -758,6 +758,13 @@ struct x_output GtkWindow *ttip_window; GtkIMContext *im_context; + +#ifdef HAVE_GTK3 + /* The CSS providers used for scroll bar foreground and background + colors. */ + GtkCssProvider *scrollbar_foreground_css_provider; + GtkCssProvider *scrollbar_background_css_provider; +#endif #endif /* USE_GTK */ /* If >=0, a bitmap index. The indicated bitmap is used for the -- 2.39.2