X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/dddcc0e78452f2186c132823a33a174d2596ba33..d81b0e1326a1ce3b588fa1b812b868fa877d41da:/src/gtkutil.c diff --git a/src/gtkutil.c b/src/gtkutil.c index f111ea80ce..90683eba7b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -26,20 +26,18 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#include "dispextern.h" +#include "frame.h" +#include "systime.h" #include "xterm.h" #include "blockinput.h" -#include "syssignal.h" #include "window.h" -#include "buffer.h" #include "gtkutil.h" #include "termhooks.h" #include "keyboard.h" -#include "charset.h" #include "coding.h" -#include "font.h" #include -#include "xsettings.h" #ifdef HAVE_XFT #include @@ -187,7 +185,9 @@ xg_display_open (char *display_name, Display **dpy) { GdkDisplay *gdpy; + unrequest_sigio (); // See comment in x_display_ok, xterm.c. gdpy = gdk_display_open (display_name); + request_sigio (); if (!gdpy_def && gdpy) { gdpy_def = gdpy; @@ -380,10 +380,11 @@ xg_get_image_for_pixmap (struct frame *f, if (STRINGP (specified_file) && STRINGP (file = x_find_image_file (specified_file))) { + char *encoded_file = SSDATA (ENCODE_FILE (file)); if (! old_widget) - old_widget = GTK_IMAGE (gtk_image_new_from_file (SSDATA (file))); + old_widget = GTK_IMAGE (gtk_image_new_from_file (encoded_file)); else - gtk_image_set_from_file (old_widget, SSDATA (file)); + gtk_image_set_from_file (old_widget, encoded_file); return GTK_WIDGET (old_widget); } @@ -516,9 +517,12 @@ get_utf8_string (const char *str) if (cp) g_free (cp); len = strlen (str); - if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad) + ptrdiff_t alloc; + if (INT_MULTIPLY_WRAPV (nr_bad, 4, &alloc) + || INT_ADD_WRAPV (len + 1, alloc, &alloc) + || SIZE_MAX < alloc) memory_full (SIZE_MAX); - up = utf8_str = xmalloc (len + nr_bad * 4 + 1); + up = utf8_str = xmalloc (alloc); p = (unsigned char *)str; while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, @@ -577,12 +581,10 @@ xg_check_special_colors (struct frame *f, gtk_style_context_get_background_color (gsty, state, &col); sprintf (buf, "rgb:%04x/%04x/%04x", - (int)(col.red * 65535), - (int)(col.green * 65535), - (int)(col.blue * 65535)); - success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), - buf, color) - != 0); + (unsigned) (col.red * 65535), + (unsigned) (col.green * 65535), + (unsigned) (col.blue * 65535)); + success_p = x_parse_color (f, buf, color) != 0; #else GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); GdkColor *grgb = get_bg @@ -867,6 +869,21 @@ xg_clear_under_internal_border (struct frame *f) } } +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. @@ -902,8 +919,6 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) change_frame_size (f, width, height, 0, 1, 0, 1); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); - - do_pending_window_change (0); } } @@ -917,6 +932,9 @@ xg_frame_set_char_size (struct frame *f, int width, int height) int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); gint gwidth, gheight; + int totalheight + = pixelheight + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); + int totalwidth = pixelwidth + FRAME_TOOLBAR_WIDTH (f); if (FRAME_PIXEL_HEIGHT (f) == 0) return; @@ -927,6 +945,15 @@ 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. */ xg_clear_under_internal_border (f); + if (FRAME_VISIBLE_P (f)) + { + int scale = xg_get_gdk_scale (); + totalheight /= scale; + totalwidth /= scale; + } + + x_wm_set_size_hint (f, 0, 0); + /* Resize the top level widget so rows and columns remain constant. When the frame is fullheight and we only want to change the width @@ -940,46 +967,34 @@ xg_frame_set_char_size (struct frame *f, int width, int height) { frame_size_history_add (f, Qxg_frame_set_char_size_1, width, height, - list2 (make_number (gheight), - make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f) - + FRAME_MENUBAR_HEIGHT (f)))); + list2 (make_number (gheight), make_number (totalheight))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - gwidth, - pixelheight + FRAME_TOOLBAR_HEIGHT (f) - + FRAME_MENUBAR_HEIGHT (f)); + gwidth, totalheight); } else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f)) { frame_size_history_add (f, Qxg_frame_set_char_size_2, width, height, - list2 (make_number (gwidth), - make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)))); + list2 (make_number (gwidth), make_number (totalwidth))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - pixelwidth + FRAME_TOOLBAR_WIDTH (f), - gheight); + totalwidth, gheight); } - else { frame_size_history_add (f, Qxg_frame_set_char_size_3, width, height, - list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)), - make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f) - + FRAME_MENUBAR_HEIGHT (f)))); + list2 (make_number (totalwidth), make_number (totalheight))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - pixelwidth + FRAME_TOOLBAR_WIDTH (f), - pixelheight + FRAME_TOOLBAR_HEIGHT (f) - + FRAME_MENUBAR_HEIGHT (f)); + totalwidth, totalheight); fullscreen = Qnil; } SET_FRAME_GARBAGED (f); cancel_mouse_face (f); - x_wm_set_size_hint (f, 0, 0); /* We can not call change_frame_size for a mapped frame, we can not set pixel width/height either. The window manager may override our resize request, XMonad does this all the time. @@ -1124,18 +1139,6 @@ delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { -#ifdef HAVE_GTK3 - /* The event doesn't arrive in the normal event loop. Send event - here. */ - struct frame *f = user_data; - struct input_event ie; - - EVENT_INIT (ie); - ie.kind = DELETE_WINDOW_EVENT; - XSETFRAME (ie.frame_or_window, f); - kbd_buffer_store_event (&ie); -#endif - return TRUE; } @@ -1354,6 +1357,7 @@ 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 (); /* Don't set size hints during initialization; that apparently leads to a race condition. See the thread at @@ -1363,7 +1367,9 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) XSETFRAME (frame, f); fs_state = Fframe_parameter (frame, Qfullscreen); - if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) + if ((EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) && + (x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state) || + x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state_fullscreen))) { /* Don't set hints when maximized or fullscreen. Apparently KWin and Gtk3 don't get along and the frame shrinks (!). @@ -1389,7 +1395,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) hint_flags |= GDK_HINT_BASE_SIZE; /* Use one row/col here so base_height/width does not become zero. - Gtk+ and/or Unity on Ubuntu 12.04 can't handle it. */ + Gtk+ and/or Unity on Ubuntu 12.04 can't handle it. + Obviously this makes the row/col value displayed off by 1. */ base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 1) + FRAME_TOOLBAR_WIDTH (f); base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); @@ -1433,6 +1440,11 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) hint_flags |= GDK_HINT_USER_POS; } + size_hints.base_width /= scale; + size_hints.base_height /= scale; + size_hints.width_inc /= scale; + size_hints.height_inc /= scale; + if (hint_flags != f->output_data.x->hint_flags || memcmp (&size_hints, &f->output_data.x->size_hints, @@ -1909,9 +1921,7 @@ xg_get_file_with_chooser (struct frame *f, if (default_filename) { Lisp_Object file; - struct gcpro gcpro1; char *utf8_filename; - GCPRO1 (file); file = build_string (default_filename); @@ -1936,8 +1946,6 @@ xg_get_file_with_chooser (struct frame *f, gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filewin), cp); } } - - UNGCPRO; } *func = xg_get_file_name_from_chooser; @@ -3523,7 +3531,9 @@ update_theme_scrollbar_width (void) gtk_widget_destroy (wscroll); g_object_unref (G_OBJECT (wscroll)); w += 2*b; +#ifndef HAVE_GTK3 if (w < 16) w = 16; +#endif scroll_bar_width_for_theme = w; } @@ -3552,14 +3562,14 @@ update_theme_scrollbar_height (void) int xg_get_default_scrollbar_width (void) { - return scroll_bar_width_for_theme; + return scroll_bar_width_for_theme * xg_get_gdk_scale (); } int xg_get_default_scrollbar_height (void) { /* Apparently there's no default height for themes. */ - return scroll_bar_width_for_theme; + return scroll_bar_width_for_theme * xg_get_gdk_scale (); } /* Return the scrollbar id for X Window WID on display DPY. @@ -3758,14 +3768,18 @@ xg_update_scrollbar_pos (struct frame *f, int width, int height) { - GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); - if (wscroll) { GtkWidget *wfixed = f->output_data.x->edit_widget; GtkWidget *wparent = gtk_widget_get_parent (wscroll); gint msl; + int scale = xg_get_gdk_scale (); + + top /= scale; + left /= scale; + height /= scale; + left -= (scale - 1) * ((width / scale) >> 1); /* Clear out old position. */ int oldx = -1, oldy = -1, oldw, oldh; @@ -3796,11 +3810,14 @@ xg_update_scrollbar_pos (struct frame *f, gdk_window_process_all_updates (); #endif if (oldx != -1 && oldw > 0 && oldh > 0) - /* Clear under old scroll bar position. This must be done after - the gtk_widget_queue_draw and gdk_window_process_all_updates - above. */ - x_clear_area (f, - oldx, oldy, oldw, oldh); + { + /* Clear under old scroll bar position. This must be done after + the gtk_widget_queue_draw and gdk_window_process_all_updates + above. */ + oldw += (scale - 1) * oldw; + oldx -= (scale - 1) * oldw; + x_clear_area (f, oldx, oldy, oldw, oldh); + } /* GTK does not redraw until the main loop is entered again, but if there are no X events pending we will not enter it. So we sync @@ -4051,7 +4068,7 @@ static GtkPrintSettings *print_settings = NULL; static GtkPageSetup *page_setup = NULL; void -xg_page_setup_dialog () +xg_page_setup_dialog (void) { GtkPageSetup *new_page_setup = NULL; @@ -4065,7 +4082,7 @@ xg_page_setup_dialog () } Lisp_Object -xg_get_page_setup () +xg_get_page_setup (void) { Lisp_Object result, orientation_symbol; GtkPageOrientation orientation; @@ -4107,11 +4124,8 @@ xg_get_page_setup () } static void -draw_page (operation, context, page_nr, user_data) - GtkPrintOperation *operation; - GtkPrintContext *context; - gint page_nr; - gpointer user_data; +draw_page (GtkPrintOperation *operation, GtkPrintContext *context, + gint page_nr, gpointer user_data) { Lisp_Object frames = *((Lisp_Object *) user_data); struct frame *f = XFRAME (Fnth (make_number (page_nr), frames)); @@ -4121,8 +4135,7 @@ draw_page (operation, context, page_nr, user_data) } void -xg_print_frames_dialog (frames) - Lisp_Object frames; +xg_print_frames_dialog (Lisp_Object frames) { GtkPrintOperation *print; GtkPrintOperationResult res; @@ -4435,8 +4448,6 @@ find_rtl_image (struct frame *f, Lisp_Object image, Lisp_Object rtl) { int i; Lisp_Object file, rtl_name; - struct gcpro gcpro1, gcpro2; - GCPRO2 (file, rtl_name); rtl_name = Ffile_name_nondirectory (rtl); @@ -4984,9 +4995,23 @@ update_frame_tool_bar (struct frame *f) gtk_widget_show_all (x->toolbar_widget); if (xg_update_tool_bar_sizes (f)) { + int inhibit + = ((f->after_make_frame + && !f->tool_bar_resized + && (EQ (frame_inhibit_implied_resize, Qt) + || (CONSP (frame_inhibit_implied_resize) + && !NILP (Fmemq (Qtool_bar_lines, + frame_inhibit_implied_resize)))) + /* This will probably fail to DTRT in the + fullheight/-width cases. */ + && NILP (get_frame_param (f, Qfullscreen))) + ? 0 + : 2); + frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); + adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines); } + f->tool_bar_resized = f->tool_bar_redisplayed; } unblock_input ();