X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/6eab3936c71951e304f13b69ad2e835ddaf9f2f4..829733104db073f8abd67765eae162e7360281fa:/src/gtkutil.c diff --git a/src/gtkutil.c b/src/gtkutil.c index 6f1707894c..e791e6ac31 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1,13 +1,13 @@ /* Functions for creating and updating GTK widgets. -Copyright (C) 2003-2015 Free Software Foundation, Inc. +Copyright (C) 2003-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -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; @@ -252,35 +252,6 @@ xg_create_default_cursor (Display *dpy) return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR); } -static GdkPixbuf * -xg_get_pixbuf_from_pixmap (struct frame *f, Pixmap pix) -{ - int iunused; - GdkPixbuf *tmp_buf; - Window wunused; - unsigned int width, height, uunused; - XImage *xim; - - XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, - &width, &height, &uunused, &uunused); - - xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height, - ~0, XYPixmap); - if (!xim) return 0; - - tmp_buf = gdk_pixbuf_new_from_data ((guchar *) xim->data, - GDK_COLORSPACE_RGB, - FALSE, - xim->bitmap_unit, - width, - height, - xim->bytes_per_line, - NULL, - NULL); - XDestroyImage (xim); - return tmp_buf; -} - /* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */ static GdkPixbuf * @@ -288,46 +259,43 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, Pixmap pix, Pixmap mask) { - int width, height; - GdkPixbuf *icon_buf, *tmp_buf; - - tmp_buf = xg_get_pixbuf_from_pixmap (f, pix); - icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0); - g_object_unref (G_OBJECT (tmp_buf)); - - width = gdk_pixbuf_get_width (icon_buf); - height = gdk_pixbuf_get_height (icon_buf); + GdkPixbuf *icon_buf = 0; + int iunused; + Window wunused; + unsigned int width, height, depth, uunused; - if (mask) + if (FRAME_DISPLAY_INFO (f)->red_bits != 8) + return 0; + XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, + &width, &height, &uunused, &depth); + if (depth != 24) + return 0; + XImage *xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height, + ~0, XYPixmap); + if (xim) { - GdkPixbuf *mask_buf = xg_get_pixbuf_from_pixmap (f, mask); - guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); - guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf); - int rowstride = gdk_pixbuf_get_rowstride (icon_buf); - int mask_rowstride = gdk_pixbuf_get_rowstride (mask_buf); - int y; - - for (y = 0; y < height; ++y) - { - guchar *iconptr, *maskptr; - int x; - - iconptr = pixels + y * rowstride; - maskptr = mask_pixels + y * mask_rowstride; - - for (x = 0; x < width; ++x) - { - /* In a bitmap, RGB is either 255/255/255 or 0/0/0. Checking - just R is sufficient. */ - if (maskptr[0] == 0) - iconptr[3] = 0; /* 0, 1, 2 is R, G, B. 3 is alpha. */ - - iconptr += rowstride/width; - maskptr += mask_rowstride/width; - } - } + XImage *xmm = (! mask ? 0 + : XGetImage (FRAME_X_DISPLAY (f), mask, 0, 0, + width, height, ~0, XYPixmap)); + icon_buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); + if (icon_buf) + { + guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); + int rowjunkwidth = gdk_pixbuf_get_rowstride (icon_buf) - width * 4; + for (int y = 0; y < height; y++, pixels += rowjunkwidth) + for (int x = 0; x < width; x++) + { + unsigned long rgb = XGetPixel (xim, x, y); + *pixels++ = (rgb >> 16) & 255; + *pixels++ = (rgb >> 8) & 255; + *pixels++ = rgb & 255; + *pixels++ = xmm && !XGetPixel (xmm, x, y) ? 0 : 255; + } + } - g_object_unref (G_OBJECT (mask_buf)); + if (xmm) + XDestroyImage (xmm); + XDestroyImage (xim); } return icon_buf; @@ -380,10 +348,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 +485,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 +549,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 @@ -845,27 +815,43 @@ xg_clear_under_internal_border (struct frame *f) { if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) { +#ifndef USE_CAIRO GtkWidget *wfixed = f->output_data.x->edit_widget; gtk_widget_queue_draw (wfixed); gdk_window_process_all_updates (); - - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, +#endif + x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, + x_clear_area (f, 0, 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, + x_clear_area (f, 0, FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + x_clear_area (f, FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f), 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (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. @@ -901,8 +887,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); } } @@ -916,6 +900,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; @@ -926,6 +913,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 @@ -939,46 +935,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. @@ -1123,18 +1107,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; } @@ -1296,7 +1268,7 @@ xg_create_frame_widgets (struct frame *f) if (! g_signal_handler_find (G_OBJECT (gs), G_SIGNAL_MATCH_FUNC, 0, 0, 0, - G_CALLBACK (style_changed_cb), + (gpointer) G_CALLBACK (style_changed_cb), 0)) { g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name", @@ -1353,6 +1325,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 @@ -1362,7 +1335,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 (!). @@ -1388,7 +1363,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); @@ -1432,6 +1408,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, @@ -1819,14 +1800,10 @@ xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data) if (!!visible != !!toggle_on) { - g_signal_handlers_block_by_func (G_OBJECT (wtoggle), - G_CALLBACK (xg_toggle_visibility_cb), - gobject); + gpointer cb = (gpointer) G_CALLBACK (xg_toggle_visibility_cb); + g_signal_handlers_block_by_func (G_OBJECT (wtoggle), cb, gobject); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle), visible); - g_signal_handlers_unblock_by_func - (G_OBJECT (wtoggle), - G_CALLBACK (xg_toggle_visibility_cb), - gobject); + g_signal_handlers_unblock_by_func (G_OBJECT (wtoggle), cb, gobject); } x_gtk_show_hidden_files = visible; } @@ -1908,9 +1885,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); @@ -1935,8 +1910,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; @@ -2125,12 +2098,18 @@ xg_get_font (struct frame *f, const char *default_name) PangoWeight weight = pango_font_description_get_weight (desc); PangoStyle style = pango_font_description_get_style (desc); +#ifdef USE_CAIRO +#define FONT_TYPE_WANTED (Qftcr) +#else +#define FONT_TYPE_WANTED (Qxft) +#endif font = CALLN (Ffont_spec, QCname, build_string (name), QCsize, make_float (pango_units_to_double (size)), QCweight, XG_WEIGHT_TO_SYMBOL (weight), QCslant, XG_STYLE_TO_SYMBOL (style), - QCtype, Qxft); + QCtype, + FONT_TYPE_WANTED); pango_font_description_free (desc); dupstring (&x_last_font_name, name); @@ -3516,7 +3495,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; } @@ -3545,14 +3526,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. @@ -3751,14 +3732,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; @@ -3784,14 +3769,19 @@ xg_update_scrollbar_pos (struct frame *f, gtk_widget_show_all (wparent); gtk_widget_set_size_request (wscroll, width, height); } +#ifndef USE_CAIRO gtk_widget_queue_draw (wfixed); 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 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (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 @@ -3856,7 +3846,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, /* 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 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + x_clear_area (f, oldx, oldy, oldw, oldh); /* GTK does not redraw until the main loop is entered again, but @@ -4033,6 +4023,111 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event) return retval; } + +/*********************************************************************** + Printing + ***********************************************************************/ +#ifdef USE_CAIRO +static GtkPrintSettings *print_settings = NULL; +static GtkPageSetup *page_setup = NULL; + +void +xg_page_setup_dialog (void) +{ + GtkPageSetup *new_page_setup = NULL; + + if (print_settings == NULL) + print_settings = gtk_print_settings_new (); + new_page_setup = gtk_print_run_page_setup_dialog (NULL, page_setup, + print_settings); + if (page_setup) + g_object_unref (page_setup); + page_setup = new_page_setup; +} + +Lisp_Object +xg_get_page_setup (void) +{ + Lisp_Object orientation_symbol; + + if (page_setup == NULL) + page_setup = gtk_page_setup_new (); + + switch (gtk_page_setup_get_orientation (page_setup)) + { + case GTK_PAGE_ORIENTATION_PORTRAIT: + orientation_symbol = Qportrait; + break; + case GTK_PAGE_ORIENTATION_LANDSCAPE: + orientation_symbol = Qlandscape; + break; + case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: + orientation_symbol = Qreverse_portrait; + break; + case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: + orientation_symbol = Qreverse_landscape; + break; + default: + eassume (false); + } + + return listn (CONSTYPE_HEAP, 7, + Fcons (Qorientation, orientation_symbol), +#define MAKE_FLOAT_PAGE_SETUP(f) make_float (f (page_setup, GTK_UNIT_POINTS)) + Fcons (Qwidth, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_page_width)), + Fcons (Qheight, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_page_height)), + Fcons (Qleft_margin, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_left_margin)), + Fcons (Qright_margin, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_right_margin)), + Fcons (Qtop_margin, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_top_margin)), + Fcons (Qbottom_margin, + MAKE_FLOAT_PAGE_SETUP (gtk_page_setup_get_bottom_margin)) +#undef MAKE_FLOAT_PAGE_SETUP + ); +} + +static void +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)); + cairo_t *cr = gtk_print_context_get_cairo_context (context); + + x_cr_draw_frame (cr, f); +} + +void +xg_print_frames_dialog (Lisp_Object frames) +{ + GtkPrintOperation *print; + GtkPrintOperationResult res; + + print = gtk_print_operation_new (); + if (print_settings != NULL) + gtk_print_operation_set_print_settings (print, print_settings); + if (page_setup != NULL) + gtk_print_operation_set_default_page_setup (print, page_setup); + gtk_print_operation_set_n_pages (print, XINT (Flength (frames))); + g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), &frames); + res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, + NULL, NULL); + if (res == GTK_PRINT_OPERATION_RESULT_APPLY) + { + if (print_settings != NULL) + g_object_unref (print_settings); + print_settings = + g_object_ref (gtk_print_operation_get_print_settings (print)); + } + g_object_unref (print); +} + +#endif /* USE_CAIRO */ + /*********************************************************************** @@ -4320,8 +4415,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); @@ -4869,9 +4962,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 ();