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
#include "../lwlib/xlwmenu.h"
#endif
-#if !defined (NO_EDITRES)
-#define HACK_EDITRES
-extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
-#endif /* not defined NO_EDITRES */
-
/* Unique id counter for widgets created by the Lucid Widget Library. */
extern LWLIB_ID widget_id_tick;
XFree (tmp_children);
#endif
- if (wm_window == rootw || had_errors)
+ if (had_errors || wm_window == rootw)
break;
win = wm_window;
if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
{
- FRAME_INTERNAL_BORDER_WIDTH (f) = border;
+ f->internal_border_width = border;
#ifdef USE_X_TOOLKIT
if (FRAME_X_OUTPUT (f)->edit_widget)
hack_wm_protocols (f, shell_widget);
-#ifdef HACK_EDITRES
+#ifdef X_TOOLKIT_EDITRES
XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
#endif
{
/* Remember the explicit font parameter, so we can re-apply it after
we've applied the `default' face settings. */
- AUTO_FRAME_ARG (arg, Qfont_param, font_param);
+ AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
x_set_frame_parameters (f, arg);
}
\f
DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
doc: /* Internal function called by `color-defined-p', which see.
-(Note that the Nextstep version of this function ignores FRAME.) */)
+\(Note that the Nextstep version of this function ignores FRAME.) */)
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
-(Labeling every distributor as a "vendor" embodies the false assumption
+\(Labeling every distributor as a "vendor" embodies the false assumption
that operating systems cannot be developed and distributed noncommercially.)
The optional argument TERMINAL specifies which display to ask about.
struct frame *f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
- && !EQ (frame, tip_frame))
+ && !FRAME_TOOLTIP_P (f))
{
int i = x_get_monitor_for_frame (f, monitors, n_monitors);
ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
RROutput pxid = None;
struct MonitorInfo *monitors;
-#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT
- resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+#define RANDR13_LIBRARY \
+ (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
+
+#if RANDR13_LIBRARY
+ /* Check if the display supports 1.3 too. */
+ bool randr13_avail = (dpyinfo->xrandr_major_version > 1
+ || (dpyinfo->xrandr_major_version == 1
+ && dpyinfo->xrandr_minor_version >= 3));
+
+ if (randr13_avail)
+ resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+ else
+ resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
#else
resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
#endif
n_monitors = resources->noutput;
monitors = xzalloc (n_monitors * sizeof *monitors);
-#ifdef HAVE_XRRGETOUTPUTPRIMARY
- pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
+#if RANDR13_LIBRARY
+ if (randr13_avail)
+ pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
#endif
for (i = 0; i < n_monitors; ++i)
{
XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
resources->outputs[i]);
- Connection conn = info ? info->connection : RR_Disconnected;
- RRCrtc id = info ? info->crtc : None;
+ if (!info)
+ continue;
if (strcmp (info->name, "default") == 0)
{
return Qnil;
}
- if (conn != RR_Disconnected && id != None)
+ if (info->connection != RR_Disconnected && info->crtc != None)
{
- XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, id);
+ XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
struct MonitorInfo *mi = &monitors[i];
XRectangle workarea_r;
xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
if (xrr_ok)
{
- int xrr_major, xrr_minor;
- XRRQueryVersion (dpy, &xrr_major, &xrr_minor);
- xrr_ok = (xrr_major == 1 && xrr_minor >= 2) || xrr_major > 1;
+ XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
+ &dpyinfo->xrandr_minor_version);
+ xrr_ok = ((dpyinfo->xrandr_major_version == 1
+ && dpyinfo->xrandr_minor_version >= 2)
+ || dpyinfo->xrandr_major_version > 1);
}
if (xrr_ok)
struct frame *f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
- && !EQ (frame, tip_frame))
+ && !FRAME_TOOLTIP_P (f))
{
GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
doc: /* Move mouse pointer to absolute pixel position (X, Y).
The coordinates X and Y are interpreted in pixels relative to a position
-(0, 0) of the selected frame's display. */)
+\(0, 0) of the selected frame's display. */)
(Lisp_Object x, Lisp_Object y)
{
struct frame *f = SELECTED_FRAME ();
Optional second arg XRM-STRING is a string of resources in xrdb format.
If the optional third arg MUST-SUCCEED is non-nil,
terminate Emacs if we can't open the connection.
-(In the Nextstep version, the last two arguments are currently ignored.) */)
+\(In the Nextstep version, the last two arguments are currently ignored.) */)
(Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
{
char *xrm_option;
Tool tips
***********************************************************************/
-static Lisp_Object x_create_tip_frame (struct x_display_info *,
- Lisp_Object, Lisp_Object);
-static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
- Lisp_Object, int, int, int *, int *);
-
-/* The frame of a currently visible tooltip. */
-
-Lisp_Object tip_frame;
-
-/* If non-nil, a timer started that hides the last tooltip when it
- fires. */
-
-static Lisp_Object tip_timer;
-Window tip_window;
-
-/* If non-nil, a vector of 3 elements containing the last args
- with which x-show-tip was called. See there. */
-
-static Lisp_Object last_show_tip_args;
-
-
-static void
-unwind_create_tip_frame (Lisp_Object frame)
-{
- Lisp_Object deleted;
-
- deleted = unwind_create_frame (frame);
- if (EQ (deleted, Qt))
- {
- tip_window = None;
- tip_frame = Qnil;
- }
-}
-
-
/* Create a frame for a tooltip on the display described by DPYINFO.
PARMS is a list of frame parameters. TEXT is the string to
display in the tip frame. Value is the frame.
when this happens. */
static Lisp_Object
-x_create_tip_frame (struct x_display_info *dpyinfo,
- Lisp_Object parms,
- Lisp_Object text)
+x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
{
struct frame *f;
Lisp_Object frame;
int width, height;
ptrdiff_t count = SPECPDL_INDEX ();
bool face_change_before = face_change;
- Lisp_Object buffer;
- struct buffer *old_buffer;
int x_width = 0, x_height = 0;
if (!dpyinfo->terminal->name)
error ("Invalid frame name--not a string or nil");
frame = Qnil;
- f = make_frame (true);
+ f = make_frame (false);
+ f->wants_modeline = false;
XSETFRAME (frame, f);
-
- AUTO_STRING (tip, " *tip*");
- buffer = Fget_buffer_create (tip);
- /* Use set_window_buffer instead of Fset_window_buffer (see
- discussion of bug#11984, bug#12025, bug#12026). */
- set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
- old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (buffer));
- bset_truncate_lines (current_buffer, Qnil);
- specbind (Qinhibit_read_only, Qt);
- specbind (Qinhibit_modification_hooks, Qt);
- Ferase_buffer ();
- Finsert (1, &text);
- set_buffer_internal_1 (old_buffer);
-
- record_unwind_protect (unwind_create_tip_frame, frame);
+ record_unwind_protect (do_unwind_create_frame, frame);
f->terminal = dpyinfo->terminal;
f->output_data.x->white_relief.pixel = -1;
f->output_data.x->black_relief.pixel = -1;
+ f->tooltip = true;
fset_icon_name (f, Qnil);
FRAME_DISPLAY_INFO (f) = dpyinfo;
f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
= f->output_data.x->text_cursor;
/* Arrange for getting MapNotify and UnmapNotify events. */
attrs.event_mask = StructureNotifyMask;
- tip_window
- = FRAME_X_WINDOW (f)
+ FRAME_X_WINDOW (f)
= XCreateWindow (FRAME_X_DISPLAY (f),
FRAME_DISPLAY_INFO (f)->root_window,
/* x, y, width, height */
f->border_width,
CopyFromParent, InputOutput, CopyFromParent,
mask, &attrs);
- XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
XA_ATOM, 32, PropModeReplace,
(unsigned char *)&type, 1);
SET_FRAME_LINES (f, 0);
change_frame_size (f, width, height, true, false, false, false);
- /* Add `tooltip' frame parameter's default value. */
- if (NILP (Fframe_parameter (frame, Qtooltip)))
- {
- AUTO_FRAME_ARG (arg, Qtooltip, Qt);
- Fmodify_frame_parameters (frame, arg);
- }
-
/* FIXME - can this be done in a similar way to normal frames?
http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
{
Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
- /* Set tip_frame here, so that */
- tip_frame = frame;
call2 (Qface_set_after_frame_default, frame, Qnil);
if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
f->no_split = true;
+ /* Now this is an official tooltip frame on this display. */
+ dpyinfo->x_tooltip_frame = f;
+
/* Now that the frame will be official, it counts as a reference to
its display and terminal. */
FRAME_DISPLAY_INFO (f)->reference_count++;
the display in *ROOT_X, and *ROOT_Y. */
static void
-compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y)
+compute_tip_xy (struct frame *f,
+ Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
+ int width, int height, int *root_x, int *root_y)
{
Lisp_Object left, top, right, bottom;
int win_x, win_y;
*root_x = min_x;
}
+/* Hide tooltip frame F and delete it if DELETE is true. */
+
+static Lisp_Object
+x_hide_tip (struct frame *f, bool delete)
+{
+ if (f)
+ {
+ Lisp_Object frame, timer;
+
+ XSETFRAME (frame, f);
+ timer = Fframe_parameter (frame, Qtooltip_timer);
+
+ if (!NILP (timer))
+ call1 (Qcancel_timer, timer);
+
+ if (!delete && !FRAME_VISIBLE_P (f))
+ return Qnil;
+ else
+ {
+ ptrdiff_t count = SPECPDL_INDEX ();
+
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+#ifdef USE_GTK
+ if (x_gtk_use_system_tooltips)
+ /* Should be handled by xg_hide_tooltip. */
+ emacs_abort ();
+#endif
+ if (delete)
+ delete_frame (frame, Qnil);
+ else
+ x_make_frame_invisible (f);
+
+#ifdef USE_LUCID
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over
+ menu items is unmapped. Redisplay the menu manually... */
+ {
+ Widget w;
+ struct frame *sf = SELECTED_FRAME ();
+ if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
+ {
+ w = sf->output_data.x->menubar_widget;
+
+ if (!DoesSaveUnders (FRAME_DISPLAY_INFO (sf)->screen)
+ && w != NULL)
+ {
+ block_input ();
+ xlwmenu_redisplay (w);
+ unblock_input ();
+ }
+ }
+ }
+#endif /* USE_LUCID */
+ return unbind_to (count, Qt);
+ }
+ }
+ return Qnil;
+}
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
doc: /* Show STRING in a "tooltip" window on frame FRAME.
A tooltip's maximum size is specified by `x-max-tooltip-size'.
Text larger than the specified size is clipped. */)
- (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
+ (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
+ Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
{
- struct frame *f;
+ struct frame *f, *tip_f;
struct window *w;
int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
- int i, width, height;
- bool seen_reversed_p;
+ int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t count = SPECPDL_INDEX ();
+ ptrdiff_t count_1;
+ Lisp_Object window, size, tip_frame, parameters;
+ AUTO_STRING (tip, " *tip*");
specbind (Qinhibit_redisplay, Qt);
{
bool ok;
- /* Hide a previous tip, if any. */
- Fx_hide_tip ();
+ /* Hide a previous tip on this frame, if any. */
+ xg_hide_tooltip (f);
block_input ();
ok = xg_prepare_tooltip (f, string, &width, &height);
{
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
xg_show_tooltip (f, root_x, root_y);
- /* This is used in Fx_hide_tip. */
- XSETFRAME (tip_frame, f);
}
unblock_input ();
- if (ok) goto start_timer;
+ if (ok)
+ /* Schedule call to xg_hide_tip from GTK event loop
+ to allow the tip disappear after timeout seconds. */
+ FRAME_X_OUTPUT (f)->ttip_timeout
+ = g_timeout_add_seconds (XINT (timeout), xg_hide_tip, (gpointer) f);
+ else
+ /* FIXME: what if not ok? */
+ FRAME_X_OUTPUT (f)->ttip_timeout = 0;
+ return unbind_to (count, Qnil);
}
#endif /* USE_GTK */
- if (NILP (last_show_tip_args))
- last_show_tip_args = Fmake_vector (make_number (3), Qnil);
+ parameters = Fframe_parameter (frame, Qtooltip_parameters);
+ if (NILP (parameters))
+ parameters = Fmake_vector (make_number (3), Qnil);
+
+ /* Look at current tooltip frame, if any. */
+ tip_f = FRAME_DISPLAY_INFO (f)->x_tooltip_frame;
+ if (tip_f)
+ XSETFRAME (tip_frame, tip_f);
+ else
+ tip_frame = Qnil;
- if (!NILP (tip_frame))
+ if (tip_f && FRAME_LIVE_P (tip_f))
{
- Lisp_Object last_string = AREF (last_show_tip_args, 0);
- Lisp_Object last_frame = AREF (last_show_tip_args, 1);
- Lisp_Object last_parms = AREF (last_show_tip_args, 2);
+ Lisp_Object last_string = AREF (parameters, 0);
+ Lisp_Object last_frame = AREF (parameters, 1);
+ Lisp_Object last_parms = AREF (parameters, 2);
- if (EQ (frame, last_frame)
- && !NILP (Fequal (last_string, string))
+ if (FRAME_VISIBLE_P (tip_f)
+ && EQ (frame, last_frame)
+ && !NILP (Fequal_including_properties (last_string, string))
&& !NILP (Fequal (last_parms, parms)))
{
- struct frame *tip_f = XFRAME (tip_frame);
-
/* Only DX and DY have changed. */
- if (!NILP (tip_timer))
- {
- Lisp_Object timer = tip_timer;
- tip_timer = Qnil;
- call1 (Qcancel_timer, timer);
- }
+ Lisp_Object timer = Fframe_parameter (tip_frame, Qtooltip_timer);
+
+ if (!NILP (timer))
+ call1 (Qcancel_timer, timer);
block_input ();
compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
root_x, root_y);
unblock_input ();
+
goto start_timer;
}
+ else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
+ {
+ bool delete = false;
+ Lisp_Object tail, elt, parm, last;
+
+ /* Check if every parameter in PARMS has the same value in
+ last_parms unless it should be ignored by means of
+ Vtooltip_reuse_hidden_frame_parameters. This may destruct
+ last_parms which, however, will be recreated below. */
+ for (tail = parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ /* The left, top, right and bottom parameters are handled
+ by compute_tip_xy so they can be ignored here. */
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
+ && !EQ (parm, Qright) && !EQ (parm, Qbottom))
+ {
+ last = Fassq (parm, last_parms);
+ if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ else
+ last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ }
+ else
+ last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ }
+
+ /* Now check if every parameter in what is left of last_parms
+ with a non-nil value has an association in PARMS unless it
+ should be ignored by means of
+ Vtooltip_reuse_hidden_frame_parameters. */
+ for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
+ && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ }
+
+ x_hide_tip (tip_f, delete);
+ }
+ else
+ x_hide_tip (tip_f, true);
}
+ else
+ x_hide_tip (tip_f, true);
- /* Hide a previous tip, if any. */
- Fx_hide_tip ();
+ /* Update tooltip parameters. */
+ {
+ AUTO_FRAME_ARG (arg, Qtooltip_parameters, parameters);
+ ASET (parameters, 0, string);
+ ASET (parameters, 1, frame);
+ ASET (parameters, 2, parms);
+ Fmodify_frame_parameters (frame, arg);
+ }
- ASET (last_show_tip_args, 0, string);
- ASET (last_show_tip_args, 1, frame);
- ASET (last_show_tip_args, 2, parms);
+ if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
+ {
+ /* Add default values to frame parameters. */
+ if (NILP (Fassq (Qname, parms)))
+ parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
+ if (NILP (Fassq (Qborder_width, parms)))
+ parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
+ if (NILP (Fassq (Qborder_color, parms)))
+ parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
+ if (NILP (Fassq (Qbackground_color, parms)))
+ parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
+ parms);
+ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
+ /* Creating the tip frame failed. */
+ return unbind_to (count, Qnil);
+ }
- /* Add default values to frame parameters. */
- if (NILP (Fassq (Qname, parms)))
- parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
- if (NILP (Fassq (Qinternal_border_width, parms)))
- parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
- if (NILP (Fassq (Qborder_width, parms)))
- parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
- if (NILP (Fassq (Qbottom_divider_width, parms)))
- parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms);
- if (NILP (Fassq (Qright_divider_width, parms)))
- parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms);
- if (NILP (Fassq (Qborder_color, parms)))
- parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
- if (NILP (Fassq (Qbackground_color, parms)))
- parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
- parms);
-
- /* Create a frame for the tooltip, and record it in the global
- variable tip_frame. */
- frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string);
- f = XFRAME (frame);
-
- /* Set up the frame's root window. */
- w = XWINDOW (FRAME_ROOT_WINDOW (f));
+ tip_f = XFRAME (tip_frame);
+ window = FRAME_ROOT_WINDOW (tip_f);
+ set_window_buffer (window, Fget_buffer_create (tip), false, false);
+ w = XWINDOW (window);
+ w->pseudo_window_p = true;
+
+ /* Set up the frame's root window. Note: The following code does not
+ try to size the window or its frame correctly. Its only purpose is
+ to make the subsequent text size calculations work. The right
+ sizes should get installed when the toolkit gets back to us. */
w->left_col = 0;
w->top_line = 0;
w->pixel_left = 0;
w->total_lines = 40;
}
- w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f);
- w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f);
+ w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
+ w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
+ FRAME_TOTAL_COLS (tip_f) = w->total_cols;
+ adjust_frame_glyphs (tip_f);
- FRAME_TOTAL_COLS (f) = w->total_cols;
- adjust_frame_glyphs (f);
- w->pseudo_window_p = true;
-
- /* Display the tooltip text in a temporary buffer. */
+ /* Insert STRING into root window's buffer and fit the frame to the
+ buffer. */
+ count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents));
+ set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
+ specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
+ specbind (Qinhibit_point_motion_hooks, Qt);
+ Ferase_buffer ();
+ Finsert (1, &string);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
- try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
-
- /* Compute width and height of the tooltip. */
- width = height = 0;
- seen_reversed_p = false;
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- {
- struct glyph_row *row = &w->desired_matrix->rows[i];
- struct glyph *last;
- int row_width;
-
- /* Stop at the first empty row at the end. */
- if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
- break;
-
- /* Let the row go over the full width of the frame. */
- row->full_width_p = true;
-
- row_width = row->pixel_width;
- if (row->used[TEXT_AREA])
- {
- /* There's a glyph at the end of rows that is used to place
- the cursor there. Don't include the width of this glyph. */
- if (!row->reversed_p)
- {
- last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (NILP (last->object))
- row_width -= last->pixel_width;
- }
- else
- {
- /* There could be a stretch glyph at the beginning of R2L
- rows that is produced by extend_face_to_end_of_line.
- Don't count that glyph. */
- struct glyph *g = row->glyphs[TEXT_AREA];
-
- if (g->type == STRETCH_GLYPH && NILP (g->object))
- {
- row_width -= g->pixel_width;
- seen_reversed_p = true;
- }
- }
- }
-
- height += row->height;
- width = max (width, row_width);
- }
-
- /* If we've seen partial-length R2L rows, we need to re-adjust the
- tool-tip frame width and redisplay it again, to avoid over-wide
- tips due to the stretch glyph that extends R2L lines to full
- width of the frame. */
- if (seen_reversed_p)
- {
- /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
- not in pixels. */
- w->pixel_width = width;
- width /= WINDOW_FRAME_COLUMN_WIDTH (w);
- w->total_cols = width;
- FRAME_TOTAL_COLS (f) = width;
- SET_FRAME_WIDTH (f, width);
- adjust_frame_glyphs (f);
- clear_glyph_matrix (w->desired_matrix);
- clear_glyph_matrix (w->current_matrix);
- try_window (FRAME_ROOT_WINDOW (f), pos, 0);
- width = height = 0;
- /* Recompute width and height of the tooltip. */
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- {
- struct glyph_row *row = &w->desired_matrix->rows[i];
- struct glyph *last;
- int row_width;
-
- if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
- break;
- row->full_width_p = true;
- row_width = row->pixel_width;
- if (row->used[TEXT_AREA] && !row->reversed_p)
- {
- last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (NILP (last->object))
- row_width -= last->pixel_width;
- }
-
- height += row->height;
- width = max (width, row_width);
- }
- }
-
- /* Add the frame's internal border to the width and height the X
- window should have. */
- height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
- width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
-
- /* Move the tooltip window where the mouse pointer is. Resize and
- show it. */
- compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
-
+ try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
+ /* Calculate size of tooltip window. */
+ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
+ make_number (w->pixel_height), Qnil);
+ /* Add the frame's internal border to calculated size. */
+ width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+ height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+
+ /* Calculate position of tooltip frame. */
+ compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
+
+ /* Show tooltip frame. */
block_input ();
- XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
root_x, root_y, width, height);
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
unblock_input ();
- /* Draw into the window. */
w->must_be_updated_p = true;
update_single_window (w);
-
- /* Restore original current buffer. */
set_buffer_internal_1 (old_buffer);
+ unbind_to (count_1, Qnil);
windows_or_buffers_changed = old_windows_or_buffers_changed;
start_timer:
- /* Let the tip disappear after timeout seconds. */
- tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
- intern ("x-hide-tip"));
-
+ {
+ /* Let the tip disappear after timeout seconds. */
+ AUTO_FRAME_ARG (arg, Qtooltip_timer,
+ call3 (intern ("run-at-time"), timeout,
+ Qnil, intern ("x-hide-tip")));
+ Fmodify_frame_parameters (tip_frame, arg);
+ }
return unbind_to (count, Qnil);
}
-
-DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
+DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 1, 0,
doc: /* Hide the current tooltip window, if there is any.
+Optional FRAME is the frame to hide tooltip on.
Value is t if tooltip was open, nil otherwise. */)
- (void)
+ (Lisp_Object frame)
{
- ptrdiff_t count;
- Lisp_Object deleted, frame, timer;
-
- /* Return quickly if nothing to do. */
- if (NILP (tip_timer) && NILP (tip_frame))
- return Qnil;
-
- frame = tip_frame;
- timer = tip_timer;
- tip_frame = tip_timer = deleted = Qnil;
-
- count = SPECPDL_INDEX ();
- specbind (Qinhibit_redisplay, Qt);
- specbind (Qinhibit_quit, Qt);
-
- if (!NILP (timer))
- call1 (Qcancel_timer, timer);
+ Lisp_Object obj = Qnil;
#ifdef USE_GTK
- {
- /* When using system tooltip, tip_frame is the Emacs frame on which
- the tip is shown. */
- struct frame *f = XFRAME (frame);
- if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
- frame = Qnil;
- }
-#endif
+ if (x_gtk_use_system_tooltips)
+ {
+ if (NILP (frame))
+ {
+ Lisp_Object tail, frame;
- if (FRAMEP (frame))
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_X_P (XFRAME (frame)))
+ if (xg_hide_tooltip (XFRAME (frame)))
+ obj = Qt;
+ }
+ else
+ {
+ CHECK_FRAME (frame);
+ if (FRAME_X_P (XFRAME (frame)))
+ if (xg_hide_tooltip (XFRAME (frame)))
+ obj = Qt;
+ }
+ return obj;
+ }
+#endif /* USE_GTK */
+
+ if (NILP (frame))
{
- delete_frame (frame, Qnil);
- deleted = Qt;
+ struct x_display_info *dpyinfo;
-#ifdef USE_LUCID
- /* Bloodcurdling hack alert: The Lucid menu bar widget's
- redisplay procedure is not called when a tip frame over menu
- items is unmapped. Redisplay the menu manually... */
- {
- Widget w;
- struct frame *f = SELECTED_FRAME ();
- if (FRAME_X_P (f) && FRAME_LIVE_P (f))
- {
- w = f->output_data.x->menubar_widget;
-
- if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
- && w != NULL)
- {
- block_input ();
- xlwmenu_redisplay (w);
- unblock_input ();
- }
- }
- }
-#endif /* USE_LUCID */
+ for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+ if (dpyinfo->x_tooltip_frame)
+ if (!NILP (x_hide_tip (dpyinfo->x_tooltip_frame,
+ !tooltip_reuse_hidden_frame)))
+ obj = Qt;
}
+ else
+ {
+ struct frame *f;
- return unbind_to (count, deleted);
+ CHECK_FRAME (frame);
+ f = XFRAME (frame);
+ if (FRAME_DISPLAY_INFO (f)
+ && FRAME_DISPLAY_INFO (f)->x_tooltip_frame)
+ obj = x_hide_tip (FRAME_DISPLAY_INFO (f)->x_tooltip_frame,
+ !tooltip_reuse_hidden_frame);
+ }
+ return obj;
}
-
\f
/***********************************************************************
File selection dialog
default_name = xlispstrdup (font_param);
else
{
- font_param = Fframe_parameter (frame, Qfont_param);
+ font_param = Fframe_parameter (frame, Qfont_parameter);
if (STRINGP (font_param))
default_name = xlispstrdup (font_param);
}
DEFSYM (Qundefined_color, "undefined-color");
DEFSYM (Qcompound_text, "compound-text");
DEFSYM (Qcancel_timer, "cancel-timer");
- DEFSYM (Qfont_param, "font-parameter");
+ DEFSYM (Qfont_parameter, "font-parameter");
DEFSYM (Qmono, "mono");
+ DEFSYM (Qassq_delete_all, "assq-delete-all");
#ifdef USE_CAIRO
DEFSYM (Qpdf, "pdf");
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
- tip_timer = Qnil;
- staticpro (&tip_timer);
- tip_frame = Qnil;
- staticpro (&tip_frame);
-
- last_show_tip_args = Qnil;
- staticpro (&last_show_tip_args);
defsubr (&Sx_uses_old_gtk_dialog);
#if defined (USE_MOTIF) || defined (USE_GTK)