X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9fcd66daf819294168e86ea5eb50c241b1d9fa11..5932ffcd028af9fc70c9f8e731f2776a9753d81d:/src/gtkutil.c diff --git a/src/gtkutil.c b/src/gtkutil.c index a4b4331c03..88e6d30bd9 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 @@ -254,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 * @@ -290,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; @@ -382,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); } @@ -518,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, @@ -582,9 +552,7 @@ xg_check_special_colors (struct frame *f, (unsigned) (col.red * 65535), (unsigned) (col.green * 65535), (unsigned) (col.blue * 65535)); - success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), - buf, color) - != 0); + success_p = x_parse_color (f, buf, color) != 0; #else GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); GdkColor *grgb = get_bg @@ -919,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); } } @@ -954,6 +920,8 @@ xg_frame_set_char_size (struct frame *f, int width, int height) 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 @@ -967,41 +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 (totalheight))); + list2 (make_number (gheight), make_number (totalheight))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - gwidth, - totalheight); + 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 (totalwidth))); + list2 (make_number (gwidth), make_number (totalwidth))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - totalwidth, - gheight); + totalwidth, gheight); } else { frame_size_history_add (f, Qxg_frame_set_char_size_3, width, height, - list2 (make_number (totalwidth), - make_number (totalheight))); + list2 (make_number (totalwidth), make_number (totalheight))); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - totalwidth, - totalheight); + 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. @@ -1307,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", @@ -1374,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 (!). @@ -1400,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); @@ -1836,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; } @@ -1869,7 +1829,8 @@ xg_get_file_with_chooser (struct frame *f, { char msgbuf[1024]; - GtkWidget *filewin, *wtoggle, *wbox, *wmessage IF_LINT (= NULL); + GtkWidget *filewin, *wtoggle, *wbox; + GtkWidget *wmessage UNINIT; GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); GtkFileChooserAction action = (mustmatch_p ? GTK_FILE_CHOOSER_ACTION_OPEN : @@ -1925,9 +1886,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); @@ -1952,8 +1911,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; @@ -4092,43 +4049,46 @@ xg_page_setup_dialog (void) Lisp_Object xg_get_page_setup (void) { - Lisp_Object result, orientation_symbol; - GtkPageOrientation orientation; + Lisp_Object orientation_symbol; if (page_setup == NULL) page_setup = gtk_page_setup_new (); - result = list4 (Fcons (Qleft_margin, - make_float (gtk_page_setup_get_left_margin (page_setup, - GTK_UNIT_POINTS))), - Fcons (Qright_margin, - make_float (gtk_page_setup_get_right_margin (page_setup, - GTK_UNIT_POINTS))), - Fcons (Qtop_margin, - make_float (gtk_page_setup_get_top_margin (page_setup, - GTK_UNIT_POINTS))), - Fcons (Qbottom_margin, - make_float (gtk_page_setup_get_bottom_margin (page_setup, - GTK_UNIT_POINTS)))); - result = Fcons (Fcons (Qheight, - make_float (gtk_page_setup_get_page_height (page_setup, - GTK_UNIT_POINTS))), - result); - result = Fcons (Fcons (Qwidth, - make_float (gtk_page_setup_get_page_width (page_setup, - GTK_UNIT_POINTS))), - result); - orientation = gtk_page_setup_get_orientation (page_setup); - if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT) - orientation_symbol = Qportrait; - else if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) - orientation_symbol = Qlandscape; - else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT) - orientation_symbol = Qreverse_portrait; - else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE) - orientation_symbol = Qreverse_landscape; - result = Fcons (Fcons (Qorientation, orientation_symbol), result); - - return result; + + 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 @@ -4456,8 +4416,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); @@ -5005,9 +4963,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 ();