diff options
author | Marcin Borkowski <mbork@mbork.pl> | 2017-12-07 14:24:57 +0100 |
---|---|---|
committer | Marcin Borkowski <mbork@mbork.pl> | 2017-12-07 14:24:57 +0100 |
commit | 0e3c10ce34c84d24013a84a725c6275ad87b1530 (patch) | |
tree | c37c89b1087a00e4d4799e6f4123c48ffca30270 /src/gtkutil.c | |
parent | ab5fc7c8215e1066449da4eb0e027f8250cc9f49 (diff) | |
parent | d4db37b283daffa0f8c942a5b526b6444edc34c5 (diff) | |
download | emacs-0e3c10ce34c84d24013a84a725c6275ad87b1530.tar.gz |
Merge branch 'master' into fix/bug-20871
Diffstat (limited to 'src/gtkutil.c')
-rw-r--r-- | src/gtkutil.c | 133 |
1 files changed, 95 insertions, 38 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index 16eb284d7c7..c279f1d2bcd 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ +along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> @@ -204,6 +204,31 @@ xg_display_open (char *display_name, Display **dpy) *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL; } +/* Scaling/HiDPI functions. */ +static int +xg_get_gdk_scale (void) +{ + const char *sscale = getenv ("GDK_SCALE"); + + if (sscale) + { + long scale = atol (sscale); + if (0 < scale) + return min (scale, INT_MAX); + } + + return 1; +} + +int +xg_get_scale (struct frame *f) +{ +#if GTK_CHECK_VERSION (3, 10, 0) + if (FRAME_GTK_WIDGET (f)) + return gtk_widget_get_scale_factor (FRAME_GTK_WIDGET (f)); +#endif + return xg_get_gdk_scale (); +} /* Close display DPY. */ @@ -552,7 +577,18 @@ xg_check_special_colors (struct frame *f, if (get_fg) gtk_style_context_get_color (gsty, state, &col); else - gtk_style_context_get_background_color (gsty, state, &col); + { + GdkRGBA *c; + /* FIXME: Retrieving the background color is deprecated in + GTK+ 3.16. New versions of GTK+ don’t use the concept of a + single background color any more, so we shouldn’t query for + it. */ + gtk_style_context_get (gsty, state, + GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c, + NULL); + col = *c; + gdk_rgba_free (c); + } unsigned short r = col.red * 65535, @@ -724,7 +760,8 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y) if (x->ttip_window) { block_input (); - gtk_window_move (x->ttip_window, root_x, root_y); + gtk_window_move (x->ttip_window, root_x / xg_get_scale (f), + root_y / xg_get_scale (f)); gtk_widget_show_all (GTK_WIDGET (x->ttip_window)); unblock_input (); } @@ -766,6 +803,7 @@ xg_hide_tooltip (struct frame *f) General functions for creating widgets, resizing, events, e.t.c. ***********************************************************************/ +#if ! GTK_CHECK_VERSION (3, 22, 0) static void my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data) @@ -773,6 +811,7 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, if (!strstr (msg, "visible children")) fprintf (stderr, "XX %s-WARNING **: %s\n", log_domain, msg); } +#endif /* Make a geometry string and pass that to GTK. It seems this is the only way to get geometry position right if the user explicitly @@ -784,8 +823,10 @@ xg_set_geometry (struct frame *f) { if (f->size_hint_flags & (USPosition | PPosition)) { +#if ! GTK_CHECK_VERSION (3, 22, 0) if (x_gtk_use_window_move) { +#endif /* Handle negative positions without consulting gtk_window_parse_geometry (Bug#25851). The position will be off by scrollbar width + window manager decorations. */ @@ -802,6 +843,7 @@ xg_set_geometry (struct frame *f) /* Reset size hint flags. */ f->size_hint_flags &= ~ (XNegative | YNegative); +# if ! GTK_CHECK_VERSION (3, 22, 0) } else { @@ -833,24 +875,10 @@ xg_set_geometry (struct frame *f) g_log_remove_handler ("Gtk", id); } +#endif } } -static int -xg_get_gdk_scale (void) -{ - const char *sscale = getenv ("GDK_SCALE"); - - if (sscale) - { - long scale = atol (sscale); - if (0 < scale) - return min (scale, INT_MAX); - } - - return 1; -} - /* Function to handle resize of our frame. As we have a Gtk+ tool bar and a Gtk+ menu bar, we get resize events for the edit part of the frame only. We let Gtk+ deal with the Gtk+ parts. @@ -912,12 +940,8 @@ xg_frame_set_char_size (struct frame *f, int width, int height) /* Do this before resize, as we don't know yet if we will be resized. */ x_clear_under_internal_border (f); - if (FRAME_VISIBLE_P (f)) - { - int scale = xg_get_gdk_scale (); - totalheight /= scale; - totalwidth /= scale; - } + totalheight /= xg_get_scale (f); + totalwidth /= xg_get_scale (f); x_wm_set_size_hint (f, 0, 0); @@ -1037,16 +1061,23 @@ static void xg_set_widget_bg (struct frame *f, GtkWidget *w, unsigned long pixel) { #ifdef HAVE_GTK3 - GdkRGBA bg; XColor xbg; xbg.pixel = pixel; if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg)) { - bg.red = (double)xbg.red/65535.0; - bg.green = (double)xbg.green/65535.0; - bg.blue = (double)xbg.blue/65535.0; - bg.alpha = 1.0; - gtk_widget_override_background_color (w, GTK_STATE_FLAG_NORMAL, &bg); + const char format[] = "* { background-color: #%02x%02x%02x; }"; + /* The format is always longer than the resulting string. */ + char buffer[sizeof format]; + int n = snprintf(buffer, sizeof buffer, format, + xbg.red >> 8, xbg.green >> 8, xbg.blue >> 8); + eassert (n > 0); + eassert (n < sizeof buffer); + GtkCssProvider *provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, buffer, -1, NULL); + gtk_style_context_add_provider (gtk_widget_get_style_context(w), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_clear_object (&provider); } #else GdkColor bg; @@ -1204,12 +1235,17 @@ 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. */ + 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. */ gtk_widget_set_double_buffered (wfixed, FALSE); +#if ! GTK_CHECK_VERSION (3, 22, 0) gtk_window_set_wmclass (GTK_WINDOW (wtop), SSDATA (Vx_resource_name), SSDATA (Vx_resource_class)); +#endif /* Add callback to do nothing on WM_DELETE_WINDOW. The default in GTK is to destroy the widget. We want Emacs to do that instead. */ @@ -1343,11 +1379,11 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) int min_rows = 0, min_cols = 0; int win_gravity = f->win_gravity; Lisp_Object fs_state, frame; - int scale = xg_get_gdk_scale (); + int scale = xg_get_scale (f); /* Don't set size hints during initialization; that apparently leads to a race condition. See the thread at - http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */ + https://lists.gnu.org/r/emacs-devel/2008-10/msg00033.html */ if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f) || FRAME_PARENT_FRAME (f)) @@ -1503,6 +1539,7 @@ xg_set_undecorated (struct frame *f, Lisp_Object undecorated) void xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) { +#if GTK_CHECK_VERSION (2, 18, 0) block_input (); if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2)) { @@ -1517,6 +1554,7 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) x_sync (f1); } unblock_input (); +#endif } @@ -3657,16 +3695,16 @@ update_theme_scrollbar_height (void) } int -xg_get_default_scrollbar_width (void) +xg_get_default_scrollbar_width (struct frame *f) { - return scroll_bar_width_for_theme * xg_get_gdk_scale (); + return scroll_bar_width_for_theme * xg_get_scale (f); } int -xg_get_default_scrollbar_height (void) +xg_get_default_scrollbar_height (struct frame *f) { /* Apparently there's no default height for themes. */ - return scroll_bar_width_for_theme * xg_get_gdk_scale (); + return scroll_bar_width_for_theme * xg_get_scale (f); } /* Return the scrollbar id for X Window WID on display DPY. @@ -3856,7 +3894,7 @@ xg_update_scrollbar_pos (struct frame *f, GtkWidget *wfixed = f->output_data.x->edit_widget; GtkWidget *wparent = gtk_widget_get_parent (wscroll); gint msl; - int scale = xg_get_gdk_scale (); + int scale = xg_get_scale (f); top /= scale; left /= scale; @@ -4070,8 +4108,10 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, if (int_gtk_range_get_value (GTK_RANGE (wscroll)) != value) gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value); +#if ! GTK_CHECK_VERSION (3, 18, 0) else if (changed) gtk_adjustment_changed (adj); +#endif xg_ignore_gtk_scrollbar = 0; @@ -4108,7 +4148,9 @@ xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, gtk_adjustment_configure (adj, (gdouble) value, (gdouble) lower, (gdouble) upper, (gdouble) step_increment, (gdouble) page_increment, (gdouble) pagesize); +#if ! GTK_CHECK_VERSION (3, 18, 0) gtk_adjustment_changed (adj); +#endif unblock_input (); } } @@ -4129,8 +4171,13 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event) GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); GdkWindow *gwin; #ifdef HAVE_GTK3 +#if GTK_CHECK_VERSION (3, 20, 0) + GdkDevice *gdev + = gdk_seat_get_pointer (gdk_display_get_default_seat (gdpy)); +#else GdkDevice *gdev = gdk_device_manager_get_client_pointer (gdk_display_get_device_manager (gdpy)); +#endif gwin = gdk_device_get_window_at_position (gdev, NULL, NULL); #else gwin = gdk_display_get_window_at_pointer (gdpy, NULL, NULL); @@ -4603,7 +4650,11 @@ xg_make_tool_item (struct frame *f, if (wimage && text_image) gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0); +#if GTK_CHECK_VERSION (3, 20, 0) + gtk_widget_set_focus_on_click (wb, FALSE); +#else gtk_button_set_focus_on_click (GTK_BUTTON (wb), FALSE); +#endif gtk_button_set_relief (GTK_BUTTON (wb), GTK_RELIEF_NONE); gtk_container_add (GTK_CONTAINER (wb), vb); gtk_container_add (GTK_CONTAINER (weventbox), wb); @@ -5220,6 +5271,7 @@ xg_initialize (void) settings = gtk_settings_get_for_screen (gdk_display_get_default_screen (gdk_display_get_default ())); +#if ! GTK_CHECK_VERSION (3, 10, 0) /* Remove F10 as a menu accelerator, it does not mix well with Emacs key bindings. It doesn't seem to be any way to remove properties, so we set it to "" which in means "no key". */ @@ -5227,13 +5279,18 @@ xg_initialize (void) "gtk-menu-bar-accel", "", EMACS_CLASS); +#endif /* Make GTK text input widgets use Emacs style keybindings. This is Emacs after all. */ +#if GTK_CHECK_VERSION (3, 16, 0) + g_object_set (settings, "gtk-key-theme-name", "Emacs", NULL); +#else gtk_settings_set_string_property (settings, "gtk-key-theme-name", "Emacs", EMACS_CLASS); +#endif /* Make dialogs close on C-g. Since file dialog inherits from dialog, this works for them also. */ |