aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2021-04-19 18:46:50 +0200
committerAndrea Corallo2021-04-19 18:46:50 +0200
commitb5c76530fab4b99e76249bfb9a105b30bef4ce67 (patch)
tree319d7a65b6f818cebed9833534a423fbcb79a9b5 /src
parente54066f3d459f67a1ee4e44552bf0356d010e03f (diff)
parent0a4dc70830f5e8286b47120cabc750cca07a75c1 (diff)
downloademacs-b5c76530fab4b99e76249bfb9a105b30bef4ce67.tar.gz
emacs-b5c76530fab4b99e76249bfb9a105b30bef4ce67.zip
Merge remote-tracking branch 'savannah/master' into native-comp
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c2
-rw-r--r--src/character.c56
-rw-r--r--src/character.h4
-rw-r--r--src/editfns.c9
-rw-r--r--src/eval.c34
-rw-r--r--src/frame.c16
-rw-r--r--src/image.c58
-rw-r--r--src/minibuf.c38
-rw-r--r--src/w32fns.c2
-rw-r--r--src/w32term.c20
-rw-r--r--src/window.c71
-rw-r--r--src/window.h1
-rw-r--r--src/xdisp.c129
-rw-r--r--src/xfns.c2
-rw-r--r--src/xselect.c21
15 files changed, 359 insertions, 104 deletions
diff --git a/src/alloc.c b/src/alloc.c
index fee8cc08aa4..76d8c7ddd11 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6268,7 +6268,7 @@ For further details, see Info node `(elisp)Garbage Collection'. */)
6268} 6268}
6269 6269
6270DEFUN ("garbage-collect-maybe", Fgarbage_collect_maybe, 6270DEFUN ("garbage-collect-maybe", Fgarbage_collect_maybe,
6271Sgarbage_collect_maybe, 1, 1, "", 6271Sgarbage_collect_maybe, 1, 1, 0,
6272 doc: /* Call `garbage-collect' if enough allocation happened. 6272 doc: /* Call `garbage-collect' if enough allocation happened.
6273FACTOR determines what "enough" means here: 6273FACTOR determines what "enough" means here:
6274If FACTOR is a positive number N, it means to run GC if more than 6274If FACTOR is a positive number N, it means to run GC if more than
diff --git a/src/character.c b/src/character.c
index a599a0355f4..41abb83a48b 100644
--- a/src/character.c
+++ b/src/character.c
@@ -321,28 +321,32 @@ strwidth (const char *str, ptrdiff_t len)
321 return c_string_width ((const unsigned char *) str, len, -1, NULL, NULL); 321 return c_string_width ((const unsigned char *) str, len, -1, NULL, NULL);
322} 322}
323 323
324/* Return width of Lisp string STRING when displayed in the current 324/* Return width of a (substring of a) Lisp string STRING when
325 buffer. The width is measured by how many columns it occupies on 325 displayed in the current buffer. The width is measured by how many
326 the screen while paying attention to compositions. If PRECISION > 326 columns it occupies on the screen while paying attention to
327 0, return the width of longest substring that doesn't exceed 327 compositions. If PRECISION > 0, return the width of longest
328 PRECISION, and set number of characters and bytes of the substring 328 substring that doesn't exceed PRECISION, and set number of
329 in *NCHARS and *NBYTES respectively. */ 329 characters and bytes of the substring in *NCHARS and *NBYTES
330 respectively. FROM and TO are zero-based character indices
331 that define the substring of STRING to consider. */
330 332
331ptrdiff_t 333ptrdiff_t
332lisp_string_width (Lisp_Object string, ptrdiff_t precision, 334lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to,
333 ptrdiff_t *nchars, ptrdiff_t *nbytes) 335 ptrdiff_t precision, ptrdiff_t *nchars, ptrdiff_t *nbytes)
334{ 336{
335 ptrdiff_t len = SCHARS (string);
336 /* This set multibyte to 0 even if STRING is multibyte when it 337 /* This set multibyte to 0 even if STRING is multibyte when it
337 contains only ascii and eight-bit-graphic, but that's 338 contains only ascii and eight-bit-graphic, but that's
338 intentional. */ 339 intentional. */
339 bool multibyte = len < SBYTES (string); 340 bool multibyte = SCHARS (string) < SBYTES (string);
340 unsigned char *str = SDATA (string); 341 unsigned char *str = SDATA (string);
341 ptrdiff_t i = 0, i_byte = 0; 342 ptrdiff_t i = from, i_byte = from ? string_char_to_byte (string, from) : 0;
343 ptrdiff_t from_byte = i_byte;
342 ptrdiff_t width = 0; 344 ptrdiff_t width = 0;
343 struct Lisp_Char_Table *dp = buffer_display_table (); 345 struct Lisp_Char_Table *dp = buffer_display_table ();
344 346
345 while (i < len) 347 eassert (precision <= 0 || (nchars && nbytes));
348
349 while (i < to)
346 { 350 {
347 ptrdiff_t chars, bytes, thiswidth; 351 ptrdiff_t chars, bytes, thiswidth;
348 Lisp_Object val; 352 Lisp_Object val;
@@ -375,8 +379,8 @@ lisp_string_width (Lisp_Object string, ptrdiff_t precision,
375 379
376 if (0 < precision && precision - width < thiswidth) 380 if (0 < precision && precision - width < thiswidth)
377 { 381 {
378 *nchars = i; 382 *nchars = i - from;
379 *nbytes = i_byte; 383 *nbytes = i_byte - from_byte;
380 return width; 384 return width;
381 } 385 }
382 if (INT_ADD_WRAPV (thiswidth, width, &width)) 386 if (INT_ADD_WRAPV (thiswidth, width, &width))
@@ -387,27 +391,37 @@ lisp_string_width (Lisp_Object string, ptrdiff_t precision,
387 391
388 if (precision > 0) 392 if (precision > 0)
389 { 393 {
390 *nchars = i; 394 *nchars = i - from;
391 *nbytes = i_byte; 395 *nbytes = i_byte - from_byte;
392 } 396 }
393 397
394 return width; 398 return width;
395} 399}
396 400
397DEFUN ("string-width", Fstring_width, Sstring_width, 1, 1, 0, 401DEFUN ("string-width", Fstring_width, Sstring_width, 1, 3, 0,
398 doc: /* Return width of STRING when displayed in the current buffer. 402 doc: /* Return width of STRING when displayed in the current buffer.
399Width is measured by how many columns it occupies on the screen. 403Width is measured by how many columns it occupies on the screen.
404Optional arguments FROM and TO specify the substring of STRING to
405consider, and are interpreted as in `substring'.
406
400When calculating width of a multibyte character in STRING, 407When calculating width of a multibyte character in STRING,
401only the base leading-code is considered; the validity of 408only the base leading-code is considered; the validity of
402the following bytes is not checked. Tabs in STRING are always 409the following bytes is not checked. Tabs in STRING are always
403taken to occupy `tab-width' columns. 410taken to occupy `tab-width' columns. The effect of faces and fonts
404usage: (string-width STRING) */) 411used for non-Latin and other unusual characters (such as emoji) is
405 (Lisp_Object str) 412ignored as well, as are display properties and invisible text.
413For these reasons, the results are not generally reliable;
414for accurate dimensions of text as it will be displayed,
415use `window-text-pixel-size' instead.
416usage: (string-width STRING &optional FROM TO) */)
417 (Lisp_Object str, Lisp_Object from, Lisp_Object to)
406{ 418{
407 Lisp_Object val; 419 Lisp_Object val;
420 ptrdiff_t ifrom, ito;
408 421
409 CHECK_STRING (str); 422 CHECK_STRING (str);
410 XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL)); 423 validate_subarray (str, from, to, SCHARS (str), &ifrom, &ito);
424 XSETFASTINT (val, lisp_string_width (str, ifrom, ito, -1, NULL, NULL));
411 return val; 425 return val;
412} 426}
413 427
diff --git a/src/character.h b/src/character.h
index cbf43097ae2..d19e1e2604c 100644
--- a/src/character.h
+++ b/src/character.h
@@ -572,8 +572,8 @@ extern ptrdiff_t str_to_unibyte (const unsigned char *, unsigned char *,
572extern ptrdiff_t strwidth (const char *, ptrdiff_t); 572extern ptrdiff_t strwidth (const char *, ptrdiff_t);
573extern ptrdiff_t c_string_width (const unsigned char *, ptrdiff_t, int, 573extern ptrdiff_t c_string_width (const unsigned char *, ptrdiff_t, int,
574 ptrdiff_t *, ptrdiff_t *); 574 ptrdiff_t *, ptrdiff_t *);
575extern ptrdiff_t lisp_string_width (Lisp_Object, ptrdiff_t, 575extern ptrdiff_t lisp_string_width (Lisp_Object, ptrdiff_t, ptrdiff_t,
576 ptrdiff_t *, ptrdiff_t *); 576 ptrdiff_t, ptrdiff_t *, ptrdiff_t *);
577 577
578extern Lisp_Object Vchar_unify_table; 578extern Lisp_Object Vchar_unify_table;
579extern Lisp_Object string_escape_byte8 (Lisp_Object); 579extern Lisp_Object string_escape_byte8 (Lisp_Object);
diff --git a/src/editfns.c b/src/editfns.c
index 87e743afc31..bc73c1e2c5b 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3386,12 +3386,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
3386 else 3386 else
3387 { 3387 {
3388 ptrdiff_t nch, nby; 3388 ptrdiff_t nch, nby;
3389 width = lisp_string_width (arg, prec, &nch, &nby); 3389 nchars_string = SCHARS (arg);
3390 width = lisp_string_width (arg, 0, nchars_string, prec,
3391 &nch, &nby);
3390 if (prec < 0) 3392 if (prec < 0)
3391 { 3393 nbytes = SBYTES (arg);
3392 nchars_string = SCHARS (arg);
3393 nbytes = SBYTES (arg);
3394 }
3395 else 3394 else
3396 { 3395 {
3397 nchars_string = nch; 3396 nchars_string = nch;
diff --git a/src/eval.c b/src/eval.c
index cf5ca3b4bbd..aeedcc50cc0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1310,7 +1310,7 @@ DEFUN ("condition-case", Fcondition_case, Scondition_case, 2, UNEVALLED, 0,
1310 doc: /* Regain control when an error is signaled. 1310 doc: /* Regain control when an error is signaled.
1311Executes BODYFORM and returns its value if no error happens. 1311Executes BODYFORM and returns its value if no error happens.
1312Each element of HANDLERS looks like (CONDITION-NAME BODY...) 1312Each element of HANDLERS looks like (CONDITION-NAME BODY...)
1313where the BODY is made of Lisp expressions. 1313or (:success BODY...), where the BODY is made of Lisp expressions.
1314 1314
1315A handler is applicable to an error if CONDITION-NAME is one of the 1315A handler is applicable to an error if CONDITION-NAME is one of the
1316error's condition names. Handlers may also apply when non-error 1316error's condition names. Handlers may also apply when non-error
@@ -1332,6 +1332,10 @@ with VAR bound to (ERROR-SYMBOL . SIGNAL-DATA) from the error.
1332Then the value of the last BODY form is returned from the `condition-case' 1332Then the value of the last BODY form is returned from the `condition-case'
1333expression. 1333expression.
1334 1334
1335The special handler (:success BODY...) is invoked if BODYFORM terminated
1336without signalling an error. BODY is then evaluated with VAR bound to
1337the value returned by BODYFORM.
1338
1335See also the function `signal' for more info. 1339See also the function `signal' for more info.
1336usage: (condition-case VAR BODYFORM &rest HANDLERS) */) 1340usage: (condition-case VAR BODYFORM &rest HANDLERS) */)
1337 (Lisp_Object args) 1341 (Lisp_Object args)
@@ -1355,16 +1359,21 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1355 1359
1356 CHECK_SYMBOL (var); 1360 CHECK_SYMBOL (var);
1357 1361
1362 Lisp_Object success_handler = Qnil;
1363
1358 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail)) 1364 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
1359 { 1365 {
1360 Lisp_Object tem = XCAR (tail); 1366 Lisp_Object tem = XCAR (tail);
1361 clausenb++;
1362 if (! (NILP (tem) 1367 if (! (NILP (tem)
1363 || (CONSP (tem) 1368 || (CONSP (tem)
1364 && (SYMBOLP (XCAR (tem)) 1369 && (SYMBOLP (XCAR (tem))
1365 || CONSP (XCAR (tem)))))) 1370 || CONSP (XCAR (tem))))))
1366 error ("Invalid condition handler: %s", 1371 error ("Invalid condition handler: %s",
1367 SDATA (Fprin1_to_string (tem, Qt))); 1372 SDATA (Fprin1_to_string (tem, Qt)));
1373 if (EQ (XCAR (tem), QCsuccess))
1374 success_handler = XCDR (tem);
1375 else
1376 clausenb++;
1368 } 1377 }
1369 1378
1370 /* The first clause is the one that should be checked first, so it 1379 /* The first clause is the one that should be checked first, so it
@@ -1378,7 +1387,8 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1378 Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses); 1387 Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses);
1379 clauses += clausenb; 1388 clauses += clausenb;
1380 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail)) 1389 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
1381 *--clauses = XCAR (tail); 1390 if (!EQ (XCAR (XCAR (tail)), QCsuccess))
1391 *--clauses = XCAR (tail);
1382 for (ptrdiff_t i = 0; i < clausenb; i++) 1392 for (ptrdiff_t i = 0; i < clausenb; i++)
1383 { 1393 {
1384 Lisp_Object clause = clauses[i]; 1394 Lisp_Object clause = clauses[i];
@@ -1418,6 +1428,23 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1418 1428
1419 Lisp_Object result = eval_sub (bodyform); 1429 Lisp_Object result = eval_sub (bodyform);
1420 handlerlist = oldhandlerlist; 1430 handlerlist = oldhandlerlist;
1431 if (!NILP (success_handler))
1432 {
1433 if (NILP (var))
1434 return Fprogn (success_handler);
1435
1436 Lisp_Object handler_var = var;
1437 if (!NILP (Vinternal_interpreter_environment))
1438 {
1439 result = Fcons (Fcons (var, result),
1440 Vinternal_interpreter_environment);
1441 handler_var = Qinternal_interpreter_environment;
1442 }
1443
1444 ptrdiff_t count = SPECPDL_INDEX ();
1445 specbind (handler_var, result);
1446 return unbind_to (count, Fprogn (success_handler));
1447 }
1421 return result; 1448 return result;
1422} 1449}
1423 1450
@@ -4490,6 +4517,7 @@ alist of active lexical bindings. */);
4490 defsubr (&Sthrow); 4517 defsubr (&Sthrow);
4491 defsubr (&Sunwind_protect); 4518 defsubr (&Sunwind_protect);
4492 defsubr (&Scondition_case); 4519 defsubr (&Scondition_case);
4520 DEFSYM (QCsuccess, ":success");
4493 defsubr (&Ssignal); 4521 defsubr (&Ssignal);
4494 defsubr (&Scommandp); 4522 defsubr (&Scommandp);
4495 defsubr (&Sautoload); 4523 defsubr (&Sautoload);
diff --git a/src/frame.c b/src/frame.c
index bbdc3b55992..097cd555c64 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1384,7 +1384,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1384 especially when deleting the initial frame during startup. */ 1384 especially when deleting the initial frame during startup. */
1385 CHECK_FRAME (frame); 1385 CHECK_FRAME (frame);
1386 f = XFRAME (frame); 1386 f = XFRAME (frame);
1387 if (!FRAME_LIVE_P (f)) 1387 /* Silently ignore dead and tooltip frames (Bug#47207). */
1388 if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f))
1388 return Qnil; 1389 return Qnil;
1389 else if (f == sf) 1390 else if (f == sf)
1390 return frame; 1391 return frame;
@@ -1508,7 +1509,16 @@ redisplay will display FRAME.
1508This function returns FRAME, or nil if FRAME has been deleted. */) 1509This function returns FRAME, or nil if FRAME has been deleted. */)
1509 (Lisp_Object frame, Lisp_Object norecord) 1510 (Lisp_Object frame, Lisp_Object norecord)
1510{ 1511{
1511 return do_switch_frame (frame, 1, 0, norecord); 1512 struct frame *f;
1513
1514 CHECK_LIVE_FRAME (frame);
1515 f = XFRAME (frame);
1516
1517 if (FRAME_TOOLTIP_P (f))
1518 /* Do not select a tooltip frame (Bug#47207). */
1519 error ("Cannot select a tooltip frame");
1520 else
1521 return do_switch_frame (frame, 1, 0, norecord);
1512} 1522}
1513 1523
1514DEFUN ("handle-switch-frame", Fhandle_switch_frame, 1524DEFUN ("handle-switch-frame", Fhandle_switch_frame,
@@ -1523,6 +1533,7 @@ necessarily represent user-visible input focus. */)
1523 /* Preserve prefix arg that the command loop just cleared. */ 1533 /* Preserve prefix arg that the command loop just cleared. */
1524 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); 1534 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1525 run_hook (Qmouse_leave_buffer_hook); 1535 run_hook (Qmouse_leave_buffer_hook);
1536
1526 return do_switch_frame (event, 0, 0, Qnil); 1537 return do_switch_frame (event, 0, 0, Qnil);
1527} 1538}
1528 1539
@@ -3747,6 +3758,7 @@ window state change flag is reset. */)
3747DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor, 3758DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
3748 0, 1, 0, 3759 0, 1, 0,
3749 doc: /* Return FRAMEs scale factor. 3760 doc: /* Return FRAMEs scale factor.
3761If FRAME is omitted or nil, the selected frame is used.
3750The scale factor is the amount by which a logical pixel size must be 3762The scale factor is the amount by which a logical pixel size must be
3751multiplied to find the real number of pixels. */) 3763multiplied to find the real number of pixels. */)
3752 (Lisp_Object frame) 3764 (Lisp_Object frame)
diff --git a/src/image.c b/src/image.c
index 18126a804f3..f2fb69ab743 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1987,46 +1987,68 @@ scale_image_size (int size, size_t divisor, size_t multiplier)
1987 return INT_MAX; 1987 return INT_MAX;
1988} 1988}
1989 1989
1990/* Return a size, in pixels, from the value specified by SYMBOL, which
1991 may be an integer or a pair of the form (VALUE . 'em) where VALUE
1992 is a float that is multiplied by the font size to get the final
1993 dimension.
1994
1995 If the value doesn't exist in the image spec, or is invalid, return
1996 -1.
1997*/
1998static int
1999image_get_dimension (struct image *img, Lisp_Object symbol)
2000{
2001 Lisp_Object value = image_spec_value (img->spec, symbol, NULL);
2002
2003 if (FIXNATP (value))
2004 return min (XFIXNAT (value), INT_MAX);
2005 if (CONSP (value) && NUMBERP (CAR (value)) && EQ (Qem, CDR (value)))
2006 return min (img->face_font_size * XFLOATINT (CAR (value)), INT_MAX);
2007
2008 return -1;
2009}
2010
1990/* Compute the desired size of an image with native size WIDTH x HEIGHT. 2011/* Compute the desired size of an image with native size WIDTH x HEIGHT.
1991 Use SPEC to deduce the size. Store the desired size into 2012 Use SPEC to deduce the size. Store the desired size into
1992 *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ 2013 *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */
1993static void 2014static void
1994compute_image_size (size_t width, size_t height, 2015compute_image_size (size_t width, size_t height,
1995 Lisp_Object spec, 2016 struct image *img,
1996 int *d_width, int *d_height) 2017 int *d_width, int *d_height)
1997{ 2018{
1998 Lisp_Object value; 2019 Lisp_Object value;
2020 int int_value;
1999 int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; 2021 int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1;
2000 double scale = 1; 2022 double scale = 1;
2001 2023
2002 value = image_spec_value (spec, QCscale, NULL); 2024 value = image_spec_value (img->spec, QCscale, NULL);
2003 if (NUMBERP (value)) 2025 if (NUMBERP (value))
2004 scale = XFLOATINT (value); 2026 scale = XFLOATINT (value);
2005 2027
2006 value = image_spec_value (spec, QCmax_width, NULL); 2028 int_value = image_get_dimension (img, QCmax_width);
2007 if (FIXNATP (value)) 2029 if (int_value >= 0)
2008 max_width = min (XFIXNAT (value), INT_MAX); 2030 max_width = int_value;
2009 2031
2010 value = image_spec_value (spec, QCmax_height, NULL); 2032 int_value = image_get_dimension (img, QCmax_height);
2011 if (FIXNATP (value)) 2033 if (int_value >= 0)
2012 max_height = min (XFIXNAT (value), INT_MAX); 2034 max_height = int_value;
2013 2035
2014 /* If width and/or height is set in the display spec assume we want 2036 /* If width and/or height is set in the display spec assume we want
2015 to scale to those values. If either h or w is unspecified, the 2037 to scale to those values. If either h or w is unspecified, the
2016 unspecified should be calculated from the specified to preserve 2038 unspecified should be calculated from the specified to preserve
2017 aspect ratio. */ 2039 aspect ratio. */
2018 value = image_spec_value (spec, QCwidth, NULL); 2040 int_value = image_get_dimension (img, QCwidth);
2019 if (FIXNATP (value)) 2041 if (int_value >= 0)
2020 { 2042 {
2021 desired_width = min (XFIXNAT (value) * scale, INT_MAX); 2043 desired_width = int_value * scale;
2022 /* :width overrides :max-width. */ 2044 /* :width overrides :max-width. */
2023 max_width = -1; 2045 max_width = -1;
2024 } 2046 }
2025 2047
2026 value = image_spec_value (spec, QCheight, NULL); 2048 int_value = image_get_dimension (img, QCheight);
2027 if (FIXNATP (value)) 2049 if (int_value >= 0)
2028 { 2050 {
2029 desired_height = min (XFIXNAT (value) * scale, INT_MAX); 2051 desired_height = int_value * scale;
2030 /* :height overrides :max-height. */ 2052 /* :height overrides :max-height. */
2031 max_height = -1; 2053 max_height = -1;
2032 } 2054 }
@@ -2216,7 +2238,7 @@ image_set_transform (struct frame *f, struct image *img)
2216 } 2238 }
2217 else 2239 else
2218#endif 2240#endif
2219 compute_image_size (img->width, img->height, img->spec, &width, &height); 2241 compute_image_size (img->width, img->height, img, &width, &height);
2220 2242
2221 /* Determine rotation. */ 2243 /* Determine rotation. */
2222 double rotation = 0.0; 2244 double rotation = 0.0;
@@ -9210,7 +9232,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
9210 9232
9211 compute_image_size (MagickGetImageWidth (image_wand), 9233 compute_image_size (MagickGetImageWidth (image_wand),
9212 MagickGetImageHeight (image_wand), 9234 MagickGetImageHeight (image_wand),
9213 img->spec, &desired_width, &desired_height); 9235 img, &desired_width, &desired_height);
9214 9236
9215 if (desired_width != -1 && desired_height != -1) 9237 if (desired_width != -1 && desired_height != -1)
9216 { 9238 {
@@ -10068,7 +10090,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
10068 viewbox_height = dimension_data.height; 10090 viewbox_height = dimension_data.height;
10069 } 10091 }
10070 10092
10071 compute_image_size (viewbox_width, viewbox_height, img->spec, 10093 compute_image_size (viewbox_width, viewbox_height, img,
10072 &width, &height); 10094 &width, &height);
10073 10095
10074 width *= FRAME_SCALE_FACTOR (f); 10096 width *= FRAME_SCALE_FACTOR (f);
@@ -10777,6 +10799,8 @@ non-numeric, there is no explicit limit on the size of images. */);
10777 DEFSYM (QCmax_width, ":max-width"); 10799 DEFSYM (QCmax_width, ":max-width");
10778 DEFSYM (QCmax_height, ":max-height"); 10800 DEFSYM (QCmax_height, ":max-height");
10779 10801
10802 DEFSYM (Qem, "em");
10803
10780#ifdef HAVE_NATIVE_TRANSFORMS 10804#ifdef HAVE_NATIVE_TRANSFORMS
10781 DEFSYM (Qscale, "scale"); 10805 DEFSYM (Qscale, "scale");
10782 DEFSYM (Qrotate, "rotate"); 10806 DEFSYM (Qrotate, "rotate");
diff --git a/src/minibuf.c b/src/minibuf.c
index c9831fd50f4..a3c1b99bf32 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -112,13 +112,15 @@ choose_minibuf_frame (void)
112{ 112{
113 if (FRAMEP (selected_frame) 113 if (FRAMEP (selected_frame)
114 && FRAME_LIVE_P (XFRAME (selected_frame)) 114 && FRAME_LIVE_P (XFRAME (selected_frame))
115 && WINDOW_LIVE_P (XFRAME (selected_frame)->minibuffer_window)
115 && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window)) 116 && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
116 { 117 {
117 struct frame *sf = XFRAME (selected_frame); 118 struct frame *sf = XFRAME (selected_frame);
118 /* I don't think that any frames may validly have a null minibuffer 119 /* I don't think that any frames may validly have a null
119 window anymore. */ 120 minibuffer window anymore. (2021-04-15): Tooltip frames have
120 if (NILP (sf->minibuffer_window)) 121 a null MB. Comment out the following. */
121 emacs_abort (); 122 /* if (NILP (sf->minibuffer_window)) */
123 /* emacs_abort (); */
122 124
123 minibuf_window = sf->minibuffer_window; 125 minibuf_window = sf->minibuffer_window;
124 } 126 }
@@ -195,7 +197,9 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
195 && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of)))) 197 && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of))))
196 return; 198 return;
197 if (FRAME_LIVE_P (f) 199 if (FRAME_LIVE_P (f)
198 && !EQ (f->minibuffer_window, of->minibuffer_window)) 200 && !EQ (f->minibuffer_window, of->minibuffer_window)
201 && WINDOW_LIVE_P (f->minibuffer_window) /* F not a tootip frame */
202 && WINDOW_LIVE_P (of->minibuffer_window))
199 { 203 {
200 zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); 204 zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
201 if (for_deletion && XFRAME (MB_frame) != of) 205 if (for_deletion && XFRAME (MB_frame) != of)
@@ -636,6 +640,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
636 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window)); 640 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
637 641
638 if (minibuf_level > 1 642 if (minibuf_level > 1
643 && WINDOW_LIVE_P (XFRAME (MB_frame)->minibuffer_window)
639 && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame, 644 && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame,
640 MB_frame) 645 MB_frame)
641 && minibuf_moves_frame_when_opened () 646 && minibuf_moves_frame_when_opened ()
@@ -908,11 +913,13 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
908 unbind_to (count, Qnil); 913 unbind_to (count, Qnil);
909 914
910 /* Switch the frame back to the calling frame. */ 915 /* Switch the frame back to the calling frame. */
911 if ((!EQ (selected_frame, calling_frame) 916 if (FRAMEP (calling_frame)
912 || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame, 917 && FRAME_LIVE_P (XFRAME (calling_frame))
913 calling_frame)) 918 && (!EQ (selected_frame, calling_frame)
914 && FRAMEP (calling_frame) 919 || (WINDOW_LIVE_P (XFRAME (calling_frame)->minibuffer_window)
915 && FRAME_LIVE_P (XFRAME (calling_frame))) 920 && !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)
921 ->frame,
922 calling_frame))))
916 call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil); 923 call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
917 924
918 /* Add the value to the appropriate history list, if any. This is 925 /* Add the value to the appropriate history list, if any. This is
@@ -1056,10 +1063,13 @@ read_minibuf_unwind (void)
1056 { 1063 {
1057 f = XFRAME (exp_MB_frame); 1064 f = XFRAME (exp_MB_frame);
1058 window = f->minibuffer_window; 1065 window = f->minibuffer_window;
1059 w = XWINDOW (window); 1066 if (WINDOW_LIVE_P (window))
1060 if (EQ (w->frame, exp_MB_frame) 1067 {
1061 && EQ (w->contents, nth_minibuffer (minibuf_level))) 1068 w = XWINDOW (window);
1062 goto found; 1069 if (EQ (w->frame, exp_MB_frame)
1070 && EQ (w->contents, nth_minibuffer (minibuf_level)))
1071 goto found;
1072 }
1063 } 1073 }
1064 return; /* expired minibuffer not found. Maybe we should output an 1074 return; /* expired minibuffer not found. Maybe we should output an
1065 error, here. */ 1075 error, here. */
diff --git a/src/w32fns.c b/src/w32fns.c
index 9db367bfafe..c07f32ab0cc 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -7434,6 +7434,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
7434 set_window_buffer (window, tip_buf, false, false); 7434 set_window_buffer (window, tip_buf, false, false);
7435 w = XWINDOW (window); 7435 w = XWINDOW (window);
7436 w->pseudo_window_p = true; 7436 w->pseudo_window_p = true;
7437 /* Try to avoid that `other-window' select us (Bug#47207). */
7438 Fset_window_parameter (window, Qno_other_window, Qt);
7437 7439
7438 /* Set up the frame's root window. Note: The following code does not 7440 /* Set up the frame's root window. Note: The following code does not
7439 try to size the window or its frame correctly. Its only purpose is 7441 try to size the window or its frame correctly. Its only purpose is
diff --git a/src/w32term.c b/src/w32term.c
index 0ee805a8526..361cf33c024 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -2031,8 +2031,11 @@ w32_draw_image_relief (struct glyph_string *s)
2031 if (s->hl == DRAW_IMAGE_SUNKEN 2031 if (s->hl == DRAW_IMAGE_SUNKEN
2032 || s->hl == DRAW_IMAGE_RAISED) 2032 || s->hl == DRAW_IMAGE_RAISED)
2033 { 2033 {
2034 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief 2034 thick = (tab_bar_button_relief < 0
2035 : DEFAULT_TOOL_BAR_BUTTON_RELIEF; 2035 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
2036 : (tool_bar_button_relief < 0
2037 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
2038 : min (tool_bar_button_relief, 1000000)));
2036 raised_p = s->hl == DRAW_IMAGE_RAISED; 2039 raised_p = s->hl == DRAW_IMAGE_RAISED;
2037 } 2040 }
2038 else 2041 else
@@ -2045,6 +2048,19 @@ w32_draw_image_relief (struct glyph_string *s)
2045 y1 = y + s->slice.height - 1; 2048 y1 = y + s->slice.height - 1;
2046 2049
2047 extra_x = extra_y = 0; 2050 extra_x = extra_y = 0;
2051 if (s->face->id == TAB_BAR_FACE_ID)
2052 {
2053 if (CONSP (Vtab_bar_button_margin)
2054 && FIXNUMP (XCAR (Vtab_bar_button_margin))
2055 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
2056 {
2057 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin));
2058 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin));
2059 }
2060 else if (FIXNUMP (Vtab_bar_button_margin))
2061 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin);
2062 }
2063
2048 if (s->face->id == TOOL_BAR_FACE_ID) 2064 if (s->face->id == TOOL_BAR_FACE_ID)
2049 { 2065 {
2050 if (CONSP (Vtool_bar_button_margin) 2066 if (CONSP (Vtool_bar_button_margin)
diff --git a/src/window.c b/src/window.c
index 661b1ae112c..399b24b1e9e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -215,20 +215,6 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val)
215 w->horizontal = horflag; 215 w->horizontal = horflag;
216} 216}
217 217
218static void
219wset_update_mode_line (struct window *w)
220{
221 /* If this window is the selected window on its frame, set the
222 global variable update_mode_lines, so that gui_consider_frame_title
223 will consider this frame's title for redisplay. */
224 Lisp_Object fselected_window = XFRAME (WINDOW_FRAME (w))->selected_window;
225
226 if (WINDOWP (fselected_window) && XWINDOW (fselected_window) == w)
227 update_mode_lines = 42;
228 else
229 w->update_mode_line = true;
230}
231
232/* True if leaf window W doesn't reflect the actual state 218/* True if leaf window W doesn't reflect the actual state
233 of displayed buffer due to its text or overlays change. */ 219 of displayed buffer due to its text or overlays change. */
234 220
@@ -518,10 +504,18 @@ select_window (Lisp_Object window, Lisp_Object norecord,
518{ 504{
519 struct window *w; 505 struct window *w;
520 struct frame *sf; 506 struct frame *sf;
507 Lisp_Object frame;
508 struct frame *f;
521 509
522 CHECK_LIVE_WINDOW (window); 510 CHECK_LIVE_WINDOW (window);
523 511
524 w = XWINDOW (window); 512 w = XWINDOW (window);
513 frame = WINDOW_FRAME (w);
514 f = XFRAME (frame);
515
516 if (FRAME_TOOLTIP_P (f))
517 /* Do not select a tooltip window (Bug#47207). */
518 error ("Cannot select a tooltip window");
525 519
526 /* Make the selected window's buffer current. */ 520 /* Make the selected window's buffer current. */
527 Fset_buffer (w->contents); 521 Fset_buffer (w->contents);
@@ -542,14 +536,14 @@ select_window (Lisp_Object window, Lisp_Object norecord,
542 redisplay_other_windows (); 536 redisplay_other_windows ();
543 537
544 sf = SELECTED_FRAME (); 538 sf = SELECTED_FRAME ();
545 if (XFRAME (WINDOW_FRAME (w)) != sf) 539 if (f != sf)
546 { 540 {
547 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window); 541 fset_selected_window (f, window);
548 /* Use this rather than Fhandle_switch_frame 542 /* Use this rather than Fhandle_switch_frame
549 so that FRAME_FOCUS_FRAME is moved appropriately as we 543 so that FRAME_FOCUS_FRAME is moved appropriately as we
550 move around in the state where a minibuffer in a separate 544 move around in the state where a minibuffer in a separate
551 frame is active. */ 545 frame is active. */
552 Fselect_frame (WINDOW_FRAME (w), norecord); 546 Fselect_frame (frame, norecord);
553 /* Fselect_frame called us back so we've done all the work already. */ 547 /* Fselect_frame called us back so we've done all the work already. */
554 eassert (EQ (window, selected_window)); 548 eassert (EQ (window, selected_window));
555 return window; 549 return window;
@@ -2556,8 +2550,13 @@ window_list (void)
2556 if (!CONSP (Vwindow_list)) 2550 if (!CONSP (Vwindow_list))
2557 { 2551 {
2558 Lisp_Object tail, frame; 2552 Lisp_Object tail, frame;
2553 ptrdiff_t count = SPECPDL_INDEX ();
2559 2554
2560 Vwindow_list = Qnil; 2555 Vwindow_list = Qnil;
2556 /* Don't allow quitting in Fnconc. Otherwise we might end up
2557 with a too short Vwindow_list and Fkill_buffer not being able
2558 to replace a buffer in all windows showing it (Bug#47244). */
2559 specbind (Qinhibit_quit, Qt);
2561 FOR_EACH_FRAME (tail, frame) 2560 FOR_EACH_FRAME (tail, frame)
2562 { 2561 {
2563 Lisp_Object arglist = Qnil; 2562 Lisp_Object arglist = Qnil;
@@ -2569,6 +2568,8 @@ window_list (void)
2569 arglist = Fnreverse (arglist); 2568 arglist = Fnreverse (arglist);
2570 Vwindow_list = nconc2 (Vwindow_list, arglist); 2569 Vwindow_list = nconc2 (Vwindow_list, arglist);
2571 } 2570 }
2571
2572 unbind_to (count, Qnil);
2572 } 2573 }
2573 2574
2574 return Vwindow_list; 2575 return Vwindow_list;
@@ -2603,7 +2604,7 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2603 candidate_p = false; 2604 candidate_p = false;
2604 else if (MINI_WINDOW_P (w) 2605 else if (MINI_WINDOW_P (w)
2605 && (EQ (minibuf, Qlambda) 2606 && (EQ (minibuf, Qlambda)
2606 || (WINDOWP (minibuf) && !EQ (minibuf, window)))) 2607 || (WINDOW_LIVE_P (minibuf) && !EQ (minibuf, window))))
2607 { 2608 {
2608 /* If MINIBUF is `lambda' don't consider any mini-windows. 2609 /* If MINIBUF is `lambda' don't consider any mini-windows.
2609 If it is a window, consider only that one. */ 2610 If it is a window, consider only that one. */
@@ -2666,12 +2667,12 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
2666 Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window; 2667 Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window;
2667 2668
2668 XSETWINDOW (*window, w); 2669 XSETWINDOW (*window, w);
2669 /* MINIBUF nil may or may not include minibuffers. Decide if it 2670 /* MINIBUF nil may or may not include minibuffer windows. Decide if
2670 does. */ 2671 it does. But first make sure that this frame's minibuffer window
2671 if (NILP (*minibuf)) 2672 is live (Bug#47207). */
2672 *minibuf = this_minibuffer_depth (XWINDOW (miniwin)->contents) 2673 if (WINDOW_LIVE_P (miniwin) && NILP (*minibuf))
2673 ? miniwin 2674 *minibuf = (this_minibuffer_depth (XWINDOW (miniwin)->contents)
2674 : Qlambda; 2675 ? miniwin : Qlambda);
2675 else if (!EQ (*minibuf, Qt)) 2676 else if (!EQ (*minibuf, Qt))
2676 *minibuf = Qlambda; 2677 *minibuf = Qlambda;
2677 2678
@@ -2682,9 +2683,10 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
2682 /* ALL_FRAMES nil doesn't specify which frames to include. */ 2683 /* ALL_FRAMES nil doesn't specify which frames to include. */
2683 if (NILP (*all_frames)) 2684 if (NILP (*all_frames))
2684 *all_frames 2685 *all_frames
2685 = (!EQ (*minibuf, Qlambda) 2686 /* Once more make sure that this frame's minibuffer window is live
2686 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame)) 2687 before including it (Bug#47207). */
2687 : Qnil); 2688 = ((WINDOW_LIVE_P (miniwin) && !EQ (*minibuf, Qlambda))
2689 ? miniwin : Qnil);
2688 else if (EQ (*all_frames, Qvisible)) 2690 else if (EQ (*all_frames, Qvisible))
2689 ; 2691 ;
2690 else if (EQ (*all_frames, make_fixnum (0))) 2692 else if (EQ (*all_frames, make_fixnum (0)))
@@ -2705,6 +2707,8 @@ static Lisp_Object
2705next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, 2707next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2706 bool next_p) 2708 bool next_p)
2707{ 2709{
2710 ptrdiff_t count = SPECPDL_INDEX ();
2711
2708 decode_next_window_args (&window, &minibuf, &all_frames); 2712 decode_next_window_args (&window, &minibuf, &all_frames);
2709 2713
2710 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just 2714 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
@@ -2713,6 +2717,9 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2713 && !EQ (all_frames, XWINDOW (window)->frame)) 2717 && !EQ (all_frames, XWINDOW (window)->frame))
2714 return Fframe_first_window (all_frames); 2718 return Fframe_first_window (all_frames);
2715 2719
2720 /* Don't allow quitting in Fmemq. */
2721 specbind (Qinhibit_quit, Qt);
2722
2716 if (next_p) 2723 if (next_p)
2717 { 2724 {
2718 Lisp_Object list; 2725 Lisp_Object list;
@@ -2762,6 +2769,8 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2762 window = candidate; 2769 window = candidate;
2763 } 2770 }
2764 2771
2772 unbind_to (count, Qnil);
2773
2765 return window; 2774 return window;
2766} 2775}
2767 2776
@@ -2852,10 +2861,14 @@ static Lisp_Object
2852window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames) 2861window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2853{ 2862{
2854 Lisp_Object tail, list, rest; 2863 Lisp_Object tail, list, rest;
2864 ptrdiff_t count = SPECPDL_INDEX ();
2855 2865
2856 decode_next_window_args (&window, &minibuf, &all_frames); 2866 decode_next_window_args (&window, &minibuf, &all_frames);
2857 list = Qnil; 2867 list = Qnil;
2858 2868
2869 /* Don't allow quitting in Fmemq and Fnconc. */
2870 specbind (Qinhibit_quit, Qt);
2871
2859 for (tail = window_list (); CONSP (tail); tail = XCDR (tail)) 2872 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2860 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames)) 2873 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2861 list = Fcons (XCAR (tail), list); 2874 list = Fcons (XCAR (tail), list);
@@ -2870,6 +2883,9 @@ window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2870 XSETCDR (tail, Qnil); 2883 XSETCDR (tail, Qnil);
2871 list = nconc2 (rest, list); 2884 list = nconc2 (rest, list);
2872 } 2885 }
2886
2887 unbind_to (count, Qnil);
2888
2873 return list; 2889 return list;
2874} 2890}
2875 2891
@@ -8225,6 +8241,7 @@ syms_of_window (void)
8225 DEFSYM (Qmode_line_format, "mode-line-format"); 8241 DEFSYM (Qmode_line_format, "mode-line-format");
8226 DEFSYM (Qheader_line_format, "header-line-format"); 8242 DEFSYM (Qheader_line_format, "header-line-format");
8227 DEFSYM (Qtab_line_format, "tab-line-format"); 8243 DEFSYM (Qtab_line_format, "tab-line-format");
8244 DEFSYM (Qno_other_window, "no-other-window");
8228 8245
8229 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, 8246 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
8230 doc: /* Non-nil means call as function to display a help buffer. 8247 doc: /* Non-nil means call as function to display a help buffer.
diff --git a/src/window.h b/src/window.h
index b6f88e8f55f..2400c422c15 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1141,6 +1141,7 @@ extern void wset_redisplay (struct window *w);
1141extern void fset_redisplay (struct frame *f); 1141extern void fset_redisplay (struct frame *f);
1142extern void bset_redisplay (struct buffer *b); 1142extern void bset_redisplay (struct buffer *b);
1143extern void bset_update_mode_line (struct buffer *b); 1143extern void bset_update_mode_line (struct buffer *b);
1144extern void wset_update_mode_line (struct window *w);
1144/* Call this to tell redisplay to look for other windows than selected-window 1145/* Call this to tell redisplay to look for other windows than selected-window
1145 that need to be redisplayed. Calling one of the *set_redisplay functions 1146 that need to be redisplayed. Calling one of the *set_redisplay functions
1146 above already does it, so it's only needed in unusual cases. */ 1147 above already does it, so it's only needed in unusual cases. */
diff --git a/src/xdisp.c b/src/xdisp.c
index 50d9040057a..8ffec93e45d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -869,6 +869,19 @@ bset_update_mode_line (struct buffer *b)
869 b->text->redisplay = true; 869 b->text->redisplay = true;
870} 870}
871 871
872void
873wset_update_mode_line (struct window *w)
874{
875 w->update_mode_line = true;
876 /* When a window's mode line needs to be updated, the window's frame's
877 title may also need to be updated, but we don't need to worry about it
878 here. Instead, `gui_consider_frame_title' is automatically called
879 whenever w->update_mode_line is set for that frame's selected window.
880 But for this to work reliably, we have to make sure the window
881 is considered, so we have to mark it for redisplay. */
882 wset_redisplay (w);
883}
884
872DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay, 885DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
873 Sset_buffer_redisplay, 4, 4, 0, 886 Sset_buffer_redisplay, 4, 4, 0,
874 doc: /* Mark the current buffer for redisplay. 887 doc: /* Mark the current buffer for redisplay.
@@ -13682,6 +13695,7 @@ void
13682handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, 13695handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13683 int modifiers) 13696 int modifiers)
13684{ 13697{
13698 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
13685 struct window *w = XWINDOW (f->tab_bar_window); 13699 struct window *w = XWINDOW (f->tab_bar_window);
13686 int hpos, vpos, prop_idx; 13700 int hpos, vpos, prop_idx;
13687 bool close_p; 13701 bool close_p;
@@ -13703,13 +13717,22 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13703 return; 13717 return;
13704 13718
13705 if (down_p) 13719 if (down_p)
13706 f->last_tab_bar_item = prop_idx; /* record the pressed tab */ 13720 {
13721 /* Show the clicked button in pressed state. */
13722 if (!NILP (Vmouse_highlight))
13723 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
13724 f->last_tab_bar_item = prop_idx; /* record the pressed tab */
13725 }
13707 else 13726 else
13708 { 13727 {
13709 Lisp_Object key, frame; 13728 Lisp_Object key, frame;
13710 struct input_event event; 13729 struct input_event event;
13711 EVENT_INIT (event); 13730 EVENT_INIT (event);
13712 13731
13732 /* Show item in released state. */
13733 if (!NILP (Vmouse_highlight))
13734 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
13735
13713 key = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY); 13736 key = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY);
13714 13737
13715 XSETFRAME (frame, f); 13738 XSETFRAME (frame, f);
@@ -13722,6 +13745,97 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13722 } 13745 }
13723} 13746}
13724 13747
13748
13749/* Possibly highlight a tab-bar item on frame F when mouse moves to
13750 tab-bar window-relative coordinates X/Y. Called from
13751 note_mouse_highlight. */
13752
13753static void
13754note_tab_bar_highlight (struct frame *f, int x, int y)
13755{
13756 Lisp_Object window = f->tab_bar_window;
13757 struct window *w = XWINDOW (window);
13758 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
13759 int hpos, vpos;
13760 struct glyph *glyph;
13761 struct glyph_row *row;
13762 int i;
13763 Lisp_Object enabled_p;
13764 int prop_idx;
13765 bool close_p;
13766 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
13767 int rc;
13768
13769 /* Function note_mouse_highlight is called with negative X/Y
13770 values when mouse moves outside of the frame. */
13771 if (x <= 0 || y <= 0)
13772 {
13773 clear_mouse_face (hlinfo);
13774 return;
13775 }
13776
13777 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
13778 if (rc < 0)
13779 {
13780 /* Not on tab-bar item. */
13781 clear_mouse_face (hlinfo);
13782 return;
13783 }
13784 else if (rc == 0)
13785 /* On same tab-bar item as before. */
13786 goto set_help_echo;
13787
13788 clear_mouse_face (hlinfo);
13789
13790 bool mouse_down_p = false;
13791#ifndef HAVE_NS
13792 /* Mouse is down, but on different tab-bar item? */
13793 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
13794 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
13795 && f == dpyinfo->last_mouse_frame);
13796
13797 if (mouse_down_p && f->last_tab_bar_item != prop_idx)
13798 return;
13799#endif
13800 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
13801
13802 /* If tab-bar item is not enabled, don't highlight it. */
13803 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
13804 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
13805 {
13806 /* Compute the x-position of the glyph. In front and past the
13807 image is a space. We include this in the highlighted area. */
13808 row = MATRIX_ROW (w->current_matrix, vpos);
13809 for (i = x = 0; i < hpos; ++i)
13810 x += row->glyphs[TEXT_AREA][i].pixel_width;
13811
13812 /* Record this as the current active region. */
13813 hlinfo->mouse_face_beg_col = hpos;
13814 hlinfo->mouse_face_beg_row = vpos;
13815 hlinfo->mouse_face_beg_x = x;
13816 hlinfo->mouse_face_past_end = false;
13817
13818 hlinfo->mouse_face_end_col = hpos + 1;
13819 hlinfo->mouse_face_end_row = vpos;
13820 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
13821 hlinfo->mouse_face_window = window;
13822 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
13823
13824 /* Display it as active. */
13825 show_mouse_face (hlinfo, draw);
13826 }
13827
13828 set_help_echo:
13829
13830 /* Set help_echo_string to a help string to display for this tab-bar item.
13831 XTread_socket does the rest. */
13832 help_echo_object = help_echo_window = Qnil;
13833 help_echo_pos = -1;
13834 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
13835 if (NILP (help_echo_string))
13836 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
13837}
13838
13725#endif /* HAVE_WINDOW_SYSTEM */ 13839#endif /* HAVE_WINDOW_SYSTEM */
13726 13840
13727/* Find the tab-bar item at X coordinate and return its information. */ 13841/* Find the tab-bar item at X coordinate and return its information. */
@@ -31860,6 +31974,11 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
31860static void 31974static void
31861show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) 31975show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
31862{ 31976{
31977 /* Don't bother doing anything if the mouse-face window is not set
31978 up. */
31979 if (!WINDOWP (hlinfo->mouse_face_window))
31980 return;
31981
31863 struct window *w = XWINDOW (hlinfo->mouse_face_window); 31982 struct window *w = XWINDOW (hlinfo->mouse_face_window);
31864 struct frame *f = XFRAME (WINDOW_FRAME (w)); 31983 struct frame *f = XFRAME (WINDOW_FRAME (w));
31865 31984
@@ -33414,9 +33533,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
33414 frame_to_window_pixel_xy (w, &x, &y); 33533 frame_to_window_pixel_xy (w, &x, &y);
33415 33534
33416#if defined (HAVE_WINDOW_SYSTEM) 33535#if defined (HAVE_WINDOW_SYSTEM)
33417 /* We don't highlight tab-bar buttons. */ 33536 /* Handle tab-bar window differently since it doesn't display a
33537 buffer. */
33418 if (EQ (window, f->tab_bar_window)) 33538 if (EQ (window, f->tab_bar_window))
33419 return; 33539 {
33540 note_tab_bar_highlight (f, x, y);
33541 return;
33542 }
33420#endif 33543#endif
33421 33544
33422#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) 33545#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
diff --git a/src/xfns.c b/src/xfns.c
index 0507dc8f61d..f120653ee7b 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7076,6 +7076,8 @@ Text larger than the specified size is clipped. */)
7076 set_window_buffer (window, tip_buf, false, false); 7076 set_window_buffer (window, tip_buf, false, false);
7077 w = XWINDOW (window); 7077 w = XWINDOW (window);
7078 w->pseudo_window_p = true; 7078 w->pseudo_window_p = true;
7079 /* Try to avoid that `other-window' select us (Bug#47207). */
7080 Fset_window_parameter (window, Qno_other_window, Qt);
7079 7081
7080 /* Set up the frame's root window. Note: The following code does not 7082 /* Set up the frame's root window. Note: The following code does not
7081 try to size the window or its frame correctly. Its only purpose is 7083 try to size the window or its frame correctly. Its only purpose is
diff --git a/src/xselect.c b/src/xselect.c
index 030f6240712..cd6d86bdf4c 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1482,14 +1482,21 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
1482 = XGetSelectionOwner (display, selection_atom) != 0; 1482 = XGetSelectionOwner (display, selection_atom) != 0;
1483 unblock_input (); 1483 unblock_input ();
1484 if (there_is_a_selection_owner) 1484 if (there_is_a_selection_owner)
1485 signal_error ("Selection owner couldn't convert", 1485 {
1486 actual_type 1486 AUTO_STRING (format, "Selection owner couldn't convert: %s");
1487 ? list2 (target_type, 1487 CALLN (Fmessage, format,
1488 x_atom_to_symbol (dpyinfo, actual_type)) 1488 actual_type
1489 : target_type); 1489 ? list2 (target_type,
1490 x_atom_to_symbol (dpyinfo, actual_type))
1491 : target_type);
1492 return Qnil;
1493 }
1490 else 1494 else
1491 signal_error ("No selection", 1495 {
1492 x_atom_to_symbol (dpyinfo, selection_atom)); 1496 AUTO_STRING (format, "No selection: %s");
1497 CALLN (Fmessage, format, x_atom_to_symbol (dpyinfo, selection_atom));
1498 return Qnil;
1499 }
1493 } 1500 }
1494 1501
1495 if (actual_type == dpyinfo->Xatom_INCR) 1502 if (actual_type == dpyinfo->Xatom_INCR)