summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2021-12-18 20:58:44 +0800
committerPo Lu <luangruo@yahoo.com>2021-12-18 20:58:44 +0800
commit4ff3a70153ac1716bf0767fbbf92b04fdb3b1c80 (patch)
treee89cdddc6e7a923bb99998f75ed974883f002272
parent7ab1b71c0dd878daa6806ce3a01d429dc5af646c (diff)
parent4544651b3f62ce4a104a058e8c6aee42c23b76bc (diff)
downloademacs-4ff3a70153ac1716bf0767fbbf92b04fdb3b1c80.tar.gz
Merge remote-tracking branch 'origin/master' into feature/pgtk
-rw-r--r--doc/lispref/display.texi8
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/emacs-lisp/multisession.el45
-rw-r--r--src/haikufns.c3
-rw-r--r--src/w32fns.c3
-rw-r--r--src/xdisp.c49
-rw-r--r--src/xfns.c3
-rw-r--r--src/xterm.c88
8 files changed, 131 insertions, 74 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index dd996fbe4a8..98a15404f91 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2086,7 +2086,7 @@ displayed in a given window. This function is used by
(@pxref{Resizing Windows}) to make a window exactly as large as the text
it contains.
-@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines
+@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines ignore-line-at-end
This function returns the size of the text of @var{window}'s buffer in
pixels. @var{window} must be a live window and defaults to the
selected one. The return value is a cons of the maximum pixel-width
@@ -2136,6 +2136,12 @@ line, if present, in the return value. If it is @code{t}, include the
height of all of these lines, if present, in the return value.
@end defun
+The optional argument @var{ignore-line-at-end} controls whether or
+not to count the height of text in @var{to}'s screen line as part of
+the returned pixel-height. This is useful if your Lisp program is
+only interested in the dimensions of text up to and excluding the
+visual beginning of @var{to}'s screen line.
+
@code{window-text-pixel-size} treats the text displayed in a window as a
whole and does not care about the size of individual lines. The
following function does.
diff --git a/etc/NEWS b/etc/NEWS
index bd1ed4da00c..e3665b918a3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -984,6 +984,12 @@ when they have changed.
This can be used to check whether a specific font has a glyph for a
character.
++++
+** 'window-text-pixel-size' now accepts a new argument 'ignore-line-at-end'.
+This controls whether or not the last screen line of the text being
+measured will be counted for the purpose of calculating the text
+dimensions.
+
** XDG support
*** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable.
diff --git a/lisp/emacs-lisp/multisession.el b/lisp/emacs-lisp/multisession.el
index bce888acc68..6ef0da10f77 100644
--- a/lisp/emacs-lisp/multisession.el
+++ b/lisp/emacs-lisp/multisession.el
@@ -250,23 +250,30 @@ DOC should be a doc string, and ARGS are keywords as applicable to
(defun multisession--encode-file-name (name)
(url-hexify-string name))
-(defun multisession--update-file-value (file object)
- (condition-case nil
- (with-temp-buffer
- (let* ((time (file-attribute-modification-time
- (file-attributes file)))
- (coding-system-for-read 'utf-8))
- (insert-file-contents file)
- (let ((stored (read (current-buffer))))
- (setf (multisession--cached-value object) stored
- (multisession--cached-sequence object) time)
- stored)))
- ;; If the file is contended (could happen with file locking in
- ;; Windws) or unreadable, just return the current value.
- (error
- (if (eq (multisession--cached-value object) multisession--unbound)
- (multisession--initial-value object)
- (multisession--cached-value object)))))
+(defun multisession--read-file-value (file object)
+ (catch 'done
+ (let ((i 0)
+ last-error)
+ (while (< i 10)
+ (condition-case err
+ (throw 'done
+ (with-temp-buffer
+ (let* ((time (file-attribute-modification-time
+ (file-attributes file)))
+ (coding-system-for-read 'utf-8))
+ (insert-file-contents file)
+ (let ((stored (read (current-buffer))))
+ (setf (multisession--cached-value object) stored
+ (multisession--cached-sequence object) time)
+ stored))))
+ ;; Windows uses OS-level file locking that may preclude
+ ;; reading the file in some circumstances. So when that
+ ;; happens, wait a bit and try again.
+ (file-error
+ (setq i (1+ i)
+ last-error err)
+ (sleep-for (+ 0.1 (/ (float (random 10)) 10))))))
+ (signal (car last-error) (cdr last-error)))))
(defun multisession--object-file-name (object)
(expand-file-name
@@ -283,7 +290,7 @@ DOC should be a doc string, and ARGS are keywords as applicable to
;; We have no value yet; see whether it's stored.
((eq (multisession--cached-value object) multisession--unbound)
(if (file-exists-p file)
- (multisession--update-file-value file object)
+ (multisession--read-file-value file object)
;; Nope; return the initial value.
(multisession--initial-value object)))
;; We have a value, but we want to update in case some other
@@ -293,7 +300,7 @@ DOC should be a doc string, and ARGS are keywords as applicable to
(time-less-p (multisession--cached-sequence object)
(file-attribute-modification-time
(file-attributes file))))
- (multisession--update-file-value file object)
+ (multisession--read-file-value file object)
;; Nothing, return the cached value.
(multisession--cached-value object)))
;; Just return the cached value.
diff --git a/src/haikufns.c b/src/haikufns.c
index 868fc71f979..737b0338994 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -1970,7 +1970,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Calculate size of tooltip window. */
size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
- make_fixnum (w->pixel_height), Qnil);
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
/* Add the frame's internal border to calculated size. */
width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
diff --git a/src/w32fns.c b/src/w32fns.c
index 65463b52616..02a6d78b51c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -7525,7 +7525,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Calculate size of tooltip window. */
size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
- make_fixnum (w->pixel_height), Qnil);
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
/* Add the frame's internal border to calculated size. */
width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
diff --git a/src/xdisp.c b/src/xdisp.c
index 2d45a8d6b9f..3a1bc1613f7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -5361,9 +5361,6 @@ handle_display_prop (struct it *it)
if (!it->string_from_display_prop_p)
it->area = TEXT_AREA;
- if (!STRINGP (it->string))
- object = it->w->contents;
-
propval = get_char_property_and_overlay (make_fixnum (position->charpos),
Qdisplay, object, &overlay);
@@ -5377,6 +5374,9 @@ handle_display_prop (struct it *it)
/* Now OVERLAY is the overlay that gave us this property, or nil
if it was a text property. */
+ if (!STRINGP (it->string))
+ object = it->w->contents;
+
display_replaced = handle_display_spec (it, propval, object, overlay,
position, bufpos,
FRAME_WINDOW_P (it->f));
@@ -10832,8 +10832,9 @@ in_display_vector_p (struct it *it)
set WINDOW's buffer to the buffer specified by its BUFFER_OR_NAME
argument. */
static Lisp_Object
-window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
- Lisp_Object y_limit, Lisp_Object mode_lines)
+window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
+ Lisp_Object x_limit, Lisp_Object y_limit,
+ Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
{
struct window *w = decode_live_window (window);
struct it it;
@@ -10841,6 +10842,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li
struct text_pos startp;
void *itdata = NULL;
int c, max_x = 0, max_y = 0, x = 0, y = 0;
+ int doff = 0;
if (NILP (from))
{
@@ -10969,8 +10971,16 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li
if (IT_CHARPOS (it) == end)
{
x += it.pixel_width;
- it.max_ascent = max (it.max_ascent, it.ascent);
- it.max_descent = max (it.max_descent, it.descent);
+
+ /* DTRT if ignore_line_at_end is t. */
+ if (!NILP (ignore_line_at_end))
+ doff = (max (it.max_ascent, it.ascent)
+ + max (it.max_descent, it.descent));
+ else
+ {
+ it.max_ascent = max (it.max_ascent, it.ascent);
+ it.max_descent = max (it.max_descent, it.descent);
+ }
}
}
else
@@ -10991,8 +11001,14 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li
/* Subtract height of header-line and tab-line which was counted
automatically by start_display. */
- y = it.current_y + it.max_ascent + it.max_descent
- - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
+ if (!NILP (ignore_line_at_end))
+ y = (it.current_y + doff
+ - WINDOW_TAB_LINE_HEIGHT (w)
+ - WINDOW_HEADER_LINE_HEIGHT (w));
+ else
+ y = (it.current_y + it.max_ascent + it.max_descent + doff
+ - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
+
/* Don't return more than Y-LIMIT. */
if (y > max_y)
y = max_y;
@@ -11039,7 +11055,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li
return Fcons (make_fixnum (x - start_x), make_fixnum (y));
}
-DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0,
+DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
doc: /* Return the size of the text of WINDOW's buffer in pixels.
WINDOW must be a live window and defaults to the selected one. The
return value is a cons of the maximum pixel-width of any text line
@@ -11086,9 +11102,12 @@ Optional argument MODE-LINES nil or omitted means do not include the
height of the mode-, tab- or header-line of WINDOW in the return value.
If it is the symbol `mode-line', 'tab-line' or `header-line', include
only the height of that line, if present, in the return value. If t,
-include the height of any of these, if present, in the return value. */)
+include the height of any of these, if present, in the return value.
+
+IGNORE-LINE-AT-END, if non-nil, means to not add the height of the
+screen line that includes TO to the returned height of the text. */)
(Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
- Lisp_Object y_limit, Lisp_Object mode_lines)
+ Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
{
struct window *w = decode_live_window (window);
struct buffer *b = XBUFFER (w->contents);
@@ -11101,7 +11120,8 @@ include the height of any of these, if present, in the return value. */)
set_buffer_internal_1 (b);
}
- value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines);
+ value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
+ ignore_line_at_end);
if (old_b)
set_buffer_internal_1 (old_b);
@@ -11151,7 +11171,8 @@ WINDOW. */)
set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
}
- value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil);
+ value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
+ Qnil);
unbind_to (count, Qnil);
diff --git a/src/xfns.c b/src/xfns.c
index dc25d7bfca2..30ed358fb28 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7169,7 +7169,8 @@ Text larger than the specified size is clipped. */)
try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Calculate size of tooltip window. */
size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
- make_fixnum (w->pixel_height), Qnil);
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
/* Add the frame's internal border to calculated size. */
width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
diff --git a/src/xterm.c b/src/xterm.c
index 03f509ba868..7456b3b6beb 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -579,7 +579,7 @@ xi_link_touch_point (struct xi_device_t *device,
device->touchpoints = touchpoint;
}
-static void
+static bool
xi_unlink_touch_point (int detail,
struct xi_device_t *device)
{
@@ -596,9 +596,11 @@ xi_unlink_touch_point (int detail,
last->next = tem->next;
xfree (tem);
- return;
+ return true;
}
}
+
+ return false;
}
static struct xi_touch_point_t *
@@ -10887,37 +10889,45 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (f && device->direct_p)
{
- xi_link_touch_point (device, xev->detail, xev->event_x,
- xev->event_y);
+ x_catch_errors (dpyinfo->display);
+ XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+ xev->detail, xev->event, XIAcceptTouch);
+ if (!x_had_errors_p (dpyinfo->display))
+ {
+ xi_link_touch_point (device, xev->detail, xev->event_x,
+ xev->event_y);
#ifdef HAVE_GTK3
- if (FRAME_X_OUTPUT (f)->menubar_widget
- && xg_event_is_for_menubar (f, event))
- {
- bool was_waiting_for_input = waiting_for_input;
- /* This hack was adopted from the NS port. Whether
- or not it is actually safe is a different story
- altogether. */
- if (waiting_for_input)
- waiting_for_input = 0;
- set_frame_menubar (f, true);
- waiting_for_input = was_waiting_for_input;
- }
+ if (FRAME_X_OUTPUT (f)->menubar_widget
+ && xg_event_is_for_menubar (f, event))
+ {
+ bool was_waiting_for_input = waiting_for_input;
+ /* This hack was adopted from the NS port. Whether
+ or not it is actually safe is a different story
+ altogether. */
+ if (waiting_for_input)
+ waiting_for_input = 0;
+ set_frame_menubar (f, true);
+ waiting_for_input = was_waiting_for_input;
+ }
#endif
- inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
- inev.ie.timestamp = xev->time;
- XSETFRAME (inev.ie.frame_or_window, f);
- XSETINT (inev.ie.x, lrint (xev->event_x));
- XSETINT (inev.ie.y, lrint (xev->event_y));
- XSETINT (inev.ie.arg, xev->detail);
-
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event, XIAcceptTouch);
+ inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
+ inev.ie.timestamp = xev->time;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ XSETINT (inev.ie.x, lrint (xev->event_x));
+ XSETINT (inev.ie.y, lrint (xev->event_y));
+ XSETINT (inev.ie.arg, xev->detail);
+ }
+ x_uncatch_errors_after_check ();
}
else
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event, XIRejectTouch);
+ {
+ x_catch_errors (dpyinfo->display);
+ XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+ xev->detail, xev->event, XIRejectTouch);
+ x_uncatch_errors ();
+ }
goto XI_OTHER;
}
@@ -10965,24 +10975,28 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case XI_TouchEnd:
{
struct xi_device_t *device;
+ bool unlinked_p;
device = xi_device_from_id (dpyinfo, xev->deviceid);
if (!device)
goto XI_OTHER;
- xi_unlink_touch_point (xev->detail, device);
-
- f = x_any_window_to_frame (dpyinfo, xev->event);
+ unlinked_p = xi_unlink_touch_point (xev->detail, device);
- if (f && device->direct_p)
+ if (unlinked_p)
{
- inev.ie.kind = TOUCHSCREEN_END_EVENT;
- inev.ie.timestamp = xev->time;
- XSETFRAME (inev.ie.frame_or_window, f);
- XSETINT (inev.ie.x, lrint (xev->event_x));
- XSETINT (inev.ie.y, lrint (xev->event_y));
- XSETINT (inev.ie.arg, xev->detail);
+ f = x_any_window_to_frame (dpyinfo, xev->event);
+
+ if (f && device->direct_p)
+ {
+ inev.ie.kind = TOUCHSCREEN_END_EVENT;
+ inev.ie.timestamp = xev->time;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ XSETINT (inev.ie.x, lrint (xev->event_x));
+ XSETINT (inev.ie.y, lrint (xev->event_y));
+ XSETINT (inev.ie.arg, xev->detail);
+ }
}
goto XI_OTHER;