diff options
| author | Yuuki Harano | 2020-05-06 12:55:04 +0900 |
|---|---|---|
| committer | Jeff Walsh | 2020-11-24 12:24:39 +1100 |
| commit | 8669feb0c5c1b8fe3a9bf8489420e786c3367b2a (patch) | |
| tree | f10ae8d747eb386f29f616cb8787e5bdf99a50d5 /src | |
| parent | 5a72a07fa5bcec2ad5265284dfb2a5dec7485e7f (diff) | |
| download | emacs-8669feb0c5c1b8fe3a9bf8489420e786c3367b2a.tar.gz emacs-8669feb0c5c1b8fe3a9bf8489420e786c3367b2a.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/pgtkfns.c | 265 | ||||
| -rw-r--r-- | src/pgtkterm.c | 42 | ||||
| -rw-r--r-- | src/pgtkterm.h | 5 |
3 files changed, 169 insertions, 143 deletions
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; | |||
| 50 | 50 | ||
| 51 | static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); | 51 | static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); |
| 52 | static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); | 52 | static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); |
| 53 | static void pgtk_set_name_as_filename (struct frame *); | ||
| 54 | 53 | ||
| 55 | static const char *pgtk_app_name = "Emacs"; | 54 | static const char *pgtk_app_name = "Emacs"; |
| 56 | 55 | ||
| @@ -253,58 +252,24 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 253 | update_face_from_frame_parameter (f, Qcursor_color, arg); | 252 | update_face_from_frame_parameter (f, Qcursor_color, arg); |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | |||
| 257 | static void | 255 | static void |
| 258 | x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 256 | pgtk_set_name_internal (struct frame *f, Lisp_Object name) |
| 259 | { | 257 | { |
| 260 | GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); | 258 | if (FRAME_GTK_WIDGET (f)) |
| 261 | PGTK_TRACE ("x_set_icon_name"); | ||
| 262 | |||
| 263 | /* see if it's changed */ | ||
| 264 | if (STRINGP (arg)) | ||
| 265 | { | 259 | { |
| 266 | if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) | 260 | block_input (); |
| 267 | return; | 261 | { |
| 268 | } | 262 | Lisp_Object encoded_name; |
| 269 | else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) | ||
| 270 | return; | ||
| 271 | 263 | ||
| 272 | fset_icon_name (f, arg); | 264 | /* As ENCODE_UTF_8 may cause GC and relocation of string data, |
| 265 | we use it before x_encode_text that may return string data. */ | ||
| 266 | encoded_name = ENCODE_UTF_8 (name); | ||
| 273 | 267 | ||
| 274 | if (NILP (arg)) | 268 | gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), |
| 275 | { | 269 | SSDATA (encoded_name)); |
| 276 | if (!NILP (f->title)) | 270 | } |
| 277 | arg = f->title; | 271 | unblock_input (); |
| 278 | else | ||
| 279 | /* Explicit name and no icon-name -> explicit_name. */ | ||
| 280 | if (f->explicit_name) | ||
| 281 | arg = f->name; | ||
| 282 | else | ||
| 283 | { | ||
| 284 | /* No explicit name and no icon-name -> | ||
| 285 | name has to be rebuild from icon_title_format. */ | ||
| 286 | windows_or_buffers_changed = 67; | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | } | 272 | } |
| 290 | |||
| 291 | gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA(arg)); | ||
| 292 | } | ||
| 293 | |||
| 294 | static void | ||
| 295 | pgtk_set_name_internal (struct frame *f, Lisp_Object name) | ||
| 296 | { | ||
| 297 | Lisp_Object encoded_name, encoded_icon_name; | ||
| 298 | GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); | ||
| 299 | |||
| 300 | encoded_name = ENCODE_UTF_8 (name); | ||
| 301 | gtk_window_set_title(GTK_WINDOW(widget), SSDATA (encoded_name)); | ||
| 302 | |||
| 303 | if (!STRINGP (f->icon_name)) | ||
| 304 | encoded_icon_name = encoded_name; | ||
| 305 | else | ||
| 306 | encoded_icon_name = ENCODE_UTF_8 (f->icon_name); | ||
| 307 | gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA (encoded_icon_name)); | ||
| 308 | } | 273 | } |
| 309 | 274 | ||
| 310 | static void | 275 | static void |
| @@ -352,7 +317,7 @@ static void | |||
| 352 | x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 317 | x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 353 | { | 318 | { |
| 354 | PGTK_TRACE ("x_explicitly_set_name"); | 319 | PGTK_TRACE ("x_explicitly_set_name"); |
| 355 | pgtk_set_name (f, arg, 1); | 320 | pgtk_set_name (f, arg, true); |
| 356 | } | 321 | } |
| 357 | 322 | ||
| 358 | 323 | ||
| @@ -363,17 +328,7 @@ void | |||
| 363 | pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 328 | pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 364 | { | 329 | { |
| 365 | PGTK_TRACE ("x_implicitly_set_name"); | 330 | PGTK_TRACE ("x_implicitly_set_name"); |
| 366 | 331 | pgtk_set_name (f, arg, false); | |
| 367 | Lisp_Object frame_title = buffer_local_value | ||
| 368 | (Qframe_title_format, XWINDOW (f->selected_window)->contents); | ||
| 369 | Lisp_Object icon_title = buffer_local_value | ||
| 370 | (Qicon_title_format, XWINDOW (f->selected_window)->contents); | ||
| 371 | |||
| 372 | if (FRAME_PGTK_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (icon_title, Qt)) | ||
| 373 | || EQ (frame_title, Qt))) | ||
| 374 | pgtk_set_name_as_filename (f); | ||
| 375 | else | ||
| 376 | pgtk_set_name (f, arg, 0); | ||
| 377 | } | 332 | } |
| 378 | 333 | ||
| 379 | 334 | ||
| @@ -401,72 +356,6 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) | |||
| 401 | } | 356 | } |
| 402 | 357 | ||
| 403 | 358 | ||
| 404 | static void | ||
| 405 | pgtk_set_name_as_filename (struct frame *f) | ||
| 406 | { | ||
| 407 | GtkWidget *widget; | ||
| 408 | Lisp_Object name, filename; | ||
| 409 | Lisp_Object buf = XWINDOW (f->selected_window)->contents; | ||
| 410 | const char *title; | ||
| 411 | Lisp_Object encoded_name, encoded_filename; | ||
| 412 | const char *str; | ||
| 413 | PGTK_TRACE ("pgtk_set_name_as_filename"); | ||
| 414 | |||
| 415 | if (f->explicit_name || ! NILP (f->title)) | ||
| 416 | return; | ||
| 417 | |||
| 418 | block_input (); | ||
| 419 | filename = BVAR (XBUFFER (buf), filename); | ||
| 420 | name = BVAR (XBUFFER (buf), name); | ||
| 421 | |||
| 422 | if (NILP (name)) | ||
| 423 | { | ||
| 424 | if (! NILP (filename)) | ||
| 425 | name = Ffile_name_nondirectory (filename); | ||
| 426 | else | ||
| 427 | name = build_string (pgtk_app_name); | ||
| 428 | } | ||
| 429 | |||
| 430 | encoded_name = ENCODE_UTF_8 (name); | ||
| 431 | |||
| 432 | widget = FRAME_GTK_OUTER_WIDGET (f); | ||
| 433 | |||
| 434 | title = FRAME_ICONIFIED_P (f) ? gtk_window_get_icon_name(GTK_WINDOW(widget)) | ||
| 435 | : gtk_window_get_title(GTK_WINDOW(widget)); | ||
| 436 | |||
| 437 | if (title && (! strcmp (title, SSDATA (encoded_name)))) | ||
| 438 | { | ||
| 439 | unblock_input (); | ||
| 440 | return; | ||
| 441 | } | ||
| 442 | |||
| 443 | str = SSDATA (encoded_name); | ||
| 444 | if (str == NULL) str = "Bad coding"; | ||
| 445 | |||
| 446 | if (FRAME_ICONIFIED_P (f)) | ||
| 447 | gtk_window_set_icon_name(GTK_WINDOW(widget), str); | ||
| 448 | else | ||
| 449 | { | ||
| 450 | const char *fstr; | ||
| 451 | |||
| 452 | if (! NILP (filename)) | ||
| 453 | { | ||
| 454 | encoded_filename = ENCODE_UTF_8 (filename); | ||
| 455 | |||
| 456 | fstr = SSDATA (encoded_filename); | ||
| 457 | if (fstr == NULL) fstr = ""; | ||
| 458 | } | ||
| 459 | else | ||
| 460 | fstr = ""; | ||
| 461 | |||
| 462 | gtk_window_set_title(GTK_WINDOW(widget), str); | ||
| 463 | fset_name (f, name); | ||
| 464 | } | ||
| 465 | |||
| 466 | unblock_input (); | ||
| 467 | } | ||
| 468 | |||
| 469 | |||
| 470 | void | 359 | void |
| 471 | pgtk_set_doc_edited (void) | 360 | pgtk_set_doc_edited (void) |
| 472 | { | 361 | { |
| @@ -665,26 +554,66 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva | |||
| 665 | static void | 554 | static void |
| 666 | x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 555 | x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 667 | { | 556 | { |
| 668 | /* This does not work if on Wayland, or if icon is defined in emacs.desktop | 557 | bool result; |
| 669 | * even if on X11. | 558 | |
| 670 | */ | 559 | if (STRINGP (arg)) |
| 671 | GdkPixbuf *pixbuf; | 560 | { |
| 672 | if (NILP (arg) || EQ (arg, Qt)) | 561 | if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) |
| 673 | pixbuf = NULL; | 562 | return; |
| 674 | else { | ||
| 675 | GError *err = NULL; | ||
| 676 | CHECK_STRING (arg); | ||
| 677 | pixbuf = gdk_pixbuf_new_from_file (SSDATA (arg), &err); | ||
| 678 | if (pixbuf == NULL) { | ||
| 679 | Lisp_Object msg = build_string (err->message); | ||
| 680 | g_error_free (err); | ||
| 681 | error ("%s", SSDATA (msg)); | ||
| 682 | } | 563 | } |
| 683 | } | 564 | else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) |
| 565 | return; | ||
| 684 | 566 | ||
| 685 | gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); | 567 | block_input (); |
| 686 | if (pixbuf != NULL) | 568 | if (NILP (arg)) |
| 687 | g_object_unref (pixbuf); | 569 | result = pgtk_text_icon (f, |
| 570 | SSDATA ((!NILP (f->icon_name) | ||
| 571 | ? f->icon_name | ||
| 572 | : f->name))); | ||
| 573 | else | ||
| 574 | result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg); | ||
| 575 | |||
| 576 | if (result) | ||
| 577 | { | ||
| 578 | unblock_input (); | ||
| 579 | error ("No icon window available"); | ||
| 580 | } | ||
| 581 | |||
| 582 | unblock_input (); | ||
| 583 | } | ||
| 584 | |||
| 585 | |||
| 586 | static void | ||
| 587 | x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | ||
| 588 | { | ||
| 589 | bool result; | ||
| 590 | |||
| 591 | if (STRINGP (arg)) | ||
| 592 | { | ||
| 593 | if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) | ||
| 594 | return; | ||
| 595 | } | ||
| 596 | else if (!NILP (arg) || NILP (oldval)) | ||
| 597 | return; | ||
| 598 | |||
| 599 | fset_icon_name (f, arg); | ||
| 600 | |||
| 601 | block_input (); | ||
| 602 | |||
| 603 | result = pgtk_text_icon (f, | ||
| 604 | SSDATA ((!NILP (f->icon_name) | ||
| 605 | ? f->icon_name | ||
| 606 | : !NILP (f->title) | ||
| 607 | ? f->title | ||
| 608 | : f->name))); | ||
| 609 | |||
| 610 | if (result) | ||
| 611 | { | ||
| 612 | unblock_input (); | ||
| 613 | error ("No icon window available"); | ||
| 614 | } | ||
| 615 | |||
| 616 | unblock_input (); | ||
| 688 | } | 617 | } |
| 689 | 618 | ||
| 690 | /* This is the same as the xfns.c definition. */ | 619 | /* 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 | |||
| 800 | } | 729 | } |
| 801 | } | 730 | } |
| 802 | 731 | ||
| 732 | /* Set icon from FILE for frame F. By using GTK functions the icon | ||
| 733 | may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */ | ||
| 734 | |||
| 735 | bool | ||
| 736 | xg_set_icon (struct frame *f, Lisp_Object file) | ||
| 737 | { | ||
| 738 | bool result = false; | ||
| 739 | Lisp_Object found; | ||
| 740 | |||
| 741 | found = image_find_image_file (file); | ||
| 742 | |||
| 743 | if (! NILP (found)) | ||
| 744 | { | ||
| 745 | GdkPixbuf *pixbuf; | ||
| 746 | GError *err = NULL; | ||
| 747 | char *filename = SSDATA (ENCODE_FILE (found)); | ||
| 748 | block_input (); | ||
| 749 | |||
| 750 | pixbuf = gdk_pixbuf_new_from_file (filename, &err); | ||
| 751 | |||
| 752 | if (pixbuf) | ||
| 753 | { | ||
| 754 | gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), | ||
| 755 | pixbuf); | ||
| 756 | g_object_unref (pixbuf); | ||
| 757 | |||
| 758 | result = true; | ||
| 759 | } | ||
| 760 | else | ||
| 761 | g_error_free (err); | ||
| 762 | |||
| 763 | unblock_input (); | ||
| 764 | } | ||
| 765 | |||
| 766 | return result; | ||
| 767 | } | ||
| 768 | |||
| 769 | bool | ||
| 770 | xg_set_icon_from_xpm_data (struct frame *f, const char **data) | ||
| 771 | { | ||
| 772 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data); | ||
| 773 | |||
| 774 | if (!pixbuf) | ||
| 775 | return false; | ||
| 776 | |||
| 777 | gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); | ||
| 778 | g_object_unref (pixbuf); | ||
| 779 | return true; | ||
| 780 | } | ||
| 781 | |||
| 803 | static void | 782 | static void |
| 804 | pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) | 783 | pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) |
| 805 | { | 784 | { |
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) | |||
| 2827 | unblock_input (); | 2827 | unblock_input (); |
| 2828 | } | 2828 | } |
| 2829 | 2829 | ||
| 2830 | /* Icons. */ | ||
| 2831 | |||
| 2832 | /* Make the x-window of frame F use the gnu icon bitmap. */ | ||
| 2833 | |||
| 2834 | static bool | ||
| 2835 | pgtk_bitmap_icon (struct frame *f, Lisp_Object file) | ||
| 2836 | { | ||
| 2837 | if (FRAME_GTK_WIDGET (f) == 0) | ||
| 2838 | return true; | ||
| 2839 | |||
| 2840 | if (STRINGP (file)) | ||
| 2841 | { | ||
| 2842 | /* Use gtk_window_set_icon_from_file () if available, | ||
| 2843 | It's not restricted to bitmaps */ | ||
| 2844 | if (xg_set_icon (f, file)) | ||
| 2845 | return false; | ||
| 2846 | |||
| 2847 | return true; | ||
| 2848 | } | ||
| 2849 | |||
| 2850 | if (xg_set_icon (f, xg_default_icon_file)) | ||
| 2851 | { | ||
| 2852 | return false; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | return true; | ||
| 2856 | } | ||
| 2857 | |||
| 2858 | |||
| 2859 | /* Make the x-window of frame F use a rectangle with text. | ||
| 2860 | Use ICON_NAME as the text. */ | ||
| 2861 | |||
| 2862 | bool | ||
| 2863 | pgtk_text_icon (struct frame *f, const char *icon_name) | ||
| 2864 | { | ||
| 2865 | gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); | ||
| 2866 | gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); | ||
| 2867 | |||
| 2868 | return false; | ||
| 2869 | } | ||
| 2870 | |||
| 2830 | /*********************************************************************** | 2871 | /*********************************************************************** |
| 2831 | Starting and ending an update | 2872 | Starting and ending an update |
| 2832 | ***********************************************************************/ | 2873 | ***********************************************************************/ |
| @@ -4620,6 +4661,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) | |||
| 4620 | terminal->query_frame_background_color = pgtk_query_frame_background_color; | 4661 | terminal->query_frame_background_color = pgtk_query_frame_background_color; |
| 4621 | terminal->defined_color_hook = pgtk_defined_color; | 4662 | terminal->defined_color_hook = pgtk_defined_color; |
| 4622 | terminal->set_new_font_hook = pgtk_new_font; | 4663 | terminal->set_new_font_hook = pgtk_new_font; |
| 4664 | terminal->set_bitmap_icon_hook = pgtk_bitmap_icon; | ||
| 4623 | terminal->implicit_set_name_hook = pgtk_implicitly_set_name; | 4665 | terminal->implicit_set_name_hook = pgtk_implicitly_set_name; |
| 4624 | terminal->iconify_frame_hook = pgtk_iconify_frame; | 4666 | terminal->iconify_frame_hook = pgtk_iconify_frame; |
| 4625 | terminal->set_scroll_bar_default_width_hook = pgtk_set_scroll_bar_default_width; | 4667 | 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); | |||
| 621 | extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); | 621 | extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); |
| 622 | extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); | 622 | extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); |
| 623 | 623 | ||
| 624 | extern bool xg_set_icon (struct frame *, Lisp_Object); | ||
| 625 | extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); | ||
| 626 | |||
| 627 | extern bool pgtk_text_icon (struct frame *f, const char *icon_name); | ||
| 628 | |||
| 624 | #endif /* HAVE_PGTK */ | 629 | #endif /* HAVE_PGTK */ |