From: Yuuki Harano Date: Wed, 6 May 2020 03:55:04 +0000 (+0900) Subject: Make icons and titles work like on X X-Git-Tag: emacs-29.0.90~3806 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8669feb0c5c1b8fe3a9bf8489420e786c3367b2a;p=emacs.git Make icons and titles work like on X * pgtk-win.el (frame-title-format, icon-title-format): remove. * pgtkfns.c (pgtk_set_name_as_filename): remove. * pgtkfns.c (pgtk_set_name_internal): remove gtk_window_set_icon_name call. * pgtkfns.c (pgtk_set_name): change value of update_mode_lines. * pgtkfns.c (pgtk_explicitly_set_name): prefer the symbol to an immediate value. * pgtkfns.c (pgtk_implicitly_set_name): remove pgtk_set_name_as_filename call. * pgtkfns.c (x_set_icon_type, x_set_icon_name): re-port from X code. * pgtkfns.c (xg_set_icon, xg_set_icon_from_xpm_data): port from X code. * pgtkterm.c (pgtk_bitmap_icon, pgtk_text_icon, pgtk_create_terminal): port from X code. * pgtkterm.h: add function declarations. --- diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index f3239c6c1ad..4598ba007b6 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -281,10 +281,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (error "Cannot suspend Emacs while a PGTK GUI frame exists"))) -;; Set some options to be as Nextstep-like as possible. -(setq frame-title-format t - icon-title-format t) - (defvar pgtk-initialized nil "Non-nil if pure-GTK windowing has been initialized.") diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 9078a78e060..79c9aab1a22 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -50,7 +50,6 @@ static ptrdiff_t image_cache_refcount; static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); -static void pgtk_set_name_as_filename (struct frame *); static const char *pgtk_app_name = "Emacs"; @@ -253,58 +252,24 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) update_face_from_frame_parameter (f, Qcursor_color, arg); } - static void -x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +pgtk_set_name_internal (struct frame *f, Lisp_Object name) { - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); - PGTK_TRACE ("x_set_icon_name"); - - /* see if it's changed */ - if (STRINGP (arg)) + if (FRAME_GTK_WIDGET (f)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) - return; - } - else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) - return; + block_input (); + { + Lisp_Object encoded_name; - fset_icon_name (f, arg); + /* As ENCODE_UTF_8 may cause GC and relocation of string data, + we use it before x_encode_text that may return string data. */ + encoded_name = ENCODE_UTF_8 (name); - if (NILP (arg)) - { - if (!NILP (f->title)) - arg = f->title; - else - /* Explicit name and no icon-name -> explicit_name. */ - if (f->explicit_name) - arg = f->name; - else - { - /* No explicit name and no icon-name -> - name has to be rebuild from icon_title_format. */ - windows_or_buffers_changed = 67; - return; - } + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + SSDATA (encoded_name)); + } + unblock_input (); } - - gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA(arg)); -} - -static void -pgtk_set_name_internal (struct frame *f, Lisp_Object name) -{ - Lisp_Object encoded_name, encoded_icon_name; - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); - - encoded_name = ENCODE_UTF_8 (name); - gtk_window_set_title(GTK_WINDOW(widget), SSDATA (encoded_name)); - - if (!STRINGP (f->icon_name)) - encoded_icon_name = encoded_name; - else - encoded_icon_name = ENCODE_UTF_8 (f->icon_name); - gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA (encoded_icon_name)); } static void @@ -352,7 +317,7 @@ static void x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { PGTK_TRACE ("x_explicitly_set_name"); - pgtk_set_name (f, arg, 1); + pgtk_set_name (f, arg, true); } @@ -363,17 +328,7 @@ void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { PGTK_TRACE ("x_implicitly_set_name"); - - Lisp_Object frame_title = buffer_local_value - (Qframe_title_format, XWINDOW (f->selected_window)->contents); - Lisp_Object icon_title = buffer_local_value - (Qicon_title_format, XWINDOW (f->selected_window)->contents); - - if (FRAME_PGTK_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (icon_title, Qt)) - || EQ (frame_title, Qt))) - pgtk_set_name_as_filename (f); - else - pgtk_set_name (f, arg, 0); + pgtk_set_name (f, arg, false); } @@ -401,72 +356,6 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) } -static void -pgtk_set_name_as_filename (struct frame *f) -{ - GtkWidget *widget; - Lisp_Object name, filename; - Lisp_Object buf = XWINDOW (f->selected_window)->contents; - const char *title; - Lisp_Object encoded_name, encoded_filename; - const char *str; - PGTK_TRACE ("pgtk_set_name_as_filename"); - - if (f->explicit_name || ! NILP (f->title)) - return; - - block_input (); - filename = BVAR (XBUFFER (buf), filename); - name = BVAR (XBUFFER (buf), name); - - if (NILP (name)) - { - if (! NILP (filename)) - name = Ffile_name_nondirectory (filename); - else - name = build_string (pgtk_app_name); - } - - encoded_name = ENCODE_UTF_8 (name); - - widget = FRAME_GTK_OUTER_WIDGET (f); - - title = FRAME_ICONIFIED_P (f) ? gtk_window_get_icon_name(GTK_WINDOW(widget)) - : gtk_window_get_title(GTK_WINDOW(widget)); - - if (title && (! strcmp (title, SSDATA (encoded_name)))) - { - unblock_input (); - return; - } - - str = SSDATA (encoded_name); - if (str == NULL) str = "Bad coding"; - - if (FRAME_ICONIFIED_P (f)) - gtk_window_set_icon_name(GTK_WINDOW(widget), str); - else - { - const char *fstr; - - if (! NILP (filename)) - { - encoded_filename = ENCODE_UTF_8 (filename); - - fstr = SSDATA (encoded_filename); - if (fstr == NULL) fstr = ""; - } - else - fstr = ""; - - gtk_window_set_title(GTK_WINDOW(widget), str); - fset_name (f, name); - } - - unblock_input (); -} - - void pgtk_set_doc_edited (void) { @@ -665,26 +554,66 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva static void x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - /* This does not work if on Wayland, or if icon is defined in emacs.desktop - * even if on X11. - */ - GdkPixbuf *pixbuf; - if (NILP (arg) || EQ (arg, Qt)) - pixbuf = NULL; - else { - GError *err = NULL; - CHECK_STRING (arg); - pixbuf = gdk_pixbuf_new_from_file (SSDATA (arg), &err); - if (pixbuf == NULL) { - Lisp_Object msg = build_string (err->message); - g_error_free (err); - error ("%s", SSDATA (msg)); + bool result; + + if (STRINGP (arg)) + { + if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + return; } - } + else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) + return; - gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); - if (pixbuf != NULL) - g_object_unref (pixbuf); + block_input (); + if (NILP (arg)) + result = pgtk_text_icon (f, + SSDATA ((!NILP (f->icon_name) + ? f->icon_name + : f->name))); + else + result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg); + + if (result) + { + unblock_input (); + error ("No icon window available"); + } + + unblock_input (); +} + + +static void +x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + bool result; + + if (STRINGP (arg)) + { + if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + return; + } + else if (!NILP (arg) || NILP (oldval)) + return; + + fset_icon_name (f, arg); + + block_input (); + + result = pgtk_text_icon (f, + SSDATA ((!NILP (f->icon_name) + ? f->icon_name + : !NILP (f->title) + ? f->title + : f->name))); + + if (result) + { + unblock_input (); + error ("No icon window available"); + } + + unblock_input (); } /* This is the same as the xfns.c definition. */ @@ -800,6 +729,56 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old } } +/* Set icon from FILE for frame F. By using GTK functions the icon + may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */ + +bool +xg_set_icon (struct frame *f, Lisp_Object file) +{ + bool result = false; + Lisp_Object found; + + found = image_find_image_file (file); + + if (! NILP (found)) + { + GdkPixbuf *pixbuf; + GError *err = NULL; + char *filename = SSDATA (ENCODE_FILE (found)); + block_input (); + + pixbuf = gdk_pixbuf_new_from_file (filename, &err); + + if (pixbuf) + { + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + pixbuf); + g_object_unref (pixbuf); + + result = true; + } + else + g_error_free (err); + + unblock_input (); + } + + return result; +} + +bool +xg_set_icon_from_xpm_data (struct frame *f, const char **data) +{ + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data); + + if (!pixbuf) + return false; + + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); + g_object_unref (pixbuf); + return true; +} + static void pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 65d250b6def..2d1a990483f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2827,6 +2827,47 @@ pgtk_scroll_run (struct window *w, struct run *run) unblock_input (); } +/* Icons. */ + +/* Make the x-window of frame F use the gnu icon bitmap. */ + +static bool +pgtk_bitmap_icon (struct frame *f, Lisp_Object file) +{ + if (FRAME_GTK_WIDGET (f) == 0) + return true; + + if (STRINGP (file)) + { + /* Use gtk_window_set_icon_from_file () if available, + It's not restricted to bitmaps */ + if (xg_set_icon (f, file)) + return false; + + return true; + } + + if (xg_set_icon (f, xg_default_icon_file)) + { + return false; + } + + return true; +} + + +/* Make the x-window of frame F use a rectangle with text. + Use ICON_NAME as the text. */ + +bool +pgtk_text_icon (struct frame *f, const char *icon_name) +{ + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); + + return false; +} + /*********************************************************************** Starting and ending an update ***********************************************************************/ @@ -4620,6 +4661,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->query_frame_background_color = pgtk_query_frame_background_color; terminal->defined_color_hook = pgtk_defined_color; terminal->set_new_font_hook = pgtk_new_font; + terminal->set_bitmap_icon_hook = pgtk_bitmap_icon; terminal->implicit_set_name_hook = pgtk_implicitly_set_name; terminal->iconify_frame_hook = pgtk_iconify_frame; terminal->set_scroll_bar_default_width_hook = pgtk_set_scroll_bar_default_width; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index e7403184393..706198aa8a4 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -621,4 +621,9 @@ extern bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev); extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); +extern bool xg_set_icon (struct frame *, Lisp_Object); +extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); + +extern bool pgtk_text_icon (struct frame *f, const char *icon_name); + #endif /* HAVE_PGTK */