aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2016-03-08 08:51:38 +0100
committerMartin Rudalics2016-03-08 08:51:38 +0100
commit80864c2a04597d31ba453c9af69d35b15c4e1e24 (patch)
tree1cbfcba4d5bbb9008014c4a89df2b2aad4d891c2 /src
parent59c7a5d71145d88933a535e222bdf30105e7d382 (diff)
downloademacs-80864c2a04597d31ba453c9af69d35b15c4e1e24.tar.gz
emacs-80864c2a04597d31ba453c9af69d35b15c4e1e24.zip
Optionally reuse tooltip frames instead of deleting/recreating them.
* src/frame.c (tooltip_reuse_hidden_frame): New option. * src/w32fns.c (x_create_tip_frame): Remove argument TEXT. Fix handling of dividers. (x_hide_tip): New function. (Fx_show_tip): Try to reuse old tooltip frame when `tooltip-reuse-hidden-frame' is non-nil and frame parameters have not changed. Insert STRING here instead of passing it to x_create_tip_frame. Compute size of tooltip window with Fwindow_text_pixel_size. Obey Vw32_tooltip_extra_pixels when padding tooltip window. (Fx_hide_tip): Call x_hide_tip. (Vw32_tooltip_extra_pixels): New variable. * src/xdisp.c (Fwindow_text_pixel_size): Don't return negative y value. Fix doc-string. * src/xfns.c (x_create_tip_frame): Remove argument TEXT. Call make_frame with mini_p argument false. (x_hide_tip): New function. (Fx_show_tip): Try to reuse old tooltip frame when `tooltip-reuse-hidden-frame' is non-nil and frame parameters have not changed. Insert STRING here instead of passing it to x_create_tip_frame. Compute size of tooltip window with Fwindow_text_pixel_size. (Fx_hide_tip): Call x_hide_tip. * lisp/cus-start.el (tooltip-reuse-hidden-frame): Add customization entry.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c15
-rw-r--r--src/w32fns.c439
-rw-r--r--src/xdisp.c73
-rw-r--r--src/xfns.c439
4 files changed, 475 insertions, 491 deletions
diff --git a/src/frame.c b/src/frame.c
index fd9f3ce0203..d5364682f61 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -5262,6 +5262,21 @@ The function `frame--size-history' displays the value of this variable
5262in a more readable form. */); 5262in a more readable form. */);
5263 frame_size_history = Qnil; 5263 frame_size_history = Qnil;
5264 5264
5265 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
5266 doc: /* Non-nil means reuse hidden tooltip frames.
5267When this is nil, delete a tooltip frame when hiding the associated
5268tooltip. When this is non-nil, make the tooltip frame invisible only,
5269so it can be reused when the next tooltip is shown.
5270
5271Setting this to non-nil may drastically reduce the consing overhead
5272incurred by creating new tooltip frames. However, a value of non-nil
5273means also that intermittent changes of faces or `default-frame-alist'
5274are not applied when showing a tooltip in a reused frame.
5275
5276This variable is effective only with the X toolkit (and there only when
5277Gtk+ tooltips are not used) and on Windows. */);
5278 tooltip_reuse_hidden_frame = false;
5279
5265 staticpro (&Vframe_list); 5280 staticpro (&Vframe_list);
5266 5281
5267 defsubr (&Sframep); 5282 defsubr (&Sframep);
diff --git a/src/w32fns.c b/src/w32fns.c
index 0fe6a6fd2b3..568a45a3114 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -6422,8 +6422,6 @@ no value of TYPE (always string in the MS Windows case). */)
6422 Tool tips 6422 Tool tips
6423 ***********************************************************************/ 6423 ***********************************************************************/
6424 6424
6425static Lisp_Object x_create_tip_frame (struct w32_display_info *,
6426 Lisp_Object, Lisp_Object);
6427static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, 6425static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
6428 Lisp_Object, int, int, int *, int *); 6426 Lisp_Object, int, int, int *, int *);
6429 6427
@@ -6458,8 +6456,7 @@ unwind_create_tip_frame (Lisp_Object frame)
6458 6456
6459 6457
6460/* Create a frame for a tooltip on the display described by DPYINFO. 6458/* Create a frame for a tooltip on the display described by DPYINFO.
6461 PARMS is a list of frame parameters. TEXT is the string to 6459 PARMS is a list of frame parameters. Value is the frame.
6462 display in the tip frame. Value is the frame.
6463 6460
6464 Note that functions called here, esp. x_default_parameter can 6461 Note that functions called here, esp. x_default_parameter can
6465 signal errors, for instance when a specified color name is 6462 signal errors, for instance when a specified color name is
@@ -6467,8 +6464,7 @@ unwind_create_tip_frame (Lisp_Object frame)
6467 when this happens. */ 6464 when this happens. */
6468 6465
6469static Lisp_Object 6466static Lisp_Object
6470x_create_tip_frame (struct w32_display_info *dpyinfo, 6467x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6471 Lisp_Object parms, Lisp_Object text)
6472{ 6468{
6473 struct frame *f; 6469 struct frame *f;
6474 Lisp_Object frame; 6470 Lisp_Object frame;
@@ -6477,8 +6473,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6477 ptrdiff_t count = SPECPDL_INDEX (); 6473 ptrdiff_t count = SPECPDL_INDEX ();
6478 struct kboard *kb; 6474 struct kboard *kb;
6479 bool face_change_before = face_change; 6475 bool face_change_before = face_change;
6480 Lisp_Object buffer;
6481 struct buffer *old_buffer;
6482 int x_width = 0, x_height = 0; 6476 int x_width = 0, x_height = 0;
6483 6477
6484 /* Use this general default value to start with until we know if 6478 /* Use this general default value to start with until we know if
@@ -6502,23 +6496,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6502 frame = Qnil; 6496 frame = Qnil;
6503 /* Make a frame without minibuffer nor mode-line. */ 6497 /* Make a frame without minibuffer nor mode-line. */
6504 f = make_frame (false); 6498 f = make_frame (false);
6505 f->wants_modeline = 0; 6499 f->wants_modeline = false;
6506 XSETFRAME (frame, f); 6500 XSETFRAME (frame, f);
6507 6501
6508 AUTO_STRING (tip, " *tip*");
6509 buffer = Fget_buffer_create (tip);
6510 /* Use set_window_buffer instead of Fset_window_buffer (see
6511 discussion of bug#11984, bug#12025, bug#12026). */
6512 set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
6513 old_buffer = current_buffer;
6514 set_buffer_internal_1 (XBUFFER (buffer));
6515 bset_truncate_lines (current_buffer, Qnil);
6516 specbind (Qinhibit_read_only, Qt);
6517 specbind (Qinhibit_modification_hooks, Qt);
6518 Ferase_buffer ();
6519 Finsert (1, &text);
6520 set_buffer_internal_1 (old_buffer);
6521
6522 record_unwind_protect (unwind_create_tip_frame, frame); 6502 record_unwind_protect (unwind_create_tip_frame, frame);
6523 6503
6524 /* By setting the output method, we're essentially saying that 6504 /* By setting the output method, we're essentially saying that
@@ -6552,7 +6532,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6552 { 6532 {
6553 fset_name (f, name); 6533 fset_name (f, name);
6554 f->explicit_name = true; 6534 f->explicit_name = true;
6555 /* use the frame's title when getting resources for this frame. */ 6535 /* Use the frame's title when getting resources for this frame. */
6556 specbind (Qx_resource_name, name); 6536 specbind (Qx_resource_name, name);
6557 } 6537 }
6558 6538
@@ -6582,14 +6562,10 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6582 parms = Fcons (Fcons (Qinternal_border_width, value), 6562 parms = Fcons (Fcons (Qinternal_border_width, value),
6583 parms); 6563 parms);
6584 } 6564 }
6565
6585 x_default_parameter (f, parms, Qinternal_border_width, make_number (1), 6566 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
6586 "internalBorderWidth", "internalBorderWidth", 6567 "internalBorderWidth", "internalBorderWidth",
6587 RES_TYPE_NUMBER); 6568 RES_TYPE_NUMBER);
6588 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
6589 NULL, NULL, RES_TYPE_NUMBER);
6590 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
6591 NULL, NULL, RES_TYPE_NUMBER);
6592
6593 /* Also do the stuff which must be set before the window exists. */ 6569 /* Also do the stuff which must be set before the window exists. */
6594 x_default_parameter (f, parms, Qforeground_color, build_string ("black"), 6570 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
6595 "foreground", "Foreground", RES_TYPE_STRING); 6571 "foreground", "Foreground", RES_TYPE_STRING);
@@ -6616,6 +6592,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6616 f->fringe_cols = 0; 6592 f->fringe_cols = 0;
6617 f->left_fringe_width = 0; 6593 f->left_fringe_width = 0;
6618 f->right_fringe_width = 0; 6594 f->right_fringe_width = 0;
6595 /* No dividers on tip frame. */
6596 f->right_divider_width = 0;
6597 f->bottom_divider_width = 0;
6619 6598
6620 block_input (); 6599 block_input ();
6621 my_create_tip_window (f); 6600 my_create_tip_window (f);
@@ -6642,7 +6621,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6642 SET_FRAME_LINES (f, 0); 6621 SET_FRAME_LINES (f, 0);
6643 adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), 6622 adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
6644 height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame); 6623 height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
6645
6646 /* Add `tooltip' frame parameter's default value. */ 6624 /* Add `tooltip' frame parameter's default value. */
6647 if (NILP (Fframe_parameter (frame, Qtooltip))) 6625 if (NILP (Fframe_parameter (frame, Qtooltip)))
6648 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); 6626 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
@@ -6660,8 +6638,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
6660 Lisp_Object fg = Fframe_parameter (frame, Qforeground_color); 6638 Lisp_Object fg = Fframe_parameter (frame, Qforeground_color);
6661 Lisp_Object colors = Qnil; 6639 Lisp_Object colors = Qnil;
6662 6640
6663 /* Set tip_frame here, so that */
6664 tip_frame = frame;
6665 call2 (Qface_set_after_frame_default, frame, Qnil); 6641 call2 (Qface_set_after_frame_default, frame, Qnil);
6666 6642
6667 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) 6643 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
@@ -6793,6 +6769,48 @@ compute_tip_xy (struct frame *f,
6793 *root_x = min_x; 6769 *root_x = min_x;
6794} 6770}
6795 6771
6772/* Hide tooltip. Delete its frame if DELETE is true. */
6773static Lisp_Object
6774x_hide_tip (bool delete)
6775{
6776 if (!NILP (tip_timer))
6777 {
6778 call1 (Qcancel_timer, tip_timer);
6779 tip_timer = Qnil;
6780 }
6781
6782 if (NILP (tip_frame)
6783 || (!delete && FRAMEP (tip_frame)
6784 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
6785 return Qnil;
6786 else
6787 {
6788 ptrdiff_t count;
6789 Lisp_Object was_open = Qnil;
6790
6791 count = SPECPDL_INDEX ();
6792 specbind (Qinhibit_redisplay, Qt);
6793 specbind (Qinhibit_quit, Qt);
6794
6795 if (FRAMEP (tip_frame))
6796 {
6797 if (delete)
6798 {
6799 delete_frame (tip_frame, Qnil);
6800 tip_frame = Qnil;
6801 }
6802 else
6803 x_make_frame_invisible (XFRAME (tip_frame));
6804
6805 was_open = Qt;
6806 }
6807 else
6808 tip_frame = Qnil;
6809
6810 return unbind_to (count, was_open);
6811 }
6812}
6813
6796 6814
6797DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, 6815DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
6798 doc: /* Show STRING in a \"tooltip\" window on frame FRAME. 6816 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
@@ -6826,15 +6844,16 @@ A tooltip's maximum size is specified by `x-max-tooltip-size'.
6826Text larger than the specified size is clipped. */) 6844Text larger than the specified size is clipped. */)
6827 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) 6845 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
6828{ 6846{
6829 struct frame *f; 6847 struct frame *f, *tip_f;
6830 struct window *w; 6848 struct window *w;
6831 int root_x, root_y; 6849 int root_x, root_y;
6832 struct buffer *old_buffer; 6850 struct buffer *old_buffer;
6833 struct text_pos pos; 6851 struct text_pos pos;
6834 int i, width, height; 6852 int i, width, height;
6835 bool seen_reversed_p;
6836 int old_windows_or_buffers_changed = windows_or_buffers_changed; 6853 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6837 ptrdiff_t count = SPECPDL_INDEX (); 6854 ptrdiff_t count = SPECPDL_INDEX ();
6855 ptrdiff_t count_1;
6856 Lisp_Object window, size;
6838 6857
6839 specbind (Qinhibit_redisplay, Qt); 6858 specbind (Qinhibit_redisplay, Qt);
6840 6859
@@ -6858,91 +6877,155 @@ Text larger than the specified size is clipped. */)
6858 if (NILP (last_show_tip_args)) 6877 if (NILP (last_show_tip_args))
6859 last_show_tip_args = Fmake_vector (make_number (3), Qnil); 6878 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
6860 6879
6861 if (!NILP (tip_frame)) 6880 if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
6862 { 6881 {
6863 Lisp_Object last_string = AREF (last_show_tip_args, 0); 6882 Lisp_Object last_string = AREF (last_show_tip_args, 0);
6864 Lisp_Object last_frame = AREF (last_show_tip_args, 1); 6883 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
6865 Lisp_Object last_parms = AREF (last_show_tip_args, 2); 6884 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
6866 6885
6867 if (EQ (frame, last_frame) 6886 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
6868 && !NILP (Fequal (last_string, string)) 6887 && EQ (frame, last_frame)
6888 && !NILP (Fequal_including_properties (last_string, string))
6869 && !NILP (Fequal (last_parms, parms))) 6889 && !NILP (Fequal (last_parms, parms)))
6870 { 6890 {
6871 struct frame *f = XFRAME (tip_frame);
6872
6873 /* Only DX and DY have changed. */ 6891 /* Only DX and DY have changed. */
6892 tip_f = XFRAME (tip_frame);
6874 if (!NILP (tip_timer)) 6893 if (!NILP (tip_timer))
6875 { 6894 {
6876 Lisp_Object timer = tip_timer; 6895 Lisp_Object timer = tip_timer;
6896
6877 tip_timer = Qnil; 6897 tip_timer = Qnil;
6878 call1 (Qcancel_timer, timer); 6898 call1 (Qcancel_timer, timer);
6879 } 6899 }
6880 6900
6881 block_input (); 6901 block_input ();
6882 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f), 6902 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
6883 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y); 6903 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
6884 6904
6885 /* Put tooltip in topmost group and in position. */ 6905 /* Put tooltip in topmost group and in position. */
6886 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST, 6906 SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
6887 root_x, root_y, 0, 0, 6907 root_x, root_y, 0, 0,
6888 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); 6908 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
6889 6909
6890 /* Ensure tooltip is on top of other topmost windows (eg menus). */ 6910 /* Ensure tooltip is on top of other topmost windows (eg menus). */
6891 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP, 6911 SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
6892 0, 0, 0, 0, 6912 0, 0, 0, 0,
6893 SWP_NOMOVE | SWP_NOSIZE 6913 SWP_NOMOVE | SWP_NOSIZE
6894 | SWP_NOACTIVATE | SWP_NOOWNERZORDER); 6914 | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
6895 6915
6916 /* Let redisplay know that we have made the frame visible already. */
6917 SET_FRAME_VISIBLE (tip_f, 1);
6918 ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
6896 unblock_input (); 6919 unblock_input ();
6920
6897 goto start_timer; 6921 goto start_timer;
6898 } 6922 }
6899 } 6923 else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
6924 {
6925 bool delete = false;
6926 Lisp_Object tail, elt, parm, last;
6900 6927
6901 /* Hide a previous tip, if any. */ 6928 /* Check if every parameter in PARMS has the same value in
6902 Fx_hide_tip (); 6929 last_parms. This may destruct last_parms which, however,
6930 will be recreated below. */
6931 for (tail = parms; CONSP (tail); tail = XCDR (tail))
6932 {
6933 elt = XCAR (tail);
6934 parm = Fcar (elt);
6935 /* The left, top, right and bottom parameters are handled
6936 by compute_tip_xy so they can be ignored here. */
6937 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
6938 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
6939 {
6940 last = Fassq (parm, last_parms);
6941 if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
6942 {
6943 /* We lost, delete the old tooltip. */
6944 delete = true;
6945 break;
6946 }
6947 else
6948 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6949 }
6950 else
6951 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6952 }
6953
6954 /* Now check if there's a parameter left in last_parms with a
6955 non-nil value. */
6956 for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
6957 {
6958 elt = XCAR (tail);
6959 parm = Fcar (elt);
6960 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
6961 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
6962 {
6963 /* We lost, delete the old tooltip. */
6964 delete = true;
6965 break;
6966 }
6967 }
6968
6969 x_hide_tip (delete);
6970 }
6971 else
6972 x_hide_tip (true);
6973 }
6974 else
6975 x_hide_tip (true);
6903 6976
6904 ASET (last_show_tip_args, 0, string); 6977 ASET (last_show_tip_args, 0, string);
6905 ASET (last_show_tip_args, 1, frame); 6978 ASET (last_show_tip_args, 1, frame);
6906 ASET (last_show_tip_args, 2, parms); 6979 ASET (last_show_tip_args, 2, parms);
6907 6980
6908 /* Add default values to frame parameters. */
6909 if (NILP (Fassq (Qname, parms)))
6910 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
6911 if (NILP (Fassq (Qinternal_border_width, parms)))
6912 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
6913 if (NILP (Fassq (Qright_divider_width, parms)))
6914 parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms);
6915 if (NILP (Fassq (Qbottom_divider_width, parms)))
6916 parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms);
6917 if (NILP (Fassq (Qborder_width, parms)))
6918 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
6919 if (NILP (Fassq (Qborder_color, parms)))
6920 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
6921 if (NILP (Fassq (Qbackground_color, parms)))
6922 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
6923 parms);
6924
6925 /* Block input until the tip has been fully drawn, to avoid crashes 6981 /* Block input until the tip has been fully drawn, to avoid crashes
6926 when drawing tips in menus. */ 6982 when drawing tips in menus. */
6927 block_input (); 6983 block_input ();
6928 6984
6929 /* Create a frame for the tooltip, and record it in the global 6985 if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
6930 variable tip_frame. */ 6986 {
6931 frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string); 6987 /* Add default values to frame parameters. */
6932 f = XFRAME (frame); 6988 if (NILP (Fassq (Qname, parms)))
6989 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
6990 if (NILP (Fassq (Qinternal_border_width, parms)))
6991 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
6992 if (NILP (Fassq (Qborder_width, parms)))
6993 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
6994 if (NILP (Fassq (Qborder_color, parms)))
6995 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
6996 if (NILP (Fassq (Qbackground_color, parms)))
6997 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
6998 parms);
6999
7000 /* Create a frame for the tooltip, and record it in the global
7001 variable tip_frame. */
7002 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
7003 {
7004 /* Creating the tip frame failed. */
7005 unblock_input ();
7006 return unbind_to (count, Qnil);
7007 }
7008 }
7009
7010 tip_f = XFRAME (tip_frame);
7011 window = FRAME_ROOT_WINDOW (tip_f);
7012 AUTO_STRING (tip, " *tip*");
7013 set_window_buffer (window, Fget_buffer_create (tip), false, false);
7014 w = XWINDOW (window);
7015 w->pseudo_window_p = true;
6933 7016
6934 /* Set up the frame's root window. */ 7017 /* Set up the frame's root window. Note: The following code does not
6935 w = XWINDOW (FRAME_ROOT_WINDOW (f)); 7018 try to size the window or its frame correctly. Its only purpose is
7019 to make the subsequent text size calculations work. The right
7020 sizes should get installed when the toolkit gets back to us. */
6936 w->left_col = 0; 7021 w->left_col = 0;
6937 w->top_line = 0; 7022 w->top_line = 0;
6938 w->pixel_left = 0; 7023 w->pixel_left = 0;
6939 w->pixel_top = 0; 7024 w->pixel_top = 0;
6940 7025
6941 if (CONSP (Vx_max_tooltip_size) 7026 if (CONSP (Vx_max_tooltip_size)
6942 && INTEGERP (XCAR (Vx_max_tooltip_size)) 7027 && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
6943 && XINT (XCAR (Vx_max_tooltip_size)) > 0 7028 && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
6944 && INTEGERP (XCDR (Vx_max_tooltip_size))
6945 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
6946 { 7029 {
6947 w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size)); 7030 w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
6948 w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size)); 7031 w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
@@ -6953,164 +7036,71 @@ Text larger than the specified size is clipped. */)
6953 w->total_lines = 40; 7036 w->total_lines = 40;
6954 } 7037 }
6955 7038
6956 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f); 7039 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
6957 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f); 7040 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
6958 7041 FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
6959 FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w); 7042 adjust_frame_glyphs (tip_f);
6960 adjust_frame_glyphs (f);
6961 w->pseudo_window_p = true;
6962 7043
6963 /* Display the tooltip text in a temporary buffer. */ 7044 /* Insert STRING into the root window's buffer and fit the frame to
7045 the buffer. */
7046 count_1 = SPECPDL_INDEX ();
6964 old_buffer = current_buffer; 7047 old_buffer = current_buffer;
6965 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents)); 7048 set_buffer_internal_1 (XBUFFER (w->contents));
6966 bset_truncate_lines (current_buffer, Qnil); 7049 bset_truncate_lines (current_buffer, Qnil);
7050 specbind (Qinhibit_read_only, Qt);
7051 specbind (Qinhibit_modification_hooks, Qt);
7052 specbind (Qinhibit_point_motion_hooks, Qt);
7053 Ferase_buffer ();
7054 Finsert (1, &string);
6967 clear_glyph_matrix (w->desired_matrix); 7055 clear_glyph_matrix (w->desired_matrix);
6968 clear_glyph_matrix (w->current_matrix); 7056 clear_glyph_matrix (w->current_matrix);
6969 SET_TEXT_POS (pos, BEGV, BEGV_BYTE); 7057 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
6970 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); 7058 try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
6971 7059 /* Calculate size of tooltip window. */
6972 /* Compute width and height of the tooltip. */ 7060 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
6973 width = height = 0; 7061 make_number (w->pixel_height), Qnil);
6974 seen_reversed_p = false; 7062 /* Add the frame's internal border to calculated size. */
6975 for (i = 0; i < w->desired_matrix->nrows; ++i) 7063 width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6976 { 7064 height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6977 struct glyph_row *row = &w->desired_matrix->rows[i]; 7065 /* Calculate position of tooltip frame. */
6978 struct glyph *last; 7066 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
6979 int row_width; 7067
6980 7068 /* Show tooltip frame. */
6981 /* Stop at the first empty row at the end. */
6982 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
6983 break;
6984
6985 /* Let the row go over the full width of the frame. */
6986 row->full_width_p = true;
6987
6988 row_width = row->pixel_width;
6989 if (row->used[TEXT_AREA])
6990 {
6991 if (!row->reversed_p)
6992 {
6993 /* There's a glyph at the end of rows that is used to
6994 place the cursor there. Don't include the width of
6995 this glyph. */
6996 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
6997 if (NILP (last->object))
6998 row_width -= last->pixel_width;
6999 }
7000 else
7001 {
7002 /* There could be a stretch glyph at the beginning of R2L
7003 rows that is produced by extend_face_to_end_of_line.
7004 Don't count that glyph. */
7005 struct glyph *g = row->glyphs[TEXT_AREA];
7006
7007 if (g->type == STRETCH_GLYPH && NILP (g->object))
7008 {
7009 row_width -= g->pixel_width;
7010 seen_reversed_p = true;
7011 }
7012 }
7013 }
7014
7015 height += row->height;
7016 width = max (width, row_width);
7017 }
7018
7019 /* If we've seen partial-length R2L rows, we need to re-adjust the
7020 tool-tip frame width and redisplay it again, to avoid over-wide
7021 tips due to the stretch glyph that extends R2L lines to full
7022 width of the frame. */
7023 if (seen_reversed_p)
7024 {
7025 /* PXW: Why do we do the pixel-to-cols conversion only if
7026 seen_reversed_p holds? Don't we have to set other fields of
7027 the window/frame structure?
7028
7029 w->total_cols and FRAME_TOTAL_COLS want the width in columns,
7030 not in pixels. */
7031 w->pixel_width = width;
7032 width /= WINDOW_FRAME_COLUMN_WIDTH (w);
7033 w->total_cols = width;
7034 FRAME_TOTAL_COLS (f) = width;
7035 SET_FRAME_WIDTH (f, width);
7036 adjust_frame_glyphs (f);
7037 w->pseudo_window_p = 1;
7038 clear_glyph_matrix (w->desired_matrix);
7039 clear_glyph_matrix (w->current_matrix);
7040 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
7041 width = height = 0;
7042 /* Recompute width and height of the tooltip. */
7043 for (i = 0; i < w->desired_matrix->nrows; ++i)
7044 {
7045 struct glyph_row *row = &w->desired_matrix->rows[i];
7046 struct glyph *last;
7047 int row_width;
7048
7049 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
7050 break;
7051 row->full_width_p = true;
7052 row_width = row->pixel_width;
7053 if (row->used[TEXT_AREA] && !row->reversed_p)
7054 {
7055 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
7056 if (NILP (last->object))
7057 row_width -= last->pixel_width;
7058 }
7059
7060 height += row->height;
7061 width = max (width, row_width);
7062 }
7063 }
7064
7065 /* Add the frame's internal border to the width and height the w32
7066 window should have. */
7067 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
7068 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
7069
7070 /* Move the tooltip window where the mouse pointer is. Resize and
7071 show it.
7072
7073 PXW: This should use the frame's pixel coordinates. */
7074 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
7075
7076 { 7069 {
7077 /* Adjust Window size to take border into account. */
7078 RECT rect; 7070 RECT rect;
7071 int pad = (NUMBERP (Vw32_tooltip_extra_pixels)
7072 ? max (0, XINT (Vw32_tooltip_extra_pixels))
7073 : FRAME_COLUMN_WIDTH (tip_f));
7074
7079 rect.left = rect.top = 0; 7075 rect.left = rect.top = 0;
7080 rect.right = width; 7076 rect.right = width;
7081 rect.bottom = height; 7077 rect.bottom = height;
7082 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false); 7078 AdjustWindowRect (&rect, tip_f->output_data.w32->dwStyle,
7083 7079 FRAME_EXTERNAL_MENU_BAR (tip_f));
7084 /* Position and size tooltip, and put it in the topmost group. 7080
7085 The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a 7081 /* Position and size tooltip and put it in the topmost group. */
7086 peculiarity of w32 display: without it, some fonts cause the 7082 SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
7087 last character of the tip to be truncated or wrapped around to
7088 the next line. */
7089 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
7090 root_x, root_y, 7083 root_x, root_y,
7091 rect.right - rect.left + FRAME_COLUMN_WIDTH (f), 7084 rect.right - rect.left + pad,
7092 rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER); 7085 rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER);
7093 7086
7094 /* Ensure tooltip is on top of other topmost windows (eg menus). */ 7087 /* Ensure tooltip is on top of other topmost windows (eg menus). */
7095 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP, 7088 SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
7096 0, 0, 0, 0, 7089 0, 0, 0, 0,
7097 SWP_NOMOVE | SWP_NOSIZE 7090 SWP_NOMOVE | SWP_NOSIZE
7098 | SWP_NOACTIVATE | SWP_NOOWNERZORDER); 7091 | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
7099 7092
7100 /* Let redisplay know that we have made the frame visible already. */ 7093 /* Let redisplay know that we have made the frame visible already. */
7101 SET_FRAME_VISIBLE (f, 1); 7094 SET_FRAME_VISIBLE (tip_f, 1);
7102 7095
7103 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE); 7096 ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
7104 } 7097 }
7105 7098
7106 /* Draw into the window. */
7107 w->must_be_updated_p = true; 7099 w->must_be_updated_p = true;
7108 update_single_window (w); 7100 update_single_window (w);
7109
7110 unblock_input ();
7111
7112 /* Restore original current buffer. */
7113 set_buffer_internal_1 (old_buffer); 7101 set_buffer_internal_1 (old_buffer);
7102 unbind_to (count_1, Qnil);
7103 unblock_input ();
7114 windows_or_buffers_changed = old_windows_or_buffers_changed; 7104 windows_or_buffers_changed = old_windows_or_buffers_changed;
7115 7105
7116 start_timer: 7106 start_timer:
@@ -7127,31 +7117,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
7127Value is t if tooltip was open, nil otherwise. */) 7117Value is t if tooltip was open, nil otherwise. */)
7128 (void) 7118 (void)
7129{ 7119{
7130 ptrdiff_t count; 7120 return x_hide_tip (!tooltip_reuse_hidden_frame);
7131 Lisp_Object deleted, frame, timer;
7132
7133 /* Return quickly if nothing to do. */
7134 if (NILP (tip_timer) && NILP (tip_frame))
7135 return Qnil;
7136
7137 frame = tip_frame;
7138 timer = tip_timer;
7139 tip_frame = tip_timer = deleted = Qnil;
7140
7141 count = SPECPDL_INDEX ();
7142 specbind (Qinhibit_redisplay, Qt);
7143 specbind (Qinhibit_quit, Qt);
7144
7145 if (!NILP (timer))
7146 call1 (Qcancel_timer, timer);
7147
7148 if (FRAMEP (frame))
7149 {
7150 delete_frame (frame, Qnil);
7151 deleted = Qt;
7152 }
7153
7154 return unbind_to (count, deleted);
7155} 7121}
7156 7122
7157/*********************************************************************** 7123/***********************************************************************
@@ -9751,6 +9717,7 @@ syms_of_w32fns (void)
9751 DEFSYM (Qmm_size, "mm-size"); 9717 DEFSYM (Qmm_size, "mm-size");
9752 DEFSYM (Qframes, "frames"); 9718 DEFSYM (Qframes, "frames");
9753 DEFSYM (Qtip_frame, "tip-frame"); 9719 DEFSYM (Qtip_frame, "tip-frame");
9720 DEFSYM (Qassq_delete_all, "assq-delete-all");
9754 DEFSYM (Qunicode_sip, "unicode-sip"); 9721 DEFSYM (Qunicode_sip, "unicode-sip");
9755#if defined WINDOWSNT && !defined HAVE_DBUS 9722#if defined WINDOWSNT && !defined HAVE_DBUS
9756 DEFSYM (QCicon, ":icon"); 9723 DEFSYM (QCicon, ":icon");
@@ -10063,6 +10030,18 @@ Default is nil.
10063This variable has effect only on Windows Vista and later. */); 10030This variable has effect only on Windows Vista and later. */);
10064 w32_disable_new_uniscribe_apis = 0; 10031 w32_disable_new_uniscribe_apis = 0;
10065 10032
10033 DEFVAR_LISP ("w32-tooltip-extra-pixels",
10034 Vw32_tooltip_extra_pixels,
10035 doc: /* Number of pixels added after tooltip text.
10036On Windows some fonts may cause the last character of a tooltip be
10037truncated or wrapped around to the next line. Adding some extra space
10038at the end of the toooltip works around this problem.
10039
10040This variable specifies the number of pixels that shall be added. The
10041default value t means to add the width of one canonical character of the
10042tip frame. */);
10043 Vw32_tooltip_extra_pixels = Qt;
10044
10066#if 0 /* TODO: Port to W32 */ 10045#if 0 /* TODO: Port to W32 */
10067 defsubr (&Sx_change_window_property); 10046 defsubr (&Sx_change_window_property);
10068 defsubr (&Sx_delete_window_property); 10047 defsubr (&Sx_delete_window_property);
diff --git a/src/xdisp.c b/src/xdisp.c
index b9d496ed556..5b961444384 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -9794,26 +9794,28 @@ the maximum pixel-height of all text lines.
9794 9794
9795The optional argument FROM, if non-nil, specifies the first text 9795The optional argument FROM, if non-nil, specifies the first text
9796position and defaults to the minimum accessible position of the buffer. 9796position and defaults to the minimum accessible position of the buffer.
9797If FROM is t, use the minimum accessible position that is not a newline 9797If FROM is t, use the minimum accessible position that starts a
9798character. TO, if non-nil, specifies the last text position and 9798non-empty line. TO, if non-nil, specifies the last text position and
9799defaults to the maximum accessible position of the buffer. If TO is t, 9799defaults to the maximum accessible position of the buffer. If TO is t,
9800use the maximum accessible position that is not a newline character. 9800use the maximum accessible position that ends a non-empty line.
9801 9801
9802The optional argument X-LIMIT, if non-nil, specifies the maximum text 9802The optional argument X-LIMIT, if non-nil, specifies the maximum text
9803width that can be returned. X-LIMIT nil or omitted, means to use the 9803width that can be returned. X-LIMIT nil or omitted, means to use the
9804pixel-width of WINDOW's body; use this if you do not intend to change 9804pixel-width of WINDOW's body; use this if you want to know how high
9805the width of WINDOW. Use the maximum width WINDOW may assume if you 9805WINDOW should be become in order to fit all of its buffer's text with
9806intend to change WINDOW's width. In any case, text whose x-coordinate 9806the width of WINDOW unaltered. Use the maximum width WINDOW may assume
9807is beyond X-LIMIT is ignored. Since calculating the width of long lines 9807if you intend to change WINDOW's width. In any case, text whose
9808can take some time, it's always a good idea to make this argument as 9808x-coordinate is beyond X-LIMIT is ignored. Since calculating the width
9809small as possible; in particular, if the buffer contains long lines that 9809of long lines can take some time, it's always a good idea to make this
9810shall be truncated anyway. 9810argument as small as possible; in particular, if the buffer contains
9811long lines that shall be truncated anyway.
9811 9812
9812The optional argument Y-LIMIT, if non-nil, specifies the maximum text 9813The optional argument Y-LIMIT, if non-nil, specifies the maximum text
9813height that can be returned. Text lines whose y-coordinate is beyond 9814height (exluding the height of the mode- or header-line, if any) that
9814Y-LIMIT are ignored. Since calculating the text height of a large 9815can be returned. Text lines whose y-coordinate is beyond Y-LIMIT are
9815buffer can take some time, it makes sense to specify this argument if 9816ignored. Since calculating the text height of a large buffer can take
9816the size of the buffer is unknown. 9817some time, it makes sense to specify this argument if the size of the
9818buffer is large or unknown.
9817 9819
9818Optional argument MODE-AND-HEADER-LINE nil or omitted means do not 9820Optional argument MODE-AND-HEADER-LINE nil or omitted means do not
9819include the height of the mode- or header-line of WINDOW in the return 9821include the height of the mode- or header-line of WINDOW in the return
@@ -9831,7 +9833,7 @@ include the height of both, if present, in the return value. */)
9831 ptrdiff_t start, end, pos; 9833 ptrdiff_t start, end, pos;
9832 struct text_pos startp; 9834 struct text_pos startp;
9833 void *itdata = NULL; 9835 void *itdata = NULL;
9834 int c, max_y = -1, x = 0, y = 0; 9836 int c, max_x = 0, max_y = 0, x = 0, y = 0;
9835 9837
9836 CHECK_BUFFER (buffer); 9838 CHECK_BUFFER (buffer);
9837 b = XBUFFER (buffer); 9839 b = XBUFFER (buffer);
@@ -9876,11 +9878,13 @@ include the height of both, if present, in the return value. */)
9876 end = max (start, min (XINT (to), ZV)); 9878 end = max (start, min (XINT (to), ZV));
9877 } 9879 }
9878 9880
9879 if (!NILP (y_limit)) 9881 if (!NILP (x_limit) && RANGED_INTEGERP (0, x_limit, INT_MAX))
9880 { 9882 max_x = XINT (x_limit);
9881 CHECK_NUMBER (y_limit); 9883
9882 max_y = min (XINT (y_limit), INT_MAX); 9884 if (NILP (y_limit))
9883 } 9885 max_y = INT_MAX;
9886 else if (RANGED_INTEGERP (0, y_limit, INT_MAX))
9887 max_y = XINT (y_limit);
9884 9888
9885 itdata = bidi_shelve_cache (); 9889 itdata = bidi_shelve_cache ();
9886 SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start)); 9890 SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
@@ -9890,27 +9894,30 @@ include the height of both, if present, in the return value. */)
9890 x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y); 9894 x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
9891 else 9895 else
9892 { 9896 {
9893 CHECK_NUMBER (x_limit); 9897 it.last_visible_x = max_x;
9894 it.last_visible_x = min (XINT (x_limit), INFINITY);
9895 /* Actually, we never want move_it_to stop at to_x. But to make 9898 /* Actually, we never want move_it_to stop at to_x. But to make
9896 sure that move_it_in_display_line_to always moves far enough, 9899 sure that move_it_in_display_line_to always moves far enough,
9897 we set it to INT_MAX and specify MOVE_TO_X. */ 9900 we set it to INT_MAX and specify MOVE_TO_X. Also bound width
9898 x = move_it_to (&it, end, INT_MAX, max_y, -1, 9901 value by X-LIMIT. */
9899 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); 9902 x = min (move_it_to (&it, end, INT_MAX, max_y, -1,
9903 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y),
9904 max_x);
9900 } 9905 }
9901 9906
9902 y = it.current_y + it.max_ascent + it.max_descent; 9907 /* Subtract height of header-line which was counted automatically by
9908 start_display. */
9909 y = min (it.current_y + it.max_ascent + it.max_descent
9910 - WINDOW_HEADER_LINE_HEIGHT (w),
9911 max_y);
9903 9912
9904 if (!EQ (mode_and_header_line, Qheader_line) 9913 if (EQ (mode_and_header_line, Qheader_line)
9905 && !EQ (mode_and_header_line, Qt)) 9914 || EQ (mode_and_header_line, Qt))
9906 /* Do not count the header-line which was counted automatically by 9915 /* Re-add height of header-line as requested. */
9907 start_display. */ 9916 y = y + WINDOW_HEADER_LINE_HEIGHT (w);
9908 y = y - WINDOW_HEADER_LINE_HEIGHT (w);
9909 9917
9910 if (EQ (mode_and_header_line, Qmode_line) 9918 if (EQ (mode_and_header_line, Qmode_line)
9911 || EQ (mode_and_header_line, Qt)) 9919 || EQ (mode_and_header_line, Qt))
9912 /* Do count the mode-line which is not included automatically by 9920 /* Add height of mode-line as requested. */
9913 start_display. */
9914 y = y + WINDOW_MODE_LINE_HEIGHT (w); 9921 y = y + WINDOW_MODE_LINE_HEIGHT (w);
9915 9922
9916 bidi_unshelve_cache (itdata, false); 9923 bidi_unshelve_cache (itdata, false);
diff --git a/src/xfns.c b/src/xfns.c
index 2a50a5a5f99..c1ce1b73a21 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5303,8 +5303,6 @@ no value of TYPE (always string in the MS Windows case). */)
5303 Tool tips 5303 Tool tips
5304 ***********************************************************************/ 5304 ***********************************************************************/
5305 5305
5306static Lisp_Object x_create_tip_frame (struct x_display_info *,
5307 Lisp_Object, Lisp_Object);
5308static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, 5306static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
5309 Lisp_Object, int, int, int *, int *); 5307 Lisp_Object, int, int, int *, int *);
5310 5308
@@ -5348,9 +5346,7 @@ unwind_create_tip_frame (Lisp_Object frame)
5348 when this happens. */ 5346 when this happens. */
5349 5347
5350static Lisp_Object 5348static Lisp_Object
5351x_create_tip_frame (struct x_display_info *dpyinfo, 5349x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
5352 Lisp_Object parms,
5353 Lisp_Object text)
5354{ 5350{
5355 struct frame *f; 5351 struct frame *f;
5356 Lisp_Object frame; 5352 Lisp_Object frame;
@@ -5359,7 +5355,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5359 ptrdiff_t count = SPECPDL_INDEX (); 5355 ptrdiff_t count = SPECPDL_INDEX ();
5360 bool face_change_before = face_change; 5356 bool face_change_before = face_change;
5361 Lisp_Object buffer; 5357 Lisp_Object buffer;
5362 struct buffer *old_buffer;
5363 int x_width = 0, x_height = 0; 5358 int x_width = 0, x_height = 0;
5364 5359
5365 if (!dpyinfo->terminal->name) 5360 if (!dpyinfo->terminal->name)
@@ -5375,23 +5370,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5375 error ("Invalid frame name--not a string or nil"); 5370 error ("Invalid frame name--not a string or nil");
5376 5371
5377 frame = Qnil; 5372 frame = Qnil;
5378 f = make_frame (true); 5373 f = make_frame (false);
5374 f->wants_modeline = false;
5379 XSETFRAME (frame, f); 5375 XSETFRAME (frame, f);
5380
5381 AUTO_STRING (tip, " *tip*");
5382 buffer = Fget_buffer_create (tip);
5383 /* Use set_window_buffer instead of Fset_window_buffer (see
5384 discussion of bug#11984, bug#12025, bug#12026). */
5385 set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
5386 old_buffer = current_buffer;
5387 set_buffer_internal_1 (XBUFFER (buffer));
5388 bset_truncate_lines (current_buffer, Qnil);
5389 specbind (Qinhibit_read_only, Qt);
5390 specbind (Qinhibit_modification_hooks, Qt);
5391 Ferase_buffer ();
5392 Finsert (1, &text);
5393 set_buffer_internal_1 (old_buffer);
5394
5395 record_unwind_protect (unwind_create_tip_frame, frame); 5376 record_unwind_protect (unwind_create_tip_frame, frame);
5396 5377
5397 f->terminal = dpyinfo->terminal; 5378 f->terminal = dpyinfo->terminal;
@@ -5633,8 +5614,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5633 { 5614 {
5634 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); 5615 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
5635 5616
5636 /* Set tip_frame here, so that */
5637 tip_frame = frame;
5638 call2 (Qface_set_after_frame_default, frame, Qnil); 5617 call2 (Qface_set_after_frame_default, frame, Qnil);
5639 5618
5640 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) 5619 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
@@ -5773,6 +5752,85 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
5773} 5752}
5774 5753
5775 5754
5755/* Hide tooltip. Delete its frame if DELETE is true. */
5756static Lisp_Object
5757x_hide_tip (bool delete)
5758{
5759 if (!NILP (tip_timer))
5760 {
5761 call1 (Qcancel_timer, tip_timer);
5762 tip_timer = Qnil;
5763 }
5764
5765
5766 if (NILP (tip_frame)
5767 || (!delete && FRAMEP (tip_frame)
5768 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
5769 return Qnil;
5770 else
5771 {
5772 ptrdiff_t count;
5773 Lisp_Object was_open = Qnil;
5774
5775 count = SPECPDL_INDEX ();
5776 specbind (Qinhibit_redisplay, Qt);
5777 specbind (Qinhibit_quit, Qt);
5778
5779#ifdef USE_GTK
5780 {
5781 /* When using system tooltip, tip_frame is the Emacs frame on
5782 which the tip is shown. */
5783 struct frame *f = XFRAME (tip_frame);
5784
5785 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
5786 {
5787 tip_frame = Qnil;
5788 was_open = Qt;
5789 }
5790 }
5791#endif
5792
5793 if (FRAMEP (tip_frame))
5794 {
5795 if (delete)
5796 {
5797 delete_frame (tip_frame, Qnil);
5798 tip_frame = Qnil;
5799 }
5800 else
5801 x_make_frame_invisible (XFRAME (tip_frame));
5802
5803 was_open = Qt;
5804
5805#ifdef USE_LUCID
5806 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5807 redisplay procedure is not called when a tip frame over
5808 menu items is unmapped. Redisplay the menu manually... */
5809 {
5810 Widget w;
5811 struct frame *f = SELECTED_FRAME ();
5812 if (FRAME_X_P (f) && FRAME_LIVE_P (f))
5813 {
5814 w = f->output_data.x->menubar_widget;
5815
5816 if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
5817 && w != NULL)
5818 {
5819 block_input ();
5820 xlwmenu_redisplay (w);
5821 unblock_input ();
5822 }
5823 }
5824 }
5825#endif /* USE_LUCID */
5826 }
5827 else
5828 tip_frame = Qnil;
5829
5830 return unbind_to (count, was_open);
5831 }
5832}
5833
5776DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, 5834DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
5777 doc: /* Show STRING in a "tooltip" window on frame FRAME. 5835 doc: /* Show STRING in a "tooltip" window on frame FRAME.
5778A tooltip window is a small X window displaying a string. 5836A tooltip window is a small X window displaying a string.
@@ -5805,15 +5863,16 @@ A tooltip's maximum size is specified by `x-max-tooltip-size'.
5805Text larger than the specified size is clipped. */) 5863Text larger than the specified size is clipped. */)
5806 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) 5864 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
5807{ 5865{
5808 struct frame *f; 5866 struct frame *f, *tip_f;
5809 struct window *w; 5867 struct window *w;
5810 int root_x, root_y; 5868 int root_x, root_y;
5811 struct buffer *old_buffer; 5869 struct buffer *old_buffer;
5812 struct text_pos pos; 5870 struct text_pos pos;
5813 int i, width, height; 5871 int width, height;
5814 bool seen_reversed_p;
5815 int old_windows_or_buffers_changed = windows_or_buffers_changed; 5872 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5816 ptrdiff_t count = SPECPDL_INDEX (); 5873 ptrdiff_t count = SPECPDL_INDEX ();
5874 ptrdiff_t count_1;
5875 Lisp_Object window, size;
5817 5876
5818 specbind (Qinhibit_redisplay, Qt); 5877 specbind (Qinhibit_redisplay, Qt);
5819 5878
@@ -5862,22 +5921,23 @@ Text larger than the specified size is clipped. */)
5862 if (NILP (last_show_tip_args)) 5921 if (NILP (last_show_tip_args))
5863 last_show_tip_args = Fmake_vector (make_number (3), Qnil); 5922 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
5864 5923
5865 if (!NILP (tip_frame)) 5924 if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
5866 { 5925 {
5867 Lisp_Object last_string = AREF (last_show_tip_args, 0); 5926 Lisp_Object last_string = AREF (last_show_tip_args, 0);
5868 Lisp_Object last_frame = AREF (last_show_tip_args, 1); 5927 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
5869 Lisp_Object last_parms = AREF (last_show_tip_args, 2); 5928 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
5870 5929
5871 if (EQ (frame, last_frame) 5930 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
5872 && !NILP (Fequal (last_string, string)) 5931 && EQ (frame, last_frame)
5932 && !NILP (Fequal_including_properties (last_string, string))
5873 && !NILP (Fequal (last_parms, parms))) 5933 && !NILP (Fequal (last_parms, parms)))
5874 { 5934 {
5875 struct frame *tip_f = XFRAME (tip_frame);
5876
5877 /* Only DX and DY have changed. */ 5935 /* Only DX and DY have changed. */
5936 tip_f = XFRAME (tip_frame);
5878 if (!NILP (tip_timer)) 5937 if (!NILP (tip_timer))
5879 { 5938 {
5880 Lisp_Object timer = tip_timer; 5939 Lisp_Object timer = tip_timer;
5940
5881 tip_timer = Qnil; 5941 tip_timer = Qnil;
5882 call1 (Qcancel_timer, timer); 5942 call1 (Qcancel_timer, timer);
5883 } 5943 }
@@ -5888,41 +5948,103 @@ Text larger than the specified size is clipped. */)
5888 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f), 5948 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
5889 root_x, root_y); 5949 root_x, root_y);
5890 unblock_input (); 5950 unblock_input ();
5951
5891 goto start_timer; 5952 goto start_timer;
5892 } 5953 }
5893 } 5954 else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
5955 {
5956 bool delete = false;
5957 Lisp_Object tail, elt, parm, last;
5958
5959 /* Check if every parameter in PARMS has the same value in
5960 last_parms unless it should be ignored by means of
5961 Vtooltip_reuse_hidden_frame_parameters. This may destruct
5962 last_parms which, however, will be recreated below. */
5963 for (tail = parms; CONSP (tail); tail = XCDR (tail))
5964 {
5965 elt = XCAR (tail);
5966 parm = Fcar (elt);
5967 /* The left, top, right and bottom parameters are handled
5968 by compute_tip_xy so they can be ignored here. */
5969 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
5970 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
5971 {
5972 last = Fassq (parm, last_parms);
5973 if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
5974 {
5975 /* We lost, delete the old tooltip. */
5976 delete = true;
5977 break;
5978 }
5979 else
5980 last_parms = call2 (Qassq_delete_all, parm, last_parms);
5981 }
5982 else
5983 last_parms = call2 (Qassq_delete_all, parm, last_parms);
5984 }
5894 5985
5895 /* Hide a previous tip, if any. */ 5986 /* Now check if every parameter in what is left of last_parms
5896 Fx_hide_tip (); 5987 with a non-nil value has an association in PARMS unless it
5988 should be ignored by means of
5989 Vtooltip_reuse_hidden_frame_parameters. */
5990 for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
5991 {
5992 elt = XCAR (tail);
5993 parm = Fcar (elt);
5994 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
5995 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
5996 {
5997 /* We lost, delete the old tooltip. */
5998 delete = true;
5999 break;
6000 }
6001 }
6002
6003 x_hide_tip (delete);
6004 }
6005 else
6006 x_hide_tip (true);
6007 }
6008 else
6009 x_hide_tip (true);
5897 6010
5898 ASET (last_show_tip_args, 0, string); 6011 ASET (last_show_tip_args, 0, string);
5899 ASET (last_show_tip_args, 1, frame); 6012 ASET (last_show_tip_args, 1, frame);
5900 ASET (last_show_tip_args, 2, parms); 6013 ASET (last_show_tip_args, 2, parms);
5901 6014
5902 /* Add default values to frame parameters. */ 6015 if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
5903 if (NILP (Fassq (Qname, parms))) 6016 {
5904 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); 6017 /* Add default values to frame parameters. */
5905 if (NILP (Fassq (Qinternal_border_width, parms))) 6018 if (NILP (Fassq (Qname, parms)))
5906 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); 6019 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5907 if (NILP (Fassq (Qborder_width, parms))) 6020 if (NILP (Fassq (Qinternal_border_width, parms)))
5908 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); 6021 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5909 if (NILP (Fassq (Qbottom_divider_width, parms))) 6022 if (NILP (Fassq (Qborder_width, parms)))
5910 parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms); 6023 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5911 if (NILP (Fassq (Qright_divider_width, parms))) 6024 if (NILP (Fassq (Qborder_color, parms)))
5912 parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms); 6025 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5913 if (NILP (Fassq (Qborder_color, parms))) 6026 if (NILP (Fassq (Qbackground_color, parms)))
5914 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); 6027 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5915 if (NILP (Fassq (Qbackground_color, parms))) 6028 parms);
5916 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), 6029
5917 parms); 6030 /* Create a frame for the tooltip, and record it in the global
5918 6031 variable tip_frame. */
5919 /* Create a frame for the tooltip, and record it in the global 6032 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
5920 variable tip_frame. */ 6033 /* Creating the tip frame failed. */
5921 frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string); 6034 return unbind_to (count, Qnil);
5922 f = XFRAME (frame); 6035 }
5923 6036
5924 /* Set up the frame's root window. */ 6037 tip_f = XFRAME (tip_frame);
5925 w = XWINDOW (FRAME_ROOT_WINDOW (f)); 6038 window = FRAME_ROOT_WINDOW (tip_f);
6039 AUTO_STRING (tip, " *tip*");
6040 set_window_buffer (window, Fget_buffer_create (tip), false, false);
6041 w = XWINDOW (window);
6042 w->pseudo_window_p = true;
6043
6044 /* Set up the frame's root window. Note: The following code does not
6045 try to size the window or its frame correctly. Its only purpose is
6046 to make the subsequent text size calculations work. The right
6047 sizes should get installed when the toolkit gets back to us. */
5926 w->left_col = 0; 6048 w->left_col = 0;
5927 w->top_line = 0; 6049 w->top_line = 0;
5928 w->pixel_left = 0; 6050 w->pixel_left = 0;
@@ -5941,130 +6063,47 @@ Text larger than the specified size is clipped. */)
5941 w->total_lines = 40; 6063 w->total_lines = 40;
5942 } 6064 }
5943 6065
5944 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f); 6066 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
5945 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f); 6067 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
5946 6068 FRAME_TOTAL_COLS (tip_f) = w->total_cols;
5947 FRAME_TOTAL_COLS (f) = w->total_cols; 6069 adjust_frame_glyphs (tip_f);
5948 adjust_frame_glyphs (f);
5949 w->pseudo_window_p = true;
5950 6070
5951 /* Display the tooltip text in a temporary buffer. */ 6071 /* Insert STRING into root window's buffer and fit the frame to the
6072 buffer. */
6073 count_1 = SPECPDL_INDEX ();
5952 old_buffer = current_buffer; 6074 old_buffer = current_buffer;
5953 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents)); 6075 set_buffer_internal_1 (XBUFFER (w->contents));
5954 bset_truncate_lines (current_buffer, Qnil); 6076 bset_truncate_lines (current_buffer, Qnil);
6077 specbind (Qinhibit_read_only, Qt);
6078 specbind (Qinhibit_modification_hooks, Qt);
6079 specbind (Qinhibit_point_motion_hooks, Qt);
6080 Ferase_buffer ();
6081 Finsert (1, &string);
5955 clear_glyph_matrix (w->desired_matrix); 6082 clear_glyph_matrix (w->desired_matrix);
5956 clear_glyph_matrix (w->current_matrix); 6083 clear_glyph_matrix (w->current_matrix);
5957 SET_TEXT_POS (pos, BEGV, BEGV_BYTE); 6084 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
5958 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); 6085 try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
5959 6086 /* Calculate size of tooltip window. */
5960 /* Compute width and height of the tooltip. */ 6087 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
5961 width = height = 0; 6088 make_number (w->pixel_height), Qnil);
5962 seen_reversed_p = false; 6089 /* Add the frame's internal border to calculated size. */
5963 for (i = 0; i < w->desired_matrix->nrows; ++i) 6090 width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
5964 { 6091 height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
5965 struct glyph_row *row = &w->desired_matrix->rows[i]; 6092
5966 struct glyph *last; 6093 /* Calculate position of tooltip frame. */
5967 int row_width; 6094 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
5968 6095
5969 /* Stop at the first empty row at the end. */ 6096 /* Show tooltip frame. */
5970 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
5971 break;
5972
5973 /* Let the row go over the full width of the frame. */
5974 row->full_width_p = true;
5975
5976 row_width = row->pixel_width;
5977 if (row->used[TEXT_AREA])
5978 {
5979 /* There's a glyph at the end of rows that is used to place
5980 the cursor there. Don't include the width of this glyph. */
5981 if (!row->reversed_p)
5982 {
5983 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5984 if (NILP (last->object))
5985 row_width -= last->pixel_width;
5986 }
5987 else
5988 {
5989 /* There could be a stretch glyph at the beginning of R2L
5990 rows that is produced by extend_face_to_end_of_line.
5991 Don't count that glyph. */
5992 struct glyph *g = row->glyphs[TEXT_AREA];
5993
5994 if (g->type == STRETCH_GLYPH && NILP (g->object))
5995 {
5996 row_width -= g->pixel_width;
5997 seen_reversed_p = true;
5998 }
5999 }
6000 }
6001
6002 height += row->height;
6003 width = max (width, row_width);
6004 }
6005
6006 /* If we've seen partial-length R2L rows, we need to re-adjust the
6007 tool-tip frame width and redisplay it again, to avoid over-wide
6008 tips due to the stretch glyph that extends R2L lines to full
6009 width of the frame. */
6010 if (seen_reversed_p)
6011 {
6012 /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
6013 not in pixels. */
6014 w->pixel_width = width;
6015 width /= WINDOW_FRAME_COLUMN_WIDTH (w);
6016 w->total_cols = width;
6017 FRAME_TOTAL_COLS (f) = width;
6018 SET_FRAME_WIDTH (f, width);
6019 adjust_frame_glyphs (f);
6020 clear_glyph_matrix (w->desired_matrix);
6021 clear_glyph_matrix (w->current_matrix);
6022 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
6023 width = height = 0;
6024 /* Recompute width and height of the tooltip. */
6025 for (i = 0; i < w->desired_matrix->nrows; ++i)
6026 {
6027 struct glyph_row *row = &w->desired_matrix->rows[i];
6028 struct glyph *last;
6029 int row_width;
6030
6031 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
6032 break;
6033 row->full_width_p = true;
6034 row_width = row->pixel_width;
6035 if (row->used[TEXT_AREA] && !row->reversed_p)
6036 {
6037 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
6038 if (NILP (last->object))
6039 row_width -= last->pixel_width;
6040 }
6041
6042 height += row->height;
6043 width = max (width, row_width);
6044 }
6045 }
6046
6047 /* Add the frame's internal border to the width and height the X
6048 window should have. */
6049 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
6050 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
6051
6052 /* Move the tooltip window where the mouse pointer is. Resize and
6053 show it. */
6054 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
6055
6056 block_input (); 6097 block_input ();
6057 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6098 XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6058 root_x, root_y, width, height); 6099 root_x, root_y, width, height);
6059 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 6100 XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
6060 unblock_input (); 6101 unblock_input ();
6061 6102
6062 /* Draw into the window. */
6063 w->must_be_updated_p = true; 6103 w->must_be_updated_p = true;
6064 update_single_window (w); 6104 update_single_window (w);
6065
6066 /* Restore original current buffer. */
6067 set_buffer_internal_1 (old_buffer); 6105 set_buffer_internal_1 (old_buffer);
6106 unbind_to (count_1, Qnil);
6068 windows_or_buffers_changed = old_windows_or_buffers_changed; 6107 windows_or_buffers_changed = old_windows_or_buffers_changed;
6069 6108
6070 start_timer: 6109 start_timer:
@@ -6081,66 +6120,9 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
6081Value is t if tooltip was open, nil otherwise. */) 6120Value is t if tooltip was open, nil otherwise. */)
6082 (void) 6121 (void)
6083{ 6122{
6084 ptrdiff_t count; 6123 return x_hide_tip (!tooltip_reuse_hidden_frame);
6085 Lisp_Object deleted, frame, timer;
6086
6087 /* Return quickly if nothing to do. */
6088 if (NILP (tip_timer) && NILP (tip_frame))
6089 return Qnil;
6090
6091 frame = tip_frame;
6092 timer = tip_timer;
6093 tip_frame = tip_timer = deleted = Qnil;
6094
6095 count = SPECPDL_INDEX ();
6096 specbind (Qinhibit_redisplay, Qt);
6097 specbind (Qinhibit_quit, Qt);
6098
6099 if (!NILP (timer))
6100 call1 (Qcancel_timer, timer);
6101
6102#ifdef USE_GTK
6103 {
6104 /* When using system tooltip, tip_frame is the Emacs frame on which
6105 the tip is shown. */
6106 struct frame *f = XFRAME (frame);
6107 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
6108 frame = Qnil;
6109 }
6110#endif
6111
6112 if (FRAMEP (frame))
6113 {
6114 delete_frame (frame, Qnil);
6115 deleted = Qt;
6116
6117#ifdef USE_LUCID
6118 /* Bloodcurdling hack alert: The Lucid menu bar widget's
6119 redisplay procedure is not called when a tip frame over menu
6120 items is unmapped. Redisplay the menu manually... */
6121 {
6122 Widget w;
6123 struct frame *f = SELECTED_FRAME ();
6124 if (FRAME_X_P (f) && FRAME_LIVE_P (f))
6125 {
6126 w = f->output_data.x->menubar_widget;
6127
6128 if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
6129 && w != NULL)
6130 {
6131 block_input ();
6132 xlwmenu_redisplay (w);
6133 unblock_input ();
6134 }
6135 }
6136 }
6137#endif /* USE_LUCID */
6138 }
6139
6140 return unbind_to (count, deleted);
6141} 6124}
6142 6125
6143
6144 6126
6145/*********************************************************************** 6127/***********************************************************************
6146 File selection dialog 6128 File selection dialog
@@ -6802,6 +6784,7 @@ syms_of_xfns (void)
6802 DEFSYM (Qcancel_timer, "cancel-timer"); 6784 DEFSYM (Qcancel_timer, "cancel-timer");
6803 DEFSYM (Qfont_param, "font-parameter"); 6785 DEFSYM (Qfont_param, "font-parameter");
6804 DEFSYM (Qmono, "mono"); 6786 DEFSYM (Qmono, "mono");
6787 DEFSYM (Qassq_delete_all, "assq-delete-all");
6805 6788
6806#ifdef USE_CAIRO 6789#ifdef USE_CAIRO
6807 DEFSYM (Qpdf, "pdf"); 6790 DEFSYM (Qpdf, "pdf");