diff options
| author | Yuan Fu | 2022-06-14 15:59:46 -0700 |
|---|---|---|
| committer | Yuan Fu | 2022-06-14 15:59:46 -0700 |
| commit | 98bfb240818bae14cd87a1ffeb8fae7cb7846e05 (patch) | |
| tree | 16e8ab06875ed54e110cf98ccdbd7e78f15905c6 /src | |
| parent | 184d212042ffa5a4f02c92085d9b6e8346d66e99 (diff) | |
| parent | 787c4ad8b0776280305a220d6669c956d9ed8a5d (diff) | |
| download | emacs-98bfb240818bae14cd87a1ffeb8fae7cb7846e05.tar.gz emacs-98bfb240818bae14cd87a1ffeb8fae7cb7846e05.zip | |
Merge remote-tracking branch 'savannah/master' into feature/tree-sitter
Diffstat (limited to 'src')
99 files changed, 12151 insertions, 4824 deletions
diff --git a/src/alloc.c b/src/alloc.c index 3c622d05ff1..14c3a4cb8d7 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1036,9 +1036,12 @@ lisp_free (void *block) | |||
| 1036 | return; | 1036 | return; |
| 1037 | 1037 | ||
| 1038 | MALLOC_BLOCK_INPUT; | 1038 | MALLOC_BLOCK_INPUT; |
| 1039 | #ifndef GC_MALLOC_CHECK | ||
| 1040 | struct mem_node *m = mem_find (block); | ||
| 1041 | #endif | ||
| 1039 | free (block); | 1042 | free (block); |
| 1040 | #ifndef GC_MALLOC_CHECK | 1043 | #ifndef GC_MALLOC_CHECK |
| 1041 | mem_delete (mem_find (block)); | 1044 | mem_delete (m); |
| 1042 | #endif | 1045 | #endif |
| 1043 | MALLOC_UNBLOCK_INPUT; | 1046 | MALLOC_UNBLOCK_INPUT; |
| 1044 | } | 1047 | } |
| @@ -6197,6 +6200,7 @@ garbage_collect (void) | |||
| 6197 | 6200 | ||
| 6198 | mark_pinned_objects (); | 6201 | mark_pinned_objects (); |
| 6199 | mark_pinned_symbols (); | 6202 | mark_pinned_symbols (); |
| 6203 | mark_lread (); | ||
| 6200 | mark_terminals (); | 6204 | mark_terminals (); |
| 6201 | mark_kboards (); | 6205 | mark_kboards (); |
| 6202 | mark_threads (); | 6206 | mark_threads (); |
| @@ -6319,7 +6323,7 @@ where each entry has the form (NAME SIZE USED FREE), where: | |||
| 6319 | to return them to the OS). | 6323 | to return them to the OS). |
| 6320 | 6324 | ||
| 6321 | However, if there was overflow in pure space, and Emacs was dumped | 6325 | However, if there was overflow in pure space, and Emacs was dumped |
| 6322 | using the 'unexec' method, `garbage-collect' returns nil, because | 6326 | using the \"unexec\" method, `garbage-collect' returns nil, because |
| 6323 | real GC can't be done. | 6327 | real GC can't be done. |
| 6324 | 6328 | ||
| 6325 | Note that calling this function does not guarantee that absolutely all | 6329 | Note that calling this function does not guarantee that absolutely all |
diff --git a/src/atimer.c b/src/atimer.c index 1c6c881fc02..18301120ffe 100644 --- a/src/atimer.c +++ b/src/atimer.c | |||
| @@ -18,6 +18,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 18 | 18 | ||
| 19 | #include <config.h> | 19 | #include <config.h> |
| 20 | 20 | ||
| 21 | #ifdef WINDOWSNT | ||
| 22 | #define raise(s) w32_raise(s) | ||
| 23 | #endif | ||
| 24 | |||
| 21 | #include "lisp.h" | 25 | #include "lisp.h" |
| 22 | #include "keyboard.h" | 26 | #include "keyboard.h" |
| 23 | #include "syssignal.h" | 27 | #include "syssignal.h" |
| @@ -297,11 +301,6 @@ set_alarm (void) | |||
| 297 | { | 301 | { |
| 298 | if (atimers) | 302 | if (atimers) |
| 299 | { | 303 | { |
| 300 | #ifdef HAVE_SETITIMER | ||
| 301 | struct itimerval it; | ||
| 302 | #endif | ||
| 303 | struct timespec now, interval; | ||
| 304 | |||
| 305 | #ifdef HAVE_ITIMERSPEC | 304 | #ifdef HAVE_ITIMERSPEC |
| 306 | if (0 <= timerfd || alarm_timer_ok) | 305 | if (0 <= timerfd || alarm_timer_ok) |
| 307 | { | 306 | { |
| @@ -337,20 +336,24 @@ set_alarm (void) | |||
| 337 | } | 336 | } |
| 338 | #endif | 337 | #endif |
| 339 | 338 | ||
| 340 | /* Determine interval till the next timer is ripe. | 339 | /* Determine interval till the next timer is ripe. */ |
| 341 | Don't set the interval to 0; this disables the timer. */ | 340 | struct timespec now = current_timespec (); |
| 342 | now = current_timespec (); | 341 | if (timespec_cmp (atimers->expiration, now) <= 0) |
| 343 | interval = (timespec_cmp (atimers->expiration, now) <= 0 | 342 | { |
| 344 | ? make_timespec (0, 1000 * 1000) | 343 | /* Timer is (over)due -- just trigger the signal right way. */ |
| 345 | : timespec_sub (atimers->expiration, now)); | 344 | raise (SIGALRM); |
| 345 | } | ||
| 346 | else | ||
| 347 | { | ||
| 348 | struct timespec interval = timespec_sub (atimers->expiration, now); | ||
| 346 | 349 | ||
| 347 | #ifdef HAVE_SETITIMER | 350 | #ifdef HAVE_SETITIMER |
| 348 | 351 | struct itimerval it = {.it_value = make_timeval (interval)}; | |
| 349 | memset (&it, 0, sizeof it); | 352 | setitimer (ITIMER_REAL, &it, 0); |
| 350 | it.it_value = make_timeval (interval); | 353 | #else |
| 351 | setitimer (ITIMER_REAL, &it, 0); | 354 | alarm (max (interval.tv_sec, 1)); |
| 352 | #endif /* not HAVE_SETITIMER */ | 355 | #endif |
| 353 | alarm (max (interval.tv_sec, 1)); | 356 | } |
| 354 | } | 357 | } |
| 355 | } | 358 | } |
| 356 | 359 | ||
diff --git a/src/buffer.c b/src/buffer.c index f8a7a4f5109..a0761f5b59a 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -1218,7 +1218,7 @@ is the default binding of the variable. */) | |||
| 1218 | { | 1218 | { |
| 1219 | register Lisp_Object result = buffer_local_value (variable, buffer); | 1219 | register Lisp_Object result = buffer_local_value (variable, buffer); |
| 1220 | 1220 | ||
| 1221 | if (EQ (result, Qunbound)) | 1221 | if (BASE_EQ (result, Qunbound)) |
| 1222 | xsignal1 (Qvoid_variable, variable); | 1222 | xsignal1 (Qvoid_variable, variable); |
| 1223 | 1223 | ||
| 1224 | return result; | 1224 | return result; |
| @@ -1313,7 +1313,7 @@ buffer_lisp_local_variables (struct buffer *buf, bool clone) | |||
| 1313 | if (buf != current_buffer) | 1313 | if (buf != current_buffer) |
| 1314 | val = XCDR (elt); | 1314 | val = XCDR (elt); |
| 1315 | 1315 | ||
| 1316 | result = Fcons (!clone && EQ (val, Qunbound) | 1316 | result = Fcons (!clone && BASE_EQ (val, Qunbound) |
| 1317 | ? XCAR (elt) | 1317 | ? XCAR (elt) |
| 1318 | : Fcons (XCAR (elt), val), | 1318 | : Fcons (XCAR (elt), val), |
| 1319 | result); | 1319 | result); |
| @@ -1336,7 +1336,7 @@ buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym) | |||
| 1336 | { | 1336 | { |
| 1337 | sym = NILP (sym) ? PER_BUFFER_SYMBOL (offset) : sym; | 1337 | sym = NILP (sym) ? PER_BUFFER_SYMBOL (offset) : sym; |
| 1338 | Lisp_Object val = per_buffer_value (buf, offset); | 1338 | Lisp_Object val = per_buffer_value (buf, offset); |
| 1339 | return EQ (val, Qunbound) ? sym : Fcons (sym, val); | 1339 | return BASE_EQ (val, Qunbound) ? sym : Fcons (sym, val); |
| 1340 | } | 1340 | } |
| 1341 | return Qnil; | 1341 | return Qnil; |
| 1342 | } | 1342 | } |
| @@ -1376,12 +1376,23 @@ No argument or nil as argument means use current buffer as BUFFER. */) | |||
| 1376 | 1376 | ||
| 1377 | DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p, | 1377 | DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p, |
| 1378 | 0, 1, 0, | 1378 | 0, 1, 0, |
| 1379 | doc: /* Return t if BUFFER was modified since its file was last read or saved. | 1379 | doc: /* Return non-nil if BUFFER was modified since its file was last read or saved. |
| 1380 | No argument or nil as argument means use current buffer as BUFFER. */) | 1380 | No argument or nil as argument means use current buffer as BUFFER. |
| 1381 | |||
| 1382 | If BUFFER was autosaved since it was last modified, this function | ||
| 1383 | returns the symbol `autosaved'. */) | ||
| 1381 | (Lisp_Object buffer) | 1384 | (Lisp_Object buffer) |
| 1382 | { | 1385 | { |
| 1383 | struct buffer *buf = decode_buffer (buffer); | 1386 | struct buffer *buf = decode_buffer (buffer); |
| 1384 | return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil; | 1387 | if (BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf)) |
| 1388 | { | ||
| 1389 | if (BUF_AUTOSAVE_MODIFF (buf) == BUF_MODIFF (buf)) | ||
| 1390 | return Qautosaved; | ||
| 1391 | else | ||
| 1392 | return Qt; | ||
| 1393 | } | ||
| 1394 | else | ||
| 1395 | return Qnil; | ||
| 1385 | } | 1396 | } |
| 1386 | 1397 | ||
| 1387 | DEFUN ("force-mode-line-update", Fforce_mode_line_update, | 1398 | DEFUN ("force-mode-line-update", Fforce_mode_line_update, |
| @@ -1436,6 +1447,11 @@ and `buffer-file-truename' are non-nil. */) | |||
| 1436 | DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p, | 1447 | DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p, |
| 1437 | Srestore_buffer_modified_p, 1, 1, 0, | 1448 | Srestore_buffer_modified_p, 1, 1, 0, |
| 1438 | doc: /* Like `set-buffer-modified-p', but doesn't redisplay buffer's mode line. | 1449 | doc: /* Like `set-buffer-modified-p', but doesn't redisplay buffer's mode line. |
| 1450 | A nil FLAG means to mark the buffer as unmodified. A non-nil FLAG | ||
| 1451 | means mark the buffer as modified. A special value of `autosaved' | ||
| 1452 | will mark the buffer as modified and also as autosaved since it was | ||
| 1453 | last modified. | ||
| 1454 | |||
| 1439 | This function also locks or unlocks the file visited by the buffer, | 1455 | This function also locks or unlocks the file visited by the buffer, |
| 1440 | if both `buffer-file-truename' and `buffer-file-name' are non-nil. | 1456 | if both `buffer-file-truename' and `buffer-file-name' are non-nil. |
| 1441 | 1457 | ||
| @@ -1475,16 +1491,19 @@ state of the current buffer. Use with care. */) | |||
| 1475 | recent-auto-save-p from t to nil. | 1491 | recent-auto-save-p from t to nil. |
| 1476 | Vice versa, if FLAG is non-nil and SAVE_MODIFF>=auto_save_modified | 1492 | Vice versa, if FLAG is non-nil and SAVE_MODIFF>=auto_save_modified |
| 1477 | we risk changing recent-auto-save-p from nil to t. */ | 1493 | we risk changing recent-auto-save-p from nil to t. */ |
| 1478 | SAVE_MODIFF = (NILP (flag) | 1494 | if (NILP (flag)) |
| 1479 | /* FIXME: This unavoidably sets recent-auto-save-p to nil. */ | 1495 | /* This unavoidably sets recent-auto-save-p to nil. */ |
| 1480 | ? MODIFF | 1496 | SAVE_MODIFF = MODIFF; |
| 1481 | /* Let's try to preserve recent-auto-save-p. */ | 1497 | else |
| 1482 | : SAVE_MODIFF < MODIFF ? SAVE_MODIFF | 1498 | { |
| 1483 | /* If SAVE_MODIFF == auto_save_modified == MODIFF, | 1499 | /* If SAVE_MODIFF == auto_save_modified == MODIFF, we can either |
| 1484 | we can either decrease SAVE_MODIFF and auto_save_modified | 1500 | decrease SAVE_MODIFF and auto_save_modified or increase |
| 1485 | or increase MODIFF. */ | 1501 | MODIFF. */ |
| 1486 | : modiff_incr (&MODIFF)); | 1502 | if (SAVE_MODIFF >= MODIFF) |
| 1487 | 1503 | SAVE_MODIFF = modiff_incr (&MODIFF); | |
| 1504 | if (EQ (flag, Qautosaved)) | ||
| 1505 | BUF_AUTOSAVE_MODIFF (b) = MODIFF; | ||
| 1506 | } | ||
| 1488 | return flag; | 1507 | return flag; |
| 1489 | } | 1508 | } |
| 1490 | 1509 | ||
| @@ -1499,6 +1518,18 @@ use current buffer as BUFFER. */) | |||
| 1499 | return modiff_to_integer (BUF_MODIFF (decode_buffer (buffer))); | 1518 | return modiff_to_integer (BUF_MODIFF (decode_buffer (buffer))); |
| 1500 | } | 1519 | } |
| 1501 | 1520 | ||
| 1521 | DEFUN ("internal--set-buffer-modified-tick", | ||
| 1522 | Finternal__set_buffer_modified_tick, Sinternal__set_buffer_modified_tick, | ||
| 1523 | 1, 2, 0, | ||
| 1524 | doc: /* Set BUFFER's tick counter to TICK. | ||
| 1525 | No argument or nil as argument means use current buffer as BUFFER. */) | ||
| 1526 | (Lisp_Object tick, Lisp_Object buffer) | ||
| 1527 | { | ||
| 1528 | CHECK_FIXNUM (tick); | ||
| 1529 | BUF_MODIFF (decode_buffer (buffer)) = XFIXNUM (tick); | ||
| 1530 | return Qnil; | ||
| 1531 | } | ||
| 1532 | |||
| 1502 | DEFUN ("buffer-chars-modified-tick", Fbuffer_chars_modified_tick, | 1533 | DEFUN ("buffer-chars-modified-tick", Fbuffer_chars_modified_tick, |
| 1503 | Sbuffer_chars_modified_tick, 0, 1, 0, | 1534 | Sbuffer_chars_modified_tick, 0, 1, 0, |
| 1504 | doc: /* Return BUFFER's character-change tick counter. | 1535 | doc: /* Return BUFFER's character-change tick counter. |
| @@ -1634,16 +1665,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */) | |||
| 1634 | if (!NILP (notsogood)) | 1665 | if (!NILP (notsogood)) |
| 1635 | return notsogood; | 1666 | return notsogood; |
| 1636 | else | 1667 | else |
| 1637 | { | 1668 | return safe_call (1, Qget_scratch_buffer_create); |
| 1638 | AUTO_STRING (scratch, "*scratch*"); | ||
| 1639 | buf = Fget_buffer (scratch); | ||
| 1640 | if (NILP (buf)) | ||
| 1641 | { | ||
| 1642 | buf = Fget_buffer_create (scratch, Qnil); | ||
| 1643 | Fset_buffer_major_mode (buf); | ||
| 1644 | } | ||
| 1645 | return buf; | ||
| 1646 | } | ||
| 1647 | } | 1669 | } |
| 1648 | 1670 | ||
| 1649 | /* The following function is a safe variant of Fother_buffer: It doesn't | 1671 | /* The following function is a safe variant of Fother_buffer: It doesn't |
| @@ -1659,15 +1681,7 @@ other_buffer_safely (Lisp_Object buffer) | |||
| 1659 | if (candidate_buffer (buf, buffer)) | 1681 | if (candidate_buffer (buf, buffer)) |
| 1660 | return buf; | 1682 | return buf; |
| 1661 | 1683 | ||
| 1662 | AUTO_STRING (scratch, "*scratch*"); | 1684 | return safe_call (1, Qget_scratch_buffer_create); |
| 1663 | buf = Fget_buffer (scratch); | ||
| 1664 | if (NILP (buf)) | ||
| 1665 | { | ||
| 1666 | buf = Fget_buffer_create (scratch, Qnil); | ||
| 1667 | Fset_buffer_major_mode (buf); | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | return buf; | ||
| 1671 | } | 1685 | } |
| 1672 | 1686 | ||
| 1673 | DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo, | 1687 | DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo, |
| @@ -4093,7 +4107,7 @@ buffer. */) | |||
| 4093 | n_end = marker_position (OVERLAY_END (overlay)); | 4107 | n_end = marker_position (OVERLAY_END (overlay)); |
| 4094 | 4108 | ||
| 4095 | /* If the overlay has changed buffers, do a thorough redisplay. */ | 4109 | /* If the overlay has changed buffers, do a thorough redisplay. */ |
| 4096 | if (!EQ (buffer, obuffer)) | 4110 | if (!BASE_EQ (buffer, obuffer)) |
| 4097 | { | 4111 | { |
| 4098 | /* Redisplay where the overlay was. */ | 4112 | /* Redisplay where the overlay was. */ |
| 4099 | if (ob) | 4113 | if (ob) |
| @@ -5552,6 +5566,7 @@ syms_of_buffer (void) | |||
| 5552 | DEFSYM (Qbefore_change_functions, "before-change-functions"); | 5566 | DEFSYM (Qbefore_change_functions, "before-change-functions"); |
| 5553 | DEFSYM (Qafter_change_functions, "after-change-functions"); | 5567 | DEFSYM (Qafter_change_functions, "after-change-functions"); |
| 5554 | DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions"); | 5568 | DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions"); |
| 5569 | DEFSYM (Qget_scratch_buffer_create, "get-scratch-buffer-create"); | ||
| 5555 | 5570 | ||
| 5556 | DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar"); | 5571 | DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar"); |
| 5557 | Fput (Qvertical_scroll_bar, Qchoice, list4 (Qnil, Qt, Qleft, Qright)); | 5572 | Fput (Qvertical_scroll_bar, Qchoice, list4 (Qnil, Qt, Qleft, Qright)); |
| @@ -5583,8 +5598,11 @@ the mode line appears at the bottom. */); | |||
| 5583 | &BVAR (current_buffer, header_line_format), | 5598 | &BVAR (current_buffer, header_line_format), |
| 5584 | Qnil, | 5599 | Qnil, |
| 5585 | doc: /* Analogous to `mode-line-format', but controls the header line. | 5600 | doc: /* Analogous to `mode-line-format', but controls the header line. |
| 5586 | The header line appears, optionally, at the top of a window; | 5601 | The header line appears, optionally, at the top of a window; the mode |
| 5587 | the mode line appears at the bottom. */); | 5602 | line appears at the bottom. |
| 5603 | |||
| 5604 | Also see `header-line-indent-mode' if `display-line-number-mode' is | ||
| 5605 | used. */); | ||
| 5588 | 5606 | ||
| 5589 | DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format), | 5607 | DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format), |
| 5590 | Qnil, | 5608 | Qnil, |
| @@ -6418,6 +6436,7 @@ will run for `clone-indirect-buffer' calls as well. */); | |||
| 6418 | defsubr (&Sforce_mode_line_update); | 6436 | defsubr (&Sforce_mode_line_update); |
| 6419 | defsubr (&Sset_buffer_modified_p); | 6437 | defsubr (&Sset_buffer_modified_p); |
| 6420 | defsubr (&Sbuffer_modified_tick); | 6438 | defsubr (&Sbuffer_modified_tick); |
| 6439 | defsubr (&Sinternal__set_buffer_modified_tick); | ||
| 6421 | defsubr (&Sbuffer_chars_modified_tick); | 6440 | defsubr (&Sbuffer_chars_modified_tick); |
| 6422 | defsubr (&Srename_buffer); | 6441 | defsubr (&Srename_buffer); |
| 6423 | defsubr (&Sother_buffer); | 6442 | defsubr (&Sother_buffer); |
| @@ -6452,5 +6471,7 @@ will run for `clone-indirect-buffer' calls as well. */); | |||
| 6452 | defsubr (&Soverlay_put); | 6471 | defsubr (&Soverlay_put); |
| 6453 | defsubr (&Srestore_buffer_modified_p); | 6472 | defsubr (&Srestore_buffer_modified_p); |
| 6454 | 6473 | ||
| 6474 | DEFSYM (Qautosaved, "autosaved"); | ||
| 6475 | |||
| 6455 | Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); | 6476 | Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); |
| 6456 | } | 6477 | } |
diff --git a/src/bytecode.c b/src/bytecode.c index 74b7d16affd..fa068e1ec6b 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -627,7 +627,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 627 | Lisp_Object v1 = vectorp[op], v2; | 627 | Lisp_Object v1 = vectorp[op], v2; |
| 628 | if (!SYMBOLP (v1) | 628 | if (!SYMBOLP (v1) |
| 629 | || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL | 629 | || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL |
| 630 | || (v2 = SYMBOL_VAL (XSYMBOL (v1)), EQ (v2, Qunbound))) | 630 | || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound))) |
| 631 | v2 = Fsymbol_value (v1); | 631 | v2 = Fsymbol_value (v1); |
| 632 | PUSH (v2); | 632 | PUSH (v2); |
| 633 | NEXT; | 633 | NEXT; |
| @@ -694,7 +694,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 694 | 694 | ||
| 695 | /* Inline the most common case. */ | 695 | /* Inline the most common case. */ |
| 696 | if (SYMBOLP (sym) | 696 | if (SYMBOLP (sym) |
| 697 | && !EQ (val, Qunbound) | 697 | && !BASE_EQ (val, Qunbound) |
| 698 | && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL | 698 | && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL |
| 699 | && !SYMBOL_TRAPPED_WRITE_P (sym)) | 699 | && !SYMBOL_TRAPPED_WRITE_P (sym)) |
| 700 | SET_SYMBOL_VAL (XSYMBOL (sym), val); | 700 | SET_SYMBOL_VAL (XSYMBOL (sym), val); |
| @@ -1209,7 +1209,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1209 | Lisp_Object v2 = POP; | 1209 | Lisp_Object v2 = POP; |
| 1210 | Lisp_Object v1 = TOP; | 1210 | Lisp_Object v1 = TOP; |
| 1211 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1211 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1212 | TOP = BASE_EQ(v1, v2) ? Qt : Qnil; | 1212 | TOP = BASE_EQ (v1, v2) ? Qt : Qnil; |
| 1213 | else | 1213 | else |
| 1214 | TOP = arithcompare (v1, v2, ARITH_EQUAL); | 1214 | TOP = arithcompare (v1, v2, ARITH_EQUAL); |
| 1215 | NEXT; | 1215 | NEXT; |
diff --git a/src/callint.c b/src/callint.c index 92bfaf8d397..8283c61da67 100644 --- a/src/callint.c +++ b/src/callint.c | |||
| @@ -170,7 +170,7 @@ check_mark (bool for_region) | |||
| 170 | of VALUES to do its job. */ | 170 | of VALUES to do its job. */ |
| 171 | 171 | ||
| 172 | static void | 172 | static void |
| 173 | fix_command (Lisp_Object input, Lisp_Object values) | 173 | fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values) |
| 174 | { | 174 | { |
| 175 | /* FIXME: Instead of this ugly hack, we should provide a way for an | 175 | /* FIXME: Instead of this ugly hack, we should provide a way for an |
| 176 | interactive spec to return an expression/function that will re-build the | 176 | interactive spec to return an expression/function that will re-build the |
| @@ -230,6 +230,37 @@ fix_command (Lisp_Object input, Lisp_Object values) | |||
| 230 | } | 230 | } |
| 231 | } | 231 | } |
| 232 | } | 232 | } |
| 233 | |||
| 234 | /* If the list contains a bunch of trailing nil values, and they are | ||
| 235 | optional, remove them from the list. This makes navigating the | ||
| 236 | history less confusing, since it doesn't contain a lot of | ||
| 237 | parameters that aren't used. */ | ||
| 238 | if (CONSP (values)) | ||
| 239 | { | ||
| 240 | Lisp_Object arity = Ffunc_arity (function); | ||
| 241 | /* We don't want to do this simplification if we have an &rest | ||
| 242 | function, because (cl-defun foo (a &optional (b 'zot)) ..) | ||
| 243 | etc. */ | ||
| 244 | if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity))) | ||
| 245 | { | ||
| 246 | Lisp_Object final = Qnil; | ||
| 247 | ptrdiff_t final_i = 0, i = 0; | ||
| 248 | for (Lisp_Object tail = values; | ||
| 249 | CONSP (tail); | ||
| 250 | tail = XCDR (tail), ++i) | ||
| 251 | { | ||
| 252 | if (!NILP (XCAR (tail))) | ||
| 253 | { | ||
| 254 | final = tail; | ||
| 255 | final_i = i; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Chop the trailing optional values. */ | ||
| 260 | if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1) | ||
| 261 | XSETCDR (final, Qnil); | ||
| 262 | } | ||
| 263 | } | ||
| 233 | } | 264 | } |
| 234 | 265 | ||
| 235 | /* Helper function to call `read-file-name' from C. */ | 266 | /* Helper function to call `read-file-name' from C. */ |
| @@ -340,7 +371,7 @@ invoke it (via an `interactive' spec that contains, for instance, an | |||
| 340 | Make a copy of the list of values, for the command history, | 371 | Make a copy of the list of values, for the command history, |
| 341 | and turn them into things we can eval. */ | 372 | and turn them into things we can eval. */ |
| 342 | Lisp_Object values = quotify_args (Fcopy_sequence (specs)); | 373 | Lisp_Object values = quotify_args (Fcopy_sequence (specs)); |
| 343 | fix_command (input, values); | 374 | fix_command (input, function, values); |
| 344 | call4 (intern ("add-to-history"), intern ("command-history"), | 375 | call4 (intern ("add-to-history"), intern ("command-history"), |
| 345 | Fcons (function, values), Qnil, Qt); | 376 | Fcons (function, values), Qnil, Qt); |
| 346 | } | 377 | } |
| @@ -35,6 +35,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 35 | #include "coding.h" | 35 | #include "coding.h" |
| 36 | #include "keyboard.h" | 36 | #include "keyboard.h" |
| 37 | 37 | ||
| 38 | /* Avoid GCC 12 bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105784>. */ | ||
| 39 | #if GNUC_PREREQ (12, 0, 0) | ||
| 40 | # pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value" | ||
| 41 | #endif | ||
| 42 | |||
| 38 | /* Table of registered CCL programs. Each element is a vector of | 43 | /* Table of registered CCL programs. Each element is a vector of |
| 39 | NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the | 44 | NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the |
| 40 | name of the program, CCL_PROG (vector) is the compiled code of the | 45 | name of the program, CCL_PROG (vector) is the compiled code of the |
diff --git a/src/coding.c b/src/coding.c index 2bed293d571..aa32efc3f61 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -6528,7 +6528,7 @@ detect_coding (struct coding_system *coding) | |||
| 6528 | if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qundecided)) | 6528 | if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qundecided)) |
| 6529 | { | 6529 | { |
| 6530 | int c, i; | 6530 | int c, i; |
| 6531 | struct coding_detection_info detect_info; | 6531 | struct coding_detection_info detect_info = {0}; |
| 6532 | bool null_byte_found = 0, eight_bit_found = 0; | 6532 | bool null_byte_found = 0, eight_bit_found = 0; |
| 6533 | bool inhibit_nbd = inhibit_flag (coding->spec.undecided.inhibit_nbd, | 6533 | bool inhibit_nbd = inhibit_flag (coding->spec.undecided.inhibit_nbd, |
| 6534 | inhibit_null_byte_detection); | 6534 | inhibit_null_byte_detection); |
| @@ -6537,7 +6537,6 @@ detect_coding (struct coding_system *coding) | |||
| 6537 | bool prefer_utf_8 = coding->spec.undecided.prefer_utf_8; | 6537 | bool prefer_utf_8 = coding->spec.undecided.prefer_utf_8; |
| 6538 | 6538 | ||
| 6539 | coding->head_ascii = 0; | 6539 | coding->head_ascii = 0; |
| 6540 | detect_info.checked = detect_info.found = detect_info.rejected = 0; | ||
| 6541 | for (src = coding->source; src < src_end; src++) | 6540 | for (src = coding->source; src < src_end; src++) |
| 6542 | { | 6541 | { |
| 6543 | c = *src; | 6542 | c = *src; |
| @@ -6712,12 +6711,8 @@ detect_coding (struct coding_system *coding) | |||
| 6712 | else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) | 6711 | else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) |
| 6713 | == coding_category_utf_8_auto) | 6712 | == coding_category_utf_8_auto) |
| 6714 | { | 6713 | { |
| 6715 | Lisp_Object coding_systems; | 6714 | Lisp_Object coding_systems |
| 6716 | struct coding_detection_info detect_info; | ||
| 6717 | |||
| 6718 | coding_systems | ||
| 6719 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); | 6715 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); |
| 6720 | detect_info.found = detect_info.rejected = 0; | ||
| 6721 | if (check_ascii (coding) == coding->src_bytes) | 6716 | if (check_ascii (coding) == coding->src_bytes) |
| 6722 | { | 6717 | { |
| 6723 | if (CONSP (coding_systems)) | 6718 | if (CONSP (coding_systems)) |
| @@ -6725,6 +6720,7 @@ detect_coding (struct coding_system *coding) | |||
| 6725 | } | 6720 | } |
| 6726 | else | 6721 | else |
| 6727 | { | 6722 | { |
| 6723 | struct coding_detection_info detect_info = {0}; | ||
| 6728 | if (CONSP (coding_systems) | 6724 | if (CONSP (coding_systems) |
| 6729 | && detect_coding_utf_8 (coding, &detect_info)) | 6725 | && detect_coding_utf_8 (coding, &detect_info)) |
| 6730 | { | 6726 | { |
| @@ -6738,20 +6734,19 @@ detect_coding (struct coding_system *coding) | |||
| 6738 | else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) | 6734 | else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) |
| 6739 | == coding_category_utf_16_auto) | 6735 | == coding_category_utf_16_auto) |
| 6740 | { | 6736 | { |
| 6741 | Lisp_Object coding_systems; | 6737 | Lisp_Object coding_systems |
| 6742 | struct coding_detection_info detect_info; | ||
| 6743 | |||
| 6744 | coding_systems | ||
| 6745 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); | 6738 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); |
| 6746 | detect_info.found = detect_info.rejected = 0; | ||
| 6747 | coding->head_ascii = 0; | 6739 | coding->head_ascii = 0; |
| 6748 | if (CONSP (coding_systems) | 6740 | if (CONSP (coding_systems)) |
| 6749 | && detect_coding_utf_16 (coding, &detect_info)) | ||
| 6750 | { | 6741 | { |
| 6751 | if (detect_info.found & CATEGORY_MASK_UTF_16_LE) | 6742 | struct coding_detection_info detect_info = {0}; |
| 6752 | found = XCAR (coding_systems); | 6743 | if (detect_coding_utf_16 (coding, &detect_info)) |
| 6753 | else if (detect_info.found & CATEGORY_MASK_UTF_16_BE) | 6744 | { |
| 6754 | found = XCDR (coding_systems); | 6745 | if (detect_info.found & CATEGORY_MASK_UTF_16_LE) |
| 6746 | found = XCAR (coding_systems); | ||
| 6747 | else if (detect_info.found & CATEGORY_MASK_UTF_16_BE) | ||
| 6748 | found = XCDR (coding_systems); | ||
| 6749 | } | ||
| 6755 | } | 6750 | } |
| 6756 | } | 6751 | } |
| 6757 | 6752 | ||
| @@ -8639,7 +8634,7 @@ detect_coding_system (const unsigned char *src, | |||
| 8639 | Lisp_Object val = Qnil; | 8634 | Lisp_Object val = Qnil; |
| 8640 | struct coding_system coding; | 8635 | struct coding_system coding; |
| 8641 | ptrdiff_t id; | 8636 | ptrdiff_t id; |
| 8642 | struct coding_detection_info detect_info; | 8637 | struct coding_detection_info detect_info = {0}; |
| 8643 | enum coding_category base_category; | 8638 | enum coding_category base_category; |
| 8644 | bool null_byte_found = 0, eight_bit_found = 0; | 8639 | bool null_byte_found = 0, eight_bit_found = 0; |
| 8645 | 8640 | ||
| @@ -8658,8 +8653,6 @@ detect_coding_system (const unsigned char *src, | |||
| 8658 | coding.mode |= CODING_MODE_LAST_BLOCK; | 8653 | coding.mode |= CODING_MODE_LAST_BLOCK; |
| 8659 | coding.head_ascii = 0; | 8654 | coding.head_ascii = 0; |
| 8660 | 8655 | ||
| 8661 | detect_info.checked = detect_info.found = detect_info.rejected = 0; | ||
| 8662 | |||
| 8663 | /* At first, detect text-format if necessary. */ | 8656 | /* At first, detect text-format if necessary. */ |
| 8664 | base_category = XFIXNUM (CODING_ATTR_CATEGORY (attrs)); | 8657 | base_category = XFIXNUM (CODING_ATTR_CATEGORY (attrs)); |
| 8665 | if (base_category == coding_category_undecided) | 8658 | if (base_category == coding_category_undecided) |
diff --git a/src/comp.c b/src/comp.c index 66a7ab789a8..c230536ac59 100644 --- a/src/comp.c +++ b/src/comp.c | |||
| @@ -756,12 +756,12 @@ comp_hash_source_file (Lisp_Object filename) | |||
| 756 | 756 | ||
| 757 | DEFUN ("comp--subr-signature", Fcomp__subr_signature, | 757 | DEFUN ("comp--subr-signature", Fcomp__subr_signature, |
| 758 | Scomp__subr_signature, 1, 1, 0, | 758 | Scomp__subr_signature, 1, 1, 0, |
| 759 | doc: /* Support function to 'hash_native_abi'. | 759 | doc: /* Support function to hash_native_abi. |
| 760 | For internal use. */) | 760 | For internal use. */) |
| 761 | (Lisp_Object subr) | 761 | (Lisp_Object subr) |
| 762 | { | 762 | { |
| 763 | return concat2 (Fsubr_name (subr), | 763 | return concat2 (Fsubr_name (subr), |
| 764 | Fprin1_to_string (Fsubr_arity (subr), Qnil)); | 764 | Fprin1_to_string (Fsubr_arity (subr), Qnil, Qnil)); |
| 765 | } | 765 | } |
| 766 | 766 | ||
| 767 | /* Produce a key hashing Vcomp_subr_list. */ | 767 | /* Produce a key hashing Vcomp_subr_list. */ |
| @@ -1707,7 +1707,7 @@ static gcc_jit_lvalue * | |||
| 1707 | emit_lisp_obj_reloc_lval (Lisp_Object obj) | 1707 | emit_lisp_obj_reloc_lval (Lisp_Object obj) |
| 1708 | { | 1708 | { |
| 1709 | emit_comment (format_string ("l-value for lisp obj: %s", | 1709 | emit_comment (format_string ("l-value for lisp obj: %s", |
| 1710 | SSDATA (Fprin1_to_string (obj, Qnil)))); | 1710 | SSDATA (Fprin1_to_string (obj, Qnil, Qnil)))); |
| 1711 | 1711 | ||
| 1712 | imm_reloc_t reloc = obj_to_reloc (obj); | 1712 | imm_reloc_t reloc = obj_to_reloc (obj); |
| 1713 | return gcc_jit_context_new_array_access (comp.ctxt, | 1713 | return gcc_jit_context_new_array_access (comp.ctxt, |
| @@ -1720,7 +1720,7 @@ static gcc_jit_rvalue * | |||
| 1720 | emit_lisp_obj_rval (Lisp_Object obj) | 1720 | emit_lisp_obj_rval (Lisp_Object obj) |
| 1721 | { | 1721 | { |
| 1722 | emit_comment (format_string ("const lisp obj: %s", | 1722 | emit_comment (format_string ("const lisp obj: %s", |
| 1723 | SSDATA (Fprin1_to_string (obj, Qnil)))); | 1723 | SSDATA (Fprin1_to_string (obj, Qnil, Qnil)))); |
| 1724 | 1724 | ||
| 1725 | if (NILP (obj)) | 1725 | if (NILP (obj)) |
| 1726 | { | 1726 | { |
| @@ -1968,7 +1968,7 @@ emit_mvar_rval (Lisp_Object mvar) | |||
| 1968 | SSDATA ( | 1968 | SSDATA ( |
| 1969 | Fprin1_to_string ( | 1969 | Fprin1_to_string ( |
| 1970 | NILP (func) ? value : CALL1I (comp-func-c-name, func), | 1970 | NILP (func) ? value : CALL1I (comp-func-c-name, func), |
| 1971 | Qnil))); | 1971 | Qnil, Qnil))); |
| 1972 | } | 1972 | } |
| 1973 | if (FIXNUMP (value)) | 1973 | if (FIXNUMP (value)) |
| 1974 | { | 1974 | { |
| @@ -2471,7 +2471,7 @@ emit_limple_insn (Lisp_Object insn) | |||
| 2471 | else if (EQ (op, Qsetimm)) | 2471 | else if (EQ (op, Qsetimm)) |
| 2472 | { | 2472 | { |
| 2473 | /* Ex: (setimm #s(comp-mvar 9 1 t 3 nil) a). */ | 2473 | /* Ex: (setimm #s(comp-mvar 9 1 t 3 nil) a). */ |
| 2474 | emit_comment (SSDATA (Fprin1_to_string (arg[1], Qnil))); | 2474 | emit_comment (SSDATA (Fprin1_to_string (arg[1], Qnil, Qnil))); |
| 2475 | imm_reloc_t reloc = obj_to_reloc (arg[1]); | 2475 | imm_reloc_t reloc = obj_to_reloc (arg[1]); |
| 2476 | emit_frame_assignment ( | 2476 | emit_frame_assignment ( |
| 2477 | arg[0], | 2477 | arg[0], |
| @@ -2647,7 +2647,7 @@ emit_static_object (const char *name, Lisp_Object obj) | |||
| 2647 | specbind (intern_c_string ("print-quoted"), Qt); | 2647 | specbind (intern_c_string ("print-quoted"), Qt); |
| 2648 | specbind (intern_c_string ("print-gensym"), Qt); | 2648 | specbind (intern_c_string ("print-gensym"), Qt); |
| 2649 | specbind (intern_c_string ("print-circle"), Qt); | 2649 | specbind (intern_c_string ("print-circle"), Qt); |
| 2650 | Lisp_Object str = Fprin1_to_string (obj, Qnil); | 2650 | Lisp_Object str = Fprin1_to_string (obj, Qnil, Qnil); |
| 2651 | unbind_to (count, Qnil); | 2651 | unbind_to (count, Qnil); |
| 2652 | 2652 | ||
| 2653 | ptrdiff_t len = SBYTES (str); | 2653 | ptrdiff_t len = SBYTES (str); |
| @@ -4262,7 +4262,7 @@ compile_function (Lisp_Object func) | |||
| 4262 | { | 4262 | { |
| 4263 | Lisp_Object block_name = HASH_KEY (ht, i); | 4263 | Lisp_Object block_name = HASH_KEY (ht, i); |
| 4264 | if (!EQ (block_name, Qentry) | 4264 | if (!EQ (block_name, Qentry) |
| 4265 | && !EQ (block_name, Qunbound)) | 4265 | && !BASE_EQ (block_name, Qunbound)) |
| 4266 | declare_block (block_name); | 4266 | declare_block (block_name); |
| 4267 | } | 4267 | } |
| 4268 | 4268 | ||
| @@ -4275,7 +4275,7 @@ compile_function (Lisp_Object func) | |||
| 4275 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++) | 4275 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++) |
| 4276 | { | 4276 | { |
| 4277 | Lisp_Object block_name = HASH_KEY (ht, i); | 4277 | Lisp_Object block_name = HASH_KEY (ht, i); |
| 4278 | if (!EQ (block_name, Qunbound)) | 4278 | if (!BASE_EQ (block_name, Qunbound)) |
| 4279 | { | 4279 | { |
| 4280 | Lisp_Object block = HASH_VALUE (ht, i); | 4280 | Lisp_Object block = HASH_VALUE (ht, i); |
| 4281 | Lisp_Object insns = CALL1I (comp-block-insns, block); | 4281 | Lisp_Object insns = CALL1I (comp-block-insns, block); |
| @@ -4890,12 +4890,12 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file, | |||
| 4890 | struct Lisp_Hash_Table *func_h = | 4890 | struct Lisp_Hash_Table *func_h = |
| 4891 | XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt)); | 4891 | XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt)); |
| 4892 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) | 4892 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) |
| 4893 | if (!EQ (HASH_VALUE (func_h, i), Qunbound)) | 4893 | if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound)) |
| 4894 | declare_function (HASH_VALUE (func_h, i)); | 4894 | declare_function (HASH_VALUE (func_h, i)); |
| 4895 | /* Compile all functions. Can't be done before because the | 4895 | /* Compile all functions. Can't be done before because the |
| 4896 | relocation structs has to be already defined. */ | 4896 | relocation structs has to be already defined. */ |
| 4897 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) | 4897 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) |
| 4898 | if (!EQ (HASH_VALUE (func_h, i), Qunbound)) | 4898 | if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound)) |
| 4899 | compile_function (HASH_VALUE (func_h, i)); | 4899 | compile_function (HASH_VALUE (func_h, i)); |
| 4900 | 4900 | ||
| 4901 | /* Work around bug#46495 (GCC PR99126). */ | 4901 | /* Work around bug#46495 (GCC PR99126). */ |
| @@ -5342,7 +5342,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump, | |||
| 5342 | are necessary exclusively during the first load. Once these | 5342 | are necessary exclusively during the first load. Once these |
| 5343 | are collected we don't have to maintain them in the heap | 5343 | are collected we don't have to maintain them in the heap |
| 5344 | forever. */ | 5344 | forever. */ |
| 5345 | Lisp_Object volatile data_ephemeral_vec; | 5345 | Lisp_Object volatile data_ephemeral_vec = Qnil; |
| 5346 | /* In case another load of the same CU is active on the stack | 5346 | /* In case another load of the same CU is active on the stack |
| 5347 | all ephemeral data is hold by that frame. Re-writing | 5347 | all ephemeral data is hold by that frame. Re-writing |
| 5348 | 'data_ephemeral_vec' would be not only a waste of cycles but | 5348 | 'data_ephemeral_vec' would be not only a waste of cycles but |
diff --git a/src/composite.c b/src/composite.c index c2ade90d54a..4d69702171f 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -688,7 +688,7 @@ composition_gstring_cache_clear_font (Lisp_Object font_object) | |||
| 688 | { | 688 | { |
| 689 | Lisp_Object k = HASH_KEY (h, i); | 689 | Lisp_Object k = HASH_KEY (h, i); |
| 690 | 690 | ||
| 691 | if (!EQ (k, Qunbound)) | 691 | if (!BASE_EQ (k, Qunbound)) |
| 692 | { | 692 | { |
| 693 | Lisp_Object gstring = HASH_VALUE (h, i); | 693 | Lisp_Object gstring = HASH_VALUE (h, i); |
| 694 | 694 | ||
diff --git a/src/data.c b/src/data.c index 8dbb2902a72..2447ed72e4a 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -705,7 +705,7 @@ global value outside of any lexical scope. */) | |||
| 705 | default: emacs_abort (); | 705 | default: emacs_abort (); |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | return (EQ (valcontents, Qunbound) ? Qnil : Qt); | 708 | return (BASE_EQ (valcontents, Qunbound) ? Qnil : Qt); |
| 709 | } | 709 | } |
| 710 | 710 | ||
| 711 | /* It has been previously suggested to make this function an alias for | 711 | /* It has been previously suggested to make this function an alias for |
| @@ -1591,7 +1591,7 @@ global value outside of any lexical scope. */) | |||
| 1591 | Lisp_Object val; | 1591 | Lisp_Object val; |
| 1592 | 1592 | ||
| 1593 | val = find_symbol_value (symbol); | 1593 | val = find_symbol_value (symbol); |
| 1594 | if (!EQ (val, Qunbound)) | 1594 | if (!BASE_EQ (val, Qunbound)) |
| 1595 | return val; | 1595 | return val; |
| 1596 | 1596 | ||
| 1597 | xsignal1 (Qvoid_variable, symbol); | 1597 | xsignal1 (Qvoid_variable, symbol); |
| @@ -1618,7 +1618,7 @@ void | |||
| 1618 | set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | 1618 | set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, |
| 1619 | enum Set_Internal_Bind bindflag) | 1619 | enum Set_Internal_Bind bindflag) |
| 1620 | { | 1620 | { |
| 1621 | bool voide = EQ (newval, Qunbound); | 1621 | bool voide = BASE_EQ (newval, Qunbound); |
| 1622 | 1622 | ||
| 1623 | /* If restoring in a dead buffer, do nothing. */ | 1623 | /* If restoring in a dead buffer, do nothing. */ |
| 1624 | /* if (BUFFERP (where) && NILP (XBUFFER (where)->name)) | 1624 | /* if (BUFFERP (where) && NILP (XBUFFER (where)->name)) |
| @@ -1945,15 +1945,15 @@ default_value (Lisp_Object symbol) | |||
| 1945 | 1945 | ||
| 1946 | DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0, | 1946 | DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0, |
| 1947 | doc: /* Return t if SYMBOL has a non-void default value. | 1947 | doc: /* Return t if SYMBOL has a non-void default value. |
| 1948 | A variable may have a buffer-local or a `let'-bound local value. This | 1948 | A variable may have a buffer-local value. This function says whether |
| 1949 | function says whether the variable has a non-void value outside of the | 1949 | the variable has a non-void value outside of the current buffer |
| 1950 | current context. Also see `default-value'. */) | 1950 | context. Also see `default-value'. */) |
| 1951 | (Lisp_Object symbol) | 1951 | (Lisp_Object symbol) |
| 1952 | { | 1952 | { |
| 1953 | register Lisp_Object value; | 1953 | register Lisp_Object value; |
| 1954 | 1954 | ||
| 1955 | value = default_value (symbol); | 1955 | value = default_value (symbol); |
| 1956 | return (EQ (value, Qunbound) ? Qnil : Qt); | 1956 | return (BASE_EQ (value, Qunbound) ? Qnil : Qt); |
| 1957 | } | 1957 | } |
| 1958 | 1958 | ||
| 1959 | DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0, | 1959 | DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0, |
| @@ -1964,7 +1964,7 @@ local bindings in certain buffers. */) | |||
| 1964 | (Lisp_Object symbol) | 1964 | (Lisp_Object symbol) |
| 1965 | { | 1965 | { |
| 1966 | Lisp_Object value = default_value (symbol); | 1966 | Lisp_Object value = default_value (symbol); |
| 1967 | if (!EQ (value, Qunbound)) | 1967 | if (!BASE_EQ (value, Qunbound)) |
| 1968 | return value; | 1968 | return value; |
| 1969 | 1969 | ||
| 1970 | xsignal1 (Qvoid_variable, symbol); | 1970 | xsignal1 (Qvoid_variable, symbol); |
| @@ -2144,7 +2144,7 @@ See also `defvar-local'. */) | |||
| 2144 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; | 2144 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 2145 | case SYMBOL_PLAINVAL: | 2145 | case SYMBOL_PLAINVAL: |
| 2146 | forwarded = 0; valcontents.value = SYMBOL_VAL (sym); | 2146 | forwarded = 0; valcontents.value = SYMBOL_VAL (sym); |
| 2147 | if (EQ (valcontents.value, Qunbound)) | 2147 | if (BASE_EQ (valcontents.value, Qunbound)) |
| 2148 | valcontents.value = Qnil; | 2148 | valcontents.value = Qnil; |
| 2149 | break; | 2149 | break; |
| 2150 | case SYMBOL_LOCALIZED: | 2150 | case SYMBOL_LOCALIZED: |
diff --git a/src/dbusbind.c b/src/dbusbind.c index 7cfdbbe23cf..943a4aff8e7 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -1690,29 +1690,30 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1690 | value = Fgethash (key, Vdbus_registered_objects_table, Qnil); | 1690 | value = Fgethash (key, Vdbus_registered_objects_table, Qnil); |
| 1691 | 1691 | ||
| 1692 | /* Loop over the registered functions. Construct an event. */ | 1692 | /* Loop over the registered functions. Construct an event. */ |
| 1693 | while (!NILP (value)) | 1693 | for (; !NILP (value); value = CDR_SAFE (value)) |
| 1694 | { | 1694 | { |
| 1695 | key = CAR_SAFE (value); | 1695 | key = CAR_SAFE (value); |
| 1696 | Lisp_Object key_uname = CAR_SAFE (key); | ||
| 1696 | /* key has the structure (UNAME SERVICE PATH HANDLER). */ | 1697 | /* key has the structure (UNAME SERVICE PATH HANDLER). */ |
| 1697 | if (((uname == NULL) | 1698 | if (uname && !NILP (key_uname) |
| 1698 | || (NILP (CAR_SAFE (key))) | 1699 | && strcmp (uname, SSDATA (key_uname)) != 0) |
| 1699 | || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0)) | 1700 | continue; |
| 1700 | && ((path == NULL) | 1701 | Lisp_Object key_service_etc = CDR_SAFE (key); |
| 1701 | || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key))))) | 1702 | Lisp_Object key_path_etc = CDR_SAFE (key_service_etc); |
| 1702 | || (strcmp (path, | 1703 | Lisp_Object key_path = CAR_SAFE (key_path_etc); |
| 1703 | SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key))))) | 1704 | if (path && !NILP (key_path) |
| 1704 | == 0)) | 1705 | && strcmp (path, SSDATA (key_path)) != 0) |
| 1705 | && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key))))))) | 1706 | continue; |
| 1706 | { | 1707 | Lisp_Object handler = CAR_SAFE (CDR_SAFE (key_path_etc)); |
| 1707 | EVENT_INIT (event); | 1708 | if (NILP (handler)) |
| 1708 | event.kind = DBUS_EVENT; | 1709 | continue; |
| 1709 | event.frame_or_window = Qnil; | 1710 | |
| 1710 | /* Handler. */ | 1711 | /* Construct an event and exit the loop. */ |
| 1711 | event.arg | 1712 | EVENT_INIT (event); |
| 1712 | = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args); | 1713 | event.kind = DBUS_EVENT; |
| 1713 | break; | 1714 | event.frame_or_window = Qnil; |
| 1714 | } | 1715 | event.arg = Fcons (handler, args); |
| 1715 | value = CDR_SAFE (value); | 1716 | break; |
| 1716 | } | 1717 | } |
| 1717 | 1718 | ||
| 1718 | if (NILP (value)) | 1719 | if (NILP (value)) |
diff --git a/src/dispextern.h b/src/dispextern.h index e9b19a7f135..c7399ca2998 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1075,6 +1075,9 @@ struct glyph_row | |||
| 1075 | right-to-left paragraph. */ | 1075 | right-to-left paragraph. */ |
| 1076 | bool_bf reversed_p : 1; | 1076 | bool_bf reversed_p : 1; |
| 1077 | 1077 | ||
| 1078 | /* Whether or not a stipple was drawn in this row at some point. */ | ||
| 1079 | bool_bf stipple_p : 1; | ||
| 1080 | |||
| 1078 | /* Continuation lines width at the start of the row. */ | 1081 | /* Continuation lines width at the start of the row. */ |
| 1079 | int continuation_lines_width; | 1082 | int continuation_lines_width; |
| 1080 | 1083 | ||
| @@ -3467,6 +3470,7 @@ extern void expose_frame (struct frame *, int, int, int, int); | |||
| 3467 | extern bool gui_intersect_rectangles (const Emacs_Rectangle *, | 3470 | extern bool gui_intersect_rectangles (const Emacs_Rectangle *, |
| 3468 | const Emacs_Rectangle *, | 3471 | const Emacs_Rectangle *, |
| 3469 | Emacs_Rectangle *); | 3472 | Emacs_Rectangle *); |
| 3473 | extern void gui_consider_frame_title (Lisp_Object); | ||
| 3470 | #endif /* HAVE_WINDOW_SYSTEM */ | 3474 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 3471 | 3475 | ||
| 3472 | extern void note_mouse_highlight (struct frame *, int, int); | 3476 | extern void note_mouse_highlight (struct frame *, int, int); |
| @@ -3612,6 +3616,9 @@ void gamma_correct (struct frame *, XColor *); | |||
| 3612 | #ifdef HAVE_NTGUI | 3616 | #ifdef HAVE_NTGUI |
| 3613 | void gamma_correct (struct frame *, COLORREF *); | 3617 | void gamma_correct (struct frame *, COLORREF *); |
| 3614 | #endif | 3618 | #endif |
| 3619 | #ifdef HAVE_HAIKU | ||
| 3620 | void gamma_correct (struct frame *, Emacs_Color *); | ||
| 3621 | #endif | ||
| 3615 | 3622 | ||
| 3616 | #ifdef HAVE_WINDOW_SYSTEM | 3623 | #ifdef HAVE_WINDOW_SYSTEM |
| 3617 | 3624 | ||
diff --git a/src/dispnew.c b/src/dispnew.c index 1dd64be4ead..7a4d9f8710b 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -1837,7 +1837,18 @@ adjust_frame_glyphs (struct frame *f) | |||
| 1837 | if (FRAME_WINDOW_P (f)) | 1837 | if (FRAME_WINDOW_P (f)) |
| 1838 | adjust_frame_glyphs_for_window_redisplay (f); | 1838 | adjust_frame_glyphs_for_window_redisplay (f); |
| 1839 | else | 1839 | else |
| 1840 | adjust_frame_glyphs_for_frame_redisplay (f); | 1840 | { |
| 1841 | adjust_frame_glyphs_for_frame_redisplay (f); | ||
| 1842 | eassert (FRAME_INITIAL_P (f) | ||
| 1843 | || noninteractive | ||
| 1844 | || !initialized | ||
| 1845 | || (f->current_matrix | ||
| 1846 | && f->current_matrix->nrows > 0 | ||
| 1847 | && f->current_matrix->rows | ||
| 1848 | && f->desired_matrix | ||
| 1849 | && f->desired_matrix->nrows > 0 | ||
| 1850 | && f->desired_matrix->rows)); | ||
| 1851 | } | ||
| 1841 | 1852 | ||
| 1842 | /* Don't forget the buffer for decode_mode_spec. */ | 1853 | /* Don't forget the buffer for decode_mode_spec. */ |
| 1843 | adjust_decode_mode_spec_buffer (f); | 1854 | adjust_decode_mode_spec_buffer (f); |
| @@ -2119,6 +2130,19 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f) | |||
| 2119 | SET_FRAME_GARBAGED (f); | 2130 | SET_FRAME_GARBAGED (f); |
| 2120 | } | 2131 | } |
| 2121 | } | 2132 | } |
| 2133 | else if (!FRAME_INITIAL_P (f) && !noninteractive && initialized) | ||
| 2134 | { | ||
| 2135 | if (!f->desired_matrix->nrows || !f->desired_matrix->rows) | ||
| 2136 | { | ||
| 2137 | adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); | ||
| 2138 | SET_FRAME_GARBAGED (f); | ||
| 2139 | } | ||
| 2140 | if (!f->current_matrix->nrows || !f->current_matrix->rows) | ||
| 2141 | { | ||
| 2142 | adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim); | ||
| 2143 | SET_FRAME_GARBAGED (f); | ||
| 2144 | } | ||
| 2145 | } | ||
| 2122 | } | 2146 | } |
| 2123 | 2147 | ||
| 2124 | 2148 | ||
| @@ -3907,7 +3931,8 @@ update_marginal_area (struct window *w, struct glyph_row *updated_row, | |||
| 3907 | Value is true if display has changed. */ | 3931 | Value is true if display has changed. */ |
| 3908 | 3932 | ||
| 3909 | static bool | 3933 | static bool |
| 3910 | update_text_area (struct window *w, struct glyph_row *updated_row, int vpos) | 3934 | update_text_area (struct window *w, struct glyph_row *updated_row, int vpos, |
| 3935 | bool *partial_p) | ||
| 3911 | { | 3936 | { |
| 3912 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); | 3937 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); |
| 3913 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); | 3938 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); |
| @@ -4013,6 +4038,13 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos) | |||
| 4013 | { | 4038 | { |
| 4014 | x += desired_glyph->pixel_width; | 4039 | x += desired_glyph->pixel_width; |
| 4015 | ++desired_glyph, ++current_glyph, ++i; | 4040 | ++desired_glyph, ++current_glyph, ++i; |
| 4041 | |||
| 4042 | /* Say that only a partial update was performed of | ||
| 4043 | the current row (i.e. not all the glyphs were | ||
| 4044 | drawn). This is used to preserve the stipple_p | ||
| 4045 | flag of the current row inside | ||
| 4046 | update_window_line. */ | ||
| 4047 | *partial_p = true; | ||
| 4016 | } | 4048 | } |
| 4017 | 4049 | ||
| 4018 | /* Consider the case that the current row contains "xxx | 4050 | /* Consider the case that the current row contains "xxx |
| @@ -4084,9 +4116,15 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos) | |||
| 4084 | rif->write_glyphs (w, updated_row, start, | 4116 | rif->write_glyphs (w, updated_row, start, |
| 4085 | TEXT_AREA, i - start_hpos); | 4117 | TEXT_AREA, i - start_hpos); |
| 4086 | changed_p = 1; | 4118 | changed_p = 1; |
| 4119 | *partial_p = true; | ||
| 4087 | } | 4120 | } |
| 4088 | } | 4121 | } |
| 4089 | 4122 | ||
| 4123 | /* This means we will draw from the start, so no partial update | ||
| 4124 | is being performed. */ | ||
| 4125 | if (!i) | ||
| 4126 | *partial_p = false; | ||
| 4127 | |||
| 4090 | /* Write the rest. */ | 4128 | /* Write the rest. */ |
| 4091 | if (i < desired_row->used[TEXT_AREA]) | 4129 | if (i < desired_row->used[TEXT_AREA]) |
| 4092 | { | 4130 | { |
| @@ -4159,7 +4197,9 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) | |||
| 4159 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); | 4197 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); |
| 4160 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); | 4198 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); |
| 4161 | struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); | 4199 | struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); |
| 4162 | bool changed_p = 0; | 4200 | |
| 4201 | /* partial_p is true if not all of desired_row was drawn. */ | ||
| 4202 | bool changed_p = 0, partial_p = 0, was_stipple; | ||
| 4163 | 4203 | ||
| 4164 | /* A row can be completely invisible in case a desired matrix was | 4204 | /* A row can be completely invisible in case a desired matrix was |
| 4165 | built with a vscroll and then make_cursor_line_fully_visible shifts | 4205 | built with a vscroll and then make_cursor_line_fully_visible shifts |
| @@ -4183,7 +4223,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) | |||
| 4183 | } | 4223 | } |
| 4184 | 4224 | ||
| 4185 | /* Update the display of the text area. */ | 4225 | /* Update the display of the text area. */ |
| 4186 | if (update_text_area (w, desired_row, vpos)) | 4226 | if (update_text_area (w, desired_row, vpos, &partial_p)) |
| 4187 | { | 4227 | { |
| 4188 | changed_p = 1; | 4228 | changed_p = 1; |
| 4189 | if (current_row->mouse_face_p) | 4229 | if (current_row->mouse_face_p) |
| @@ -4212,7 +4252,17 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) | |||
| 4212 | } | 4252 | } |
| 4213 | 4253 | ||
| 4214 | /* Update current_row from desired_row. */ | 4254 | /* Update current_row from desired_row. */ |
| 4255 | was_stipple = current_row->stipple_p; | ||
| 4215 | make_current (w->desired_matrix, w->current_matrix, vpos); | 4256 | make_current (w->desired_matrix, w->current_matrix, vpos); |
| 4257 | |||
| 4258 | /* If only a partial update was performed, any stipple already | ||
| 4259 | displayed in MATRIX_ROW (w->current_matrix, vpos) might still be | ||
| 4260 | there, so don't hurry to clear that flag if it's not in | ||
| 4261 | desired_row. */ | ||
| 4262 | |||
| 4263 | if (partial_p && was_stipple) | ||
| 4264 | current_row->stipple_p = true; | ||
| 4265 | |||
| 4216 | return changed_p; | 4266 | return changed_p; |
| 4217 | } | 4267 | } |
| 4218 | 4268 | ||
| @@ -4392,7 +4442,6 @@ add_row_entry (struct glyph_row *row) | |||
| 4392 | return entry; | 4442 | return entry; |
| 4393 | } | 4443 | } |
| 4394 | 4444 | ||
| 4395 | |||
| 4396 | /* Try to reuse part of the current display of W by scrolling lines. | 4445 | /* Try to reuse part of the current display of W by scrolling lines. |
| 4397 | HEADER_LINE_P means W has a header line. | 4446 | HEADER_LINE_P means W has a header line. |
| 4398 | 4447 | ||
| @@ -4438,6 +4487,14 @@ scrolling_window (struct window *w, int tab_line_p) | |||
| 4438 | struct glyph_row *d = MATRIX_ROW (desired_matrix, i); | 4487 | struct glyph_row *d = MATRIX_ROW (desired_matrix, i); |
| 4439 | struct glyph_row *c = MATRIX_ROW (current_matrix, i); | 4488 | struct glyph_row *c = MATRIX_ROW (current_matrix, i); |
| 4440 | 4489 | ||
| 4490 | /* If there is a row with a stipple currently on the glass, give | ||
| 4491 | up. Stipples look different depending on where on the | ||
| 4492 | display they are drawn, so scrolling the display will produce | ||
| 4493 | incorrect results. */ | ||
| 4494 | |||
| 4495 | if (c->stipple_p) | ||
| 4496 | return 0; | ||
| 4497 | |||
| 4441 | if (c->enabled_p | 4498 | if (c->enabled_p |
| 4442 | && d->enabled_p | 4499 | && d->enabled_p |
| 4443 | && !d->redraw_fringe_bitmaps_p | 4500 | && !d->redraw_fringe_bitmaps_p |
| @@ -4467,6 +4524,16 @@ scrolling_window (struct window *w, int tab_line_p) | |||
| 4467 | 4524 | ||
| 4468 | first_old = first_new = i; | 4525 | first_old = first_new = i; |
| 4469 | 4526 | ||
| 4527 | while (i < current_matrix->nrows - 1) | ||
| 4528 | { | ||
| 4529 | /* If there is a stipple after the first change, give up as | ||
| 4530 | well. */ | ||
| 4531 | if (MATRIX_ROW (current_matrix, i)->stipple_p) | ||
| 4532 | return 0; | ||
| 4533 | |||
| 4534 | ++i; | ||
| 4535 | } | ||
| 4536 | |||
| 4470 | /* Set last_new to the index + 1 of the row that reaches the | 4537 | /* Set last_new to the index + 1 of the row that reaches the |
| 4471 | bottom boundary in the desired matrix. Give up if we find a | 4538 | bottom boundary in the desired matrix. Give up if we find a |
| 4472 | disabled row before we reach the bottom boundary. */ | 4539 | disabled row before we reach the bottom boundary. */ |
| @@ -569,6 +569,8 @@ the same file name is found in the `doc-directory'. */) | |||
| 569 | if (p) | 569 | if (p) |
| 570 | { | 570 | { |
| 571 | end = strchr (p, '\n'); | 571 | end = strchr (p, '\n'); |
| 572 | if (!end) | ||
| 573 | error ("DOC file invalid at position %"pI"d", pos); | ||
| 572 | 574 | ||
| 573 | /* We used to skip files not in build_files, so that when a | 575 | /* We used to skip files not in build_files, so that when a |
| 574 | function was defined several times in different files | 576 | function was defined several times in different files |
diff --git a/src/editfns.c b/src/editfns.c index 6cb684d4d85..17f0252969e 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3327,7 +3327,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3327 | if (EQ (arg, args[n])) | 3327 | if (EQ (arg, args[n])) |
| 3328 | { | 3328 | { |
| 3329 | Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; | 3329 | Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; |
| 3330 | spec->argument = arg = Fprin1_to_string (arg, noescape); | 3330 | spec->argument = arg = Fprin1_to_string (arg, noescape, Qnil); |
| 3331 | if (STRING_MULTIBYTE (arg) && ! multibyte) | 3331 | if (STRING_MULTIBYTE (arg) && ! multibyte) |
| 3332 | { | 3332 | { |
| 3333 | multibyte = true; | 3333 | multibyte = true; |
diff --git a/src/emacs-module.c b/src/emacs-module.c index 0d3cce0276b..1c392d65df8 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -411,7 +411,7 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n) | |||
| 411 | reference that's identical to some global reference. */ | 411 | reference that's identical to some global reference. */ |
| 412 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 412 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 413 | { | 413 | { |
| 414 | if (!EQ (HASH_KEY (h, i), Qunbound) | 414 | if (!BASE_EQ (HASH_KEY (h, i), Qunbound) |
| 415 | && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v) | 415 | && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v) |
| 416 | return true; | 416 | return true; |
| 417 | } | 417 | } |
diff --git a/src/emacs.c b/src/emacs.c index 9f20a1597c9..189692a02ea 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1409,7 +1409,7 @@ main (int argc, char **argv) | |||
| 1409 | related to the GUI system, like -font, -geometry, and -title, and | 1409 | related to the GUI system, like -font, -geometry, and -title, and |
| 1410 | then processes the rest of arguments whose priority is below | 1410 | then processes the rest of arguments whose priority is below |
| 1411 | those that are related to the GUI system. The arguments | 1411 | those that are related to the GUI system. The arguments |
| 1412 | porcessed by 'command-line' are removed from 'command-line-args'; | 1412 | processed by 'command-line' are removed from 'command-line-args'; |
| 1413 | the arguments processed by 'command-line-1' aren't, they are only | 1413 | the arguments processed by 'command-line-1' aren't, they are only |
| 1414 | removed from 'command-line-args-left'. | 1414 | removed from 'command-line-args-left'. |
| 1415 | 1415 | ||
| @@ -1419,54 +1419,19 @@ main (int argc, char **argv) | |||
| 1419 | should be explicitly recognized, ignored, and removed from | 1419 | should be explicitly recognized, ignored, and removed from |
| 1420 | 'command-line-args-left' in 'command-line-1'. */ | 1420 | 'command-line-args-left' in 'command-line-1'. */ |
| 1421 | 1421 | ||
| 1422 | bool only_version = false; | ||
| 1422 | sort_args (argc, argv); | 1423 | sort_args (argc, argv); |
| 1423 | argc = 0; | 1424 | argc = 0; |
| 1424 | while (argv[argc]) argc++; | 1425 | while (argv[argc]) argc++; |
| 1425 | 1426 | ||
| 1426 | skip_args = 0; | 1427 | skip_args = 0; |
| 1427 | if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args)) | 1428 | if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args)) |
| 1428 | { | 1429 | only_version = true; |
| 1429 | const char *version, *copyright; | ||
| 1430 | if (initialized) | ||
| 1431 | { | ||
| 1432 | Lisp_Object tem, tem2; | ||
| 1433 | tem = Fsymbol_value (intern_c_string ("emacs-version")); | ||
| 1434 | tem2 = Fsymbol_value (intern_c_string ("emacs-copyright")); | ||
| 1435 | if (!STRINGP (tem)) | ||
| 1436 | { | ||
| 1437 | fputs ("Invalid value of 'emacs-version'\n", stderr); | ||
| 1438 | exit (1); | ||
| 1439 | } | ||
| 1440 | if (!STRINGP (tem2)) | ||
| 1441 | { | ||
| 1442 | fputs ("Invalid value of 'emacs-copyright'\n", stderr); | ||
| 1443 | exit (1); | ||
| 1444 | } | ||
| 1445 | else | ||
| 1446 | { | ||
| 1447 | version = SSDATA (tem); | ||
| 1448 | copyright = SSDATA (tem2); | ||
| 1449 | } | ||
| 1450 | } | ||
| 1451 | else | ||
| 1452 | { | ||
| 1453 | version = emacs_version; | ||
| 1454 | copyright = emacs_copyright; | ||
| 1455 | } | ||
| 1456 | printf (("%s %s\n" | ||
| 1457 | "%s\n" | ||
| 1458 | "%s comes with ABSOLUTELY NO WARRANTY.\n" | ||
| 1459 | "You may redistribute copies of %s\n" | ||
| 1460 | "under the terms of the GNU General Public License.\n" | ||
| 1461 | "For more information about these matters, " | ||
| 1462 | "see the file named COPYING.\n"), | ||
| 1463 | PACKAGE_NAME, version, copyright, PACKAGE_NAME, PACKAGE_NAME); | ||
| 1464 | exit (0); | ||
| 1465 | } | ||
| 1466 | 1430 | ||
| 1467 | #ifdef HAVE_PDUMPER | 1431 | #ifdef HAVE_PDUMPER |
| 1468 | if (argmatch (argv, argc, "-fingerprint", "--fingerprint", 4, | 1432 | if (argmatch (argv, argc, "-fingerprint", "--fingerprint", 4, |
| 1469 | NULL, &skip_args)) | 1433 | NULL, &skip_args) |
| 1434 | && !only_version) | ||
| 1470 | { | 1435 | { |
| 1471 | if (initialized) | 1436 | if (initialized) |
| 1472 | { | 1437 | { |
| @@ -1491,7 +1456,8 @@ main (int argc, char **argv) | |||
| 1491 | pdumper_record_wd (emacs_wd); | 1456 | pdumper_record_wd (emacs_wd); |
| 1492 | #endif | 1457 | #endif |
| 1493 | 1458 | ||
| 1494 | if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args)) | 1459 | if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args) |
| 1460 | && !only_version) | ||
| 1495 | { | 1461 | { |
| 1496 | #ifdef WINDOWSNT | 1462 | #ifdef WINDOWSNT |
| 1497 | /* argv[] array is kept in its original ANSI codepage encoding, | 1463 | /* argv[] array is kept in its original ANSI codepage encoding, |
| @@ -1617,7 +1583,7 @@ main (int argc, char **argv) | |||
| 1617 | inhibit_window_system = 0; | 1583 | inhibit_window_system = 0; |
| 1618 | 1584 | ||
| 1619 | /* Handle the -t switch, which specifies filename to use as terminal. */ | 1585 | /* Handle the -t switch, which specifies filename to use as terminal. */ |
| 1620 | while (1) | 1586 | while (!only_version) |
| 1621 | { | 1587 | { |
| 1622 | char *term; | 1588 | char *term; |
| 1623 | if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) | 1589 | if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) |
| @@ -1655,7 +1621,8 @@ main (int argc, char **argv) | |||
| 1655 | 1621 | ||
| 1656 | /* Handle the -batch switch, which means don't do interactive display. */ | 1622 | /* Handle the -batch switch, which means don't do interactive display. */ |
| 1657 | noninteractive = 0; | 1623 | noninteractive = 0; |
| 1658 | if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args)) | 1624 | if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args) |
| 1625 | || only_version) | ||
| 1659 | { | 1626 | { |
| 1660 | noninteractive = 1; | 1627 | noninteractive = 1; |
| 1661 | Vundo_outer_limit = Qnil; | 1628 | Vundo_outer_limit = Qnil; |
| @@ -1672,7 +1639,8 @@ main (int argc, char **argv) | |||
| 1672 | } | 1639 | } |
| 1673 | 1640 | ||
| 1674 | /* Handle the --help option, which gives a usage message. */ | 1641 | /* Handle the --help option, which gives a usage message. */ |
| 1675 | if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)) | 1642 | if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args) |
| 1643 | && !only_version) | ||
| 1676 | { | 1644 | { |
| 1677 | int i; | 1645 | int i; |
| 1678 | printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); | 1646 | printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); |
| @@ -1693,20 +1661,27 @@ main (int argc, char **argv) | |||
| 1693 | 1661 | ||
| 1694 | int sockfd = -1; | 1662 | int sockfd = -1; |
| 1695 | 1663 | ||
| 1696 | if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, &skip_args) | 1664 | if (!only_version) |
| 1697 | || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, &skip_args)) | ||
| 1698 | { | 1665 | { |
| 1699 | daemon_type = 1; /* foreground */ | 1666 | if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, |
| 1700 | } | 1667 | &skip_args) |
| 1701 | else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) | 1668 | || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, |
| 1702 | || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args) | 1669 | &skip_args)) |
| 1703 | || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL, &skip_args) | 1670 | { |
| 1704 | || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, &dname_arg, &skip_args)) | 1671 | daemon_type = 1; /* foreground */ |
| 1705 | { | 1672 | } |
| 1706 | daemon_type = 2; /* background */ | 1673 | else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) |
| 1674 | || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, | ||
| 1675 | &skip_args) | ||
| 1676 | || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL, | ||
| 1677 | &skip_args) | ||
| 1678 | || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, | ||
| 1679 | &dname_arg, &skip_args)) | ||
| 1680 | { | ||
| 1681 | daemon_type = 2; /* background */ | ||
| 1682 | } | ||
| 1707 | } | 1683 | } |
| 1708 | 1684 | ||
| 1709 | |||
| 1710 | if (daemon_type > 0) | 1685 | if (daemon_type > 0) |
| 1711 | { | 1686 | { |
| 1712 | #ifndef DOS_NT | 1687 | #ifndef DOS_NT |
| @@ -1956,15 +1931,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1956 | init_threads (); | 1931 | init_threads (); |
| 1957 | init_eval (); | 1932 | init_eval (); |
| 1958 | #ifdef HAVE_PGTK | 1933 | #ifdef HAVE_PGTK |
| 1959 | init_pgtkterm (); /* before init_atimer(). */ | 1934 | init_pgtkterm (); /* Must come before `init_atimer'. */ |
| 1960 | #endif | 1935 | #endif |
| 1961 | running_asynch_code = 0; | 1936 | running_asynch_code = 0; |
| 1962 | init_random (); | 1937 | init_random (); |
| 1963 | 1938 | init_xfaces (); | |
| 1964 | #ifdef HAVE_PDUMPER | ||
| 1965 | if (dumped_with_pdumper_p ()) | ||
| 1966 | init_xfaces (); | ||
| 1967 | #endif | ||
| 1968 | 1939 | ||
| 1969 | #if defined HAVE_JSON && !defined WINDOWSNT | 1940 | #if defined HAVE_JSON && !defined WINDOWSNT |
| 1970 | init_json (); | 1941 | init_json (); |
| @@ -1986,7 +1957,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1986 | bool module_assertions | 1957 | bool module_assertions |
| 1987 | = argmatch (argv, argc, "-module-assertions", "--module-assertions", 15, | 1958 | = argmatch (argv, argc, "-module-assertions", "--module-assertions", 15, |
| 1988 | NULL, &skip_args); | 1959 | NULL, &skip_args); |
| 1989 | if (will_dump_p () && module_assertions) | 1960 | if (will_dump_p () && module_assertions && !only_version) |
| 1990 | { | 1961 | { |
| 1991 | fputs ("Module assertions are not supported during dumping\n", stderr); | 1962 | fputs ("Module assertions are not supported during dumping\n", stderr); |
| 1992 | exit (1); | 1963 | exit (1); |
| @@ -2034,7 +2005,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 2034 | int count_before = skip_args; | 2005 | int count_before = skip_args; |
| 2035 | 2006 | ||
| 2036 | /* Skip any number of -d options, but only use the last one. */ | 2007 | /* Skip any number of -d options, but only use the last one. */ |
| 2037 | while (1) | 2008 | while (!only_version) |
| 2038 | { | 2009 | { |
| 2039 | int count_before_this = skip_args; | 2010 | int count_before_this = skip_args; |
| 2040 | 2011 | ||
| @@ -2176,6 +2147,72 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 2176 | init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ | 2147 | init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ |
| 2177 | init_fileio (); | 2148 | init_fileio (); |
| 2178 | init_lread (); | 2149 | init_lread (); |
| 2150 | |||
| 2151 | /* If "-version" was specified, produce version information and | ||
| 2152 | exit. We do it here because the code below needs to call Lisp | ||
| 2153 | primitives, which cannot be done safely before we call all the | ||
| 2154 | init_FOO initialization functions above. */ | ||
| 2155 | if (only_version) | ||
| 2156 | { | ||
| 2157 | const char *version, *copyright; | ||
| 2158 | |||
| 2159 | if (initialized) | ||
| 2160 | { | ||
| 2161 | Lisp_Object tem = Fsymbol_value (intern_c_string ("emacs-version")); | ||
| 2162 | Lisp_Object tem2 = Fsymbol_value (intern_c_string ("emacs-copyright")); | ||
| 2163 | if (!STRINGP (tem)) | ||
| 2164 | { | ||
| 2165 | fputs ("Invalid value of 'emacs-version'\n", stderr); | ||
| 2166 | exit (1); | ||
| 2167 | } | ||
| 2168 | if (!STRINGP (tem2)) | ||
| 2169 | { | ||
| 2170 | fputs ("Invalid value of 'emacs-copyright'\n", stderr); | ||
| 2171 | exit (1); | ||
| 2172 | } | ||
| 2173 | else | ||
| 2174 | { | ||
| 2175 | version = SSDATA (tem); | ||
| 2176 | copyright = SSDATA (tem2); | ||
| 2177 | } | ||
| 2178 | } | ||
| 2179 | else | ||
| 2180 | { | ||
| 2181 | version = emacs_version; | ||
| 2182 | copyright = emacs_copyright; | ||
| 2183 | } | ||
| 2184 | printf ("%s %s\n", PACKAGE_NAME, version); | ||
| 2185 | |||
| 2186 | if (initialized) | ||
| 2187 | { | ||
| 2188 | Lisp_Object rversion, rbranch, rtime; | ||
| 2189 | |||
| 2190 | rversion | ||
| 2191 | = Fsymbol_value (intern_c_string ("emacs-repository-version")); | ||
| 2192 | rbranch | ||
| 2193 | = Fsymbol_value (intern_c_string ("emacs-repository-branch")); | ||
| 2194 | rtime | ||
| 2195 | = Fsymbol_value (intern_c_string ("emacs-build-time")); | ||
| 2196 | |||
| 2197 | if (!NILP (rversion) && !NILP (rbranch) && !NILP (rtime)) | ||
| 2198 | printf ("Development version %s on %s branch; build date %s.\n", | ||
| 2199 | SSDATA (Fsubstring (rversion, make_fixnum (0), | ||
| 2200 | make_fixnum (12))), | ||
| 2201 | SSDATA (rbranch), | ||
| 2202 | SSDATA (Fformat_time_string (build_string ("%Y-%m-%d"), | ||
| 2203 | rtime, Qnil))); | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | printf (("%s\n" | ||
| 2207 | "%s comes with ABSOLUTELY NO WARRANTY.\n" | ||
| 2208 | "You may redistribute copies of %s\n" | ||
| 2209 | "under the terms of the GNU General Public License.\n" | ||
| 2210 | "For more information about these matters, " | ||
| 2211 | "see the file named COPYING.\n"), | ||
| 2212 | copyright, PACKAGE_NAME, PACKAGE_NAME); | ||
| 2213 | exit (0); | ||
| 2214 | } | ||
| 2215 | |||
| 2179 | #ifdef WINDOWSNT | 2216 | #ifdef WINDOWSNT |
| 2180 | /* Check to see if Emacs has been installed correctly. */ | 2217 | /* Check to see if Emacs has been installed correctly. */ |
| 2181 | check_windows_init_file (); | 2218 | check_windows_init_file (); |
| @@ -2954,6 +2991,10 @@ shut_down_emacs (int sig, Lisp_Object stuff) | |||
| 2954 | check_message_stack (); | 2991 | check_message_stack (); |
| 2955 | } | 2992 | } |
| 2956 | 2993 | ||
| 2994 | #ifdef HAVE_NATIVE_COMP | ||
| 2995 | eln_load_path_final_clean_up (); | ||
| 2996 | #endif | ||
| 2997 | |||
| 2957 | #ifdef MSDOS | 2998 | #ifdef MSDOS |
| 2958 | dos_cleanup (); | 2999 | dos_cleanup (); |
| 2959 | #endif | 3000 | #endif |
diff --git a/src/eval.c b/src/eval.c index 3ec03de1376..45ddbab2a2c 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -707,7 +707,7 @@ DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_valu | |||
| 707 | union specbinding *binding = default_toplevel_binding (symbol); | 707 | union specbinding *binding = default_toplevel_binding (symbol); |
| 708 | Lisp_Object value | 708 | Lisp_Object value |
| 709 | = binding ? specpdl_old_value (binding) : Fdefault_value (symbol); | 709 | = binding ? specpdl_old_value (binding) : Fdefault_value (symbol); |
| 710 | if (!EQ (value, Qunbound)) | 710 | if (!BASE_EQ (value, Qunbound)) |
| 711 | return value; | 711 | return value; |
| 712 | xsignal1 (Qvoid_variable, symbol); | 712 | xsignal1 (Qvoid_variable, symbol); |
| 713 | } | 713 | } |
| @@ -741,7 +741,9 @@ value. */) | |||
| 741 | and where the `foo` package only gets loaded when <foo-function> | 741 | and where the `foo` package only gets loaded when <foo-function> |
| 742 | is called, so the outer `let` incorrectly made the binding lexical | 742 | is called, so the outer `let` incorrectly made the binding lexical |
| 743 | because the <foo-var> wasn't yet declared as dynamic at that point. */ | 743 | because the <foo-var> wasn't yet declared as dynamic at that point. */ |
| 744 | error ("Defining as dynamic an already lexical var"); | 744 | xsignal2 (Qerror, |
| 745 | build_string ("Defining as dynamic an already lexical var"), | ||
| 746 | symbol); | ||
| 745 | 747 | ||
| 746 | XSYMBOL (symbol)->u.s.declared_special = true; | 748 | XSYMBOL (symbol)->u.s.declared_special = true; |
| 747 | if (!NILP (doc)) | 749 | if (!NILP (doc)) |
| @@ -754,6 +756,33 @@ value. */) | |||
| 754 | return Qnil; | 756 | return Qnil; |
| 755 | } | 757 | } |
| 756 | 758 | ||
| 759 | static Lisp_Object | ||
| 760 | defvar (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring, bool eval) | ||
| 761 | { | ||
| 762 | Lisp_Object tem; | ||
| 763 | |||
| 764 | CHECK_SYMBOL (sym); | ||
| 765 | |||
| 766 | tem = Fdefault_boundp (sym); | ||
| 767 | |||
| 768 | /* Do it before evaluating the initial value, for self-references. */ | ||
| 769 | Finternal__define_uninitialized_variable (sym, docstring); | ||
| 770 | |||
| 771 | if (NILP (tem)) | ||
| 772 | Fset_default (sym, eval ? eval_sub (initvalue) : initvalue); | ||
| 773 | else | ||
| 774 | { /* Check if there is really a global binding rather than just a let | ||
| 775 | binding that shadows the global unboundness of the var. */ | ||
| 776 | union specbinding *binding = default_toplevel_binding (sym); | ||
| 777 | if (binding && BASE_EQ (specpdl_old_value (binding), Qunbound)) | ||
| 778 | { | ||
| 779 | set_specpdl_old_value (binding, | ||
| 780 | eval ? eval_sub (initvalue) : initvalue); | ||
| 781 | } | ||
| 782 | } | ||
| 783 | return sym; | ||
| 784 | } | ||
| 785 | |||
| 757 | DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, | 786 | DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, |
| 758 | doc: /* Define SYMBOL as a variable, and return SYMBOL. | 787 | doc: /* Define SYMBOL as a variable, and return SYMBOL. |
| 759 | You are not required to define a variable in order to use it, but | 788 | You are not required to define a variable in order to use it, but |
| @@ -768,12 +797,10 @@ value. If SYMBOL is buffer-local, its default value is what is set; | |||
| 768 | buffer-local values are not affected. If INITVALUE is missing, | 797 | buffer-local values are not affected. If INITVALUE is missing, |
| 769 | SYMBOL's value is not set. | 798 | SYMBOL's value is not set. |
| 770 | 799 | ||
| 771 | If SYMBOL has a local binding, then this form affects the local | 800 | If SYMBOL is let-bound, then this form does not affect the local let |
| 772 | binding. This is usually not what you want. Thus, if you need to | 801 | binding but the toplevel default binding instead, like |
| 773 | load a file defining variables, with this form or with `defconst' or | 802 | `set-toplevel-default-binding`. |
| 774 | `defcustom', you should always load that file _outside_ any bindings | 803 | (`defcustom' behaves similarly in this respect.) |
| 775 | for these variables. (`defconst' and `defcustom' behave similarly in | ||
| 776 | this respect.) | ||
| 777 | 804 | ||
| 778 | The optional argument DOCSTRING is a documentation string for the | 805 | The optional argument DOCSTRING is a documentation string for the |
| 779 | variable. | 806 | variable. |
| @@ -784,7 +811,7 @@ To define a buffer-local variable, use `defvar-local'. | |||
| 784 | usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | 811 | usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) |
| 785 | (Lisp_Object args) | 812 | (Lisp_Object args) |
| 786 | { | 813 | { |
| 787 | Lisp_Object sym, tem, tail; | 814 | Lisp_Object sym, tail; |
| 788 | 815 | ||
| 789 | sym = XCAR (args); | 816 | sym = XCAR (args); |
| 790 | tail = XCDR (args); | 817 | tail = XCDR (args); |
| @@ -796,24 +823,8 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 796 | if (!NILP (XCDR (tail)) && !NILP (XCDR (XCDR (tail)))) | 823 | if (!NILP (XCDR (tail)) && !NILP (XCDR (XCDR (tail)))) |
| 797 | error ("Too many arguments"); | 824 | error ("Too many arguments"); |
| 798 | Lisp_Object exp = XCAR (tail); | 825 | Lisp_Object exp = XCAR (tail); |
| 799 | |||
| 800 | tem = Fdefault_boundp (sym); | ||
| 801 | tail = XCDR (tail); | 826 | tail = XCDR (tail); |
| 802 | 827 | return defvar (sym, exp, CAR (tail), true); | |
| 803 | /* Do it before evaluating the initial value, for self-references. */ | ||
| 804 | Finternal__define_uninitialized_variable (sym, CAR (tail)); | ||
| 805 | |||
| 806 | if (NILP (tem)) | ||
| 807 | Fset_default (sym, eval_sub (exp)); | ||
| 808 | else | ||
| 809 | { /* Check if there is really a global binding rather than just a let | ||
| 810 | binding that shadows the global unboundness of the var. */ | ||
| 811 | union specbinding *binding = default_toplevel_binding (sym); | ||
| 812 | if (binding && EQ (specpdl_old_value (binding), Qunbound)) | ||
| 813 | { | ||
| 814 | set_specpdl_old_value (binding, eval_sub (exp)); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | } | 828 | } |
| 818 | else if (!NILP (Vinternal_interpreter_environment) | 829 | else if (!NILP (Vinternal_interpreter_environment) |
| 819 | && (SYMBOLP (sym) && !XSYMBOL (sym)->u.s.declared_special)) | 830 | && (SYMBOLP (sym) && !XSYMBOL (sym)->u.s.declared_special)) |
| @@ -832,6 +843,14 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 832 | return sym; | 843 | return sym; |
| 833 | } | 844 | } |
| 834 | 845 | ||
| 846 | DEFUN ("defvar-1", Fdefvar_1, Sdefvar_1, 2, 3, 0, | ||
| 847 | doc: /* Like `defvar' but as a function. | ||
| 848 | More specifically behaves like (defvar SYM 'INITVALUE DOCSTRING). */) | ||
| 849 | (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring) | ||
| 850 | { | ||
| 851 | return defvar (sym, initvalue, docstring, false); | ||
| 852 | } | ||
| 853 | |||
| 835 | DEFUN ("defconst", Fdefconst, Sdefconst, 2, UNEVALLED, 0, | 854 | DEFUN ("defconst", Fdefconst, Sdefconst, 2, UNEVALLED, 0, |
| 836 | doc: /* Define SYMBOL as a constant variable. | 855 | doc: /* Define SYMBOL as a constant variable. |
| 837 | This declares that neither programs nor users should ever change the | 856 | This declares that neither programs nor users should ever change the |
| @@ -861,9 +880,18 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */) | |||
| 861 | error ("Too many arguments"); | 880 | error ("Too many arguments"); |
| 862 | docstring = XCAR (XCDR (XCDR (args))); | 881 | docstring = XCAR (XCDR (XCDR (args))); |
| 863 | } | 882 | } |
| 883 | tem = eval_sub (XCAR (XCDR (args))); | ||
| 884 | return Fdefconst_1 (sym, tem, docstring); | ||
| 885 | } | ||
| 864 | 886 | ||
| 887 | DEFUN ("defconst-1", Fdefconst_1, Sdefconst_1, 2, 3, 0, | ||
| 888 | doc: /* Like `defconst' but as a function. | ||
| 889 | More specifically, behaves like (defconst SYM 'INITVALUE DOCSTRING). */) | ||
| 890 | (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring) | ||
| 891 | { | ||
| 892 | CHECK_SYMBOL (sym); | ||
| 893 | Lisp_Object tem = initvalue; | ||
| 865 | Finternal__define_uninitialized_variable (sym, docstring); | 894 | Finternal__define_uninitialized_variable (sym, docstring); |
| 866 | tem = eval_sub (XCAR (XCDR (args))); | ||
| 867 | if (!NILP (Vpurify_flag)) | 895 | if (!NILP (Vpurify_flag)) |
| 868 | tem = Fpurecopy (tem); | 896 | tem = Fpurecopy (tem); |
| 869 | Fset_default (sym, tem); /* FIXME: set-default-toplevel-value? */ | 897 | Fset_default (sym, tem); /* FIXME: set-default-toplevel-value? */ |
| @@ -1223,6 +1251,13 @@ unwind_to_catch (struct handler *catch, enum nonlocal_exit type, | |||
| 1223 | set_poll_suppress_count (catch->poll_suppress_count); | 1251 | set_poll_suppress_count (catch->poll_suppress_count); |
| 1224 | unblock_input_to (catch->interrupt_input_blocked); | 1252 | unblock_input_to (catch->interrupt_input_blocked); |
| 1225 | 1253 | ||
| 1254 | #ifdef HAVE_X_WINDOWS | ||
| 1255 | /* Restore the X error handler stack. This is important because | ||
| 1256 | otherwise a display disconnect won't unwind the stack of error | ||
| 1257 | traps to the right depth. */ | ||
| 1258 | x_unwind_errors_to (catch->x_error_handler_depth); | ||
| 1259 | #endif | ||
| 1260 | |||
| 1226 | do | 1261 | do |
| 1227 | { | 1262 | { |
| 1228 | /* Unwind the specpdl stack, and then restore the proper set of | 1263 | /* Unwind the specpdl stack, and then restore the proper set of |
| @@ -1341,7 +1376,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, | |||
| 1341 | && (SYMBOLP (XCAR (tem)) | 1376 | && (SYMBOLP (XCAR (tem)) |
| 1342 | || CONSP (XCAR (tem)))))) | 1377 | || CONSP (XCAR (tem)))))) |
| 1343 | error ("Invalid condition handler: %s", | 1378 | error ("Invalid condition handler: %s", |
| 1344 | SDATA (Fprin1_to_string (tem, Qt))); | 1379 | SDATA (Fprin1_to_string (tem, Qt, Qnil))); |
| 1345 | if (CONSP (tem) && EQ (XCAR (tem), QCsuccess)) | 1380 | if (CONSP (tem) && EQ (XCAR (tem), QCsuccess)) |
| 1346 | success_handler = XCDR (tem); | 1381 | success_handler = XCDR (tem); |
| 1347 | else | 1382 | else |
| @@ -1597,6 +1632,9 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) | |||
| 1597 | c->act_rec = get_act_rec (current_thread); | 1632 | c->act_rec = get_act_rec (current_thread); |
| 1598 | c->poll_suppress_count = poll_suppress_count; | 1633 | c->poll_suppress_count = poll_suppress_count; |
| 1599 | c->interrupt_input_blocked = interrupt_input_blocked; | 1634 | c->interrupt_input_blocked = interrupt_input_blocked; |
| 1635 | #ifdef HAVE_X_WINDOWS | ||
| 1636 | c->x_error_handler_depth = x_error_message_count; | ||
| 1637 | #endif | ||
| 1600 | handlerlist = c; | 1638 | handlerlist = c; |
| 1601 | return c; | 1639 | return c; |
| 1602 | } | 1640 | } |
| @@ -2740,7 +2778,7 @@ run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args, | |||
| 2740 | sym = args[0]; | 2778 | sym = args[0]; |
| 2741 | val = find_symbol_value (sym); | 2779 | val = find_symbol_value (sym); |
| 2742 | 2780 | ||
| 2743 | if (EQ (val, Qunbound) || NILP (val)) | 2781 | if (BASE_EQ (val, Qunbound) || NILP (val)) |
| 2744 | return ret; | 2782 | return ret; |
| 2745 | else if (!CONSP (val) || FUNCTIONP (val)) | 2783 | else if (!CONSP (val) || FUNCTIONP (val)) |
| 2746 | { | 2784 | { |
| @@ -2816,7 +2854,13 @@ apply1 (Lisp_Object fn, Lisp_Object arg) | |||
| 2816 | } | 2854 | } |
| 2817 | 2855 | ||
| 2818 | DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0, | 2856 | DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0, |
| 2819 | doc: /* Return t if OBJECT is a function. */) | 2857 | doc: /* Return t if OBJECT is a function. |
| 2858 | |||
| 2859 | An object is a function if it is callable via `funcall'; this includes | ||
| 2860 | symbols with function bindings, but excludes macros and special forms. | ||
| 2861 | |||
| 2862 | Ordinarily return nil if OBJECT is not a function, although t might be | ||
| 2863 | returned in rare cases. */) | ||
| 2820 | (Lisp_Object object) | 2864 | (Lisp_Object object) |
| 2821 | { | 2865 | { |
| 2822 | if (FUNCTIONP (object)) | 2866 | if (FUNCTIONP (object)) |
| @@ -4338,9 +4382,11 @@ alist of active lexical bindings. */); | |||
| 4338 | defsubr (&Sdefault_toplevel_value); | 4382 | defsubr (&Sdefault_toplevel_value); |
| 4339 | defsubr (&Sset_default_toplevel_value); | 4383 | defsubr (&Sset_default_toplevel_value); |
| 4340 | defsubr (&Sdefvar); | 4384 | defsubr (&Sdefvar); |
| 4385 | defsubr (&Sdefvar_1); | ||
| 4341 | defsubr (&Sdefvaralias); | 4386 | defsubr (&Sdefvaralias); |
| 4342 | DEFSYM (Qdefvaralias, "defvaralias"); | 4387 | DEFSYM (Qdefvaralias, "defvaralias"); |
| 4343 | defsubr (&Sdefconst); | 4388 | defsubr (&Sdefconst); |
| 4389 | defsubr (&Sdefconst_1); | ||
| 4344 | defsubr (&Sinternal__define_uninitialized_variable); | 4390 | defsubr (&Sinternal__define_uninitialized_variable); |
| 4345 | defsubr (&Smake_var_non_special); | 4391 | defsubr (&Smake_var_non_special); |
| 4346 | defsubr (&Slet); | 4392 | defsubr (&Slet); |
diff --git a/src/fileio.c b/src/fileio.c index c418036fc6e..e29685e07bf 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -2718,6 +2718,20 @@ This is what happens in interactive use with M-x. */) | |||
| 2718 | : Qnil); | 2718 | : Qnil); |
| 2719 | if (!NILP (symlink_target)) | 2719 | if (!NILP (symlink_target)) |
| 2720 | Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); | 2720 | Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); |
| 2721 | else if (S_ISFIFO (file_st.st_mode)) | ||
| 2722 | { | ||
| 2723 | /* If it's a FIFO, calling `copy-file' will hang if it's a | ||
| 2724 | inter-file system move, so do it here. (It will signal | ||
| 2725 | an error in that case, but it won't hang in any case.) */ | ||
| 2726 | if (!NILP (ok_if_already_exists)) | ||
| 2727 | barf_or_query_if_file_exists (newname, false, | ||
| 2728 | "rename to it", | ||
| 2729 | FIXNUMP (ok_if_already_exists), | ||
| 2730 | false); | ||
| 2731 | if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) != 0) | ||
| 2732 | report_file_errno ("Renaming", list2 (file, newname), errno); | ||
| 2733 | return Qnil; | ||
| 2734 | } | ||
| 2721 | else | 2735 | else |
| 2722 | Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt); | 2736 | Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt); |
| 2723 | } | 2737 | } |
| @@ -3884,6 +3898,10 @@ The optional third and fourth arguments BEG and END specify what portion | |||
| 3884 | of the file to insert. These arguments count bytes in the file, not | 3898 | of the file to insert. These arguments count bytes in the file, not |
| 3885 | characters in the buffer. If VISIT is non-nil, BEG and END must be nil. | 3899 | characters in the buffer. If VISIT is non-nil, BEG and END must be nil. |
| 3886 | 3900 | ||
| 3901 | When inserting data from a special file (e.g., /dev/urandom), you | ||
| 3902 | can't specify VISIT or BEG, and END should be specified to avoid | ||
| 3903 | inserting unlimited data into the buffer. | ||
| 3904 | |||
| 3887 | If optional fifth argument REPLACE is non-nil, replace the current | 3905 | If optional fifth argument REPLACE is non-nil, replace the current |
| 3888 | buffer contents (in the accessible portion) with the file contents. | 3906 | buffer contents (in the accessible portion) with the file contents. |
| 3889 | This is better than simply deleting and inserting the whole thing | 3907 | This is better than simply deleting and inserting the whole thing |
| @@ -3911,7 +3929,7 @@ by calling `format-decode', which see. */) | |||
| 3911 | Lisp_Object handler, val, insval, orig_filename, old_undo; | 3929 | Lisp_Object handler, val, insval, orig_filename, old_undo; |
| 3912 | Lisp_Object p; | 3930 | Lisp_Object p; |
| 3913 | ptrdiff_t total = 0; | 3931 | ptrdiff_t total = 0; |
| 3914 | bool not_regular = 0; | 3932 | bool regular = true; |
| 3915 | int save_errno = 0; | 3933 | int save_errno = 0; |
| 3916 | char read_buf[READ_BUF_SIZE]; | 3934 | char read_buf[READ_BUF_SIZE]; |
| 3917 | struct coding_system coding; | 3935 | struct coding_system coding; |
| @@ -3934,6 +3952,7 @@ by calling `format-decode', which see. */) | |||
| 3934 | /* SAME_AT_END_CHARPOS counts characters, because | 3952 | /* SAME_AT_END_CHARPOS counts characters, because |
| 3935 | restore_window_points needs the old character count. */ | 3953 | restore_window_points needs the old character count. */ |
| 3936 | ptrdiff_t same_at_end_charpos = ZV; | 3954 | ptrdiff_t same_at_end_charpos = ZV; |
| 3955 | bool seekable = true; | ||
| 3937 | 3956 | ||
| 3938 | if (current_buffer->base_buffer && ! NILP (visit)) | 3957 | if (current_buffer->base_buffer && ! NILP (visit)) |
| 3939 | error ("Cannot do file visiting in an indirect buffer"); | 3958 | error ("Cannot do file visiting in an indirect buffer"); |
| @@ -4007,7 +4026,8 @@ by calling `format-decode', which see. */) | |||
| 4007 | least signal an error. */ | 4026 | least signal an error. */ |
| 4008 | if (!S_ISREG (st.st_mode)) | 4027 | if (!S_ISREG (st.st_mode)) |
| 4009 | { | 4028 | { |
| 4010 | not_regular = 1; | 4029 | regular = false; |
| 4030 | seekable = lseek (fd, 0, SEEK_CUR) < 0; | ||
| 4011 | 4031 | ||
| 4012 | if (! NILP (visit)) | 4032 | if (! NILP (visit)) |
| 4013 | { | 4033 | { |
| @@ -4015,7 +4035,12 @@ by calling `format-decode', which see. */) | |||
| 4015 | goto notfound; | 4035 | goto notfound; |
| 4016 | } | 4036 | } |
| 4017 | 4037 | ||
| 4018 | if (! NILP (replace) || ! NILP (beg) || ! NILP (end)) | 4038 | if (!NILP (beg) && !seekable) |
| 4039 | xsignal2 (Qfile_error, | ||
| 4040 | build_string ("cannot use a start position in a non-seekable file/device"), | ||
| 4041 | orig_filename); | ||
| 4042 | |||
| 4043 | if (!NILP (replace)) | ||
| 4019 | xsignal2 (Qfile_error, | 4044 | xsignal2 (Qfile_error, |
| 4020 | build_string ("not a regular file"), orig_filename); | 4045 | build_string ("not a regular file"), orig_filename); |
| 4021 | } | 4046 | } |
| @@ -4037,7 +4062,7 @@ by calling `format-decode', which see. */) | |||
| 4037 | end_offset = file_offset (end); | 4062 | end_offset = file_offset (end); |
| 4038 | else | 4063 | else |
| 4039 | { | 4064 | { |
| 4040 | if (not_regular) | 4065 | if (!regular) |
| 4041 | end_offset = TYPE_MAXIMUM (off_t); | 4066 | end_offset = TYPE_MAXIMUM (off_t); |
| 4042 | else | 4067 | else |
| 4043 | { | 4068 | { |
| @@ -4059,7 +4084,7 @@ by calling `format-decode', which see. */) | |||
| 4059 | /* Check now whether the buffer will become too large, | 4084 | /* Check now whether the buffer will become too large, |
| 4060 | in the likely case where the file's length is not changing. | 4085 | in the likely case where the file's length is not changing. |
| 4061 | This saves a lot of needless work before a buffer overflow. */ | 4086 | This saves a lot of needless work before a buffer overflow. */ |
| 4062 | if (! not_regular) | 4087 | if (regular) |
| 4063 | { | 4088 | { |
| 4064 | /* The likely offset where we will stop reading. We could read | 4089 | /* The likely offset where we will stop reading. We could read |
| 4065 | more (or less), if the file grows (or shrinks) as we read it. */ | 4090 | more (or less), if the file grows (or shrinks) as we read it. */ |
| @@ -4097,7 +4122,7 @@ by calling `format-decode', which see. */) | |||
| 4097 | { | 4122 | { |
| 4098 | /* Don't try looking inside a file for a coding system | 4123 | /* Don't try looking inside a file for a coding system |
| 4099 | specification if it is not seekable. */ | 4124 | specification if it is not seekable. */ |
| 4100 | if (! not_regular && ! NILP (Vset_auto_coding_function)) | 4125 | if (regular && !NILP (Vset_auto_coding_function)) |
| 4101 | { | 4126 | { |
| 4102 | /* Find a coding system specified in the heading two | 4127 | /* Find a coding system specified in the heading two |
| 4103 | lines or in the tailing several lines of the file. | 4128 | lines or in the tailing several lines of the file. |
| @@ -4559,7 +4584,7 @@ by calling `format-decode', which see. */) | |||
| 4559 | goto handled; | 4584 | goto handled; |
| 4560 | } | 4585 | } |
| 4561 | 4586 | ||
| 4562 | if (! not_regular) | 4587 | if (seekable || !NILP (end)) |
| 4563 | total = end_offset - beg_offset; | 4588 | total = end_offset - beg_offset; |
| 4564 | else | 4589 | else |
| 4565 | /* For a special file, all we can do is guess. */ | 4590 | /* For a special file, all we can do is guess. */ |
| @@ -4605,7 +4630,7 @@ by calling `format-decode', which see. */) | |||
| 4605 | ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE); | 4630 | ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE); |
| 4606 | ptrdiff_t this; | 4631 | ptrdiff_t this; |
| 4607 | 4632 | ||
| 4608 | if (not_regular) | 4633 | if (!seekable && NILP (end)) |
| 4609 | { | 4634 | { |
| 4610 | Lisp_Object nbytes; | 4635 | Lisp_Object nbytes; |
| 4611 | 4636 | ||
| @@ -4656,7 +4681,7 @@ by calling `format-decode', which see. */) | |||
| 4656 | For a special file, where TOTAL is just a buffer size, | 4681 | For a special file, where TOTAL is just a buffer size, |
| 4657 | so don't bother counting in HOW_MUCH. | 4682 | so don't bother counting in HOW_MUCH. |
| 4658 | (INSERTED is where we count the number of characters inserted.) */ | 4683 | (INSERTED is where we count the number of characters inserted.) */ |
| 4659 | if (! not_regular) | 4684 | if (seekable || !NILP (end)) |
| 4660 | how_much += this; | 4685 | how_much += this; |
| 4661 | inserted += this; | 4686 | inserted += this; |
| 4662 | } | 4687 | } |
| @@ -4834,7 +4859,7 @@ by calling `format-decode', which see. */) | |||
| 4834 | Funlock_file (BVAR (current_buffer, file_truename)); | 4859 | Funlock_file (BVAR (current_buffer, file_truename)); |
| 4835 | Funlock_file (filename); | 4860 | Funlock_file (filename); |
| 4836 | } | 4861 | } |
| 4837 | if (not_regular) | 4862 | if (!regular) |
| 4838 | xsignal2 (Qfile_error, | 4863 | xsignal2 (Qfile_error, |
| 4839 | build_string ("not a regular file"), orig_filename); | 4864 | build_string ("not a regular file"), orig_filename); |
| 4840 | } | 4865 | } |
| @@ -5958,14 +5983,19 @@ do_auto_save_eh (Lisp_Object ignore) | |||
| 5958 | 5983 | ||
| 5959 | DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "", | 5984 | DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "", |
| 5960 | doc: /* Auto-save all buffers that need it. | 5985 | doc: /* Auto-save all buffers that need it. |
| 5961 | This is all buffers that have auto-saving enabled | 5986 | This auto-saves all buffers that have auto-saving enabled and |
| 5962 | and are changed since last auto-saved. | 5987 | were changed since last auto-saved. |
| 5963 | Auto-saving writes the buffer into a file | 5988 | |
| 5964 | so that your editing is not lost if the system crashes. | 5989 | Auto-saving writes the buffer into a file so that your edits are |
| 5965 | This file is not the file you visited; that changes only when you save. | 5990 | not lost if the system crashes. |
| 5991 | |||
| 5992 | The auto-save file is not the file you visited; that changes only | ||
| 5993 | when you save. | ||
| 5994 | |||
| 5966 | Normally, run the normal hook `auto-save-hook' before saving. | 5995 | Normally, run the normal hook `auto-save-hook' before saving. |
| 5967 | 5996 | ||
| 5968 | A non-nil NO-MESSAGE argument means do not print any message if successful. | 5997 | A non-nil NO-MESSAGE argument means do not print any message if successful. |
| 5998 | |||
| 5969 | A non-nil CURRENT-ONLY argument means save only current buffer. */) | 5999 | A non-nil CURRENT-ONLY argument means save only current buffer. */) |
| 5970 | (Lisp_Object no_message, Lisp_Object current_only) | 6000 | (Lisp_Object no_message, Lisp_Object current_only) |
| 5971 | { | 6001 | { |
diff --git a/src/floatfns.c b/src/floatfns.c index f2b3b13acd8..293184c70f1 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -29,14 +29,20 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 29 | 29 | ||
| 30 | C99 and C11 require the following math.h functions in addition to | 30 | C99 and C11 require the following math.h functions in addition to |
| 31 | the C89 functions. Of these, Emacs currently exports only the | 31 | the C89 functions. Of these, Emacs currently exports only the |
| 32 | starred ones to Lisp, since we haven't found a use for the others: | 32 | starred ones to Lisp, since we haven't found a use for the others. |
| 33 | acosh, atanh, cbrt, *copysign, erf, erfc, exp2, expm1, fdim, fma, | 33 | Also, it uses the ones marked "+" internally: |
| 34 | fmax, fmin, fpclassify, hypot, ilogb, isfinite, isgreater, | 34 | acosh, atanh, cbrt, copysign (implemented by signbit), erf, erfc, |
| 35 | isgreaterequal, isinf, isless, islessequal, islessgreater, *isnan, | 35 | exp2, expm1, fdim, fma, fmax, fmin, fpclassify, hypot, +ilogb, |
| 36 | isnormal, isunordered, lgamma, log1p, *log2 [via (log X 2)], *logb | 36 | isfinite, isgreater, isgreaterequal, isinf, isless, islessequal, |
| 37 | (approximately), lrint/llrint, lround/llround, nan, nearbyint, | 37 | islessgreater, *isnan, isnormal, isunordered, lgamma, log1p, *log2 |
| 38 | nextafter, nexttoward, remainder, remquo, *rint, round, scalbln, | 38 | [via (log X 2)], logb (approximately; implemented by frexp), |
| 39 | scalbn, signbit, tgamma, *trunc. | 39 | +lrint/llrint, +lround/llround, nan, nearbyint, nextafter, |
| 40 | nexttoward, remainder, remquo, *rint, round, scalbln, +scalbn, | ||
| 41 | +signbit, tgamma, *trunc. | ||
| 42 | |||
| 43 | The C standard also requires functions for float and long double | ||
| 44 | that are not listed above. Of these functions, Emacs uses only the | ||
| 45 | following internally: fabsf, powf, sprintf. | ||
| 40 | */ | 46 | */ |
| 41 | 47 | ||
| 42 | #include <config.h> | 48 | #include <config.h> |
| @@ -2519,7 +2519,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, | |||
| 2519 | if (SYMBOL_WITH_POS_P (o2)) | 2519 | if (SYMBOL_WITH_POS_P (o2)) |
| 2520 | o2 = SYMBOL_WITH_POS_SYM (o2); | 2520 | o2 = SYMBOL_WITH_POS_SYM (o2); |
| 2521 | 2521 | ||
| 2522 | if (EQ (o1, o2)) | 2522 | if (BASE_EQ (o1, o2)) |
| 2523 | return true; | 2523 | return true; |
| 2524 | if (XTYPE (o1) != XTYPE (o2)) | 2524 | if (XTYPE (o1) != XTYPE (o2)) |
| 2525 | return false; | 2525 | return false; |
| @@ -4113,7 +4113,7 @@ hash_table_user_defined_call (ptrdiff_t nargs, Lisp_Object *args, | |||
| 4113 | return unbind_to (count, Ffuncall (nargs, args)); | 4113 | return unbind_to (count, Ffuncall (nargs, args)); |
| 4114 | } | 4114 | } |
| 4115 | 4115 | ||
| 4116 | /* Ignore HT and compare KEY1 and KEY2 using 'eql'. | 4116 | /* Ignore H and compare KEY1 and KEY2 using 'eql'. |
| 4117 | Value is true if KEY1 and KEY2 are the same. */ | 4117 | Value is true if KEY1 and KEY2 are the same. */ |
| 4118 | 4118 | ||
| 4119 | static Lisp_Object | 4119 | static Lisp_Object |
| @@ -4122,7 +4122,7 @@ cmpfn_eql (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) | |||
| 4122 | return Feql (key1, key2); | 4122 | return Feql (key1, key2); |
| 4123 | } | 4123 | } |
| 4124 | 4124 | ||
| 4125 | /* Ignore HT and compare KEY1 and KEY2 using 'equal'. | 4125 | /* Ignore H and compare KEY1 and KEY2 using 'equal'. |
| 4126 | Value is true if KEY1 and KEY2 are the same. */ | 4126 | Value is true if KEY1 and KEY2 are the same. */ |
| 4127 | 4127 | ||
| 4128 | static Lisp_Object | 4128 | static Lisp_Object |
| @@ -4132,7 +4132,7 @@ cmpfn_equal (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) | |||
| 4132 | } | 4132 | } |
| 4133 | 4133 | ||
| 4134 | 4134 | ||
| 4135 | /* Given HT, compare KEY1 and KEY2 using HT->user_cmp_function. | 4135 | /* Given H, compare KEY1 and KEY2 using H->user_cmp_function. |
| 4136 | Value is true if KEY1 and KEY2 are the same. */ | 4136 | Value is true if KEY1 and KEY2 are the same. */ |
| 4137 | 4137 | ||
| 4138 | static Lisp_Object | 4138 | static Lisp_Object |
| @@ -4143,8 +4143,7 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2, | |||
| 4143 | return hash_table_user_defined_call (ARRAYELTS (args), args, h); | 4143 | return hash_table_user_defined_call (ARRAYELTS (args), args, h); |
| 4144 | } | 4144 | } |
| 4145 | 4145 | ||
| 4146 | /* Ignore HT and return a hash code for KEY which uses 'eq' to compare | 4146 | /* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */ |
| 4147 | keys. */ | ||
| 4148 | 4147 | ||
| 4149 | static Lisp_Object | 4148 | static Lisp_Object |
| 4150 | hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) | 4149 | hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) |
| @@ -4154,7 +4153,7 @@ hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) | |||
| 4154 | return make_ufixnum (XHASH (key) ^ XTYPE (key)); | 4153 | return make_ufixnum (XHASH (key) ^ XTYPE (key)); |
| 4155 | } | 4154 | } |
| 4156 | 4155 | ||
| 4157 | /* Ignore HT and return a hash code for KEY which uses 'equal' to compare keys. | 4156 | /* Ignore H and return a hash code for KEY which uses 'equal' to compare keys. |
| 4158 | The hash code is at most INTMASK. */ | 4157 | The hash code is at most INTMASK. */ |
| 4159 | 4158 | ||
| 4160 | static Lisp_Object | 4159 | static Lisp_Object |
| @@ -4163,7 +4162,7 @@ hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h) | |||
| 4163 | return make_ufixnum (sxhash (key)); | 4162 | return make_ufixnum (sxhash (key)); |
| 4164 | } | 4163 | } |
| 4165 | 4164 | ||
| 4166 | /* Ignore HT and return a hash code for KEY which uses 'eql' to compare keys. | 4165 | /* Ignore H and return a hash code for KEY which uses 'eql' to compare keys. |
| 4167 | The hash code is at most INTMASK. */ | 4166 | The hash code is at most INTMASK. */ |
| 4168 | 4167 | ||
| 4169 | static Lisp_Object | 4168 | static Lisp_Object |
| @@ -4172,7 +4171,7 @@ hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) | |||
| 4172 | return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h); | 4171 | return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h); |
| 4173 | } | 4172 | } |
| 4174 | 4173 | ||
| 4175 | /* Given HT, return a hash code for KEY which uses a user-defined | 4174 | /* Given H, return a hash code for KEY which uses a user-defined |
| 4176 | function to compare keys. */ | 4175 | function to compare keys. */ |
| 4177 | 4176 | ||
| 4178 | Lisp_Object | 4177 | Lisp_Object |
| @@ -4479,7 +4478,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 4479 | /* Store key/value in the key_and_value vector. */ | 4478 | /* Store key/value in the key_and_value vector. */ |
| 4480 | i = h->next_free; | 4479 | i = h->next_free; |
| 4481 | eassert (NILP (HASH_HASH (h, i))); | 4480 | eassert (NILP (HASH_HASH (h, i))); |
| 4482 | eassert (EQ (Qunbound, (HASH_KEY (h, i)))); | 4481 | eassert (BASE_EQ (Qunbound, (HASH_KEY (h, i)))); |
| 4483 | h->next_free = HASH_NEXT (h, i); | 4482 | h->next_free = HASH_NEXT (h, i); |
| 4484 | set_hash_key_slot (h, i, key); | 4483 | set_hash_key_slot (h, i, key); |
| 4485 | set_hash_value_slot (h, i, value); | 4484 | set_hash_value_slot (h, i, value); |
| @@ -5220,7 +5219,7 @@ FUNCTION is called with two arguments, KEY and VALUE. | |||
| 5220 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 5219 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 5221 | { | 5220 | { |
| 5222 | Lisp_Object k = HASH_KEY (h, i); | 5221 | Lisp_Object k = HASH_KEY (h, i); |
| 5223 | if (!EQ (k, Qunbound)) | 5222 | if (!BASE_EQ (k, Qunbound)) |
| 5224 | call2 (function, k, HASH_VALUE (h, i)); | 5223 | call2 (function, k, HASH_VALUE (h, i)); |
| 5225 | } | 5224 | } |
| 5226 | 5225 | ||
| @@ -5870,9 +5869,12 @@ from the absolute start of the buffer, disregarding the narrowing. */) | |||
| 5870 | if (!NILP (absolute)) | 5869 | if (!NILP (absolute)) |
| 5871 | start = BEG_BYTE; | 5870 | start = BEG_BYTE; |
| 5872 | 5871 | ||
| 5873 | /* Check that POSITION is in the accessible range of the buffer. */ | 5872 | /* Check that POSITION is in the accessible range of the buffer, or, |
| 5874 | if (pos < BEGV || pos > ZV) | 5873 | if we're reporting absolute positions, in the buffer. */ |
| 5874 | if (NILP (absolute) && (pos < BEGV || pos > ZV)) | ||
| 5875 | args_out_of_range_3 (make_int (pos), make_int (BEGV), make_int (ZV)); | 5875 | args_out_of_range_3 (make_int (pos), make_int (BEGV), make_int (ZV)); |
| 5876 | else if (!NILP (absolute) && (pos < 1 || pos > Z)) | ||
| 5877 | args_out_of_range_3 (make_int (pos), make_int (1), make_int (Z)); | ||
| 5876 | 5878 | ||
| 5877 | return make_int (count_lines (start, CHAR_TO_BYTE (pos)) + 1); | 5879 | return make_int (count_lines (start, CHAR_TO_BYTE (pos)) + 1); |
| 5878 | } | 5880 | } |
diff --git a/src/font.c b/src/font.c index 6297452d3e0..702536c1cab 100644 --- a/src/font.c +++ b/src/font.c | |||
| @@ -731,7 +731,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val) | |||
| 731 | { | 731 | { |
| 732 | Lisp_Object prev = Qnil; | 732 | Lisp_Object prev = Qnil; |
| 733 | 733 | ||
| 734 | if (EQ (val, Qunbound)) | 734 | if (BASE_EQ (val, Qunbound)) |
| 735 | return val; | 735 | return val; |
| 736 | while (CONSP (extra) | 736 | while (CONSP (extra) |
| 737 | && NILP (Fstring_lessp (prop, XCAR (XCAR (extra))))) | 737 | && NILP (Fstring_lessp (prop, XCAR (XCAR (extra))))) |
| @@ -745,7 +745,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val) | |||
| 745 | return val; | 745 | return val; |
| 746 | } | 746 | } |
| 747 | XSETCDR (slot, val); | 747 | XSETCDR (slot, val); |
| 748 | if (EQ (val, Qunbound)) | 748 | if (BASE_EQ (val, Qunbound)) |
| 749 | ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra)); | 749 | ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra)); |
| 750 | return val; | 750 | return val; |
| 751 | } | 751 | } |
diff --git a/src/frame.c b/src/frame.c index 93028aa8958..c21461d49fe 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -1572,6 +1572,19 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor | |||
| 1572 | if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) | 1572 | if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) |
| 1573 | last_nonminibuf_frame = XFRAME (selected_frame); | 1573 | last_nonminibuf_frame = XFRAME (selected_frame); |
| 1574 | 1574 | ||
| 1575 | /* If the selected window in the target frame is its mini-window, we move | ||
| 1576 | to a different window, the most recently used one, unless there is a | ||
| 1577 | valid active minibuffer in the mini-window. */ | ||
| 1578 | if (EQ (f->selected_window, f->minibuffer_window) | ||
| 1579 | /* The following test might fail if the mini-window contains a | ||
| 1580 | non-active minibuffer. */ | ||
| 1581 | && NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) | ||
| 1582 | { | ||
| 1583 | Lisp_Object w = call1 (Qget_mru_window, frame); | ||
| 1584 | if (WINDOW_LIVE_P (w)) /* W can be nil in minibuffer-only frames. */ | ||
| 1585 | Fset_frame_selected_window (frame, w, Qnil); | ||
| 1586 | } | ||
| 1587 | |||
| 1575 | Fselect_window (f->selected_window, norecord); | 1588 | Fselect_window (f->selected_window, norecord); |
| 1576 | 1589 | ||
| 1577 | /* We want to make sure that the next event generates a frame-switch | 1590 | /* We want to make sure that the next event generates a frame-switch |
| @@ -1988,7 +2001,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 1988 | error ("Attempt to delete the only frame"); | 2001 | error ("Attempt to delete the only frame"); |
| 1989 | } | 2002 | } |
| 1990 | #ifdef HAVE_X_WINDOWS | 2003 | #ifdef HAVE_X_WINDOWS |
| 1991 | else if (x_dnd_in_progress && f == x_dnd_frame) | 2004 | else if ((x_dnd_in_progress && f == x_dnd_frame) |
| 2005 | || (x_dnd_waiting_for_finish && f == x_dnd_finish_frame)) | ||
| 1992 | error ("Attempt to delete the drop source frame"); | 2006 | error ("Attempt to delete the drop source frame"); |
| 1993 | #endif | 2007 | #endif |
| 1994 | #ifdef HAVE_HAIKU | 2008 | #ifdef HAVE_HAIKU |
| @@ -2333,7 +2347,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2333 | kset_default_minibuffer_frame (kb, Qnil); | 2347 | kset_default_minibuffer_frame (kb, Qnil); |
| 2334 | } | 2348 | } |
| 2335 | 2349 | ||
| 2336 | /* Cause frame titles to update--necessary if we now have just one frame. */ | 2350 | /* Cause frame titles to update--necessary if we now have just one |
| 2351 | frame. */ | ||
| 2337 | if (!is_tooltip_frame) | 2352 | if (!is_tooltip_frame) |
| 2338 | update_mode_lines = 15; | 2353 | update_mode_lines = 15; |
| 2339 | 2354 | ||
| @@ -3642,7 +3657,7 @@ DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0, | |||
| 3642 | 3657 | ||
| 3643 | DEFUN ("frame-child-frame-border-width", Fframe_child_frame_border_width, Sframe_child_frame_border_width, 0, 1, 0, | 3658 | DEFUN ("frame-child-frame-border-width", Fframe_child_frame_border_width, Sframe_child_frame_border_width, 0, 1, 0, |
| 3644 | doc: /* Return width of FRAME's child-frame border in pixels. | 3659 | doc: /* Return width of FRAME's child-frame border in pixels. |
| 3645 | If FRAME's 'child-frame-border-width' parameter is nil, return FRAME's | 3660 | If FRAME's `child-frame-border-width' parameter is nil, return FRAME's |
| 3646 | internal border width instead. */) | 3661 | internal border width instead. */) |
| 3647 | (Lisp_Object frame) | 3662 | (Lisp_Object frame) |
| 3648 | { | 3663 | { |
| @@ -4276,7 +4291,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) | |||
| 4276 | } | 4291 | } |
| 4277 | 4292 | ||
| 4278 | /* Don't die if just one of these was set. */ | 4293 | /* Don't die if just one of these was set. */ |
| 4279 | if (EQ (left, Qunbound)) | 4294 | if (BASE_EQ (left, Qunbound)) |
| 4280 | { | 4295 | { |
| 4281 | left_no_change = 1; | 4296 | left_no_change = 1; |
| 4282 | if (f->left_pos < 0) | 4297 | if (f->left_pos < 0) |
| @@ -4284,7 +4299,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) | |||
| 4284 | else | 4299 | else |
| 4285 | XSETINT (left, f->left_pos); | 4300 | XSETINT (left, f->left_pos); |
| 4286 | } | 4301 | } |
| 4287 | if (EQ (top, Qunbound)) | 4302 | if (BASE_EQ (top, Qunbound)) |
| 4288 | { | 4303 | { |
| 4289 | top_no_change = 1; | 4304 | top_no_change = 1; |
| 4290 | if (f->top_pos < 0) | 4305 | if (f->top_pos < 0) |
| @@ -5442,7 +5457,7 @@ gui_frame_get_and_record_arg (struct frame *f, Lisp_Object alist, | |||
| 5442 | 5457 | ||
| 5443 | value = gui_display_get_arg (FRAME_DISPLAY_INFO (f), alist, param, | 5458 | value = gui_display_get_arg (FRAME_DISPLAY_INFO (f), alist, param, |
| 5444 | attribute, class, type); | 5459 | attribute, class, type); |
| 5445 | if (! NILP (value) && ! EQ (value, Qunbound)) | 5460 | if (! NILP (value) && ! BASE_EQ (value, Qunbound)) |
| 5446 | store_frame_param (f, param, value); | 5461 | store_frame_param (f, param, value); |
| 5447 | 5462 | ||
| 5448 | return value; | 5463 | return value; |
| @@ -5463,7 +5478,7 @@ gui_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop, | |||
| 5463 | Lisp_Object tem; | 5478 | Lisp_Object tem; |
| 5464 | 5479 | ||
| 5465 | tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type); | 5480 | tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type); |
| 5466 | if (EQ (tem, Qunbound)) | 5481 | if (BASE_EQ (tem, Qunbound)) |
| 5467 | tem = deflt; | 5482 | tem = deflt; |
| 5468 | AUTO_FRAME_ARG (arg, prop, tem); | 5483 | AUTO_FRAME_ARG (arg, prop, tem); |
| 5469 | gui_set_frame_parameters (f, arg); | 5484 | gui_set_frame_parameters (f, arg); |
| @@ -5725,9 +5740,9 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5725 | 5740 | ||
| 5726 | height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); | 5741 | height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); |
| 5727 | width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); | 5742 | width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); |
| 5728 | if (!EQ (width, Qunbound) || !EQ (height, Qunbound)) | 5743 | if (!BASE_EQ (width, Qunbound) || !BASE_EQ (height, Qunbound)) |
| 5729 | { | 5744 | { |
| 5730 | if (!EQ (width, Qunbound)) | 5745 | if (!BASE_EQ (width, Qunbound)) |
| 5731 | { | 5746 | { |
| 5732 | if (CONSP (width) && EQ (XCAR (width), Qtext_pixels)) | 5747 | if (CONSP (width) && EQ (XCAR (width), Qtext_pixels)) |
| 5733 | { | 5748 | { |
| @@ -5763,7 +5778,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5763 | } | 5778 | } |
| 5764 | } | 5779 | } |
| 5765 | 5780 | ||
| 5766 | if (!EQ (height, Qunbound)) | 5781 | if (!BASE_EQ (height, Qunbound)) |
| 5767 | { | 5782 | { |
| 5768 | if (CONSP (height) && EQ (XCAR (height), Qtext_pixels)) | 5783 | if (CONSP (height) && EQ (XCAR (height), Qtext_pixels)) |
| 5769 | { | 5784 | { |
| @@ -5801,7 +5816,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5801 | 5816 | ||
| 5802 | user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0, | 5817 | user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0, |
| 5803 | RES_TYPE_NUMBER); | 5818 | RES_TYPE_NUMBER); |
| 5804 | if (!NILP (user_size) && !EQ (user_size, Qunbound)) | 5819 | if (!NILP (user_size) && !BASE_EQ (user_size, Qunbound)) |
| 5805 | window_prompting |= USSize; | 5820 | window_prompting |= USSize; |
| 5806 | else | 5821 | else |
| 5807 | window_prompting |= PSize; | 5822 | window_prompting |= PSize; |
| @@ -5814,7 +5829,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5814 | left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); | 5829 | left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); |
| 5815 | user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0, | 5830 | user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0, |
| 5816 | RES_TYPE_NUMBER); | 5831 | RES_TYPE_NUMBER); |
| 5817 | if (! EQ (top, Qunbound) || ! EQ (left, Qunbound)) | 5832 | if (! BASE_EQ (top, Qunbound) || ! BASE_EQ (left, Qunbound)) |
| 5818 | { | 5833 | { |
| 5819 | if (EQ (top, Qminus)) | 5834 | if (EQ (top, Qminus)) |
| 5820 | { | 5835 | { |
| @@ -5837,7 +5852,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5837 | else if (FLOATP (top)) | 5852 | else if (FLOATP (top)) |
| 5838 | f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done, | 5853 | f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done, |
| 5839 | &outer_done, 0); | 5854 | &outer_done, 0); |
| 5840 | else if (EQ (top, Qunbound)) | 5855 | else if (BASE_EQ (top, Qunbound)) |
| 5841 | f->top_pos = 0; | 5856 | f->top_pos = 0; |
| 5842 | else | 5857 | else |
| 5843 | { | 5858 | { |
| @@ -5867,7 +5882,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5867 | else if (FLOATP (left)) | 5882 | else if (FLOATP (left)) |
| 5868 | f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done, | 5883 | f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done, |
| 5869 | &outer_done, 0); | 5884 | &outer_done, 0); |
| 5870 | else if (EQ (left, Qunbound)) | 5885 | else if (BASE_EQ (left, Qunbound)) |
| 5871 | f->left_pos = 0; | 5886 | f->left_pos = 0; |
| 5872 | else | 5887 | else |
| 5873 | { | 5888 | { |
| @@ -5876,7 +5891,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, | |||
| 5876 | window_prompting |= XNegative; | 5891 | window_prompting |= XNegative; |
| 5877 | } | 5892 | } |
| 5878 | 5893 | ||
| 5879 | if (!NILP (user_position) && ! EQ (user_position, Qunbound)) | 5894 | if (!NILP (user_position) && ! BASE_EQ (user_position, Qunbound)) |
| 5880 | window_prompting |= USPosition; | 5895 | window_prompting |= USPosition; |
| 5881 | else | 5896 | else |
| 5882 | window_prompting |= PPosition; | 5897 | window_prompting |= PPosition; |
diff --git a/src/frame.h b/src/frame.h index 4942e640d27..458b6257e49 100644 --- a/src/frame.h +++ b/src/frame.h | |||
| @@ -127,6 +127,7 @@ struct frame | |||
| 127 | /* This frame's selected window. | 127 | /* This frame's selected window. |
| 128 | Each frame has its own window hierarchy | 128 | Each frame has its own window hierarchy |
| 129 | and one of the windows in it is selected within the frame. | 129 | and one of the windows in it is selected within the frame. |
| 130 | This window may be the mini-window of the frame, if any. | ||
| 130 | The selected window of the selected frame is Emacs's selected window. */ | 131 | The selected window of the selected frame is Emacs's selected window. */ |
| 131 | Lisp_Object selected_window; | 132 | Lisp_Object selected_window; |
| 132 | 133 | ||
| @@ -1292,8 +1293,28 @@ SET_FRAME_VISIBLE (struct frame *f, int v) | |||
| 1292 | } | 1293 | } |
| 1293 | 1294 | ||
| 1294 | /* Set iconified status of frame F. */ | 1295 | /* Set iconified status of frame F. */ |
| 1295 | #define SET_FRAME_ICONIFIED(f, i) \ | 1296 | INLINE void |
| 1296 | (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i)) | 1297 | SET_FRAME_ICONIFIED (struct frame *f, int i) |
| 1298 | { | ||
| 1299 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1300 | Lisp_Object frame; | ||
| 1301 | #endif | ||
| 1302 | |||
| 1303 | eassert (0 <= (i) && (i) <= 1); | ||
| 1304 | |||
| 1305 | f->iconified = i; | ||
| 1306 | |||
| 1307 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1308 | /* Iconifying a frame might cause the frame title to change if no | ||
| 1309 | title was explicitly specified. Force the frame title to be | ||
| 1310 | recomputed. */ | ||
| 1311 | |||
| 1312 | XSETFRAME (frame, f); | ||
| 1313 | |||
| 1314 | if (FRAME_WINDOW_P (f)) | ||
| 1315 | gui_consider_frame_title (frame); | ||
| 1316 | #endif | ||
| 1317 | } | ||
| 1297 | 1318 | ||
| 1298 | extern Lisp_Object selected_frame; | 1319 | extern Lisp_Object selected_frame; |
| 1299 | extern Lisp_Object old_selected_frame; | 1320 | extern Lisp_Object old_selected_frame; |
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 98a28af5f22..6bb41110d5c 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c | |||
| @@ -37,6 +37,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 37 | #include "font.h" | 37 | #include "font.h" |
| 38 | #include "ftfont.h" | 38 | #include "ftfont.h" |
| 39 | #include "pdumper.h" | 39 | #include "pdumper.h" |
| 40 | #ifdef HAVE_PGTK | ||
| 41 | #include "xsettings.h" | ||
| 42 | #endif | ||
| 40 | 43 | ||
| 41 | #ifdef USE_BE_CAIRO | 44 | #ifdef USE_BE_CAIRO |
| 42 | #define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) | 45 | #define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) |
| @@ -168,7 +171,12 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 168 | cairo_matrix_t font_matrix, ctm; | 171 | cairo_matrix_t font_matrix, ctm; |
| 169 | cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); | 172 | cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); |
| 170 | cairo_matrix_init_identity (&ctm); | 173 | cairo_matrix_init_identity (&ctm); |
| 174 | |||
| 175 | #ifdef HAVE_PGTK | ||
| 176 | cairo_font_options_t *options = xsettings_get_font_options (); | ||
| 177 | #else | ||
| 171 | cairo_font_options_t *options = cairo_font_options_create (); | 178 | cairo_font_options_t *options = cairo_font_options_create (); |
| 179 | #endif | ||
| 172 | #ifdef USE_BE_CAIRO | 180 | #ifdef USE_BE_CAIRO |
| 173 | if (be_use_subpixel_antialiasing ()) | 181 | if (be_use_subpixel_antialiasing ()) |
| 174 | cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL); | 182 | cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL); |
| @@ -624,6 +632,28 @@ ftcrfont_draw (struct glyph_string *s, | |||
| 624 | return len; | 632 | return len; |
| 625 | } | 633 | } |
| 626 | 634 | ||
| 635 | #ifdef HAVE_PGTK | ||
| 636 | /* Determine if FONT_OBJECT is a valid cached font for ENTITY by | ||
| 637 | comparing the options used to open it with the user's current | ||
| 638 | preferences specified via GSettings. */ | ||
| 639 | static bool | ||
| 640 | ftcrfont_cached_font_ok (struct frame *f, Lisp_Object font_object, | ||
| 641 | Lisp_Object entity) | ||
| 642 | { | ||
| 643 | struct font_info *info = (struct font_info *) XFONT_OBJECT (font_object); | ||
| 644 | |||
| 645 | cairo_font_options_t *options = cairo_font_options_create (); | ||
| 646 | cairo_scaled_font_get_font_options (info->cr_scaled_font, options); | ||
| 647 | cairo_font_options_t *gsettings_options = xsettings_get_font_options (); | ||
| 648 | |||
| 649 | bool equal = cairo_font_options_equal (options, gsettings_options); | ||
| 650 | cairo_font_options_destroy (options); | ||
| 651 | cairo_font_options_destroy (gsettings_options); | ||
| 652 | |||
| 653 | return equal; | ||
| 654 | } | ||
| 655 | #endif | ||
| 656 | |||
| 627 | #ifdef HAVE_HARFBUZZ | 657 | #ifdef HAVE_HARFBUZZ |
| 628 | 658 | ||
| 629 | static Lisp_Object | 659 | static Lisp_Object |
| @@ -694,6 +724,9 @@ struct font_driver const ftcrfont_driver = | |||
| 694 | #endif | 724 | #endif |
| 695 | .filter_properties = ftfont_filter_properties, | 725 | .filter_properties = ftfont_filter_properties, |
| 696 | .combining_capability = ftfont_combining_capability, | 726 | .combining_capability = ftfont_combining_capability, |
| 727 | #ifdef HAVE_PGTK | ||
| 728 | .cached_font_ok = ftcrfont_cached_font_ok | ||
| 729 | #endif | ||
| 697 | }; | 730 | }; |
| 698 | #ifdef HAVE_HARFBUZZ | 731 | #ifdef HAVE_HARFBUZZ |
| 699 | struct font_driver ftcrhbfont_driver; | 732 | struct font_driver ftcrhbfont_driver; |
diff --git a/src/ftfont.c b/src/ftfont.c index 5797300d231..301a145b7ac 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -645,8 +645,29 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec) | |||
| 645 | return spec; | 645 | return spec; |
| 646 | } | 646 | } |
| 647 | 647 | ||
| 648 | #if defined HAVE_XFT && defined FC_COLOR | ||
| 649 | static bool | ||
| 650 | xft_color_font_whitelisted_p (const char *family) | ||
| 651 | { | ||
| 652 | Lisp_Object tem, name; | ||
| 653 | |||
| 654 | tem = Vxft_color_font_whitelist; | ||
| 655 | |||
| 656 | FOR_EACH_TAIL_SAFE (tem) | ||
| 657 | { | ||
| 658 | name = XCAR (tem); | ||
| 659 | |||
| 660 | if (STRINGP (name) && !strcmp (family, SSDATA (name))) | ||
| 661 | return true; | ||
| 662 | } | ||
| 663 | |||
| 664 | return false; | ||
| 665 | } | ||
| 666 | #endif | ||
| 667 | |||
| 648 | static FcPattern * | 668 | static FcPattern * |
| 649 | ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, const char **langname) | 669 | ftfont_spec_pattern (Lisp_Object spec, char *otlayout, |
| 670 | struct OpenTypeSpec **otspec, const char **langname) | ||
| 650 | { | 671 | { |
| 651 | Lisp_Object tmp, extra; | 672 | Lisp_Object tmp, extra; |
| 652 | FcPattern *pattern = NULL; | 673 | FcPattern *pattern = NULL; |
| @@ -785,6 +806,8 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots | |||
| 785 | /* We really don't like color fonts, they cause Xft crashes. See | 806 | /* We really don't like color fonts, they cause Xft crashes. See |
| 786 | Bug#30874. */ | 807 | Bug#30874. */ |
| 787 | if (xft_ignore_color_fonts | 808 | if (xft_ignore_color_fonts |
| 809 | && (NILP (AREF (spec, FONT_FAMILY_INDEX)) | ||
| 810 | || NILP (Vxft_color_font_whitelist)) | ||
| 788 | && ! FcPatternAddBool (pattern, FC_COLOR, FcFalse)) | 811 | && ! FcPatternAddBool (pattern, FC_COLOR, FcFalse)) |
| 789 | goto err; | 812 | goto err; |
| 790 | #endif | 813 | #endif |
| @@ -930,7 +953,12 @@ ftfont_list (struct frame *f, Lisp_Object spec) | |||
| 930 | returns them even when it shouldn't really do so, so we | 953 | returns them even when it shouldn't really do so, so we |
| 931 | need to manually skip them here (Bug#37786). */ | 954 | need to manually skip them here (Bug#37786). */ |
| 932 | FcBool b; | 955 | FcBool b; |
| 956 | FcChar8 *str; | ||
| 957 | |||
| 933 | if (xft_ignore_color_fonts | 958 | if (xft_ignore_color_fonts |
| 959 | && (FcPatternGetString (fontset->fonts[i], FC_FAMILY, | ||
| 960 | 0, &str) != FcResultMatch | ||
| 961 | || !xft_color_font_whitelisted_p ((char *) str)) | ||
| 934 | && FcPatternGetBool (fontset->fonts[i], FC_COLOR, 0, &b) | 962 | && FcPatternGetBool (fontset->fonts[i], FC_COLOR, 0, &b) |
| 935 | == FcResultMatch && b != FcFalse) | 963 | == FcResultMatch && b != FcFalse) |
| 936 | continue; | 964 | continue; |
diff --git a/src/gtkutil.c b/src/gtkutil.c index a2ab01d02c5..f2018bc01f5 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -736,67 +736,74 @@ xg_check_special_colors (struct frame *f, | |||
| 736 | const char *color_name, | 736 | const char *color_name, |
| 737 | Emacs_Color *color) | 737 | Emacs_Color *color) |
| 738 | { | 738 | { |
| 739 | bool success_p = 0; | 739 | bool success_p; |
| 740 | bool get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0; | 740 | bool get_bg; |
| 741 | bool get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0; | 741 | bool get_fg; |
| 742 | #ifdef HAVE_GTK3 | ||
| 743 | GtkStyleContext *gsty; | ||
| 744 | GdkRGBA col; | ||
| 745 | char buf[sizeof "rgb://rrrr/gggg/bbbb"]; | ||
| 746 | int state; | ||
| 747 | GdkRGBA *c; | ||
| 748 | unsigned short r, g, b; | ||
| 749 | #else | ||
| 750 | GtkStyle *gsty; | ||
| 751 | GdkColor *grgb; | ||
| 752 | #endif | ||
| 753 | |||
| 754 | get_bg = !strcmp ("gtk_selection_bg_color", color_name); | ||
| 755 | get_fg = !get_bg && !strcmp ("gtk_selection_fg_color", color_name); | ||
| 756 | success_p = false; | ||
| 742 | 757 | ||
| 743 | if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg)) | 758 | #ifdef HAVE_PGTK |
| 759 | while (FRAME_PARENT_FRAME (f)) | ||
| 760 | f = FRAME_PARENT_FRAME (f); | ||
| 761 | #endif | ||
| 762 | |||
| 763 | if (!FRAME_GTK_WIDGET (f) || !(get_bg || get_fg)) | ||
| 744 | return success_p; | 764 | return success_p; |
| 745 | 765 | ||
| 746 | block_input (); | 766 | block_input (); |
| 747 | { | ||
| 748 | #ifdef HAVE_GTK3 | 767 | #ifdef HAVE_GTK3 |
| 749 | #ifndef HAVE_PGTK | 768 | gsty = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); |
| 750 | GtkStyleContext *gsty | 769 | state = GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED; |
| 751 | = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); | ||
| 752 | #else | ||
| 753 | GtkStyleContext *gsty | ||
| 754 | = gtk_widget_get_style_context (FRAME_WIDGET (f)); | ||
| 755 | #endif | ||
| 756 | GdkRGBA col; | ||
| 757 | char buf[sizeof "rgb://rrrr/gggg/bbbb"]; | ||
| 758 | int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED; | ||
| 759 | if (get_fg) | ||
| 760 | gtk_style_context_get_color (gsty, state, &col); | ||
| 761 | else | ||
| 762 | { | ||
| 763 | GdkRGBA *c; | ||
| 764 | /* FIXME: Retrieving the background color is deprecated in | ||
| 765 | GTK+ 3.16. New versions of GTK+ don't use the concept of a | ||
| 766 | single background color any more, so we shouldn't query for | ||
| 767 | it. */ | ||
| 768 | gtk_style_context_get (gsty, state, | ||
| 769 | GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c, | ||
| 770 | NULL); | ||
| 771 | col = *c; | ||
| 772 | gdk_rgba_free (c); | ||
| 773 | } | ||
| 774 | 770 | ||
| 775 | unsigned short | 771 | if (get_fg) |
| 776 | r = col.red * 65535, | 772 | gtk_style_context_get_color (gsty, state, &col); |
| 777 | g = col.green * 65535, | 773 | else |
| 778 | b = col.blue * 65535; | 774 | { |
| 775 | /* FIXME: Retrieving the background color is deprecated in | ||
| 776 | GTK+ 3.16. New versions of GTK+ don't use the concept of a | ||
| 777 | single background color any more, so we shouldn't query for | ||
| 778 | it. */ | ||
| 779 | gtk_style_context_get (gsty, state, | ||
| 780 | GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c, | ||
| 781 | NULL); | ||
| 782 | col = *c; | ||
| 783 | gdk_rgba_free (c); | ||
| 784 | } | ||
| 785 | |||
| 786 | r = col.red * 65535; | ||
| 787 | g = col.green * 65535; | ||
| 788 | b = col.blue * 65535; | ||
| 779 | #ifndef HAVE_PGTK | 789 | #ifndef HAVE_PGTK |
| 780 | sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b); | 790 | sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b); |
| 781 | success_p = x_parse_color (f, buf, color) != 0; | 791 | success_p = x_parse_color (f, buf, color) != 0; |
| 782 | #else | 792 | #else |
| 783 | sprintf (buf, "#%04x%04x%04x", r, g, b); | 793 | sprintf (buf, "#%04x%04x%04x", r, g, b); |
| 784 | success_p = pgtk_parse_color (f, buf, color) != 0; | 794 | success_p = pgtk_parse_color (f, buf, color) != 0; |
| 785 | #endif | 795 | #endif |
| 786 | #else | 796 | #else |
| 787 | GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); | 797 | gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); |
| 788 | GdkColor *grgb = get_bg | 798 | grgb = (get_bg ? &gsty->bg[GTK_STATE_SELECTED] |
| 789 | ? &gsty->bg[GTK_STATE_SELECTED] | 799 | : &gsty->fg[GTK_STATE_SELECTED]); |
| 790 | : &gsty->fg[GTK_STATE_SELECTED]; | ||
| 791 | 800 | ||
| 792 | color->red = grgb->red; | 801 | color->red = grgb->red; |
| 793 | color->green = grgb->green; | 802 | color->green = grgb->green; |
| 794 | color->blue = grgb->blue; | 803 | color->blue = grgb->blue; |
| 795 | color->pixel = grgb->pixel; | 804 | color->pixel = grgb->pixel; |
| 796 | success_p = 1; | 805 | success_p = 1; |
| 797 | #endif | 806 | #endif |
| 798 | |||
| 799 | } | ||
| 800 | unblock_input (); | 807 | unblock_input (); |
| 801 | return success_p; | 808 | return success_p; |
| 802 | } | 809 | } |
| @@ -6395,6 +6402,9 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, | |||
| 6395 | if (!f) | 6402 | if (!f) |
| 6396 | return true; | 6403 | return true; |
| 6397 | 6404 | ||
| 6405 | if (popup_activated ()) | ||
| 6406 | return true; | ||
| 6407 | |||
| 6398 | #ifdef HAVE_XINPUT2 | 6408 | #ifdef HAVE_XINPUT2 |
| 6399 | pending_keystroke_time | 6409 | pending_keystroke_time |
| 6400 | = FRAME_DISPLAY_INFO (f)->pending_keystroke_time; | 6410 | = FRAME_DISPLAY_INFO (f)->pending_keystroke_time; |
diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index a8d46d000a3..f0cc084bb37 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc | |||
| @@ -285,11 +285,32 @@ BView_DrawBitmap (void *view, void *bitmap, int x, int y, | |||
| 285 | BView *vw = get_view (view); | 285 | BView *vw = get_view (view); |
| 286 | BBitmap *bm = (BBitmap *) bitmap; | 286 | BBitmap *bm = (BBitmap *) bitmap; |
| 287 | 287 | ||
| 288 | vw->PushState (); | ||
| 289 | vw->SetDrawingMode (B_OP_OVER); | 288 | vw->SetDrawingMode (B_OP_OVER); |
| 290 | vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), | 289 | vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), |
| 291 | BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); | 290 | BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); |
| 292 | vw->PopState (); | 291 | vw->SetDrawingMode (B_OP_COPY); |
| 292 | } | ||
| 293 | |||
| 294 | void | ||
| 295 | BView_DrawBitmapTiled (void *view, void *bitmap, int x, int y, | ||
| 296 | int width, int height, int vx, int vy, | ||
| 297 | int vwidth, int vheight) | ||
| 298 | { | ||
| 299 | BView *vw = get_view (view); | ||
| 300 | BBitmap *bm = (BBitmap *) bitmap; | ||
| 301 | BRect bounds = bm->Bounds (); | ||
| 302 | |||
| 303 | if (width == -1) | ||
| 304 | width = BE_RECT_WIDTH (bounds); | ||
| 305 | |||
| 306 | if (height == -1) | ||
| 307 | height = BE_RECT_HEIGHT (bounds); | ||
| 308 | |||
| 309 | vw->SetDrawingMode (B_OP_OVER); | ||
| 310 | vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), | ||
| 311 | BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1), | ||
| 312 | B_TILE_BITMAP); | ||
| 313 | vw->SetDrawingMode (B_OP_COPY); | ||
| 293 | } | 314 | } |
| 294 | 315 | ||
| 295 | void | 316 | void |
| @@ -300,17 +321,22 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, | |||
| 300 | BBitmap *bm = (BBitmap *) bitmap; | 321 | BBitmap *bm = (BBitmap *) bitmap; |
| 301 | BBitmap bc (bm->Bounds (), B_RGBA32); | 322 | BBitmap bc (bm->Bounds (), B_RGBA32); |
| 302 | BRect rect (x, y, x + width - 1, y + height - 1); | 323 | BRect rect (x, y, x + width - 1, y + height - 1); |
| 324 | uint32_t *bits; | ||
| 325 | size_t stride; | ||
| 326 | rgb_color low_color; | ||
| 327 | BRect bounds; | ||
| 303 | 328 | ||
| 304 | if (bc.InitCheck () != B_OK || bc.ImportBits (bm) != B_OK) | 329 | if (bc.InitCheck () != B_OK || bc.ImportBits (bm) != B_OK) |
| 305 | return; | 330 | return; |
| 306 | 331 | ||
| 307 | uint32_t *bits = (uint32_t *) bc.Bits (); | 332 | bits = (uint32_t *) bc.Bits (); |
| 308 | size_t stride = bc.BytesPerRow (); | 333 | stride = bc.BytesPerRow (); |
| 309 | 334 | ||
| 310 | if (bm->ColorSpace () == B_GRAY1) | 335 | if (bm->ColorSpace () == B_GRAY1) |
| 311 | { | 336 | { |
| 312 | rgb_color low_color = vw->LowColor (); | 337 | low_color = vw->LowColor (); |
| 313 | BRect bounds = bc.Bounds (); | 338 | bounds = bc.Bounds (); |
| 339 | |||
| 314 | for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) | 340 | for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) |
| 315 | { | 341 | { |
| 316 | for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) | 342 | for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) |
| @@ -323,10 +349,11 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, | |||
| 323 | } | 349 | } |
| 324 | } | 350 | } |
| 325 | 351 | ||
| 326 | vw->PushState (); | 352 | vw->SetDrawingMode ((bm->ColorSpace () |
| 327 | vw->SetDrawingMode (bm->ColorSpace () == B_GRAY1 ? B_OP_OVER : B_OP_ERASE); | 353 | == B_GRAY1) |
| 354 | ? B_OP_OVER : B_OP_ERASE); | ||
| 328 | vw->DrawBitmap (&bc, rect); | 355 | vw->DrawBitmap (&bc, rect); |
| 329 | vw->PopState (); | 356 | vw->SetDrawingMode (B_OP_COPY); |
| 330 | } | 357 | } |
| 331 | 358 | ||
| 332 | void | 359 | void |
| @@ -357,6 +384,7 @@ BView_DrawMask (void *src, void *view, | |||
| 357 | vw->SetDrawingMode (B_OP_OVER); | 384 | vw->SetDrawingMode (B_OP_OVER); |
| 358 | vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1), | 385 | vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1), |
| 359 | BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); | 386 | BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); |
| 387 | vw->SetDrawingMode (B_OP_COPY); | ||
| 360 | } | 388 | } |
| 361 | 389 | ||
| 362 | static BBitmap * | 390 | static BBitmap * |
| @@ -475,3 +503,40 @@ BView_InvertRect (void *view, int x, int y, int width, int height) | |||
| 475 | 503 | ||
| 476 | vw->InvertRect (BRect (x, y, x + width - 1, y + height - 1)); | 504 | vw->InvertRect (BRect (x, y, x + width - 1, y + height - 1)); |
| 477 | } | 505 | } |
| 506 | |||
| 507 | static void | ||
| 508 | be_draw_cross_on_pixmap_1 (BBitmap *bitmap, int x, int y, int width, | ||
| 509 | int height, uint32_t color) | ||
| 510 | { | ||
| 511 | BBitmap dest (bitmap->Bounds (), | ||
| 512 | bitmap->ColorSpace (), | ||
| 513 | true, false); | ||
| 514 | BView view (bitmap->Bounds (), NULL, B_FOLLOW_NONE, 0); | ||
| 515 | rgb_color high_color; | ||
| 516 | |||
| 517 | rgb32_to_rgb_color (color, &high_color); | ||
| 518 | dest.ImportBits (bitmap); | ||
| 519 | |||
| 520 | if (!dest.Lock ()) | ||
| 521 | return; | ||
| 522 | |||
| 523 | dest.AddChild (&view); | ||
| 524 | |||
| 525 | view.SetHighColor (high_color); | ||
| 526 | view.StrokeLine (BPoint (x, y), | ||
| 527 | BPoint (x + width - 1, y + height - 1)); | ||
| 528 | view.StrokeLine (BPoint (x, y + height - 1), | ||
| 529 | BPoint (x + width - 1, y)); | ||
| 530 | view.RemoveSelf (); | ||
| 531 | bitmap->ImportBits (&dest); | ||
| 532 | } | ||
| 533 | |||
| 534 | void | ||
| 535 | be_draw_cross_on_pixmap (void *bitmap, int x, int y, int width, | ||
| 536 | int height, uint32_t color) | ||
| 537 | { | ||
| 538 | BBitmap *target = (BBitmap *) bitmap; | ||
| 539 | |||
| 540 | be_draw_cross_on_pixmap_1 (target, x, y, width, height, | ||
| 541 | color); | ||
| 542 | } | ||
diff --git a/src/haiku_io.c b/src/haiku_io.c index 5d0031ef712..d3455276855 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c | |||
| @@ -105,6 +105,8 @@ haiku_len (enum haiku_event_type type) | |||
| 105 | return sizeof (struct haiku_menu_bar_left_event); | 105 | return sizeof (struct haiku_menu_bar_left_event); |
| 106 | case SCROLL_BAR_PART_EVENT: | 106 | case SCROLL_BAR_PART_EVENT: |
| 107 | return sizeof (struct haiku_scroll_bar_part_event); | 107 | return sizeof (struct haiku_scroll_bar_part_event); |
| 108 | case SCREEN_CHANGED_EVENT: | ||
| 109 | return sizeof (struct haiku_screen_changed_event); | ||
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | emacs_abort (); | 112 | emacs_abort (); |
diff --git a/src/haiku_select.cc b/src/haiku_select.cc index a26a0049cbf..764001f62b0 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc | |||
| @@ -28,29 +28,64 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | 28 | ||
| 29 | #include "haikuselect.h" | 29 | #include "haikuselect.h" |
| 30 | 30 | ||
| 31 | /* The clipboard object representing the primary selection. */ | ||
| 31 | static BClipboard *primary = NULL; | 32 | static BClipboard *primary = NULL; |
| 33 | |||
| 34 | /* The clipboard object representing the secondary selection. */ | ||
| 32 | static BClipboard *secondary = NULL; | 35 | static BClipboard *secondary = NULL; |
| 36 | |||
| 37 | /* The clipboard object used by other programs, representing the | ||
| 38 | clipboard. */ | ||
| 33 | static BClipboard *system_clipboard = NULL; | 39 | static BClipboard *system_clipboard = NULL; |
| 40 | |||
| 41 | /* The number of times the system clipboard has changed. */ | ||
| 34 | static int64 count_clipboard = -1; | 42 | static int64 count_clipboard = -1; |
| 43 | |||
| 44 | /* The number of times the primary selection has changed. */ | ||
| 35 | static int64 count_primary = -1; | 45 | static int64 count_primary = -1; |
| 46 | |||
| 47 | /* The number of times the secondary selection has changed. */ | ||
| 36 | static int64 count_secondary = -1; | 48 | static int64 count_secondary = -1; |
| 37 | 49 | ||
| 50 | static BClipboard * | ||
| 51 | get_clipboard_object (enum haiku_clipboard clipboard) | ||
| 52 | { | ||
| 53 | switch (clipboard) | ||
| 54 | { | ||
| 55 | case CLIPBOARD_PRIMARY: | ||
| 56 | return primary; | ||
| 57 | |||
| 58 | case CLIPBOARD_SECONDARY: | ||
| 59 | return secondary; | ||
| 60 | |||
| 61 | case CLIPBOARD_CLIPBOARD: | ||
| 62 | return system_clipboard; | ||
| 63 | } | ||
| 64 | |||
| 65 | abort (); | ||
| 66 | } | ||
| 67 | |||
| 38 | static char * | 68 | static char * |
| 39 | BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len) | 69 | be_find_clipboard_data_1 (BClipboard *cb, const char *type, ssize_t *len) |
| 40 | { | 70 | { |
| 71 | BMessage *data; | ||
| 72 | const char *ptr; | ||
| 73 | ssize_t nbytes; | ||
| 74 | void *value; | ||
| 75 | |||
| 41 | if (!cb->Lock ()) | 76 | if (!cb->Lock ()) |
| 42 | return 0; | 77 | return NULL; |
| 78 | |||
| 79 | data = cb->Data (); | ||
| 43 | 80 | ||
| 44 | BMessage *dat = cb->Data (); | 81 | if (!data) |
| 45 | if (!dat) | ||
| 46 | { | 82 | { |
| 47 | cb->Unlock (); | 83 | cb->Unlock (); |
| 48 | return 0; | 84 | return NULL; |
| 49 | } | 85 | } |
| 50 | 86 | ||
| 51 | const char *ptr; | 87 | data->FindData (type, B_MIME_TYPE, (const void **) &ptr, |
| 52 | ssize_t bt; | 88 | &nbytes); |
| 53 | dat->FindData (type, B_MIME_TYPE, (const void **) &ptr, &bt); | ||
| 54 | 89 | ||
| 55 | if (!ptr) | 90 | if (!ptr) |
| 56 | { | 91 | { |
| @@ -59,9 +94,9 @@ BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len) | |||
| 59 | } | 94 | } |
| 60 | 95 | ||
| 61 | if (len) | 96 | if (len) |
| 62 | *len = bt; | 97 | *len = nbytes; |
| 63 | 98 | ||
| 64 | void *data = malloc (bt); | 99 | value = malloc (nbytes); |
| 65 | 100 | ||
| 66 | if (!data) | 101 | if (!data) |
| 67 | { | 102 | { |
| @@ -69,13 +104,14 @@ BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len) | |||
| 69 | return NULL; | 104 | return NULL; |
| 70 | } | 105 | } |
| 71 | 106 | ||
| 72 | memcpy (data, ptr, bt); | 107 | memcpy (value, ptr, nbytes); |
| 73 | cb->Unlock (); | 108 | cb->Unlock (); |
| 74 | return (char *) data; | 109 | |
| 110 | return (char *) value; | ||
| 75 | } | 111 | } |
| 76 | 112 | ||
| 77 | static void | 113 | static void |
| 78 | BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size) | 114 | be_get_clipboard_targets_1 (BClipboard *cb, char **buf, int buf_size) |
| 79 | { | 115 | { |
| 80 | BMessage *data; | 116 | BMessage *data; |
| 81 | char *name; | 117 | char *name; |
| @@ -122,142 +158,125 @@ BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size) | |||
| 122 | } | 158 | } |
| 123 | 159 | ||
| 124 | static void | 160 | static void |
| 125 | BClipboard_set_data (BClipboard *cb, const char *type, const char *dat, | 161 | be_set_clipboard_data_1 (BClipboard *cb, const char *type, const char *data, |
| 126 | ssize_t len, bool clear) | 162 | ssize_t len, bool clear) |
| 127 | { | 163 | { |
| 164 | BMessage *message_data; | ||
| 165 | |||
| 128 | if (!cb->Lock ()) | 166 | if (!cb->Lock ()) |
| 129 | return; | 167 | return; |
| 130 | 168 | ||
| 131 | if (clear) | 169 | if (clear) |
| 132 | cb->Clear (); | 170 | cb->Clear (); |
| 133 | 171 | ||
| 134 | BMessage *mdat = cb->Data (); | 172 | message_data = cb->Data (); |
| 135 | if (!mdat) | 173 | |
| 174 | if (!message_data) | ||
| 136 | { | 175 | { |
| 137 | cb->Unlock (); | 176 | cb->Unlock (); |
| 138 | return; | 177 | return; |
| 139 | } | 178 | } |
| 140 | 179 | ||
| 141 | if (dat) | 180 | if (data) |
| 142 | { | 181 | { |
| 143 | if (mdat->ReplaceData (type, B_MIME_TYPE, dat, len) | 182 | if (message_data->ReplaceData (type, B_MIME_TYPE, data, len) |
| 144 | == B_NAME_NOT_FOUND) | 183 | == B_NAME_NOT_FOUND) |
| 145 | mdat->AddData (type, B_MIME_TYPE, dat, len); | 184 | message_data->AddData (type, B_MIME_TYPE, data, len); |
| 146 | } | 185 | } |
| 147 | else | 186 | else |
| 148 | mdat->RemoveName (type); | 187 | message_data->RemoveName (type); |
| 188 | |||
| 149 | cb->Commit (); | 189 | cb->Commit (); |
| 150 | cb->Unlock (); | 190 | cb->Unlock (); |
| 151 | } | 191 | } |
| 152 | 192 | ||
| 153 | char * | ||
| 154 | BClipboard_find_system_data (const char *type, ssize_t *len) | ||
| 155 | { | ||
| 156 | if (!system_clipboard) | ||
| 157 | return 0; | ||
| 158 | |||
| 159 | return BClipboard_find_data (system_clipboard, type, len); | ||
| 160 | } | ||
| 161 | |||
| 162 | char * | ||
| 163 | BClipboard_find_primary_selection_data (const char *type, ssize_t *len) | ||
| 164 | { | ||
| 165 | if (!primary) | ||
| 166 | return 0; | ||
| 167 | |||
| 168 | return BClipboard_find_data (primary, type, len); | ||
| 169 | } | ||
| 170 | |||
| 171 | char * | ||
| 172 | BClipboard_find_secondary_selection_data (const char *type, ssize_t *len) | ||
| 173 | { | ||
| 174 | if (!secondary) | ||
| 175 | return 0; | ||
| 176 | |||
| 177 | return BClipboard_find_data (secondary, type, len); | ||
| 178 | } | ||
| 179 | |||
| 180 | void | ||
| 181 | BClipboard_set_system_data (const char *type, const char *data, | ||
| 182 | ssize_t len, bool clear) | ||
| 183 | { | ||
| 184 | if (!system_clipboard) | ||
| 185 | return; | ||
| 186 | |||
| 187 | count_clipboard = system_clipboard->SystemCount (); | ||
| 188 | BClipboard_set_data (system_clipboard, type, data, len, clear); | ||
| 189 | } | ||
| 190 | |||
| 191 | void | 193 | void |
| 192 | BClipboard_set_primary_selection_data (const char *type, const char *data, | 194 | be_update_clipboard_count (enum haiku_clipboard id) |
| 193 | ssize_t len, bool clear) | ||
| 194 | { | 195 | { |
| 195 | if (!primary) | 196 | switch (id) |
| 196 | return; | 197 | { |
| 198 | case CLIPBOARD_CLIPBOARD: | ||
| 199 | count_clipboard = system_clipboard->SystemCount (); | ||
| 200 | break; | ||
| 197 | 201 | ||
| 198 | count_primary = primary->SystemCount (); | 202 | case CLIPBOARD_PRIMARY: |
| 199 | BClipboard_set_data (primary, type, data, len, clear); | 203 | count_primary = primary->SystemCount (); |
| 200 | } | 204 | break; |
| 201 | 205 | ||
| 202 | void | 206 | case CLIPBOARD_SECONDARY: |
| 203 | BClipboard_set_secondary_selection_data (const char *type, const char *data, | 207 | count_secondary = secondary->SystemCount (); |
| 204 | ssize_t len, bool clear) | 208 | break; |
| 205 | { | 209 | } |
| 206 | if (!secondary) | ||
| 207 | return; | ||
| 208 | |||
| 209 | count_secondary = secondary->SystemCount (); | ||
| 210 | BClipboard_set_data (secondary, type, data, len, clear); | ||
| 211 | } | 210 | } |
| 212 | 211 | ||
| 213 | void | 212 | char * |
| 214 | BClipboard_free_data (void *ptr) | 213 | be_find_clipboard_data (enum haiku_clipboard id, const char *type, |
| 214 | ssize_t *len) | ||
| 215 | { | 215 | { |
| 216 | std::free (ptr); | 216 | return be_find_clipboard_data_1 (get_clipboard_object (id), |
| 217 | type, len); | ||
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | void | 220 | void |
| 220 | BClipboard_system_targets (char **buf, int len) | 221 | be_set_clipboard_data (enum haiku_clipboard id, const char *type, |
| 222 | const char *data, ssize_t len, bool clear) | ||
| 221 | { | 223 | { |
| 222 | BClipboard_get_targets (system_clipboard, buf, len); | 224 | be_update_clipboard_count (id); |
| 223 | } | ||
| 224 | 225 | ||
| 225 | void | 226 | be_set_clipboard_data_1 (get_clipboard_object (id), type, |
| 226 | BClipboard_primary_targets (char **buf, int len) | 227 | data, len, clear); |
| 227 | { | ||
| 228 | BClipboard_get_targets (primary, buf, len); | ||
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | void | 230 | void |
| 232 | BClipboard_secondary_targets (char **buf, int len) | 231 | be_get_clipboard_targets (enum haiku_clipboard id, char **targets, |
| 232 | int len) | ||
| 233 | { | 233 | { |
| 234 | BClipboard_get_targets (secondary, buf, len); | 234 | be_get_clipboard_targets_1 (get_clipboard_object (id), targets, |
| 235 | len); | ||
| 235 | } | 236 | } |
| 236 | 237 | ||
| 237 | bool | 238 | static bool |
| 238 | BClipboard_owns_clipboard (void) | 239 | clipboard_owner_p (void) |
| 239 | { | 240 | { |
| 240 | return (count_clipboard >= 0 | 241 | return (count_clipboard >= 0 |
| 241 | && (count_clipboard + 1 | 242 | && (count_clipboard + 1 |
| 242 | == system_clipboard->SystemCount ())); | 243 | == system_clipboard->SystemCount ())); |
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | bool | 246 | static bool |
| 246 | BClipboard_owns_primary (void) | 247 | primary_owner_p (void) |
| 247 | { | 248 | { |
| 248 | return (count_primary >= 0 | 249 | return (count_primary >= 0 |
| 249 | && (count_primary + 1 | 250 | && (count_primary + 1 |
| 250 | == primary->SystemCount ())); | 251 | == primary->SystemCount ())); |
| 251 | } | 252 | } |
| 252 | 253 | ||
| 253 | bool | 254 | static bool |
| 254 | BClipboard_owns_secondary (void) | 255 | secondary_owner_p (void) |
| 255 | { | 256 | { |
| 256 | return (count_secondary >= 0 | 257 | return (count_secondary >= 0 |
| 257 | && (count_secondary + 1 | 258 | && (count_secondary + 1 |
| 258 | == secondary->SystemCount ())); | 259 | == secondary->SystemCount ())); |
| 259 | } | 260 | } |
| 260 | 261 | ||
| 262 | bool | ||
| 263 | be_clipboard_owner_p (enum haiku_clipboard clipboard) | ||
| 264 | { | ||
| 265 | switch (clipboard) | ||
| 266 | { | ||
| 267 | case CLIPBOARD_PRIMARY: | ||
| 268 | return primary_owner_p (); | ||
| 269 | |||
| 270 | case CLIPBOARD_SECONDARY: | ||
| 271 | return secondary_owner_p (); | ||
| 272 | |||
| 273 | case CLIPBOARD_CLIPBOARD: | ||
| 274 | return clipboard_owner_p (); | ||
| 275 | } | ||
| 276 | |||
| 277 | abort (); | ||
| 278 | } | ||
| 279 | |||
| 261 | void | 280 | void |
| 262 | init_haiku_select (void) | 281 | init_haiku_select (void) |
| 263 | { | 282 | { |
| @@ -443,12 +462,7 @@ be_lock_clipboard_message (enum haiku_clipboard clipboard, | |||
| 443 | { | 462 | { |
| 444 | BClipboard *board; | 463 | BClipboard *board; |
| 445 | 464 | ||
| 446 | if (clipboard == CLIPBOARD_PRIMARY) | 465 | board = get_clipboard_object (clipboard); |
| 447 | board = primary; | ||
| 448 | else if (clipboard == CLIPBOARD_SECONDARY) | ||
| 449 | board = secondary; | ||
| 450 | else | ||
| 451 | board = system_clipboard; | ||
| 452 | 466 | ||
| 453 | if (!board->Lock ()) | 467 | if (!board->Lock ()) |
| 454 | return 1; | 468 | return 1; |
| @@ -465,12 +479,7 @@ be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard) | |||
| 465 | { | 479 | { |
| 466 | BClipboard *board; | 480 | BClipboard *board; |
| 467 | 481 | ||
| 468 | if (clipboard == CLIPBOARD_PRIMARY) | 482 | board = get_clipboard_object (clipboard); |
| 469 | board = primary; | ||
| 470 | else if (clipboard == CLIPBOARD_SECONDARY) | ||
| 471 | board = secondary; | ||
| 472 | else | ||
| 473 | board = system_clipboard; | ||
| 474 | 483 | ||
| 475 | if (discard) | 484 | if (discard) |
| 476 | board->Revert (); | 485 | board->Revert (); |
diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 5dfb25d6dd7..182f2128473 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc | |||
| @@ -17,10 +17,12 @@ You should have received a copy of the GNU General Public License | |||
| 17 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | 17 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ |
| 18 | 18 | ||
| 19 | #include <config.h> | 19 | #include <config.h> |
| 20 | #include <attribute.h> | ||
| 20 | 21 | ||
| 21 | #include <app/Application.h> | 22 | #include <app/Application.h> |
| 22 | #include <app/Cursor.h> | 23 | #include <app/Cursor.h> |
| 23 | #include <app/Messenger.h> | 24 | #include <app/Messenger.h> |
| 25 | #include <app/Roster.h> | ||
| 24 | 26 | ||
| 25 | #include <interface/GraphicsDefs.h> | 27 | #include <interface/GraphicsDefs.h> |
| 26 | #include <interface/InterfaceDefs.h> | 28 | #include <interface/InterfaceDefs.h> |
| @@ -81,8 +83,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 81 | #include <csignal> | 83 | #include <csignal> |
| 82 | #include <cfloat> | 84 | #include <cfloat> |
| 83 | 85 | ||
| 84 | #include <pthread.h> | ||
| 85 | |||
| 86 | #ifdef USE_BE_CAIRO | 86 | #ifdef USE_BE_CAIRO |
| 87 | #include <cairo.h> | 87 | #include <cairo.h> |
| 88 | #endif | 88 | #endif |
| @@ -107,6 +107,7 @@ enum | |||
| 107 | SET_FONT_INDICES = 3012, | 107 | SET_FONT_INDICES = 3012, |
| 108 | SET_PREVIEW_DIALOG = 3013, | 108 | SET_PREVIEW_DIALOG = 3013, |
| 109 | UPDATE_PREVIEW_DIALOG = 3014, | 109 | UPDATE_PREVIEW_DIALOG = 3014, |
| 110 | SEND_MOVE_FRAME_EVENT = 3015, | ||
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| 112 | /* X11 keysyms that we use. */ | 113 | /* X11 keysyms that we use. */ |
| @@ -142,7 +143,7 @@ struct font_selection_dialog_message | |||
| 142 | /* Whether or not font selection was cancelled. */ | 143 | /* Whether or not font selection was cancelled. */ |
| 143 | bool_bf cancel : 1; | 144 | bool_bf cancel : 1; |
| 144 | 145 | ||
| 145 | /* Whether or not a size was explictly specified. */ | 146 | /* Whether or not a size was explicitly specified. */ |
| 146 | bool_bf size_specified : 1; | 147 | bool_bf size_specified : 1; |
| 147 | 148 | ||
| 148 | /* The index of the selected font family. */ | 149 | /* The index of the selected font family. */ |
| @@ -155,44 +156,45 @@ struct font_selection_dialog_message | |||
| 155 | int size; | 156 | int size; |
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| 159 | /* The color space of the main screen. B_NO_COLOR_SPACE means it has | ||
| 160 | not yet been computed. */ | ||
| 158 | static color_space dpy_color_space = B_NO_COLOR_SPACE; | 161 | static color_space dpy_color_space = B_NO_COLOR_SPACE; |
| 159 | static key_map *key_map = NULL; | 162 | |
| 160 | static char *key_chars = NULL; | 163 | /* The keymap, or NULL if it has not been initialized. */ |
| 164 | static key_map *key_map; | ||
| 165 | |||
| 166 | /* Indices of characters into the keymap. */ | ||
| 167 | static char *key_chars; | ||
| 168 | |||
| 169 | /* Lock around keymap data, since it's touched from different | ||
| 170 | threads. */ | ||
| 161 | static BLocker key_map_lock; | 171 | static BLocker key_map_lock; |
| 162 | 172 | ||
| 163 | /* The locking semantics of BWindows running in multiple threads are | 173 | /* The locking semantics of BWindows running in multiple threads are |
| 164 | so complex that child frame state (which is the only state that is | 174 | so complex that child frame state (which is the only state that is |
| 165 | shared between different BWindows at runtime) does best with a | 175 | shared between different BWindows at runtime) does best with a |
| 166 | single global lock. */ | 176 | single global lock. */ |
| 167 | |||
| 168 | static BLocker child_frame_lock; | 177 | static BLocker child_frame_lock; |
| 169 | 178 | ||
| 170 | /* A LeaveNotify event (well, the closest equivalent on Haiku, which | 179 | /* Variable where the popup menu thread returns the chosen menu |
| 171 | is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might | 180 | item. */ |
| 172 | be sent out-of-order with regards to motion events from other | ||
| 173 | windows, such as when the mouse pointer rapidly moves from an | ||
| 174 | undecorated child frame to its parent. This can cause a failure to | ||
| 175 | clear the mouse face on the former if an event for the latter is | ||
| 176 | read by Emacs first and ends up showing the mouse face there. | ||
| 177 | |||
| 178 | While this lock doesn't really ensure that the events will be | ||
| 179 | delivered in the correct order, it makes them arrive in the correct | ||
| 180 | order "most of the time" on my machine, which is good enough and | ||
| 181 | preferable to adding a lot of extra complexity to the event | ||
| 182 | handling code to sort motion events by their timestamps. | ||
| 183 | |||
| 184 | Obviously this depends on the number of execution units that are | ||
| 185 | available, and the scheduling priority of each thread involved in | ||
| 186 | the input handling, but it will be good enough for most people. */ | ||
| 187 | |||
| 188 | static BLocker movement_locker; | ||
| 189 | |||
| 190 | static BMessage volatile *popup_track_message; | 181 | static BMessage volatile *popup_track_message; |
| 182 | |||
| 183 | /* Variable in which alert dialog threads return the selected button | ||
| 184 | number. */ | ||
| 191 | static int32 volatile alert_popup_value; | 185 | static int32 volatile alert_popup_value; |
| 186 | |||
| 187 | /* The current window ID. This is increased every time a frame is | ||
| 188 | created. */ | ||
| 192 | static int current_window_id; | 189 | static int current_window_id; |
| 193 | 190 | ||
| 194 | static void *grab_view = NULL; | 191 | /* The view that has the passive grab. */ |
| 192 | static void *grab_view; | ||
| 193 | |||
| 194 | /* The locker for that variable. */ | ||
| 195 | static BLocker grab_view_locker; | 195 | static BLocker grab_view_locker; |
| 196 | |||
| 197 | /* Whether or not a drag-and-drop operation is in progress. */ | ||
| 196 | static bool drag_and_drop_in_progress; | 198 | static bool drag_and_drop_in_progress; |
| 197 | 199 | ||
| 198 | /* Many places require us to lock the child frame data, and then lock | 200 | /* Many places require us to lock the child frame data, and then lock |
| @@ -448,13 +450,143 @@ map_normal (uint32_t kc, uint32_t *ch) | |||
| 448 | key_map_lock.Unlock (); | 450 | key_map_lock.Unlock (); |
| 449 | } | 451 | } |
| 450 | 452 | ||
| 453 | static BRect | ||
| 454 | get_zoom_rect (BWindow *window) | ||
| 455 | { | ||
| 456 | BScreen screen; | ||
| 457 | BDeskbar deskbar; | ||
| 458 | BRect screen_frame; | ||
| 459 | BRect frame; | ||
| 460 | BRect deskbar_frame; | ||
| 461 | BRect window_frame; | ||
| 462 | BRect decorator_frame; | ||
| 463 | |||
| 464 | if (!screen.IsValid ()) | ||
| 465 | gui_abort ("Failed to calculate screen rect"); | ||
| 466 | |||
| 467 | screen_frame = frame = screen.Frame (); | ||
| 468 | deskbar_frame = deskbar.Frame (); | ||
| 469 | |||
| 470 | if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ()) | ||
| 471 | { | ||
| 472 | switch (deskbar.Location ()) | ||
| 473 | { | ||
| 474 | case B_DESKBAR_TOP: | ||
| 475 | frame.top = deskbar_frame.bottom + 2; | ||
| 476 | break; | ||
| 477 | |||
| 478 | case B_DESKBAR_BOTTOM: | ||
| 479 | case B_DESKBAR_LEFT_BOTTOM: | ||
| 480 | case B_DESKBAR_RIGHT_BOTTOM: | ||
| 481 | frame.bottom = deskbar_frame.top - 2; | ||
| 482 | break; | ||
| 483 | |||
| 484 | case B_DESKBAR_LEFT_TOP: | ||
| 485 | if (!deskbar.IsExpanded ()) | ||
| 486 | frame.top = deskbar_frame.bottom + 2; | ||
| 487 | else if (!deskbar.IsAlwaysOnTop () | ||
| 488 | && !deskbar.IsAutoRaise ()) | ||
| 489 | frame.left = deskbar_frame.right + 2; | ||
| 490 | break; | ||
| 491 | |||
| 492 | default: | ||
| 493 | if (deskbar.IsExpanded () | ||
| 494 | && !deskbar.IsAlwaysOnTop () | ||
| 495 | && !deskbar.IsAutoRaise ()) | ||
| 496 | frame.right = deskbar_frame.left - 2; | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | if (window) | ||
| 501 | { | ||
| 502 | window_frame = window->Frame (); | ||
| 503 | decorator_frame = window->DecoratorFrame (); | ||
| 504 | |||
| 505 | frame.top += (window_frame.top | ||
| 506 | - decorator_frame.top); | ||
| 507 | frame.bottom -= (decorator_frame.bottom | ||
| 508 | - window_frame.bottom); | ||
| 509 | frame.left += (window_frame.left | ||
| 510 | - decorator_frame.left); | ||
| 511 | frame.right -= (decorator_frame.right | ||
| 512 | - window_frame.right); | ||
| 513 | |||
| 514 | if (frame.top > deskbar_frame.bottom | ||
| 515 | || frame.bottom < deskbar_frame.top) | ||
| 516 | { | ||
| 517 | frame.left = screen_frame.left + (window_frame.left | ||
| 518 | - decorator_frame.left); | ||
| 519 | frame.right = screen_frame.right - (decorator_frame.right | ||
| 520 | - window_frame.right); | ||
| 521 | } | ||
| 522 | } | ||
| 523 | |||
| 524 | return frame; | ||
| 525 | } | ||
| 526 | |||
| 527 | /* Invisible window used to get B_SCREEN_CHANGED events. */ | ||
| 528 | class EmacsScreenChangeMonitor : public BWindow | ||
| 529 | { | ||
| 530 | BRect previous_screen_frame; | ||
| 531 | |||
| 532 | public: | ||
| 533 | EmacsScreenChangeMonitor (void) : BWindow (BRect (-100, -100, 0, 0), "", | ||
| 534 | B_NO_BORDER_WINDOW_LOOK, | ||
| 535 | B_FLOATING_ALL_WINDOW_FEEL, | ||
| 536 | B_AVOID_FRONT | B_AVOID_FOCUS) | ||
| 537 | { | ||
| 538 | BScreen screen (this); | ||
| 539 | |||
| 540 | if (!screen.IsValid ()) | ||
| 541 | return; | ||
| 542 | |||
| 543 | previous_screen_frame = screen.Frame (); | ||
| 544 | |||
| 545 | /* Immediately show this window upon creation. It will not steal | ||
| 546 | the focus or become visible. */ | ||
| 547 | Show (); | ||
| 548 | |||
| 549 | if (!LockLooper ()) | ||
| 550 | return; | ||
| 551 | |||
| 552 | Hide (); | ||
| 553 | UnlockLooper (); | ||
| 554 | } | ||
| 555 | |||
| 556 | void | ||
| 557 | DispatchMessage (BMessage *msg, BHandler *handler) | ||
| 558 | { | ||
| 559 | struct haiku_screen_changed_event rq; | ||
| 560 | BRect frame; | ||
| 561 | |||
| 562 | if (msg->what == B_SCREEN_CHANGED) | ||
| 563 | { | ||
| 564 | if (msg->FindInt64 ("when", &rq.when) != B_OK) | ||
| 565 | rq.when = 0; | ||
| 566 | |||
| 567 | if (msg->FindRect ("frame", &frame) != B_OK | ||
| 568 | || frame != previous_screen_frame) | ||
| 569 | { | ||
| 570 | haiku_write (SCREEN_CHANGED_EVENT, &rq); | ||
| 571 | |||
| 572 | if (frame.IsValid ()) | ||
| 573 | previous_screen_frame = frame; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | BWindow::DispatchMessage (msg, handler); | ||
| 578 | } | ||
| 579 | }; | ||
| 580 | |||
| 451 | class Emacs : public BApplication | 581 | class Emacs : public BApplication |
| 452 | { | 582 | { |
| 453 | public: | 583 | public: |
| 454 | BMessage settings; | 584 | BMessage settings; |
| 455 | bool settings_valid_p = false; | 585 | bool settings_valid_p; |
| 586 | EmacsScreenChangeMonitor *monitor; | ||
| 456 | 587 | ||
| 457 | Emacs () : BApplication ("application/x-vnd.GNU-emacs") | 588 | Emacs (void) : BApplication ("application/x-vnd.GNU-emacs"), |
| 589 | settings_valid_p (false) | ||
| 458 | { | 590 | { |
| 459 | BPath settings_path; | 591 | BPath settings_path; |
| 460 | 592 | ||
| @@ -470,6 +602,15 @@ public: | |||
| 470 | return; | 602 | return; |
| 471 | 603 | ||
| 472 | settings_valid_p = true; | 604 | settings_valid_p = true; |
| 605 | monitor = new EmacsScreenChangeMonitor; | ||
| 606 | } | ||
| 607 | |||
| 608 | ~Emacs (void) | ||
| 609 | { | ||
| 610 | if (monitor->LockLooper ()) | ||
| 611 | monitor->Quit (); | ||
| 612 | else | ||
| 613 | delete monitor; | ||
| 473 | } | 614 | } |
| 474 | 615 | ||
| 475 | void | 616 | void |
| @@ -518,33 +659,42 @@ public: | |||
| 518 | struct child_frame *next; | 659 | struct child_frame *next; |
| 519 | int xoff, yoff; | 660 | int xoff, yoff; |
| 520 | EmacsWindow *window; | 661 | EmacsWindow *window; |
| 521 | } *subset_windows = NULL; | 662 | } *subset_windows; |
| 522 | 663 | ||
| 523 | EmacsWindow *parent = NULL; | 664 | EmacsWindow *parent; |
| 524 | BRect pre_fullscreen_rect; | 665 | BRect pre_fullscreen_rect; |
| 525 | BRect pre_zoom_rect; | 666 | BRect pre_zoom_rect; |
| 526 | int x_before_zoom = INT_MIN; | 667 | int x_before_zoom; |
| 527 | int y_before_zoom = INT_MIN; | 668 | int y_before_zoom; |
| 528 | bool fullscreen_p = false; | 669 | bool shown_flag; |
| 529 | bool zoomed_p = false; | 670 | volatile bool was_shown_p; |
| 530 | bool shown_flag = false; | 671 | bool menu_bar_active_p; |
| 531 | volatile int was_shown_p = 0; | 672 | bool override_redirect_p; |
| 532 | bool menu_bar_active_p = false; | ||
| 533 | bool override_redirect_p = false; | ||
| 534 | window_look pre_override_redirect_look; | 673 | window_look pre_override_redirect_look; |
| 535 | window_feel pre_override_redirect_feel; | 674 | window_feel pre_override_redirect_feel; |
| 536 | uint32 pre_override_redirect_workspaces; | 675 | uint32 pre_override_redirect_workspaces; |
| 537 | int window_id; | 676 | int window_id; |
| 538 | bool *menus_begun = NULL; | 677 | bool *menus_begun; |
| 539 | enum haiku_z_group z_group; | 678 | enum haiku_z_group z_group; |
| 540 | bool tooltip_p = false; | 679 | bool tooltip_p; |
| 680 | enum haiku_fullscreen_mode fullscreen_mode; | ||
| 541 | 681 | ||
| 542 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, | 682 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, |
| 543 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) | 683 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS), |
| 684 | subset_windows (NULL), | ||
| 685 | parent (NULL), | ||
| 686 | x_before_zoom (INT_MIN), | ||
| 687 | y_before_zoom (INT_MIN), | ||
| 688 | shown_flag (false), | ||
| 689 | was_shown_p (false), | ||
| 690 | menu_bar_active_p (false), | ||
| 691 | override_redirect_p (false), | ||
| 692 | window_id (current_window_id), | ||
| 693 | menus_begun (NULL), | ||
| 694 | z_group (Z_GROUP_NONE), | ||
| 695 | tooltip_p (false), | ||
| 696 | fullscreen_mode (FULLSCREEN_MODE_NONE) | ||
| 544 | { | 697 | { |
| 545 | window_id = current_window_id++; | ||
| 546 | z_group = Z_GROUP_NONE; | ||
| 547 | |||
| 548 | /* This pulse rate is used by scroll bars for repeating a button | 698 | /* This pulse rate is used by scroll bars for repeating a button |
| 549 | action while a button is held down. */ | 699 | action while a button is held down. */ |
| 550 | SetPulseRate (30000); | 700 | SetPulseRate (30000); |
| @@ -583,77 +733,6 @@ public: | |||
| 583 | SetFeel (B_NORMAL_WINDOW_FEEL); | 733 | SetFeel (B_NORMAL_WINDOW_FEEL); |
| 584 | } | 734 | } |
| 585 | 735 | ||
| 586 | BRect | ||
| 587 | CalculateZoomRect (void) | ||
| 588 | { | ||
| 589 | BScreen screen (this); | ||
| 590 | BDeskbar deskbar; | ||
| 591 | BRect screen_frame; | ||
| 592 | BRect frame; | ||
| 593 | BRect deskbar_frame; | ||
| 594 | BRect window_frame; | ||
| 595 | BRect decorator_frame; | ||
| 596 | |||
| 597 | if (!screen.IsValid ()) | ||
| 598 | gui_abort ("Failed to calculate screen rect"); | ||
| 599 | |||
| 600 | screen_frame = frame = screen.Frame (); | ||
| 601 | deskbar_frame = deskbar.Frame (); | ||
| 602 | |||
| 603 | if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ()) | ||
| 604 | { | ||
| 605 | switch (deskbar.Location ()) | ||
| 606 | { | ||
| 607 | case B_DESKBAR_TOP: | ||
| 608 | frame.top = deskbar_frame.bottom + 2; | ||
| 609 | break; | ||
| 610 | |||
| 611 | case B_DESKBAR_BOTTOM: | ||
| 612 | case B_DESKBAR_LEFT_BOTTOM: | ||
| 613 | case B_DESKBAR_RIGHT_BOTTOM: | ||
| 614 | frame.bottom = deskbar_frame.top - 2; | ||
| 615 | break; | ||
| 616 | |||
| 617 | case B_DESKBAR_LEFT_TOP: | ||
| 618 | if (!deskbar.IsExpanded ()) | ||
| 619 | frame.top = deskbar_frame.bottom + 2; | ||
| 620 | else if (!deskbar.IsAlwaysOnTop () | ||
| 621 | && !deskbar.IsAutoRaise ()) | ||
| 622 | frame.left = deskbar_frame.right + 2; | ||
| 623 | break; | ||
| 624 | |||
| 625 | default: | ||
| 626 | if (deskbar.IsExpanded () | ||
| 627 | && !deskbar.IsAlwaysOnTop () | ||
| 628 | && !deskbar.IsAutoRaise ()) | ||
| 629 | frame.right = deskbar_frame.left - 2; | ||
| 630 | } | ||
| 631 | } | ||
| 632 | |||
| 633 | window_frame = Frame (); | ||
| 634 | decorator_frame = DecoratorFrame (); | ||
| 635 | |||
| 636 | frame.top += (window_frame.top | ||
| 637 | - decorator_frame.top); | ||
| 638 | frame.bottom -= (decorator_frame.bottom | ||
| 639 | - window_frame.bottom); | ||
| 640 | frame.left += (window_frame.left | ||
| 641 | - decorator_frame.left); | ||
| 642 | frame.right -= (decorator_frame.right | ||
| 643 | - window_frame.right); | ||
| 644 | |||
| 645 | if (frame.top > deskbar_frame.bottom | ||
| 646 | || frame.bottom < deskbar_frame.top) | ||
| 647 | { | ||
| 648 | frame.left = screen_frame.left + (window_frame.left | ||
| 649 | - decorator_frame.left); | ||
| 650 | frame.right = screen_frame.right - (decorator_frame.right | ||
| 651 | - window_frame.right); | ||
| 652 | } | ||
| 653 | |||
| 654 | return frame; | ||
| 655 | } | ||
| 656 | |||
| 657 | void | 736 | void |
| 658 | UpwardsSubset (EmacsWindow *w) | 737 | UpwardsSubset (EmacsWindow *w) |
| 659 | { | 738 | { |
| @@ -711,12 +790,6 @@ public: | |||
| 711 | RecomputeFeel (); | 790 | RecomputeFeel (); |
| 712 | UpwardsUnSubsetChildren (parent); | 791 | UpwardsUnSubsetChildren (parent); |
| 713 | this->RemoveFromSubset (this); | 792 | this->RemoveFromSubset (this); |
| 714 | |||
| 715 | if (fullscreen_p) | ||
| 716 | { | ||
| 717 | fullscreen_p = 0; | ||
| 718 | MakeFullscreen (1); | ||
| 719 | } | ||
| 720 | child_frame_lock.Unlock (); | 793 | child_frame_lock.Unlock (); |
| 721 | } | 794 | } |
| 722 | 795 | ||
| @@ -766,11 +839,6 @@ public: | |||
| 766 | this->AddToSubset (this); | 839 | this->AddToSubset (this); |
| 767 | if (!IsHidden () && this->parent) | 840 | if (!IsHidden () && this->parent) |
| 768 | UpwardsSubsetChildren (parent); | 841 | UpwardsSubsetChildren (parent); |
| 769 | if (fullscreen_p) | ||
| 770 | { | ||
| 771 | fullscreen_p = 0; | ||
| 772 | MakeFullscreen (1); | ||
| 773 | } | ||
| 774 | window->LinkChild (this); | 842 | window->LinkChild (this); |
| 775 | 843 | ||
| 776 | child_frame_lock.Unlock (); | 844 | child_frame_lock.Unlock (); |
| @@ -797,11 +865,23 @@ public: | |||
| 797 | } | 865 | } |
| 798 | 866 | ||
| 799 | void | 867 | void |
| 868 | MoveToIncludingFrame (int x, int y) | ||
| 869 | { | ||
| 870 | BRect decorator, frame; | ||
| 871 | |||
| 872 | decorator = DecoratorFrame (); | ||
| 873 | frame = Frame (); | ||
| 874 | |||
| 875 | MoveTo (x + frame.left - decorator.left, | ||
| 876 | y + frame.top - decorator.top); | ||
| 877 | } | ||
| 878 | |||
| 879 | void | ||
| 800 | DoMove (struct child_frame *f) | 880 | DoMove (struct child_frame *f) |
| 801 | { | 881 | { |
| 802 | BRect frame = this->Frame (); | 882 | BRect frame = this->Frame (); |
| 803 | f->window->MoveTo (frame.left + f->xoff, | 883 | f->window->MoveToIncludingFrame (frame.left + f->xoff, |
| 804 | frame.top + f->yoff); | 884 | frame.top + f->yoff); |
| 805 | } | 885 | } |
| 806 | 886 | ||
| 807 | void | 887 | void |
| @@ -982,6 +1062,15 @@ public: | |||
| 982 | haiku_write (WHEEL_MOVE_EVENT, &rq); | 1062 | haiku_write (WHEEL_MOVE_EVENT, &rq); |
| 983 | }; | 1063 | }; |
| 984 | } | 1064 | } |
| 1065 | else if (msg->what == SEND_MOVE_FRAME_EVENT) | ||
| 1066 | FrameMoved (Frame ().LeftTop ()); | ||
| 1067 | else if (msg->what == B_SCREEN_CHANGED) | ||
| 1068 | { | ||
| 1069 | if (fullscreen_mode != FULLSCREEN_MODE_NONE) | ||
| 1070 | SetFullscreen (fullscreen_mode); | ||
| 1071 | |||
| 1072 | BWindow::DispatchMessage (msg, handler); | ||
| 1073 | } | ||
| 985 | else | 1074 | else |
| 986 | BWindow::DispatchMessage (msg, handler); | 1075 | BWindow::DispatchMessage (msg, handler); |
| 987 | } | 1076 | } |
| @@ -1015,41 +1104,66 @@ public: | |||
| 1015 | { | 1104 | { |
| 1016 | struct haiku_resize_event rq; | 1105 | struct haiku_resize_event rq; |
| 1017 | rq.window = this; | 1106 | rq.window = this; |
| 1018 | rq.px_heightf = newHeight + 1.0f; | 1107 | rq.width = newWidth + 1.0f; |
| 1019 | rq.px_widthf = newWidth + 1.0f; | 1108 | rq.height = newHeight + 1.0f; |
| 1020 | 1109 | ||
| 1021 | haiku_write (FRAME_RESIZED, &rq); | 1110 | haiku_write (FRAME_RESIZED, &rq); |
| 1022 | BWindow::FrameResized (newWidth, newHeight); | 1111 | BWindow::FrameResized (newWidth, newHeight); |
| 1023 | } | 1112 | } |
| 1024 | 1113 | ||
| 1025 | void | 1114 | void |
| 1026 | FrameMoved (BPoint newPosition) | 1115 | FrameMoved (BPoint new_position) |
| 1027 | { | 1116 | { |
| 1028 | struct haiku_move_event rq; | 1117 | struct haiku_move_event rq; |
| 1118 | BRect frame, decorator_frame; | ||
| 1119 | struct child_frame *f; | ||
| 1120 | |||
| 1121 | if (fullscreen_mode == FULLSCREEN_MODE_WIDTH | ||
| 1122 | && new_position.x != 0) | ||
| 1123 | { | ||
| 1124 | MoveTo (0, new_position.y); | ||
| 1125 | return; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | if (fullscreen_mode == FULLSCREEN_MODE_HEIGHT | ||
| 1129 | && new_position.y != 0) | ||
| 1130 | { | ||
| 1131 | MoveTo (new_position.x, 0); | ||
| 1132 | return; | ||
| 1133 | } | ||
| 1134 | |||
| 1029 | rq.window = this; | 1135 | rq.window = this; |
| 1030 | rq.x = std::lrint (newPosition.x); | 1136 | rq.x = std::lrint (new_position.x); |
| 1031 | rq.y = std::lrint (newPosition.y); | 1137 | rq.y = std::lrint (new_position.y); |
| 1138 | |||
| 1139 | frame = Frame (); | ||
| 1140 | decorator_frame = DecoratorFrame (); | ||
| 1141 | |||
| 1142 | rq.decorator_width | ||
| 1143 | = std::lrint (frame.left - decorator_frame.left); | ||
| 1144 | rq.decorator_height | ||
| 1145 | = std::lrint (frame.top - decorator_frame.top); | ||
| 1032 | 1146 | ||
| 1033 | haiku_write (MOVE_EVENT, &rq); | 1147 | haiku_write (MOVE_EVENT, &rq); |
| 1034 | 1148 | ||
| 1035 | CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK | 1149 | CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK |
| 1036 | { | 1150 | { |
| 1037 | for (struct child_frame *f = subset_windows; | 1151 | for (f = subset_windows; f; f = f->next) |
| 1038 | f; f = f->next) | ||
| 1039 | DoMove (f); | 1152 | DoMove (f); |
| 1040 | child_frame_lock.Unlock (); | 1153 | child_frame_lock.Unlock (); |
| 1041 | 1154 | ||
| 1042 | BWindow::FrameMoved (newPosition); | 1155 | BWindow::FrameMoved (new_position); |
| 1043 | } | 1156 | } |
| 1044 | } | 1157 | } |
| 1045 | 1158 | ||
| 1046 | void | 1159 | void |
| 1047 | WorkspacesChanged (uint32_t old, uint32_t n) | 1160 | WorkspacesChanged (uint32_t old, uint32_t n) |
| 1048 | { | 1161 | { |
| 1162 | struct child_frame *f; | ||
| 1163 | |||
| 1049 | CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK | 1164 | CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK |
| 1050 | { | 1165 | { |
| 1051 | for (struct child_frame *f = subset_windows; | 1166 | for (f = subset_windows; f; f = f->next) |
| 1052 | f; f = f->next) | ||
| 1053 | DoUpdateWorkspace (f); | 1167 | DoUpdateWorkspace (f); |
| 1054 | 1168 | ||
| 1055 | child_frame_lock.Unlock (); | 1169 | child_frame_lock.Unlock (); |
| @@ -1063,7 +1177,7 @@ public: | |||
| 1063 | gui_abort ("Failed to lock child frame state lock"); | 1177 | gui_abort ("Failed to lock child frame state lock"); |
| 1064 | 1178 | ||
| 1065 | if (!this->parent) | 1179 | if (!this->parent) |
| 1066 | this->MoveTo (x, y); | 1180 | this->MoveToIncludingFrame (x, y); |
| 1067 | else | 1181 | else |
| 1068 | this->parent->MoveChild (this, x, y, 0); | 1182 | this->parent->MoveChild (this, x, y, 0); |
| 1069 | child_frame_lock.Unlock (); | 1183 | child_frame_lock.Unlock (); |
| @@ -1135,66 +1249,113 @@ public: | |||
| 1135 | child_frame_lock.Unlock (); | 1249 | child_frame_lock.Unlock (); |
| 1136 | } | 1250 | } |
| 1137 | 1251 | ||
| 1138 | void | 1252 | BRect |
| 1139 | Zoom (BPoint o, float w, float h) | 1253 | ClearFullscreen (enum haiku_fullscreen_mode target_mode) |
| 1140 | { | 1254 | { |
| 1141 | struct haiku_zoom_event rq; | 1255 | BRect original_frame; |
| 1142 | BRect rect; | ||
| 1143 | rq.window = this; | ||
| 1144 | |||
| 1145 | if (fullscreen_p) | ||
| 1146 | MakeFullscreen (0); | ||
| 1147 | 1256 | ||
| 1148 | if (!zoomed_p) | 1257 | switch (fullscreen_mode) |
| 1149 | { | ||
| 1150 | pre_zoom_rect = Frame (); | ||
| 1151 | zoomed_p = true; | ||
| 1152 | rect = CalculateZoomRect (); | ||
| 1153 | } | ||
| 1154 | else | ||
| 1155 | { | 1258 | { |
| 1156 | zoomed_p = false; | 1259 | case FULLSCREEN_MODE_MAXIMIZED: |
| 1157 | rect = pre_zoom_rect; | 1260 | original_frame = pre_zoom_rect; |
| 1158 | } | ||
| 1159 | 1261 | ||
| 1160 | rq.zoomed = zoomed_p; | 1262 | if (target_mode == FULLSCREEN_MODE_NONE) |
| 1161 | haiku_write (ZOOM_EVENT, &rq); | 1263 | BWindow::Zoom (pre_zoom_rect.LeftTop (), |
| 1264 | BE_RECT_WIDTH (pre_zoom_rect) - 1, | ||
| 1265 | BE_RECT_HEIGHT (pre_zoom_rect) - 1); | ||
| 1266 | break; | ||
| 1267 | |||
| 1268 | case FULLSCREEN_MODE_BOTH: | ||
| 1269 | case FULLSCREEN_MODE_HEIGHT: | ||
| 1270 | case FULLSCREEN_MODE_WIDTH: | ||
| 1271 | original_frame = pre_fullscreen_rect; | ||
| 1272 | SetFlags (Flags () & ~(B_NOT_MOVABLE | ||
| 1273 | | B_NOT_ZOOMABLE | ||
| 1274 | | B_NOT_RESIZABLE)); | ||
| 1275 | |||
| 1276 | if (target_mode != FULLSCREEN_MODE_NONE) | ||
| 1277 | goto out; | ||
| 1278 | |||
| 1279 | MoveTo (pre_fullscreen_rect.LeftTop ()); | ||
| 1280 | ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1, | ||
| 1281 | BE_RECT_HEIGHT (pre_fullscreen_rect) - 1); | ||
| 1282 | break; | ||
| 1283 | |||
| 1284 | case FULLSCREEN_MODE_NONE: | ||
| 1285 | original_frame = Frame (); | ||
| 1286 | break; | ||
| 1287 | } | ||
| 1162 | 1288 | ||
| 1163 | BWindow::Zoom (rect.LeftTop (), BE_RECT_WIDTH (rect) - 1, | 1289 | out: |
| 1164 | BE_RECT_HEIGHT (rect) - 1); | 1290 | fullscreen_mode = FULLSCREEN_MODE_NONE; |
| 1291 | return original_frame; | ||
| 1165 | } | 1292 | } |
| 1166 | 1293 | ||
| 1167 | void | 1294 | BRect |
| 1168 | UnZoom (void) | 1295 | FullscreenRectForMode (enum haiku_fullscreen_mode mode) |
| 1169 | { | 1296 | { |
| 1170 | if (!zoomed_p) | 1297 | BScreen screen (this); |
| 1171 | return; | 1298 | BRect frame; |
| 1299 | |||
| 1300 | if (!screen.IsValid ()) | ||
| 1301 | return BRect (0, 0, 0, 0); | ||
| 1302 | |||
| 1303 | frame = screen.Frame (); | ||
| 1304 | |||
| 1305 | if (mode == FULLSCREEN_MODE_HEIGHT) | ||
| 1306 | frame.right -= BE_RECT_WIDTH (frame) / 2; | ||
| 1307 | else if (mode == FULLSCREEN_MODE_WIDTH) | ||
| 1308 | frame.bottom -= BE_RECT_HEIGHT (frame) / 2; | ||
| 1172 | 1309 | ||
| 1173 | BWindow::Zoom (); | 1310 | return frame; |
| 1174 | } | 1311 | } |
| 1175 | 1312 | ||
| 1176 | void | 1313 | void |
| 1177 | GetParentWidthHeight (int *width, int *height) | 1314 | SetFullscreen (enum haiku_fullscreen_mode mode) |
| 1178 | { | 1315 | { |
| 1179 | if (!child_frame_lock.Lock ()) | 1316 | BRect zoom_rect, frame; |
| 1180 | gui_abort ("Failed to lock child frame state lock"); | ||
| 1181 | 1317 | ||
| 1182 | if (parent) | 1318 | frame = ClearFullscreen (mode); |
| 1183 | { | 1319 | |
| 1184 | BRect frame = parent->Frame (); | 1320 | switch (mode) |
| 1185 | *width = BE_RECT_WIDTH (frame); | ||
| 1186 | *height = BE_RECT_HEIGHT (frame); | ||
| 1187 | } | ||
| 1188 | else | ||
| 1189 | { | 1321 | { |
| 1190 | BScreen s (this); | 1322 | case FULLSCREEN_MODE_MAXIMIZED: |
| 1191 | BRect frame = s.Frame (); | 1323 | pre_zoom_rect = frame; |
| 1324 | zoom_rect = get_zoom_rect (this); | ||
| 1325 | BWindow::Zoom (zoom_rect.LeftTop (), | ||
| 1326 | BE_RECT_WIDTH (zoom_rect) - 1, | ||
| 1327 | BE_RECT_HEIGHT (zoom_rect) - 1); | ||
| 1328 | break; | ||
| 1329 | |||
| 1330 | case FULLSCREEN_MODE_BOTH: | ||
| 1331 | SetFlags (Flags () | B_NOT_MOVABLE); | ||
| 1332 | FALLTHROUGH; | ||
| 1333 | |||
| 1334 | case FULLSCREEN_MODE_HEIGHT: | ||
| 1335 | case FULLSCREEN_MODE_WIDTH: | ||
| 1336 | SetFlags (Flags () | B_NOT_ZOOMABLE | B_NOT_RESIZABLE); | ||
| 1337 | pre_fullscreen_rect = frame; | ||
| 1338 | zoom_rect = FullscreenRectForMode (mode); | ||
| 1339 | ResizeTo (BE_RECT_WIDTH (zoom_rect) - 1, | ||
| 1340 | BE_RECT_HEIGHT (zoom_rect) - 1); | ||
| 1341 | MoveTo (zoom_rect.left, zoom_rect.top); | ||
| 1342 | break; | ||
| 1192 | 1343 | ||
| 1193 | *width = BE_RECT_WIDTH (frame); | 1344 | case FULLSCREEN_MODE_NONE: |
| 1194 | *height = BE_RECT_HEIGHT (frame); | 1345 | break; |
| 1195 | } | 1346 | } |
| 1196 | 1347 | ||
| 1197 | child_frame_lock.Unlock (); | 1348 | fullscreen_mode = mode; |
| 1349 | } | ||
| 1350 | |||
| 1351 | void | ||
| 1352 | Zoom (BPoint origin, float width, float height) | ||
| 1353 | { | ||
| 1354 | struct haiku_zoom_event rq; | ||
| 1355 | |||
| 1356 | rq.window = this; | ||
| 1357 | rq.fullscreen_mode = fullscreen_mode; | ||
| 1358 | haiku_write (ZOOM_EVENT, &rq); | ||
| 1198 | } | 1359 | } |
| 1199 | 1360 | ||
| 1200 | void | 1361 | void |
| @@ -1217,53 +1378,6 @@ public: | |||
| 1217 | child_frame_lock.Lock (); | 1378 | child_frame_lock.Lock (); |
| 1218 | gui_abort ("Trying to calculate offsets for a child frame that doesn't exist"); | 1379 | gui_abort ("Trying to calculate offsets for a child frame that doesn't exist"); |
| 1219 | } | 1380 | } |
| 1220 | |||
| 1221 | void | ||
| 1222 | MakeFullscreen (int make_fullscreen_p) | ||
| 1223 | { | ||
| 1224 | BScreen screen (this); | ||
| 1225 | |||
| 1226 | if (!screen.IsValid ()) | ||
| 1227 | gui_abort ("Trying to make a window fullscreen without a screen"); | ||
| 1228 | |||
| 1229 | UnZoom (); | ||
| 1230 | |||
| 1231 | if (make_fullscreen_p == fullscreen_p) | ||
| 1232 | return; | ||
| 1233 | |||
| 1234 | fullscreen_p = make_fullscreen_p; | ||
| 1235 | uint32 flags = Flags (); | ||
| 1236 | if (fullscreen_p) | ||
| 1237 | { | ||
| 1238 | if (zoomed_p) | ||
| 1239 | UnZoom (); | ||
| 1240 | |||
| 1241 | flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE; | ||
| 1242 | pre_fullscreen_rect = Frame (); | ||
| 1243 | |||
| 1244 | if (!child_frame_lock.Lock ()) | ||
| 1245 | gui_abort ("Failed to lock child frame state lock"); | ||
| 1246 | |||
| 1247 | if (parent) | ||
| 1248 | parent->OffsetChildRect (&pre_fullscreen_rect, this); | ||
| 1249 | |||
| 1250 | child_frame_lock.Unlock (); | ||
| 1251 | |||
| 1252 | int w, h; | ||
| 1253 | EmacsMoveTo (0, 0); | ||
| 1254 | GetParentWidthHeight (&w, &h); | ||
| 1255 | ResizeTo (w - 1, h - 1); | ||
| 1256 | } | ||
| 1257 | else | ||
| 1258 | { | ||
| 1259 | flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE); | ||
| 1260 | EmacsMoveTo (pre_fullscreen_rect.left, | ||
| 1261 | pre_fullscreen_rect.top); | ||
| 1262 | ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1, | ||
| 1263 | BE_RECT_HEIGHT (pre_fullscreen_rect) - 1); | ||
| 1264 | } | ||
| 1265 | SetFlags (flags); | ||
| 1266 | } | ||
| 1267 | }; | 1381 | }; |
| 1268 | 1382 | ||
| 1269 | class EmacsMenuBar : public BMenuBar | 1383 | class EmacsMenuBar : public BMenuBar |
| @@ -1322,11 +1436,7 @@ public: | |||
| 1322 | rq.y = std::lrint (point.y); | 1436 | rq.y = std::lrint (point.y); |
| 1323 | rq.window = this->Window (); | 1437 | rq.window = this->Window (); |
| 1324 | 1438 | ||
| 1325 | if (movement_locker.Lock ()) | 1439 | haiku_write (MENU_BAR_LEFT, &rq); |
| 1326 | { | ||
| 1327 | haiku_write (MENU_BAR_LEFT, &rq); | ||
| 1328 | movement_locker.Unlock (); | ||
| 1329 | } | ||
| 1330 | } | 1440 | } |
| 1331 | 1441 | ||
| 1332 | BMenuBar::MouseMoved (point, transit, msg); | 1442 | BMenuBar::MouseMoved (point, transit, msg); |
| @@ -1383,25 +1493,36 @@ public: | |||
| 1383 | class EmacsView : public BView | 1493 | class EmacsView : public BView |
| 1384 | { | 1494 | { |
| 1385 | public: | 1495 | public: |
| 1386 | uint32_t previous_buttons = 0; | 1496 | uint32_t previous_buttons; |
| 1387 | int looper_locked_count = 0; | 1497 | int looper_locked_count; |
| 1388 | BRegion sb_region; | 1498 | BRegion sb_region; |
| 1389 | BRegion invalid_region; | 1499 | BRegion invalid_region; |
| 1390 | 1500 | ||
| 1391 | BView *offscreen_draw_view = NULL; | 1501 | BView *offscreen_draw_view; |
| 1392 | BBitmap *offscreen_draw_bitmap_1 = NULL; | 1502 | BBitmap *offscreen_draw_bitmap_1; |
| 1393 | BBitmap *copy_bitmap = NULL; | 1503 | BBitmap *copy_bitmap; |
| 1394 | 1504 | ||
| 1395 | #ifdef USE_BE_CAIRO | 1505 | #ifdef USE_BE_CAIRO |
| 1396 | cairo_surface_t *cr_surface = NULL; | 1506 | cairo_surface_t *cr_surface; |
| 1397 | cairo_t *cr_context = NULL; | 1507 | cairo_t *cr_context; |
| 1398 | BLocker cr_surface_lock; | 1508 | BLocker cr_surface_lock; |
| 1399 | #endif | 1509 | #endif |
| 1400 | 1510 | ||
| 1401 | BPoint tt_absl_pos; | 1511 | BPoint tt_absl_pos; |
| 1402 | BMessage *wait_for_release_message = NULL; | 1512 | BMessage *wait_for_release_message; |
| 1403 | 1513 | ||
| 1404 | EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", B_FOLLOW_NONE, B_WILL_DRAW) | 1514 | EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", |
| 1515 | B_FOLLOW_NONE, B_WILL_DRAW), | ||
| 1516 | previous_buttons (0), | ||
| 1517 | looper_locked_count (0), | ||
| 1518 | offscreen_draw_view (NULL), | ||
| 1519 | offscreen_draw_bitmap_1 (NULL), | ||
| 1520 | copy_bitmap (NULL), | ||
| 1521 | #ifdef USE_BE_CAIRO | ||
| 1522 | cr_surface (NULL), | ||
| 1523 | cr_context (NULL), | ||
| 1524 | #endif | ||
| 1525 | wait_for_release_message (NULL) | ||
| 1405 | { | 1526 | { |
| 1406 | 1527 | ||
| 1407 | } | 1528 | } |
| @@ -1549,9 +1670,7 @@ public: | |||
| 1549 | #endif | 1670 | #endif |
| 1550 | 1671 | ||
| 1551 | if (looper_locked_count) | 1672 | if (looper_locked_count) |
| 1552 | { | 1673 | offscreen_draw_bitmap_1->Lock (); |
| 1553 | offscreen_draw_bitmap_1->Lock (); | ||
| 1554 | } | ||
| 1555 | 1674 | ||
| 1556 | UnlockLooper (); | 1675 | UnlockLooper (); |
| 1557 | } | 1676 | } |
| @@ -1618,16 +1737,17 @@ public: | |||
| 1618 | copy_bitmap = NULL; | 1737 | copy_bitmap = NULL; |
| 1619 | } | 1738 | } |
| 1620 | if (!copy_bitmap) | 1739 | if (!copy_bitmap) |
| 1621 | copy_bitmap = new BBitmap (offscreen_draw_bitmap_1); | 1740 | { |
| 1741 | copy_bitmap = new BBitmap (offscreen_draw_bitmap_1); | ||
| 1742 | SetViewBitmap (copy_bitmap, Frame (), | ||
| 1743 | Frame (), B_FOLLOW_NONE, 0); | ||
| 1744 | } | ||
| 1622 | else | 1745 | else |
| 1623 | copy_bitmap->ImportBits (offscreen_draw_bitmap_1); | 1746 | copy_bitmap->ImportBits (offscreen_draw_bitmap_1); |
| 1624 | 1747 | ||
| 1625 | if (copy_bitmap->InitCheck () != B_OK) | 1748 | if (copy_bitmap->InitCheck () != B_OK) |
| 1626 | gui_abort ("Failed to init copy bitmap during buffer flip"); | 1749 | gui_abort ("Failed to init copy bitmap during buffer flip"); |
| 1627 | 1750 | ||
| 1628 | SetViewBitmap (copy_bitmap, | ||
| 1629 | Frame (), Frame (), B_FOLLOW_NONE, 0); | ||
| 1630 | |||
| 1631 | Invalidate (&invalid_region); | 1751 | Invalidate (&invalid_region); |
| 1632 | invalid_region.MakeEmpty (); | 1752 | invalid_region.MakeEmpty (); |
| 1633 | UnlockLooper (); | 1753 | UnlockLooper (); |
| @@ -1668,8 +1788,11 @@ public: | |||
| 1668 | struct haiku_mouse_motion_event rq; | 1788 | struct haiku_mouse_motion_event rq; |
| 1669 | int32 windowid; | 1789 | int32 windowid; |
| 1670 | EmacsWindow *window; | 1790 | EmacsWindow *window; |
| 1791 | BToolTip *tooltip; | ||
| 1671 | 1792 | ||
| 1672 | window = (EmacsWindow *) Window (); | 1793 | window = (EmacsWindow *) Window (); |
| 1794 | tooltip = ToolTip (); | ||
| 1795 | |||
| 1673 | rq.just_exited_p = transit == B_EXITED_VIEW; | 1796 | rq.just_exited_p = transit == B_EXITED_VIEW; |
| 1674 | rq.x = point.x; | 1797 | rq.x = point.x; |
| 1675 | rq.y = point.y; | 1798 | rq.y = point.y; |
| @@ -1684,9 +1807,9 @@ public: | |||
| 1684 | else | 1807 | else |
| 1685 | rq.dnd_message = false; | 1808 | rq.dnd_message = false; |
| 1686 | 1809 | ||
| 1687 | if (ToolTip ()) | 1810 | if (tooltip) |
| 1688 | ToolTip ()->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x), | 1811 | tooltip->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x), |
| 1689 | -(point.y - tt_absl_pos.y))); | 1812 | -(point.y - tt_absl_pos.y))); |
| 1690 | 1813 | ||
| 1691 | if (!grab_view_locker.Lock ()) | 1814 | if (!grab_view_locker.Lock ()) |
| 1692 | gui_abort ("Couldn't lock grab view locker"); | 1815 | gui_abort ("Couldn't lock grab view locker"); |
| @@ -1699,18 +1822,14 @@ public: | |||
| 1699 | 1822 | ||
| 1700 | grab_view_locker.Unlock (); | 1823 | grab_view_locker.Unlock (); |
| 1701 | 1824 | ||
| 1702 | if (movement_locker.Lock ()) | 1825 | haiku_write (MOUSE_MOTION, &rq); |
| 1703 | { | ||
| 1704 | haiku_write (MOUSE_MOTION, &rq); | ||
| 1705 | movement_locker.Unlock (); | ||
| 1706 | } | ||
| 1707 | } | 1826 | } |
| 1708 | 1827 | ||
| 1709 | void | 1828 | void |
| 1710 | MouseDown (BPoint point) | 1829 | BasicMouseDown (BPoint point, BView *scroll_bar) |
| 1711 | { | 1830 | { |
| 1712 | struct haiku_button_event rq; | 1831 | struct haiku_button_event rq; |
| 1713 | uint32 buttons; | 1832 | uint32 mods, buttons; |
| 1714 | 1833 | ||
| 1715 | this->GetMouse (&point, &buttons, false); | 1834 | this->GetMouse (&point, &buttons, false); |
| 1716 | 1835 | ||
| @@ -1721,6 +1840,7 @@ public: | |||
| 1721 | grab_view_locker.Unlock (); | 1840 | grab_view_locker.Unlock (); |
| 1722 | 1841 | ||
| 1723 | rq.window = this->Window (); | 1842 | rq.window = this->Window (); |
| 1843 | rq.scroll_bar = scroll_bar; | ||
| 1724 | 1844 | ||
| 1725 | if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON) | 1845 | if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON) |
| 1726 | && (buttons & B_PRIMARY_MOUSE_BUTTON)) | 1846 | && (buttons & B_PRIMARY_MOUSE_BUTTON)) |
| @@ -1739,7 +1859,7 @@ public: | |||
| 1739 | rq.x = point.x; | 1859 | rq.x = point.x; |
| 1740 | rq.y = point.y; | 1860 | rq.y = point.y; |
| 1741 | 1861 | ||
| 1742 | uint32_t mods = modifiers (); | 1862 | mods = modifiers (); |
| 1743 | 1863 | ||
| 1744 | rq.modifiers = 0; | 1864 | rq.modifiers = 0; |
| 1745 | if (mods & B_SHIFT_KEY) | 1865 | if (mods & B_SHIFT_KEY) |
| @@ -1754,18 +1874,25 @@ public: | |||
| 1754 | if (mods & B_OPTION_KEY) | 1874 | if (mods & B_OPTION_KEY) |
| 1755 | rq.modifiers |= HAIKU_MODIFIER_SUPER; | 1875 | rq.modifiers |= HAIKU_MODIFIER_SUPER; |
| 1756 | 1876 | ||
| 1757 | SetMouseEventMask (B_POINTER_EVENTS, (B_LOCK_WINDOW_FOCUS | 1877 | if (!scroll_bar) |
| 1758 | | B_NO_POINTER_HISTORY)); | 1878 | SetMouseEventMask (B_POINTER_EVENTS, (B_LOCK_WINDOW_FOCUS |
| 1879 | | B_NO_POINTER_HISTORY)); | ||
| 1759 | 1880 | ||
| 1760 | rq.time = system_time (); | 1881 | rq.time = system_time (); |
| 1761 | haiku_write (BUTTON_DOWN, &rq); | 1882 | haiku_write (BUTTON_DOWN, &rq); |
| 1762 | } | 1883 | } |
| 1763 | 1884 | ||
| 1764 | void | 1885 | void |
| 1765 | MouseUp (BPoint point) | 1886 | MouseDown (BPoint point) |
| 1887 | { | ||
| 1888 | BasicMouseDown (point, NULL); | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | void | ||
| 1892 | BasicMouseUp (BPoint point, BView *scroll_bar) | ||
| 1766 | { | 1893 | { |
| 1767 | struct haiku_button_event rq; | 1894 | struct haiku_button_event rq; |
| 1768 | uint32 buttons; | 1895 | uint32 buttons, mods; |
| 1769 | 1896 | ||
| 1770 | this->GetMouse (&point, &buttons, false); | 1897 | this->GetMouse (&point, &buttons, false); |
| 1771 | 1898 | ||
| @@ -1786,6 +1913,7 @@ public: | |||
| 1786 | } | 1913 | } |
| 1787 | 1914 | ||
| 1788 | rq.window = this->Window (); | 1915 | rq.window = this->Window (); |
| 1916 | rq.scroll_bar = scroll_bar; | ||
| 1789 | 1917 | ||
| 1790 | if ((previous_buttons & B_PRIMARY_MOUSE_BUTTON) | 1918 | if ((previous_buttons & B_PRIMARY_MOUSE_BUTTON) |
| 1791 | && !(buttons & B_PRIMARY_MOUSE_BUTTON)) | 1919 | && !(buttons & B_PRIMARY_MOUSE_BUTTON)) |
| @@ -1804,7 +1932,7 @@ public: | |||
| 1804 | rq.x = point.x; | 1932 | rq.x = point.x; |
| 1805 | rq.y = point.y; | 1933 | rq.y = point.y; |
| 1806 | 1934 | ||
| 1807 | uint32_t mods = modifiers (); | 1935 | mods = modifiers (); |
| 1808 | 1936 | ||
| 1809 | rq.modifiers = 0; | 1937 | rq.modifiers = 0; |
| 1810 | if (mods & B_SHIFT_KEY) | 1938 | if (mods & B_SHIFT_KEY) |
| @@ -1819,37 +1947,48 @@ public: | |||
| 1819 | if (mods & B_OPTION_KEY) | 1947 | if (mods & B_OPTION_KEY) |
| 1820 | rq.modifiers |= HAIKU_MODIFIER_SUPER; | 1948 | rq.modifiers |= HAIKU_MODIFIER_SUPER; |
| 1821 | 1949 | ||
| 1822 | if (!buttons) | ||
| 1823 | SetMouseEventMask (0, 0); | ||
| 1824 | |||
| 1825 | rq.time = system_time (); | 1950 | rq.time = system_time (); |
| 1826 | haiku_write (BUTTON_UP, &rq); | 1951 | haiku_write (BUTTON_UP, &rq); |
| 1827 | } | 1952 | } |
| 1953 | |||
| 1954 | void | ||
| 1955 | MouseUp (BPoint point) | ||
| 1956 | { | ||
| 1957 | BasicMouseUp (point, NULL); | ||
| 1958 | } | ||
| 1828 | }; | 1959 | }; |
| 1829 | 1960 | ||
| 1830 | class EmacsScrollBar : public BScrollBar | 1961 | class EmacsScrollBar : public BScrollBar |
| 1831 | { | 1962 | { |
| 1832 | public: | 1963 | public: |
| 1833 | int dragging = 0; | 1964 | int dragging; |
| 1834 | bool horizontal; | 1965 | bool horizontal; |
| 1835 | enum haiku_scroll_bar_part current_part; | 1966 | enum haiku_scroll_bar_part current_part; |
| 1836 | float old_value; | 1967 | float old_value; |
| 1837 | scroll_bar_info info; | 1968 | scroll_bar_info info; |
| 1838 | 1969 | ||
| 1839 | /* True if button events should be passed to the parent. */ | 1970 | /* True if button events should be passed to the parent. */ |
| 1840 | bool handle_button = false; | 1971 | bool handle_button; |
| 1841 | bool in_overscroll = false; | 1972 | bool in_overscroll; |
| 1842 | bool can_overscroll = false; | 1973 | bool can_overscroll; |
| 1843 | bool maybe_overscroll = false; | 1974 | bool maybe_overscroll; |
| 1844 | BPoint last_overscroll; | 1975 | BPoint last_overscroll; |
| 1845 | int last_reported_overscroll_value; | 1976 | int last_reported_overscroll_value; |
| 1846 | int max_value, real_max_value; | 1977 | int max_value, real_max_value; |
| 1847 | int overscroll_start_value; | 1978 | int overscroll_start_value; |
| 1848 | bigtime_t repeater_start; | 1979 | bigtime_t repeater_start; |
| 1849 | 1980 | EmacsView *parent; | |
| 1850 | EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) : | 1981 | |
| 1851 | BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? | 1982 | EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p, |
| 1852 | B_HORIZONTAL : B_VERTICAL) | 1983 | EmacsView *parent) |
| 1984 | : BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? | ||
| 1985 | B_HORIZONTAL : B_VERTICAL), | ||
| 1986 | dragging (0), | ||
| 1987 | handle_button (false), | ||
| 1988 | in_overscroll (false), | ||
| 1989 | can_overscroll (false), | ||
| 1990 | maybe_overscroll (false), | ||
| 1991 | parent (parent) | ||
| 1853 | { | 1992 | { |
| 1854 | BView *vw = (BView *) this; | 1993 | BView *vw = (BView *) this; |
| 1855 | vw->SetResizingMode (B_FOLLOW_NONE); | 1994 | vw->SetResizingMode (B_FOLLOW_NONE); |
| @@ -2050,7 +2189,6 @@ public: | |||
| 2050 | BLooper *looper; | 2189 | BLooper *looper; |
| 2051 | BMessage *message; | 2190 | BMessage *message; |
| 2052 | int32 buttons, mods; | 2191 | int32 buttons, mods; |
| 2053 | BView *parent; | ||
| 2054 | 2192 | ||
| 2055 | looper = Looper (); | 2193 | looper = Looper (); |
| 2056 | message = NULL; | 2194 | message = NULL; |
| @@ -2071,8 +2209,9 @@ public: | |||
| 2071 | { | 2209 | { |
| 2072 | /* Allow C-mouse-3 to split the window on a scroll bar. */ | 2210 | /* Allow C-mouse-3 to split the window on a scroll bar. */ |
| 2073 | handle_button = true; | 2211 | handle_button = true; |
| 2074 | parent = Parent (); | 2212 | SetMouseEventMask (B_POINTER_EVENTS, (B_SUSPEND_VIEW_FOCUS |
| 2075 | parent->MouseDown (ConvertToParent (pt)); | 2213 | | B_LOCK_WINDOW_FOCUS)); |
| 2214 | parent->BasicMouseDown (ConvertToParent (pt), this); | ||
| 2076 | 2215 | ||
| 2077 | return; | 2216 | return; |
| 2078 | } | 2217 | } |
| @@ -2135,7 +2274,6 @@ public: | |||
| 2135 | MouseUp (BPoint pt) | 2274 | MouseUp (BPoint pt) |
| 2136 | { | 2275 | { |
| 2137 | struct haiku_scroll_bar_drag_event rq; | 2276 | struct haiku_scroll_bar_drag_event rq; |
| 2138 | BView *parent; | ||
| 2139 | 2277 | ||
| 2140 | in_overscroll = false; | 2278 | in_overscroll = false; |
| 2141 | maybe_overscroll = false; | 2279 | maybe_overscroll = false; |
| @@ -2143,8 +2281,7 @@ public: | |||
| 2143 | if (handle_button) | 2281 | if (handle_button) |
| 2144 | { | 2282 | { |
| 2145 | handle_button = false; | 2283 | handle_button = false; |
| 2146 | parent = Parent (); | 2284 | parent->BasicMouseUp (ConvertToParent (pt), this); |
| 2147 | parent->MouseUp (ConvertToParent (pt)); | ||
| 2148 | 2285 | ||
| 2149 | return; | 2286 | return; |
| 2150 | } | 2287 | } |
| @@ -2179,11 +2316,7 @@ public: | |||
| 2179 | rq.y = std::lrint (conv.y); | 2316 | rq.y = std::lrint (conv.y); |
| 2180 | rq.window = this->Window (); | 2317 | rq.window = this->Window (); |
| 2181 | 2318 | ||
| 2182 | if (movement_locker.Lock ()) | 2319 | haiku_write (MENU_BAR_LEFT, &rq); |
| 2183 | { | ||
| 2184 | haiku_write (MENU_BAR_LEFT, &rq); | ||
| 2185 | movement_locker.Unlock (); | ||
| 2186 | } | ||
| 2187 | } | 2320 | } |
| 2188 | 2321 | ||
| 2189 | if (in_overscroll) | 2322 | if (in_overscroll) |
| @@ -2280,30 +2413,26 @@ public: | |||
| 2280 | class EmacsMenuItem : public BMenuItem | 2413 | class EmacsMenuItem : public BMenuItem |
| 2281 | { | 2414 | { |
| 2282 | public: | 2415 | public: |
| 2283 | int menu_bar_id = -1; | 2416 | int menu_bar_id; |
| 2284 | void *menu_ptr = NULL; | 2417 | void *menu_ptr; |
| 2285 | void *wind_ptr = NULL; | 2418 | void *wind_ptr; |
| 2286 | char *key = NULL; | 2419 | char *key; |
| 2287 | char *help = NULL; | 2420 | char *help; |
| 2288 | 2421 | ||
| 2289 | EmacsMenuItem (const char *ky, | 2422 | EmacsMenuItem (const char *key_label, const char *label, |
| 2290 | const char *str, | 2423 | const char *help, BMessage *message = NULL) |
| 2291 | const char *help, | 2424 | : BMenuItem (label, message), |
| 2292 | BMessage *message = NULL) : BMenuItem (str, message) | 2425 | menu_bar_id (-1), |
| 2426 | menu_ptr (NULL), | ||
| 2427 | wind_ptr (NULL), | ||
| 2428 | key (NULL), | ||
| 2429 | help (NULL) | ||
| 2293 | { | 2430 | { |
| 2294 | if (ky) | 2431 | if (key_label) |
| 2295 | { | 2432 | key = strdup (key_label); |
| 2296 | key = strdup (ky); | ||
| 2297 | if (!key) | ||
| 2298 | gui_abort ("strdup failed"); | ||
| 2299 | } | ||
| 2300 | 2433 | ||
| 2301 | if (help) | 2434 | if (help) |
| 2302 | { | 2435 | this->help = strdup (help); |
| 2303 | this->help = strdup (help); | ||
| 2304 | if (!this->help) | ||
| 2305 | gui_abort ("strdup failed"); | ||
| 2306 | } | ||
| 2307 | } | 2436 | } |
| 2308 | 2437 | ||
| 2309 | ~EmacsMenuItem () | 2438 | ~EmacsMenuItem () |
| @@ -2383,22 +2512,6 @@ public: | |||
| 2383 | } | 2512 | } |
| 2384 | }; | 2513 | }; |
| 2385 | 2514 | ||
| 2386 | class EmacsPopUpMenu : public BPopUpMenu | ||
| 2387 | { | ||
| 2388 | public: | ||
| 2389 | EmacsPopUpMenu (const char *name) : BPopUpMenu (name, 0) | ||
| 2390 | { | ||
| 2391 | |||
| 2392 | } | ||
| 2393 | |||
| 2394 | void | ||
| 2395 | FrameResized (float w, float h) | ||
| 2396 | { | ||
| 2397 | Invalidate (); | ||
| 2398 | BPopUpMenu::FrameResized (w, h); | ||
| 2399 | } | ||
| 2400 | }; | ||
| 2401 | |||
| 2402 | class EmacsFontPreviewDialog : public BWindow | 2515 | class EmacsFontPreviewDialog : public BWindow |
| 2403 | { | 2516 | { |
| 2404 | BStringView text_view; | 2517 | BStringView text_view; |
| @@ -2618,13 +2731,22 @@ class EmacsFontSelectionDialog : public BWindow | |||
| 2618 | void | 2731 | void |
| 2619 | UpdateStylesForIndex (int idx) | 2732 | UpdateStylesForIndex (int idx) |
| 2620 | { | 2733 | { |
| 2621 | int n, i; | 2734 | int n, i, previous_selection; |
| 2622 | uint32 flags; | 2735 | uint32 flags; |
| 2623 | font_family family; | 2736 | font_family family; |
| 2624 | font_style style; | 2737 | font_style style; |
| 2625 | BStringItem *item; | 2738 | BStringItem *item; |
| 2739 | char *current_style; | ||
| 2626 | 2740 | ||
| 2627 | n = all_styles.CountItems (); | 2741 | n = all_styles.CountItems (); |
| 2742 | current_style = NULL; | ||
| 2743 | previous_selection = font_style_pane.CurrentSelection (); | ||
| 2744 | |||
| 2745 | if (previous_selection >= 0) | ||
| 2746 | { | ||
| 2747 | item = all_styles.ItemAt (previous_selection); | ||
| 2748 | current_style = strdup (item->Text ()); | ||
| 2749 | } | ||
| 2628 | 2750 | ||
| 2629 | font_style_pane.MakeEmpty (); | 2751 | font_style_pane.MakeEmpty (); |
| 2630 | all_styles.MakeEmpty (); | 2752 | all_styles.MakeEmpty (); |
| @@ -2640,6 +2762,10 @@ class EmacsFontSelectionDialog : public BWindow | |||
| 2640 | else | 2762 | else |
| 2641 | item = new BStringItem ("<error>"); | 2763 | item = new BStringItem ("<error>"); |
| 2642 | 2764 | ||
| 2765 | if (current_style && pending_selection_idx < 0 | ||
| 2766 | && !strcmp (current_style, style)) | ||
| 2767 | pending_selection_idx = i; | ||
| 2768 | |||
| 2643 | font_style_pane.AddItem (item); | 2769 | font_style_pane.AddItem (item); |
| 2644 | all_styles.AddItem (item); | 2770 | all_styles.AddItem (item); |
| 2645 | } | 2771 | } |
| @@ -2653,6 +2779,9 @@ class EmacsFontSelectionDialog : public BWindow | |||
| 2653 | 2779 | ||
| 2654 | pending_selection_idx = -1; | 2780 | pending_selection_idx = -1; |
| 2655 | UpdateForSelectedStyle (); | 2781 | UpdateForSelectedStyle (); |
| 2782 | |||
| 2783 | if (current_style) | ||
| 2784 | free (current_style); | ||
| 2656 | } | 2785 | } |
| 2657 | 2786 | ||
| 2658 | bool | 2787 | bool |
| @@ -3361,56 +3490,28 @@ BView_resize_to (void *view, int width, int height) | |||
| 3361 | vw->UnlockLooper (); | 3490 | vw->UnlockLooper (); |
| 3362 | } | 3491 | } |
| 3363 | 3492 | ||
| 3364 | void * | 3493 | void |
| 3365 | BCursor_create_default (void) | 3494 | be_delete_cursor (void *cursor) |
| 3366 | { | ||
| 3367 | return new BCursor (B_CURSOR_ID_SYSTEM_DEFAULT); | ||
| 3368 | } | ||
| 3369 | |||
| 3370 | void * | ||
| 3371 | BCursor_create_modeline (void) | ||
| 3372 | { | ||
| 3373 | return new BCursor (B_CURSOR_ID_CONTEXT_MENU); | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | void * | ||
| 3377 | BCursor_from_id (enum haiku_cursor cursor) | ||
| 3378 | { | ||
| 3379 | return new BCursor ((enum BCursorID) cursor); | ||
| 3380 | } | ||
| 3381 | |||
| 3382 | void * | ||
| 3383 | BCursor_create_i_beam (void) | ||
| 3384 | { | ||
| 3385 | return new BCursor (B_CURSOR_ID_I_BEAM); | ||
| 3386 | } | ||
| 3387 | |||
| 3388 | void * | ||
| 3389 | BCursor_create_progress_cursor (void) | ||
| 3390 | { | 3495 | { |
| 3391 | return new BCursor (B_CURSOR_ID_PROGRESS); | 3496 | if (cursor) |
| 3497 | delete (BCursor *) cursor; | ||
| 3392 | } | 3498 | } |
| 3393 | 3499 | ||
| 3394 | void * | 3500 | void * |
| 3395 | BCursor_create_grab (void) | 3501 | be_create_cursor_from_id (int id) |
| 3396 | { | ||
| 3397 | return new BCursor (B_CURSOR_ID_GRAB); | ||
| 3398 | } | ||
| 3399 | |||
| 3400 | void | ||
| 3401 | BCursor_delete (void *cursor) | ||
| 3402 | { | 3502 | { |
| 3403 | if (cursor) | 3503 | return new BCursor ((enum BCursorID) id); |
| 3404 | delete (BCursor *) cursor; | ||
| 3405 | } | 3504 | } |
| 3406 | 3505 | ||
| 3407 | void | 3506 | void |
| 3408 | BView_set_view_cursor (void *view, void *cursor) | 3507 | BView_set_view_cursor (void *view, void *cursor) |
| 3409 | { | 3508 | { |
| 3410 | if (!((BView *) view)->LockLooper ()) | 3509 | BView *v = (BView *) view; |
| 3510 | |||
| 3511 | if (!v->LockLooper ()) | ||
| 3411 | gui_abort ("Failed to lock view setting cursor"); | 3512 | gui_abort ("Failed to lock view setting cursor"); |
| 3412 | ((BView *) view)->SetViewCursor ((BCursor *) cursor); | 3513 | v->SetViewCursor ((BCursor *) cursor); |
| 3413 | ((BView *) view)->UnlockLooper (); | 3514 | v->UnlockLooper (); |
| 3414 | } | 3515 | } |
| 3415 | 3516 | ||
| 3416 | void | 3517 | void |
| @@ -3421,20 +3522,22 @@ BWindow_Flush (void *window) | |||
| 3421 | 3522 | ||
| 3422 | /* Make a scrollbar, attach it to VIEW's window, and return it. */ | 3523 | /* Make a scrollbar, attach it to VIEW's window, and return it. */ |
| 3423 | void * | 3524 | void * |
| 3424 | BScrollBar_make_for_view (void *view, int horizontal_p, | 3525 | be_make_scroll_bar_for_view (void *view, int horizontal_p, |
| 3425 | int x, int y, int x1, int y1, | 3526 | int x, int y, int x1, int y1) |
| 3426 | void *scroll_bar_ptr) | ||
| 3427 | { | 3527 | { |
| 3428 | EmacsScrollBar *sb = new EmacsScrollBar (x, y, x1, y1, horizontal_p); | 3528 | EmacsScrollBar *scroll_bar; |
| 3429 | BView *vw = (BView *) view; | 3529 | BView *vw = (BView *) view; |
| 3430 | BView *sv = (BView *) sb; | ||
| 3431 | 3530 | ||
| 3432 | if (!vw->LockLooper ()) | 3531 | if (!vw->LockLooper ()) |
| 3433 | gui_abort ("Failed to lock scrollbar owner"); | 3532 | gui_abort ("Failed to lock scrollbar owner"); |
| 3434 | vw->AddChild ((BView *) sb); | 3533 | |
| 3435 | sv->WindowActivated (vw->Window ()->IsActive ()); | 3534 | scroll_bar = new EmacsScrollBar (x, y, x1, y1, horizontal_p, |
| 3535 | (EmacsView *) vw); | ||
| 3536 | |||
| 3537 | vw->AddChild (scroll_bar); | ||
| 3436 | vw->UnlockLooper (); | 3538 | vw->UnlockLooper (); |
| 3437 | return sb; | 3539 | |
| 3540 | return scroll_bar; | ||
| 3438 | } | 3541 | } |
| 3439 | 3542 | ||
| 3440 | void | 3543 | void |
| @@ -3599,17 +3702,6 @@ BBitmap_import_fringe_bitmap (void *bitmap, unsigned short *bits, int wd, int h) | |||
| 3599 | } | 3702 | } |
| 3600 | } | 3703 | } |
| 3601 | 3704 | ||
| 3602 | void | ||
| 3603 | BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h) | ||
| 3604 | { | ||
| 3605 | BBitmap *bmp = (BBitmap *) bitmap; | ||
| 3606 | |||
| 3607 | if (wd % 8) | ||
| 3608 | wd += 8 - (wd % 8); | ||
| 3609 | |||
| 3610 | bmp->ImportBits (bits, wd / 8 * h, wd / 8, 0, B_GRAY1); | ||
| 3611 | } | ||
| 3612 | |||
| 3613 | /* Make a scrollbar at X, Y known to the view VIEW. */ | 3705 | /* Make a scrollbar at X, Y known to the view VIEW. */ |
| 3614 | void | 3706 | void |
| 3615 | BView_publish_scroll_bar (void *view, int x, int y, int width, int height) | 3707 | BView_publish_scroll_bar (void *view, int x, int y, int width, int height) |
| @@ -3768,7 +3860,8 @@ BView_emacs_delete (void *view) | |||
| 3768 | void * | 3860 | void * |
| 3769 | BPopUpMenu_new (const char *name) | 3861 | BPopUpMenu_new (const char *name) |
| 3770 | { | 3862 | { |
| 3771 | BPopUpMenu *menu = new EmacsPopUpMenu (name); | 3863 | BPopUpMenu *menu = new BPopUpMenu (name); |
| 3864 | |||
| 3772 | menu->SetRadioMode (0); | 3865 | menu->SetRadioMode (0); |
| 3773 | return menu; | 3866 | return menu; |
| 3774 | } | 3867 | } |
| @@ -3778,9 +3871,11 @@ BPopUpMenu_new (const char *name) | |||
| 3778 | void | 3871 | void |
| 3779 | BMenu_add_title (void *menu, const char *text) | 3872 | BMenu_add_title (void *menu, const char *text) |
| 3780 | { | 3873 | { |
| 3781 | EmacsTitleMenuItem *it = new EmacsTitleMenuItem (text); | 3874 | BMenu *be_menu = (BMenu *) menu; |
| 3782 | BMenu *mn = (BMenu *) menu; | 3875 | EmacsTitleMenuItem *it; |
| 3783 | mn->AddItem (it); | 3876 | |
| 3877 | it = new EmacsTitleMenuItem (text); | ||
| 3878 | be_menu->AddItem (it); | ||
| 3784 | } | 3879 | } |
| 3785 | 3880 | ||
| 3786 | /* Add an item to the menu MENU. */ | 3881 | /* Add an item to the menu MENU. */ |
| @@ -4522,30 +4617,6 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, | |||
| 4522 | return file_name; | 4617 | return file_name; |
| 4523 | } | 4618 | } |
| 4524 | 4619 | ||
| 4525 | /* Zoom WINDOW. */ | ||
| 4526 | void | ||
| 4527 | BWindow_zoom (void *window) | ||
| 4528 | { | ||
| 4529 | BWindow *w = (BWindow *) window; | ||
| 4530 | w->Zoom (); | ||
| 4531 | } | ||
| 4532 | |||
| 4533 | /* Make WINDOW fullscreen if FULLSCREEN_P. */ | ||
| 4534 | void | ||
| 4535 | EmacsWindow_make_fullscreen (void *window, int fullscreen_p) | ||
| 4536 | { | ||
| 4537 | EmacsWindow *w = (EmacsWindow *) window; | ||
| 4538 | w->MakeFullscreen (fullscreen_p); | ||
| 4539 | } | ||
| 4540 | |||
| 4541 | /* Unzoom (maximize) WINDOW. */ | ||
| 4542 | void | ||
| 4543 | EmacsWindow_unzoom (void *window) | ||
| 4544 | { | ||
| 4545 | EmacsWindow *w = (EmacsWindow *) window; | ||
| 4546 | w->UnZoom (); | ||
| 4547 | } | ||
| 4548 | |||
| 4549 | /* Move the pointer into MBAR and start tracking. Return whether the | 4620 | /* Move the pointer into MBAR and start tracking. Return whether the |
| 4550 | menu bar was opened correctly. */ | 4621 | menu bar was opened correctly. */ |
| 4551 | bool | 4622 | bool |
| @@ -5082,3 +5153,172 @@ BWindow_set_sticky (void *window, bool sticky) | |||
| 5082 | w->UnlockLooper (); | 5153 | w->UnlockLooper (); |
| 5083 | } | 5154 | } |
| 5084 | } | 5155 | } |
| 5156 | |||
| 5157 | status_t | ||
| 5158 | be_roster_launch (const char *type, const char *file, char **cargs, | ||
| 5159 | ptrdiff_t nargs, void *message, team_id *team_id) | ||
| 5160 | { | ||
| 5161 | BEntry entry; | ||
| 5162 | entry_ref ref; | ||
| 5163 | |||
| 5164 | if (type) | ||
| 5165 | { | ||
| 5166 | if (message) | ||
| 5167 | return be_roster->Launch (type, (BMessage *) message, | ||
| 5168 | team_id); | ||
| 5169 | |||
| 5170 | return be_roster->Launch (type, (nargs > INT_MAX | ||
| 5171 | ? INT_MAX : nargs), | ||
| 5172 | cargs, team_id); | ||
| 5173 | } | ||
| 5174 | |||
| 5175 | if (entry.SetTo (file) != B_OK) | ||
| 5176 | return B_ERROR; | ||
| 5177 | |||
| 5178 | if (entry.GetRef (&ref) != B_OK) | ||
| 5179 | return B_ERROR; | ||
| 5180 | |||
| 5181 | if (message) | ||
| 5182 | return be_roster->Launch (&ref, (BMessage *) message, | ||
| 5183 | team_id); | ||
| 5184 | |||
| 5185 | return be_roster->Launch (&ref, (nargs > INT_MAX | ||
| 5186 | ? INT_MAX : nargs), | ||
| 5187 | cargs, team_id); | ||
| 5188 | } | ||
| 5189 | |||
| 5190 | void * | ||
| 5191 | be_create_pixmap_cursor (void *bitmap, int x, int y) | ||
| 5192 | { | ||
| 5193 | BBitmap *bm; | ||
| 5194 | BCursor *cursor; | ||
| 5195 | |||
| 5196 | bm = (BBitmap *) bitmap; | ||
| 5197 | cursor = new BCursor (bm, BPoint (x, y)); | ||
| 5198 | |||
| 5199 | if (cursor->InitCheck () != B_OK) | ||
| 5200 | { | ||
| 5201 | delete cursor; | ||
| 5202 | return NULL; | ||
| 5203 | } | ||
| 5204 | |||
| 5205 | return cursor; | ||
| 5206 | } | ||
| 5207 | |||
| 5208 | void | ||
| 5209 | be_get_window_decorator_dimensions (void *window, int *left, int *top, | ||
| 5210 | int *right, int *bottom) | ||
| 5211 | { | ||
| 5212 | BWindow *wnd; | ||
| 5213 | BRect frame, window_frame; | ||
| 5214 | |||
| 5215 | wnd = (BWindow *) window; | ||
| 5216 | |||
| 5217 | if (!wnd->LockLooper ()) | ||
| 5218 | gui_abort ("Failed to lock window looper frame"); | ||
| 5219 | |||
| 5220 | frame = wnd->DecoratorFrame (); | ||
| 5221 | window_frame = wnd->Frame (); | ||
| 5222 | |||
| 5223 | if (left) | ||
| 5224 | *left = window_frame.left - frame.left; | ||
| 5225 | |||
| 5226 | if (top) | ||
| 5227 | *top = window_frame.top - frame.top; | ||
| 5228 | |||
| 5229 | if (right) | ||
| 5230 | *right = frame.right - window_frame.right; | ||
| 5231 | |||
| 5232 | if (bottom) | ||
| 5233 | *bottom = frame.bottom - window_frame.bottom; | ||
| 5234 | |||
| 5235 | wnd->UnlockLooper (); | ||
| 5236 | } | ||
| 5237 | |||
| 5238 | void | ||
| 5239 | be_get_window_decorator_frame (void *window, int *left, int *top, | ||
| 5240 | int *width, int *height) | ||
| 5241 | { | ||
| 5242 | BWindow *wnd; | ||
| 5243 | BRect frame; | ||
| 5244 | |||
| 5245 | wnd = (BWindow *) window; | ||
| 5246 | |||
| 5247 | if (!wnd->LockLooper ()) | ||
| 5248 | gui_abort ("Failed to lock window looper frame"); | ||
| 5249 | |||
| 5250 | frame = wnd->DecoratorFrame (); | ||
| 5251 | |||
| 5252 | *left = frame.left; | ||
| 5253 | *top = frame.top; | ||
| 5254 | *width = BE_RECT_WIDTH (frame); | ||
| 5255 | *height = BE_RECT_HEIGHT (frame); | ||
| 5256 | |||
| 5257 | wnd->UnlockLooper (); | ||
| 5258 | } | ||
| 5259 | |||
| 5260 | /* Request that a MOVE_EVENT be sent for WINDOW. This is so that | ||
| 5261 | frame offsets can be updated after a frame parameter affecting | ||
| 5262 | decorators changes. Sending an event instead of updating the | ||
| 5263 | offsets directly avoids race conditions where events with older | ||
| 5264 | information are received after the update happens. */ | ||
| 5265 | void | ||
| 5266 | be_send_move_frame_event (void *window) | ||
| 5267 | { | ||
| 5268 | BWindow *wnd = (BWindow *) window; | ||
| 5269 | BMessenger msg (wnd); | ||
| 5270 | |||
| 5271 | msg.SendMessage (SEND_MOVE_FRAME_EVENT); | ||
| 5272 | } | ||
| 5273 | |||
| 5274 | void | ||
| 5275 | be_lock_window (void *window) | ||
| 5276 | { | ||
| 5277 | BWindow *wnd = (BWindow *) window; | ||
| 5278 | |||
| 5279 | if (!wnd->LockLooper ()) | ||
| 5280 | gui_abort ("Failed to lock window looper"); | ||
| 5281 | } | ||
| 5282 | |||
| 5283 | void | ||
| 5284 | be_unlock_window (void *window) | ||
| 5285 | { | ||
| 5286 | BWindow *wnd = (BWindow *) window; | ||
| 5287 | |||
| 5288 | wnd->UnlockLooper (); | ||
| 5289 | } | ||
| 5290 | |||
| 5291 | void | ||
| 5292 | be_set_window_fullscreen_mode (void *window, enum haiku_fullscreen_mode mode) | ||
| 5293 | { | ||
| 5294 | EmacsWindow *w = (EmacsWindow *) window; | ||
| 5295 | |||
| 5296 | if (!w->LockLooper ()) | ||
| 5297 | gui_abort ("Failed to lock window to set fullscreen mode"); | ||
| 5298 | |||
| 5299 | w->SetFullscreen (mode); | ||
| 5300 | w->UnlockLooper (); | ||
| 5301 | } | ||
| 5302 | |||
| 5303 | bool | ||
| 5304 | be_get_explicit_workarea (int *x, int *y, int *width, int *height) | ||
| 5305 | { | ||
| 5306 | BDeskbar deskbar; | ||
| 5307 | BRect zoom; | ||
| 5308 | deskbar_location location; | ||
| 5309 | |||
| 5310 | location = deskbar.Location (); | ||
| 5311 | |||
| 5312 | if (location != B_DESKBAR_TOP | ||
| 5313 | && location != B_DESKBAR_BOTTOM) | ||
| 5314 | return false; | ||
| 5315 | |||
| 5316 | zoom = get_zoom_rect (NULL); | ||
| 5317 | |||
| 5318 | *x = zoom.left; | ||
| 5319 | *y = zoom.top; | ||
| 5320 | *width = BE_RECT_WIDTH (zoom); | ||
| 5321 | *height = BE_RECT_HEIGHT (zoom); | ||
| 5322 | |||
| 5323 | return true; | ||
| 5324 | } | ||
diff --git a/src/haiku_support.h b/src/haiku_support.h index 5ded9300d8a..7f8d471b650 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h | |||
| @@ -38,7 +38,21 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 38 | 38 | ||
| 39 | enum haiku_cursor | 39 | enum haiku_cursor |
| 40 | { | 40 | { |
| 41 | CURSOR_ID_SYSTEM_DEFAULT = 1, | ||
| 42 | CURSOR_ID_CONTEXT_MENU = 3, | ||
| 43 | CURSOR_ID_COPY = 4, | ||
| 44 | CURSOR_ID_CREATE_LINK = 29, | ||
| 45 | CURSOR_ID_CROSS_HAIR = 5, | ||
| 46 | CURSOR_ID_FOLLOW_LINK = 6, | ||
| 47 | CURSOR_ID_GRAB = 7, | ||
| 48 | CURSOR_ID_GRABBING = 8, | ||
| 49 | CURSOR_ID_HELP = 9, | ||
| 50 | CURSOR_ID_I_BEAM = 2, | ||
| 51 | CURSOR_ID_I_BEAM_HORIZONTAL = 10, | ||
| 52 | CURSOR_ID_MOVE = 11, | ||
| 41 | CURSOR_ID_NO_CURSOR = 12, | 53 | CURSOR_ID_NO_CURSOR = 12, |
| 54 | CURSOR_ID_NOT_ALLOWED = 13, | ||
| 55 | CURSOR_ID_PROGRESS = 14, | ||
| 42 | CURSOR_ID_RESIZE_NORTH = 15, | 56 | CURSOR_ID_RESIZE_NORTH = 15, |
| 43 | CURSOR_ID_RESIZE_EAST = 16, | 57 | CURSOR_ID_RESIZE_EAST = 16, |
| 44 | CURSOR_ID_RESIZE_SOUTH = 17, | 58 | CURSOR_ID_RESIZE_SOUTH = 17, |
| @@ -50,7 +64,9 @@ enum haiku_cursor | |||
| 50 | CURSOR_ID_RESIZE_NORTH_SOUTH = 23, | 64 | CURSOR_ID_RESIZE_NORTH_SOUTH = 23, |
| 51 | CURSOR_ID_RESIZE_EAST_WEST = 24, | 65 | CURSOR_ID_RESIZE_EAST_WEST = 24, |
| 52 | CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST = 25, | 66 | CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST = 25, |
| 53 | CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST = 26 | 67 | CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST = 26, |
| 68 | CURSOR_ID_ZOOM_IN = 27, | ||
| 69 | CURSOR_ID_ZOOM_OUT = 28 | ||
| 54 | }; | 70 | }; |
| 55 | 71 | ||
| 56 | enum haiku_z_group | 72 | enum haiku_z_group |
| @@ -96,9 +112,15 @@ enum haiku_event_type | |||
| 96 | DRAG_AND_DROP_EVENT, | 112 | DRAG_AND_DROP_EVENT, |
| 97 | APP_QUIT_REQUESTED_EVENT, | 113 | APP_QUIT_REQUESTED_EVENT, |
| 98 | DUMMY_EVENT, | 114 | DUMMY_EVENT, |
| 99 | MENU_BAR_LEFT | 115 | SCREEN_CHANGED_EVENT, |
| 116 | MENU_BAR_LEFT, | ||
| 100 | }; | 117 | }; |
| 101 | 118 | ||
| 119 | struct haiku_screen_changed_event | ||
| 120 | { | ||
| 121 | bigtime_t when; | ||
| 122 | }; | ||
| 123 | |||
| 102 | struct haiku_quit_requested_event | 124 | struct haiku_quit_requested_event |
| 103 | { | 125 | { |
| 104 | void *window; | 126 | void *window; |
| @@ -107,8 +129,8 @@ struct haiku_quit_requested_event | |||
| 107 | struct haiku_resize_event | 129 | struct haiku_resize_event |
| 108 | { | 130 | { |
| 109 | void *window; | 131 | void *window; |
| 110 | float px_heightf; | 132 | float width; |
| 111 | float px_widthf; | 133 | float height; |
| 112 | }; | 134 | }; |
| 113 | 135 | ||
| 114 | struct haiku_expose_event | 136 | struct haiku_expose_event |
| @@ -187,6 +209,7 @@ struct haiku_menu_bar_click_event | |||
| 187 | struct haiku_button_event | 209 | struct haiku_button_event |
| 188 | { | 210 | { |
| 189 | void *window; | 211 | void *window; |
| 212 | void *scroll_bar; | ||
| 190 | int btn_no; | 213 | int btn_no; |
| 191 | int modifiers; | 214 | int modifiers; |
| 192 | int x; | 215 | int x; |
| @@ -203,8 +226,9 @@ struct haiku_iconification_event | |||
| 203 | struct haiku_move_event | 226 | struct haiku_move_event |
| 204 | { | 227 | { |
| 205 | void *window; | 228 | void *window; |
| 206 | int x; | 229 | int x, y; |
| 207 | int y; | 230 | int decorator_width; |
| 231 | int decorator_height; | ||
| 208 | }; | 232 | }; |
| 209 | 233 | ||
| 210 | struct haiku_wheel_move_event | 234 | struct haiku_wheel_move_event |
| @@ -232,7 +256,7 @@ struct haiku_menu_bar_help_event | |||
| 232 | struct haiku_zoom_event | 256 | struct haiku_zoom_event |
| 233 | { | 257 | { |
| 234 | void *window; | 258 | void *window; |
| 235 | bool zoomed; | 259 | int fullscreen_mode; |
| 236 | }; | 260 | }; |
| 237 | 261 | ||
| 238 | enum haiku_font_specification | 262 | enum haiku_font_specification |
| @@ -299,6 +323,15 @@ enum haiku_font_weight | |||
| 299 | HAIKU_MEDIUM = 2000, | 323 | HAIKU_MEDIUM = 2000, |
| 300 | }; | 324 | }; |
| 301 | 325 | ||
| 326 | enum haiku_fullscreen_mode | ||
| 327 | { | ||
| 328 | FULLSCREEN_MODE_NONE, | ||
| 329 | FULLSCREEN_MODE_WIDTH, | ||
| 330 | FULLSCREEN_MODE_HEIGHT, | ||
| 331 | FULLSCREEN_MODE_BOTH, | ||
| 332 | FULLSCREEN_MODE_MAXIMIZED, | ||
| 333 | }; | ||
| 334 | |||
| 302 | struct haiku_font_pattern | 335 | struct haiku_font_pattern |
| 303 | { | 336 | { |
| 304 | /* Bitmask indicating which fields are set. */ | 337 | /* Bitmask indicating which fields are set. */ |
| @@ -421,32 +454,14 @@ struct haiku_session_manager_reply | |||
| 421 | dimensions of a BRect, instead of relying on the broken Width and | 454 | dimensions of a BRect, instead of relying on the broken Width and |
| 422 | Height functions. */ | 455 | Height functions. */ |
| 423 | 456 | ||
| 424 | #define BE_RECT_HEIGHT(rect) (ceil (((rect).bottom - (rect).top) + 1)) | 457 | #define BE_RECT_HEIGHT(rect) (ceil (((rect).bottom - (rect).top) + 1)) |
| 425 | #define BE_RECT_WIDTH(rect) (ceil (((rect).right - (rect).left) + 1)) | 458 | #define BE_RECT_WIDTH(rect) (ceil (((rect).right - (rect).left) + 1)) |
| 426 | #endif /* __cplusplus */ | 459 | #endif /* __cplusplus */ |
| 427 | 460 | ||
| 428 | /* C++ code cannot include lisp.h, but file dialogs need to be able | ||
| 429 | to bind to the specpdl and handle quitting correctly. */ | ||
| 430 | |||
| 431 | #ifdef __cplusplus | ||
| 432 | #if SIZE_MAX > 0xffffffff | ||
| 433 | #define WRAP_SPECPDL_REF 1 | ||
| 434 | #endif | ||
| 435 | #ifdef WRAP_SPECPDL_REF | ||
| 436 | typedef struct { ptrdiff_t bytes; } specpdl_ref; | ||
| 437 | #else | ||
| 438 | typedef ptrdiff_t specpdl_ref; | ||
| 439 | #endif | ||
| 440 | |||
| 441 | #else | ||
| 442 | #include "lisp.h" | ||
| 443 | #endif | ||
| 444 | |||
| 445 | #ifdef __cplusplus | 461 | #ifdef __cplusplus |
| 446 | extern "C" | 462 | extern "C" |
| 447 | { | 463 | { |
| 448 | #endif | 464 | #endif |
| 449 | #include <pthread.h> | ||
| 450 | #include <OS.h> | 465 | #include <OS.h> |
| 451 | 466 | ||
| 452 | #ifdef __cplusplus | 467 | #ifdef __cplusplus |
| @@ -477,6 +492,8 @@ extern void hsl_color_rgb (double, double, double, uint32_t *); | |||
| 477 | extern void *BBitmap_new (int, int, int); | 492 | extern void *BBitmap_new (int, int, int); |
| 478 | extern void *BBitmap_data (void *); | 493 | extern void *BBitmap_data (void *); |
| 479 | extern int BBitmap_convert (void *, void **); | 494 | extern int BBitmap_convert (void *, void **); |
| 495 | extern void be_draw_cross_on_pixmap (void *, int, int, int, int, | ||
| 496 | uint32_t); | ||
| 480 | 497 | ||
| 481 | extern void BBitmap_free (void *); | 498 | extern void BBitmap_free (void *); |
| 482 | 499 | ||
| @@ -496,7 +513,6 @@ extern void BWindow_center_on_screen (void *); | |||
| 496 | extern void BWindow_change_decoration (void *, int); | 513 | extern void BWindow_change_decoration (void *, int); |
| 497 | extern void BWindow_set_tooltip_decoration (void *); | 514 | extern void BWindow_set_tooltip_decoration (void *); |
| 498 | extern void BWindow_set_avoid_focus (void *, int); | 515 | extern void BWindow_set_avoid_focus (void *, int); |
| 499 | extern void BWindow_zoom (void *); | ||
| 500 | extern void BWindow_set_size_alignment (void *, int, int); | 516 | extern void BWindow_set_size_alignment (void *, int, int); |
| 501 | extern void BWindow_sync (void *); | 517 | extern void BWindow_sync (void *); |
| 502 | extern void BWindow_send_behind (void *, void *); | 518 | extern void BWindow_send_behind (void *, void *); |
| @@ -541,6 +557,8 @@ extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int, | |||
| 541 | extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); | 557 | extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); |
| 542 | extern void BView_DrawMask (void *, void *, int, int, int, int, int, int, | 558 | extern void BView_DrawMask (void *, void *, int, int, int, int, int, int, |
| 543 | int, int, uint32_t); | 559 | int, int, uint32_t); |
| 560 | extern void BView_DrawBitmapTiled (void *, void *, int, int, | ||
| 561 | int, int, int, int, int, int); | ||
| 544 | 562 | ||
| 545 | extern void BView_resize_to (void *, int, int); | 563 | extern void BView_resize_to (void *, int, int); |
| 546 | extern void BView_set_view_cursor (void *, void *); | 564 | extern void BView_set_view_cursor (void *, void *); |
| @@ -554,15 +572,11 @@ extern void be_get_display_resolution (double *, double *); | |||
| 554 | extern void be_get_screen_dimensions (int *, int *); | 572 | extern void be_get_screen_dimensions (int *, int *); |
| 555 | 573 | ||
| 556 | /* Functions for creating and freeing cursors. */ | 574 | /* Functions for creating and freeing cursors. */ |
| 557 | extern void *BCursor_create_default (void); | 575 | extern void *be_create_cursor_from_id (int); |
| 558 | extern void *BCursor_from_id (enum haiku_cursor); | 576 | extern void *be_create_pixmap_cursor (void *, int, int); |
| 559 | extern void *BCursor_create_modeline (void); | 577 | extern void be_delete_cursor (void *); |
| 560 | extern void *BCursor_create_i_beam (void); | 578 | |
| 561 | extern void *BCursor_create_progress_cursor (void); | 579 | extern void *be_make_scroll_bar_for_view (void *, int, int, int, int, int); |
| 562 | extern void *BCursor_create_grab (void); | ||
| 563 | extern void BCursor_delete (void *); | ||
| 564 | |||
| 565 | extern void *BScrollBar_make_for_view (void *, int, int, int, int, int, void *); | ||
| 566 | extern void BScrollBar_delete (void *); | 580 | extern void BScrollBar_delete (void *); |
| 567 | extern int BScrollBar_default_size (int); | 581 | extern int BScrollBar_default_size (int); |
| 568 | 582 | ||
| @@ -570,9 +584,7 @@ extern void BView_invalidate (void *); | |||
| 570 | extern void BView_draw_lock (void *, bool, int, int, int, int); | 584 | extern void BView_draw_lock (void *, bool, int, int, int, int); |
| 571 | extern void BView_invalidate_region (void *, int, int, int, int); | 585 | extern void BView_invalidate_region (void *, int, int, int, int); |
| 572 | extern void BView_draw_unlock (void *); | 586 | extern void BView_draw_unlock (void *); |
| 573 | |||
| 574 | extern void BBitmap_import_fringe_bitmap (void *, unsigned short *, int, int); | 587 | extern void BBitmap_import_fringe_bitmap (void *, unsigned short *, int, int); |
| 575 | extern void BBitmap_import_mono_bits (void *, void *, int, int); | ||
| 576 | 588 | ||
| 577 | extern void haiku_font_pattern_free (struct haiku_font_pattern *); | 589 | extern void haiku_font_pattern_free (struct haiku_font_pattern *); |
| 578 | 590 | ||
| @@ -628,8 +640,6 @@ extern void BAlert_delete (void *); | |||
| 628 | extern void EmacsWindow_parent_to (void *, void *); | 640 | extern void EmacsWindow_parent_to (void *, void *); |
| 629 | extern void EmacsWindow_unparent (void *); | 641 | extern void EmacsWindow_unparent (void *); |
| 630 | extern void EmacsWindow_move_weak_child (void *, void *, int, int); | 642 | extern void EmacsWindow_move_weak_child (void *, void *, int, int); |
| 631 | extern void EmacsWindow_make_fullscreen (void *, int); | ||
| 632 | extern void EmacsWindow_unzoom (void *); | ||
| 633 | 643 | ||
| 634 | extern void be_get_version_string (char *, int); | 644 | extern void be_get_version_string (char *, int); |
| 635 | extern int be_get_display_planes (void); | 645 | extern int be_get_display_planes (void); |
| @@ -690,6 +700,16 @@ extern bool be_select_font (void (*) (void), bool (*) (void), | |||
| 690 | int *, bool, int, int, int); | 700 | int *, bool, int, int, int); |
| 691 | 701 | ||
| 692 | extern int be_find_font_indices (struct haiku_font_pattern *, int *, int *); | 702 | extern int be_find_font_indices (struct haiku_font_pattern *, int *, int *); |
| 703 | extern status_t be_roster_launch (const char *, const char *, char **, | ||
| 704 | ptrdiff_t, void *, team_id *); | ||
| 705 | extern void be_get_window_decorator_dimensions (void *, int *, int *, int *, int *); | ||
| 706 | extern void be_get_window_decorator_frame (void *, int *, int *, int *, int *); | ||
| 707 | extern void be_send_move_frame_event (void *); | ||
| 708 | extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode); | ||
| 709 | |||
| 710 | extern void be_lock_window (void *); | ||
| 711 | extern void be_unlock_window (void *); | ||
| 712 | extern bool be_get_explicit_workarea (int *, int *, int *, int *); | ||
| 693 | #ifdef __cplusplus | 713 | #ifdef __cplusplus |
| 694 | } | 714 | } |
| 695 | 715 | ||
diff --git a/src/haikufns.c b/src/haikufns.c index 8596317de25..b79443203ff 100644 --- a/src/haikufns.c +++ b/src/haikufns.c | |||
| @@ -34,6 +34,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 34 | #include "haiku_support.h" | 34 | #include "haiku_support.h" |
| 35 | #include "termhooks.h" | 35 | #include "termhooks.h" |
| 36 | 36 | ||
| 37 | #include "bitmaps/leftptr.xbm" | ||
| 38 | #include "bitmaps/leftpmsk.xbm" | ||
| 39 | |||
| 37 | #include <stdlib.h> | 40 | #include <stdlib.h> |
| 38 | 41 | ||
| 39 | #include <kernel/OS.h> | 42 | #include <kernel/OS.h> |
| @@ -47,6 +50,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 47 | /* The frame of the currently visible tooltip. */ | 50 | /* The frame of the currently visible tooltip. */ |
| 48 | Lisp_Object tip_frame; | 51 | Lisp_Object tip_frame; |
| 49 | 52 | ||
| 53 | /* The X and Y deltas of the last call to `x-show-tip'. */ | ||
| 54 | Lisp_Object tip_dx, tip_dy; | ||
| 55 | |||
| 50 | /* The window-system window corresponding to the frame of the | 56 | /* The window-system window corresponding to the frame of the |
| 51 | currently visible tooltip. */ | 57 | currently visible tooltip. */ |
| 52 | static Window tip_window; | 58 | static Window tip_window; |
| @@ -93,7 +99,7 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo, | |||
| 93 | Lisp_Object value | 99 | Lisp_Object value |
| 94 | = gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls, | 100 | = gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls, |
| 95 | RES_TYPE_NUMBER); | 101 | RES_TYPE_NUMBER); |
| 96 | if (! EQ (value, Qunbound)) | 102 | if (! BASE_EQ (value, Qunbound)) |
| 97 | parms = Fcons (Fcons (r[i].tem, value), parms); | 103 | parms = Fcons (Fcons (r[i].tem, value), parms); |
| 98 | } | 104 | } |
| 99 | } | 105 | } |
| @@ -101,6 +107,22 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo, | |||
| 101 | return parms; | 107 | return parms; |
| 102 | } | 108 | } |
| 103 | 109 | ||
| 110 | /* Update the left and top offsets of F after its decorators | ||
| 111 | change. */ | ||
| 112 | static void | ||
| 113 | haiku_update_after_decoration_change (struct frame *f) | ||
| 114 | { | ||
| 115 | /* Don't reset offsets during initial frame creation, since the | ||
| 116 | contents of f->left_pos and f->top_pos won't be applied to the | ||
| 117 | window until `x-create-frame' finishes, so setting them here will | ||
| 118 | overwrite the offsets that the window should be moved to. */ | ||
| 119 | |||
| 120 | if (!FRAME_OUTPUT_DATA (f)->configury_done) | ||
| 121 | return; | ||
| 122 | |||
| 123 | be_send_move_frame_event (FRAME_HAIKU_WINDOW (f)); | ||
| 124 | } | ||
| 125 | |||
| 104 | void | 126 | void |
| 105 | haiku_change_tool_bar_height (struct frame *f, int height) | 127 | haiku_change_tool_bar_height (struct frame *f, int height) |
| 106 | { | 128 | { |
| @@ -249,6 +271,22 @@ haiku_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) | |||
| 249 | haiku_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); | 271 | haiku_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); |
| 250 | } | 272 | } |
| 251 | 273 | ||
| 274 | void | ||
| 275 | gamma_correct (struct frame *f, Emacs_Color *color) | ||
| 276 | { | ||
| 277 | if (f->gamma) | ||
| 278 | { | ||
| 279 | color->red = (pow (color->red / 65535.0, f->gamma) | ||
| 280 | * 65535.0 + 0.5); | ||
| 281 | color->green = (pow (color->green / 65535.0, f->gamma) | ||
| 282 | * 65535.0 + 0.5); | ||
| 283 | color->blue = (pow (color->blue / 65535.0, f->gamma) | ||
| 284 | * 65535.0 + 0.5); | ||
| 285 | color->pixel = RGB_TO_ULONG (color->red / 256, | ||
| 286 | color->green / 256, | ||
| 287 | color->blue / 256); | ||
| 288 | } | ||
| 289 | } | ||
| 252 | 290 | ||
| 253 | int | 291 | int |
| 254 | haiku_get_color (const char *name, Emacs_Color *color) | 292 | haiku_get_color (const char *name, Emacs_Color *color) |
| @@ -323,12 +361,12 @@ haiku_display_info_for_name (Lisp_Object name) | |||
| 323 | { | 361 | { |
| 324 | CHECK_STRING (name); | 362 | CHECK_STRING (name); |
| 325 | 363 | ||
| 326 | if (!NILP (Fstring_equal (name, build_string ("be")))) | 364 | if (!strcmp (SSDATA (name), "be")) |
| 327 | { | 365 | { |
| 328 | if (!x_display_list) | 366 | if (x_display_list) |
| 329 | return x_display_list; | 367 | return x_display_list; |
| 330 | 368 | ||
| 331 | error ("Haiku windowing not initialized"); | 369 | return haiku_term_init (); |
| 332 | } | 370 | } |
| 333 | 371 | ||
| 334 | error ("Haiku displays can only be named \"be\""); | 372 | error ("Haiku displays can only be named \"be\""); |
| @@ -498,8 +536,12 @@ haiku_set_z_group (struct frame *f, Lisp_Object new_value, | |||
| 498 | rc = 0; | 536 | rc = 0; |
| 499 | 537 | ||
| 500 | unblock_input (); | 538 | unblock_input (); |
| 539 | |||
| 501 | if (!rc) | 540 | if (!rc) |
| 502 | error ("Invalid z-group specification"); | 541 | error ("Invalid z-group specification"); |
| 542 | |||
| 543 | /* Setting the Z-group can change the frame's decorator. */ | ||
| 544 | haiku_update_after_decoration_change (f); | ||
| 503 | } | 545 | } |
| 504 | 546 | ||
| 505 | static void | 547 | static void |
| @@ -578,37 +620,34 @@ unwind_create_tip_frame (Lisp_Object frame) | |||
| 578 | tip_frame = Qnil; | 620 | tip_frame = Qnil; |
| 579 | } | 621 | } |
| 580 | 622 | ||
| 581 | static void | 623 | static unsigned long |
| 582 | haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 624 | haiku_decode_color (struct frame *f, Lisp_Object color_name) |
| 583 | { | 625 | { |
| 584 | struct haiku_output *output = FRAME_OUTPUT_DATA (f); | 626 | Emacs_Color cdef; |
| 585 | unsigned long old_fg; | ||
| 586 | 627 | ||
| 587 | Emacs_Color color; | 628 | CHECK_STRING (color_name); |
| 588 | 629 | ||
| 589 | if (haiku_get_color (SSDATA (arg), &color)) | 630 | if (!haiku_get_color (SSDATA (color_name), &cdef)) |
| 590 | { | 631 | return cdef.pixel; |
| 591 | store_frame_param (f, Qforeground_color, oldval); | 632 | |
| 592 | unblock_input (); | 633 | signal_error ("Undefined color", color_name); |
| 593 | error ("Bad color"); | 634 | } |
| 594 | } | ||
| 595 | 635 | ||
| 636 | static void | ||
| 637 | haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | ||
| 638 | { | ||
| 639 | struct haiku_output *output; | ||
| 640 | unsigned long fg, old_fg; | ||
| 641 | |||
| 642 | fg = haiku_decode_color (f, arg); | ||
| 596 | old_fg = FRAME_FOREGROUND_PIXEL (f); | 643 | old_fg = FRAME_FOREGROUND_PIXEL (f); |
| 597 | FRAME_FOREGROUND_PIXEL (f) = color.pixel; | 644 | FRAME_FOREGROUND_PIXEL (f) = fg; |
| 645 | output = FRAME_OUTPUT_DATA (f); | ||
| 598 | 646 | ||
| 599 | if (FRAME_HAIKU_WINDOW (f)) | 647 | if (FRAME_HAIKU_WINDOW (f)) |
| 600 | { | 648 | { |
| 601 | |||
| 602 | block_input (); | ||
| 603 | if (output->cursor_color.pixel == old_fg) | 649 | if (output->cursor_color.pixel == old_fg) |
| 604 | { | 650 | haiku_query_color (fg, &output->cursor_color); |
| 605 | output->cursor_color.pixel = old_fg; | ||
| 606 | output->cursor_color.red = RED_FROM_ULONG (old_fg); | ||
| 607 | output->cursor_color.green = GREEN_FROM_ULONG (old_fg); | ||
| 608 | output->cursor_color.blue = BLUE_FROM_ULONG (old_fg); | ||
| 609 | } | ||
| 610 | |||
| 611 | unblock_input (); | ||
| 612 | 651 | ||
| 613 | update_face_from_frame_parameter (f, Qforeground_color, arg); | 652 | update_face_from_frame_parameter (f, Qforeground_color, arg); |
| 614 | 653 | ||
| @@ -648,7 +687,7 @@ haiku_create_frame (Lisp_Object parms) | |||
| 648 | 687 | ||
| 649 | display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, | 688 | display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, |
| 650 | RES_TYPE_STRING); | 689 | RES_TYPE_STRING); |
| 651 | if (EQ (display, Qunbound)) | 690 | if (BASE_EQ (display, Qunbound)) |
| 652 | display = Qnil; | 691 | display = Qnil; |
| 653 | dpyinfo = check_haiku_display_info (display); | 692 | dpyinfo = check_haiku_display_info (display); |
| 654 | kb = dpyinfo->terminal->kboard; | 693 | kb = dpyinfo->terminal->kboard; |
| @@ -659,7 +698,7 @@ haiku_create_frame (Lisp_Object parms) | |||
| 659 | name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0, | 698 | name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0, |
| 660 | RES_TYPE_STRING); | 699 | RES_TYPE_STRING); |
| 661 | if (!STRINGP (name) | 700 | if (!STRINGP (name) |
| 662 | && ! EQ (name, Qunbound) | 701 | && ! BASE_EQ (name, Qunbound) |
| 663 | && ! NILP (name)) | 702 | && ! NILP (name)) |
| 664 | error ("Invalid frame name--not a string or nil"); | 703 | error ("Invalid frame name--not a string or nil"); |
| 665 | 704 | ||
| @@ -707,7 +746,7 @@ haiku_create_frame (Lisp_Object parms) | |||
| 707 | 746 | ||
| 708 | /* Set the name; the functions to which we pass f expect the name to | 747 | /* Set the name; the functions to which we pass f expect the name to |
| 709 | be set. */ | 748 | be set. */ |
| 710 | if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name)) | 749 | if (BASE_EQ (name, Qunbound) || NILP (name) || ! STRINGP (name)) |
| 711 | { | 750 | { |
| 712 | fset_name (f, Vinvocation_name); | 751 | fset_name (f, Vinvocation_name); |
| 713 | f->explicit_name = 0; | 752 | f->explicit_name = 0; |
| @@ -763,6 +802,8 @@ haiku_create_frame (Lisp_Object parms) | |||
| 763 | "foreground", "Foreground", RES_TYPE_STRING); | 802 | "foreground", "Foreground", RES_TYPE_STRING); |
| 764 | gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), | 803 | gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), |
| 765 | "background", "Background", RES_TYPE_STRING); | 804 | "background", "Background", RES_TYPE_STRING); |
| 805 | gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"), | ||
| 806 | "pointerColor", "Foreground", RES_TYPE_STRING); | ||
| 766 | gui_default_parameter (f, parms, Qline_spacing, Qnil, | 807 | gui_default_parameter (f, parms, Qline_spacing, Qnil, |
| 767 | "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); | 808 | "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); |
| 768 | gui_default_parameter (f, parms, Qleft_fringe, Qnil, | 809 | gui_default_parameter (f, parms, Qleft_fringe, Qnil, |
| @@ -818,36 +859,11 @@ haiku_create_frame (Lisp_Object parms) | |||
| 818 | 859 | ||
| 819 | tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, | 860 | tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, |
| 820 | RES_TYPE_BOOLEAN); | 861 | RES_TYPE_BOOLEAN); |
| 821 | f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem)); | 862 | f->no_split = minibuffer_only || (!BASE_EQ (tem, Qunbound) && !NILP (tem)); |
| 822 | |||
| 823 | block_input (); | ||
| 824 | #define ASSIGN_CURSOR(cursor) \ | ||
| 825 | (FRAME_OUTPUT_DATA (f)->cursor = dpyinfo->cursor) | ||
| 826 | |||
| 827 | ASSIGN_CURSOR (text_cursor); | ||
| 828 | ASSIGN_CURSOR (nontext_cursor); | ||
| 829 | ASSIGN_CURSOR (modeline_cursor); | ||
| 830 | ASSIGN_CURSOR (hand_cursor); | ||
| 831 | ASSIGN_CURSOR (hourglass_cursor); | ||
| 832 | ASSIGN_CURSOR (horizontal_drag_cursor); | ||
| 833 | ASSIGN_CURSOR (vertical_drag_cursor); | ||
| 834 | ASSIGN_CURSOR (left_edge_cursor); | ||
| 835 | ASSIGN_CURSOR (top_left_corner_cursor); | ||
| 836 | ASSIGN_CURSOR (top_edge_cursor); | ||
| 837 | ASSIGN_CURSOR (top_right_corner_cursor); | ||
| 838 | ASSIGN_CURSOR (right_edge_cursor); | ||
| 839 | ASSIGN_CURSOR (bottom_right_corner_cursor); | ||
| 840 | ASSIGN_CURSOR (bottom_edge_cursor); | ||
| 841 | ASSIGN_CURSOR (bottom_left_corner_cursor); | ||
| 842 | ASSIGN_CURSOR (no_cursor); | ||
| 843 | |||
| 844 | FRAME_OUTPUT_DATA (f)->current_cursor = dpyinfo->text_cursor; | ||
| 845 | #undef ASSIGN_CURSOR | ||
| 846 | 863 | ||
| 847 | f->terminal->reference_count++; | 864 | f->terminal->reference_count++; |
| 848 | 865 | ||
| 849 | FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); | 866 | FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); |
| 850 | unblock_input (); | ||
| 851 | 867 | ||
| 852 | if (!FRAME_OUTPUT_DATA (f)->window) | 868 | if (!FRAME_OUTPUT_DATA (f)->window) |
| 853 | xsignal1 (Qerror, build_unibyte_string ("Could not create window")); | 869 | xsignal1 (Qerror, build_unibyte_string ("Could not create window")); |
| @@ -859,10 +875,11 @@ haiku_create_frame (Lisp_Object parms) | |||
| 859 | 875 | ||
| 860 | Vframe_list = Fcons (frame, Vframe_list); | 876 | Vframe_list = Fcons (frame, Vframe_list); |
| 861 | 877 | ||
| 862 | Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, | 878 | Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, |
| 879 | Qparent_frame, NULL, NULL, | ||
| 863 | RES_TYPE_SYMBOL); | 880 | RES_TYPE_SYMBOL); |
| 864 | 881 | ||
| 865 | if (EQ (parent_frame, Qunbound) | 882 | if (BASE_EQ (parent_frame, Qunbound) |
| 866 | || NILP (parent_frame) | 883 | || NILP (parent_frame) |
| 867 | || !FRAMEP (parent_frame) | 884 | || !FRAMEP (parent_frame) |
| 868 | || !FRAME_LIVE_P (XFRAME (parent_frame))) | 885 | || !FRAME_LIVE_P (XFRAME (parent_frame))) |
| @@ -916,7 +933,7 @@ haiku_create_frame (Lisp_Object parms) | |||
| 916 | 933 | ||
| 917 | visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, | 934 | visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, |
| 918 | RES_TYPE_SYMBOL); | 935 | RES_TYPE_SYMBOL); |
| 919 | if (EQ (visibility, Qunbound)) | 936 | if (BASE_EQ (visibility, Qunbound)) |
| 920 | visibility = Qt; | 937 | visibility = Qt; |
| 921 | if (EQ (visibility, Qicon)) | 938 | if (EQ (visibility, Qicon)) |
| 922 | haiku_iconify_frame (f); | 939 | haiku_iconify_frame (f); |
| @@ -989,7 +1006,7 @@ haiku_create_tip_frame (Lisp_Object parms) | |||
| 989 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 1006 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 990 | RES_TYPE_STRING); | 1007 | RES_TYPE_STRING); |
| 991 | if (!STRINGP (name) | 1008 | if (!STRINGP (name) |
| 992 | && !EQ (name, Qunbound) | 1009 | && !BASE_EQ (name, Qunbound) |
| 993 | && !NILP (name)) | 1010 | && !NILP (name)) |
| 994 | error ("Invalid frame name--not a string or nil"); | 1011 | error ("Invalid frame name--not a string or nil"); |
| 995 | 1012 | ||
| @@ -1018,7 +1035,7 @@ haiku_create_tip_frame (Lisp_Object parms) | |||
| 1018 | 1035 | ||
| 1019 | /* Set the name; the functions to which we pass f expect the name to | 1036 | /* Set the name; the functions to which we pass f expect the name to |
| 1020 | be set. */ | 1037 | be set. */ |
| 1021 | if (EQ (name, Qunbound) || NILP (name)) | 1038 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 1022 | f->explicit_name = false; | 1039 | f->explicit_name = false; |
| 1023 | else | 1040 | else |
| 1024 | { | 1041 | { |
| @@ -1056,7 +1073,7 @@ haiku_create_tip_frame (Lisp_Object parms) | |||
| 1056 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 1073 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 1057 | "internalBorder", "internalBorder", | 1074 | "internalBorder", "internalBorder", |
| 1058 | RES_TYPE_NUMBER); | 1075 | RES_TYPE_NUMBER); |
| 1059 | if (! EQ (value, Qunbound)) | 1076 | if (! BASE_EQ (value, Qunbound)) |
| 1060 | parms = Fcons (Fcons (Qinternal_border_width, value), | 1077 | parms = Fcons (Fcons (Qinternal_border_width, value), |
| 1061 | parms); | 1078 | parms); |
| 1062 | } | 1079 | } |
| @@ -1076,7 +1093,10 @@ haiku_create_tip_frame (Lisp_Object parms) | |||
| 1076 | 1093 | ||
| 1077 | gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), | 1094 | gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), |
| 1078 | "background", "Background", RES_TYPE_STRING); | 1095 | "background", "Background", RES_TYPE_STRING); |
| 1079 | gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), | 1096 | |
| 1097 | /* FIXME: is there a better method to tell Emacs to not recolor the | ||
| 1098 | cursors other than setting the color to a special value? */ | ||
| 1099 | gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"), | ||
| 1080 | "pointerColor", "Foreground", RES_TYPE_STRING); | 1100 | "pointerColor", "Foreground", RES_TYPE_STRING); |
| 1081 | gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), | 1101 | gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), |
| 1082 | "cursorColor", "Foreground", RES_TYPE_STRING); | 1102 | "cursorColor", "Foreground", RES_TYPE_STRING); |
| @@ -1133,6 +1153,23 @@ haiku_create_tip_frame (Lisp_Object parms) | |||
| 1133 | /* FIXME - can this be done in a similar way to normal frames? | 1153 | /* FIXME - can this be done in a similar way to normal frames? |
| 1134 | https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */ | 1154 | https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */ |
| 1135 | 1155 | ||
| 1156 | { | ||
| 1157 | Lisp_Object disptype; | ||
| 1158 | |||
| 1159 | if (be_get_display_planes () == 1) | ||
| 1160 | disptype = Qmono; | ||
| 1161 | else if (be_is_display_grayscale ()) | ||
| 1162 | disptype = Qgrayscale; | ||
| 1163 | else | ||
| 1164 | disptype = Qcolor; | ||
| 1165 | |||
| 1166 | if (NILP (Fframe_parameter (frame, Qdisplay_type))) | ||
| 1167 | { | ||
| 1168 | AUTO_FRAME_ARG (arg, Qdisplay_type, disptype); | ||
| 1169 | Fmodify_frame_parameters (frame, arg); | ||
| 1170 | } | ||
| 1171 | } | ||
| 1172 | |||
| 1136 | /* Set up faces after all frame parameters are known. This call | 1173 | /* Set up faces after all frame parameters are known. This call |
| 1137 | also merges in face attributes specified for new frames. | 1174 | also merges in face attributes specified for new frames. |
| 1138 | 1175 | ||
| @@ -1312,6 +1349,8 @@ haiku_set_undecorated (struct frame *f, Lisp_Object new_value, | |||
| 1312 | FRAME_UNDECORATED (f) = !NILP (new_value); | 1349 | FRAME_UNDECORATED (f) = !NILP (new_value); |
| 1313 | BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value)); | 1350 | BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value)); |
| 1314 | unblock_input (); | 1351 | unblock_input (); |
| 1352 | |||
| 1353 | haiku_update_after_decoration_change (f); | ||
| 1315 | } | 1354 | } |
| 1316 | 1355 | ||
| 1317 | static void | 1356 | static void |
| @@ -1326,6 +1365,8 @@ haiku_set_override_redirect (struct frame *f, Lisp_Object new_value, | |||
| 1326 | !NILP (new_value)); | 1365 | !NILP (new_value)); |
| 1327 | FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value); | 1366 | FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value); |
| 1328 | unblock_input (); | 1367 | unblock_input (); |
| 1368 | |||
| 1369 | haiku_update_after_decoration_change (f); | ||
| 1329 | } | 1370 | } |
| 1330 | 1371 | ||
| 1331 | static void | 1372 | static void |
| @@ -1372,122 +1413,129 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval | |||
| 1372 | static Lisp_Object | 1413 | static Lisp_Object |
| 1373 | frame_geometry (Lisp_Object frame, Lisp_Object attribute) | 1414 | frame_geometry (Lisp_Object frame, Lisp_Object attribute) |
| 1374 | { | 1415 | { |
| 1375 | struct frame *f = decode_live_frame (frame); | 1416 | struct frame *f, *parent; |
| 1376 | check_window_system (f); | 1417 | void *window; |
| 1418 | int outer_x, outer_y, outer_width, outer_height; | ||
| 1419 | int right_off, bottom_off, top_off; | ||
| 1420 | int native_x, native_y; | ||
| 1421 | |||
| 1422 | f = decode_window_system_frame (frame); | ||
| 1423 | parent = FRAME_PARENT_FRAME (f); | ||
| 1424 | window = FRAME_HAIKU_WINDOW (f); | ||
| 1425 | |||
| 1426 | be_lock_window (window); | ||
| 1427 | be_get_window_decorator_frame (window, &outer_x, &outer_y, | ||
| 1428 | &outer_width, &outer_height); | ||
| 1429 | be_get_window_decorator_dimensions (window, NULL, &top_off, | ||
| 1430 | &right_off, &bottom_off); | ||
| 1431 | be_unlock_window (window); | ||
| 1432 | |||
| 1433 | native_x = FRAME_OUTPUT_DATA (f)->frame_x; | ||
| 1434 | native_y = FRAME_OUTPUT_DATA (f)->frame_y; | ||
| 1435 | |||
| 1436 | if (parent) | ||
| 1437 | { | ||
| 1438 | /* Adjust all the coordinates by the coordinates of the parent | ||
| 1439 | frame. */ | ||
| 1440 | outer_x -= FRAME_OUTPUT_DATA (parent)->frame_x; | ||
| 1441 | outer_y -= FRAME_OUTPUT_DATA (parent)->frame_y; | ||
| 1442 | native_x -= FRAME_OUTPUT_DATA (parent)->frame_x; | ||
| 1443 | native_y -= FRAME_OUTPUT_DATA (parent)->frame_y; | ||
| 1444 | } | ||
| 1377 | 1445 | ||
| 1378 | if (EQ (attribute, Qouter_edges)) | 1446 | if (EQ (attribute, Qouter_edges)) |
| 1379 | return list4i (f->left_pos, f->top_pos, | 1447 | return list4i (outer_x, outer_y, |
| 1380 | f->left_pos, f->top_pos); | 1448 | outer_x + outer_width, |
| 1449 | outer_y + outer_height); | ||
| 1381 | else if (EQ (attribute, Qnative_edges)) | 1450 | else if (EQ (attribute, Qnative_edges)) |
| 1382 | return list4i (f->left_pos, f->top_pos, | 1451 | return list4i (native_x, native_y, |
| 1383 | f->left_pos + FRAME_PIXEL_WIDTH (f), | 1452 | native_x + FRAME_PIXEL_WIDTH (f), |
| 1384 | f->top_pos + FRAME_PIXEL_HEIGHT (f)); | 1453 | native_y + FRAME_PIXEL_HEIGHT (f)); |
| 1385 | else if (EQ (attribute, Qinner_edges)) | 1454 | else if (EQ (attribute, Qinner_edges)) |
| 1386 | return list4i (f->left_pos + FRAME_INTERNAL_BORDER_WIDTH (f), | 1455 | return list4i (native_x + FRAME_INTERNAL_BORDER_WIDTH (f), |
| 1387 | f->top_pos + FRAME_INTERNAL_BORDER_WIDTH (f) + | 1456 | native_y + FRAME_INTERNAL_BORDER_WIDTH (f) |
| 1388 | FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f), | 1457 | + FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f), |
| 1389 | f->left_pos - FRAME_INTERNAL_BORDER_WIDTH (f) + | 1458 | native_x - FRAME_INTERNAL_BORDER_WIDTH (f) |
| 1390 | FRAME_PIXEL_WIDTH (f), | 1459 | + FRAME_PIXEL_WIDTH (f), |
| 1391 | f->top_pos + FRAME_PIXEL_HEIGHT (f) - | 1460 | native_y + FRAME_PIXEL_HEIGHT (f) |
| 1392 | FRAME_INTERNAL_BORDER_WIDTH (f)); | 1461 | - FRAME_INTERNAL_BORDER_WIDTH (f)); |
| 1393 | 1462 | ||
| 1394 | else | 1463 | else |
| 1395 | return | 1464 | return list (Fcons (Qouter_position, |
| 1396 | list (Fcons (Qouter_position, | 1465 | Fcons (make_fixnum (outer_x), |
| 1397 | Fcons (make_fixnum (f->left_pos), | 1466 | make_fixnum (outer_y))), |
| 1398 | make_fixnum (f->top_pos))), | 1467 | Fcons (Qouter_size, |
| 1399 | Fcons (Qouter_size, | 1468 | Fcons (make_fixnum (outer_width), |
| 1400 | Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)), | 1469 | make_fixnum (outer_height))), |
| 1401 | make_fixnum (FRAME_PIXEL_HEIGHT (f)))), | 1470 | Fcons (Qexternal_border_size, |
| 1402 | Fcons (Qexternal_border_size, | 1471 | Fcons (make_fixnum (right_off), |
| 1403 | Fcons (make_fixnum (0), make_fixnum (0))), | 1472 | make_fixnum (bottom_off))), |
| 1404 | Fcons (Qtitle_bar_size, | 1473 | Fcons (Qtitle_bar_size, |
| 1405 | Fcons (make_fixnum (0), make_fixnum (0))), | 1474 | Fcons (make_fixnum (outer_width), |
| 1406 | Fcons (Qmenu_bar_external, Qnil), | 1475 | make_fixnum (top_off))), |
| 1407 | Fcons (Qmenu_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) - | 1476 | Fcons (Qmenu_bar_external, Qnil), |
| 1408 | (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), | 1477 | Fcons (Qmenu_bar_size, |
| 1409 | make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))), | 1478 | Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) |
| 1410 | Fcons (Qtool_bar_external, Qnil), | 1479 | - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), |
| 1411 | Fcons (Qtool_bar_position, Qtop), | 1480 | make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))), |
| 1412 | Fcons (Qtool_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) - | 1481 | Fcons (Qtool_bar_external, Qnil), |
| 1413 | (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), | 1482 | Fcons (Qtool_bar_position, Qtop), |
| 1414 | make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))), | 1483 | Fcons (Qtool_bar_size, |
| 1415 | Fcons (Qinternal_border_width, make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f)))); | 1484 | Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) |
| 1485 | - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), | ||
| 1486 | make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))), | ||
| 1487 | Fcons (Qinternal_border_width, | ||
| 1488 | make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f)))); | ||
| 1416 | } | 1489 | } |
| 1417 | 1490 | ||
| 1418 | void | 1491 | void |
| 1419 | haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 1492 | haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 1420 | { | 1493 | { |
| 1421 | Emacs_Color color; | 1494 | unsigned long background; |
| 1422 | struct face *defface; | ||
| 1423 | 1495 | ||
| 1424 | CHECK_STRING (arg); | 1496 | background = haiku_decode_color (f, arg); |
| 1425 | 1497 | ||
| 1426 | block_input (); | 1498 | FRAME_OUTPUT_DATA (f)->cursor_fg = background; |
| 1427 | if (haiku_get_color (SSDATA (arg), &color)) | 1499 | FRAME_BACKGROUND_PIXEL (f) = background; |
| 1428 | { | ||
| 1429 | store_frame_param (f, Qbackground_color, oldval); | ||
| 1430 | unblock_input (); | ||
| 1431 | error ("Bad color"); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | FRAME_OUTPUT_DATA (f)->cursor_fg = color.pixel; | ||
| 1435 | FRAME_BACKGROUND_PIXEL (f) = color.pixel; | ||
| 1436 | 1500 | ||
| 1437 | if (FRAME_HAIKU_VIEW (f)) | 1501 | if (FRAME_HAIKU_VIEW (f)) |
| 1438 | { | 1502 | { |
| 1439 | BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); | 1503 | BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); |
| 1440 | BView_SetViewColor (FRAME_HAIKU_VIEW (f), color.pixel); | 1504 | BView_SetViewColor (FRAME_HAIKU_VIEW (f), background); |
| 1441 | BView_draw_unlock (FRAME_HAIKU_VIEW (f)); | 1505 | BView_draw_unlock (FRAME_HAIKU_VIEW (f)); |
| 1442 | 1506 | ||
| 1443 | defface = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID); | 1507 | FRAME_OUTPUT_DATA (f)->cursor_fg = background; |
| 1444 | if (defface) | 1508 | update_face_from_frame_parameter (f, Qbackground_color, arg); |
| 1445 | { | ||
| 1446 | defface->background = color.pixel; | ||
| 1447 | update_face_from_frame_parameter (f, Qbackground_color, arg); | ||
| 1448 | clear_frame (f); | ||
| 1449 | } | ||
| 1450 | } | ||
| 1451 | 1509 | ||
| 1452 | if (FRAME_VISIBLE_P (f)) | 1510 | if (FRAME_VISIBLE_P (f)) |
| 1453 | SET_FRAME_GARBAGED (f); | 1511 | redraw_frame (f); |
| 1454 | unblock_input (); | 1512 | } |
| 1455 | } | 1513 | } |
| 1456 | 1514 | ||
| 1457 | void | 1515 | void |
| 1458 | haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 1516 | haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 1459 | { | 1517 | { |
| 1460 | Emacs_Color color, fore_pixel; | 1518 | unsigned long fore_pixel, pixel; |
| 1461 | |||
| 1462 | CHECK_STRING (arg); | ||
| 1463 | block_input (); | ||
| 1464 | |||
| 1465 | if (haiku_get_color (SSDATA (arg), &color)) | ||
| 1466 | { | ||
| 1467 | store_frame_param (f, Qcursor_color, oldval); | ||
| 1468 | unblock_input (); | ||
| 1469 | error ("Bad color"); | ||
| 1470 | } | ||
| 1471 | 1519 | ||
| 1472 | FRAME_CURSOR_COLOR (f) = color; | 1520 | pixel = haiku_decode_color (f, arg); |
| 1473 | 1521 | ||
| 1474 | if (STRINGP (Vx_cursor_fore_pixel)) | 1522 | if (!NILP (Vx_cursor_fore_pixel)) |
| 1475 | { | 1523 | { |
| 1476 | if (haiku_get_color (SSDATA (Vx_cursor_fore_pixel), | 1524 | fore_pixel = haiku_decode_color (f, Vx_cursor_fore_pixel); |
| 1477 | &fore_pixel)) | 1525 | FRAME_OUTPUT_DATA (f)->cursor_fg = fore_pixel; |
| 1478 | error ("Bad color %s", SSDATA (Vx_cursor_fore_pixel)); | ||
| 1479 | FRAME_OUTPUT_DATA (f)->cursor_fg = fore_pixel.pixel; | ||
| 1480 | } | 1526 | } |
| 1481 | else | 1527 | else |
| 1482 | FRAME_OUTPUT_DATA (f)->cursor_fg = FRAME_BACKGROUND_PIXEL (f); | 1528 | FRAME_OUTPUT_DATA (f)->cursor_fg = FRAME_BACKGROUND_PIXEL (f); |
| 1483 | 1529 | ||
| 1530 | haiku_query_color (pixel, &FRAME_CURSOR_COLOR (f)); | ||
| 1531 | |||
| 1484 | if (FRAME_VISIBLE_P (f)) | 1532 | if (FRAME_VISIBLE_P (f)) |
| 1485 | { | 1533 | { |
| 1486 | gui_update_cursor (f, 0); | 1534 | gui_update_cursor (f, false); |
| 1487 | gui_update_cursor (f, 1); | 1535 | gui_update_cursor (f, true); |
| 1488 | } | 1536 | } |
| 1537 | |||
| 1489 | update_face_from_frame_parameter (f, Qcursor_color, arg); | 1538 | update_face_from_frame_parameter (f, Qcursor_color, arg); |
| 1490 | unblock_input (); | ||
| 1491 | } | 1539 | } |
| 1492 | 1540 | ||
| 1493 | void | 1541 | void |
| @@ -1567,6 +1615,7 @@ haiku_free_frame_resources (struct frame *f) | |||
| 1567 | dpyinfo = FRAME_DISPLAY_INFO (f); | 1615 | dpyinfo = FRAME_DISPLAY_INFO (f); |
| 1568 | 1616 | ||
| 1569 | free_frame_faces (f); | 1617 | free_frame_faces (f); |
| 1618 | haiku_free_custom_cursors (f); | ||
| 1570 | 1619 | ||
| 1571 | /* Free scroll bars */ | 1620 | /* Free scroll bars */ |
| 1572 | for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next) | 1621 | for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next) |
| @@ -1792,6 +1841,279 @@ haiku_set_sticky (struct frame *f, Lisp_Object new_value, | |||
| 1792 | unblock_input (); | 1841 | unblock_input (); |
| 1793 | } | 1842 | } |
| 1794 | 1843 | ||
| 1844 | struct user_cursor_info | ||
| 1845 | { | ||
| 1846 | /* A pointer to the Lisp_Object describing the cursor. */ | ||
| 1847 | Lisp_Object *lisp_cursor; | ||
| 1848 | |||
| 1849 | /* The offset of the cursor in the `struct haiku_output' of each | ||
| 1850 | frame. */ | ||
| 1851 | ptrdiff_t output_offset; | ||
| 1852 | |||
| 1853 | /* The offset of the default value of the cursor in the display | ||
| 1854 | info structure. */ | ||
| 1855 | ptrdiff_t default_offset; | ||
| 1856 | }; | ||
| 1857 | |||
| 1858 | struct user_cursor_bitmap_info | ||
| 1859 | { | ||
| 1860 | /* A bitmap to use instead of the font cursor to create cursors in a | ||
| 1861 | certain color. */ | ||
| 1862 | const void *bits; | ||
| 1863 | |||
| 1864 | /* The mask for that bitmap. */ | ||
| 1865 | const void *mask; | ||
| 1866 | |||
| 1867 | /* The dimensions of the cursor bitmap. */ | ||
| 1868 | int width, height; | ||
| 1869 | |||
| 1870 | /* The position inside the cursor bitmap corresponding to the | ||
| 1871 | position of the mouse pointer. */ | ||
| 1872 | int x, y; | ||
| 1873 | }; | ||
| 1874 | |||
| 1875 | #define INIT_USER_CURSOR(lisp, cursor) \ | ||
| 1876 | { (lisp), offsetof (struct haiku_output, cursor), \ | ||
| 1877 | offsetof (struct haiku_display_info, cursor) } | ||
| 1878 | |||
| 1879 | struct user_cursor_info custom_cursors[] = | ||
| 1880 | { | ||
| 1881 | INIT_USER_CURSOR (&Vx_pointer_shape, text_cursor), | ||
| 1882 | INIT_USER_CURSOR (NULL, nontext_cursor), | ||
| 1883 | INIT_USER_CURSOR (NULL, modeline_cursor), | ||
| 1884 | INIT_USER_CURSOR (&Vx_sensitive_text_pointer_shape, hand_cursor), | ||
| 1885 | INIT_USER_CURSOR (&Vx_hourglass_pointer_shape, hourglass_cursor), | ||
| 1886 | INIT_USER_CURSOR (NULL, horizontal_drag_cursor), | ||
| 1887 | INIT_USER_CURSOR (NULL, vertical_drag_cursor), | ||
| 1888 | INIT_USER_CURSOR (NULL, left_edge_cursor), | ||
| 1889 | INIT_USER_CURSOR (NULL, top_left_corner_cursor), | ||
| 1890 | INIT_USER_CURSOR (NULL, top_edge_cursor), | ||
| 1891 | INIT_USER_CURSOR (NULL, top_right_corner_cursor), | ||
| 1892 | INIT_USER_CURSOR (NULL, right_edge_cursor), | ||
| 1893 | INIT_USER_CURSOR (NULL, bottom_right_corner_cursor), | ||
| 1894 | INIT_USER_CURSOR (NULL, bottom_edge_cursor), | ||
| 1895 | INIT_USER_CURSOR (NULL, bottom_left_corner_cursor), | ||
| 1896 | INIT_USER_CURSOR (NULL, no_cursor), | ||
| 1897 | }; | ||
| 1898 | |||
| 1899 | struct user_cursor_bitmap_info cursor_bitmaps[] = | ||
| 1900 | { | ||
| 1901 | { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7 }, /* text_cursor */ | ||
| 1902 | { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 }, /* nontext_cursor */ | ||
| 1903 | { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 }, /* modeline_cursor */ | ||
| 1904 | { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3 }, /* hand_cursor */ | ||
| 1905 | { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7 }, /* hourglass_cursor */ | ||
| 1906 | { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7 }, /* horizontal_drag_cursor */ | ||
| 1907 | { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7 }, /* vertical_drag_cursor */ | ||
| 1908 | { NULL, NULL, 0, 0, 0, 0 }, /* left_edge_cursor */ | ||
| 1909 | { NULL, NULL, 0, 0, 0, 0 }, /* top_left_corner_cursor */ | ||
| 1910 | { NULL, NULL, 0, 0, 0, 0 }, /* top_edge_cursor */ | ||
| 1911 | { NULL, NULL, 0, 0, 0, 0 }, /* top_right_corner_cursor */ | ||
| 1912 | { NULL, NULL, 0, 0, 0, 0 }, /* right_edge_cursor */ | ||
| 1913 | { NULL, NULL, 0, 0, 0, 0 }, /* bottom_right_corner_cursor */ | ||
| 1914 | { NULL, NULL, 0, 0, 0, 0 }, /* bottom_edge_cursor */ | ||
| 1915 | { NULL, NULL, 0, 0, 0, 0 }, /* bottom_left_corner_cursor */ | ||
| 1916 | { NULL, NULL, 0, 0, 0, 0 }, /* no_cursor */ | ||
| 1917 | }; | ||
| 1918 | |||
| 1919 | /* Array of cursor bitmaps for each system cursor ID. This is used to | ||
| 1920 | color in user-specified cursors. */ | ||
| 1921 | struct user_cursor_bitmap_info cursor_bitmaps_for_id[28] = | ||
| 1922 | { | ||
| 1923 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1924 | { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 }, | ||
| 1925 | { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7 }, | ||
| 1926 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1927 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1928 | { cross_ptr_bits, cross_ptrmask_bits, 30, 30, 15, 15 }, | ||
| 1929 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1930 | { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3 }, | ||
| 1931 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1932 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1933 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1934 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1935 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1936 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1937 | { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7 }, | ||
| 1938 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1939 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1940 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1941 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1942 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1943 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1944 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1945 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1946 | { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7 }, | ||
| 1947 | { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7 }, | ||
| 1948 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1949 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1950 | { NULL, NULL, 0, 0, 0, 0 }, | ||
| 1951 | }; | ||
| 1952 | |||
| 1953 | static void * | ||
| 1954 | haiku_create_colored_cursor (struct user_cursor_bitmap_info *info, | ||
| 1955 | uint32_t foreground, uint32_t background) | ||
| 1956 | { | ||
| 1957 | const char *bits, *mask; | ||
| 1958 | void *bitmap, *cursor; | ||
| 1959 | int width, height, bytes_per_line, x, y; | ||
| 1960 | |||
| 1961 | bits = info->bits; | ||
| 1962 | mask = info->mask; | ||
| 1963 | width = info->width; | ||
| 1964 | height = info->height; | ||
| 1965 | bytes_per_line = (width + 7) / 8; | ||
| 1966 | |||
| 1967 | bitmap = BBitmap_new (width, height, false); | ||
| 1968 | |||
| 1969 | if (!bitmap) | ||
| 1970 | memory_full (SIZE_MAX); | ||
| 1971 | |||
| 1972 | for (y = 0; y < height; ++y) | ||
| 1973 | { | ||
| 1974 | for (x = 0; x < width; ++x) | ||
| 1975 | { | ||
| 1976 | if (mask[x / 8] >> (x % 8) & 1) | ||
| 1977 | haiku_put_pixel (bitmap, x, y, | ||
| 1978 | (bits[x / 8] >> (x % 8) & 1 | ||
| 1979 | ? (foreground | 255u << 24) | ||
| 1980 | : (background | 255u << 24))); | ||
| 1981 | else | ||
| 1982 | haiku_put_pixel (bitmap, x, y, 0); | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | mask += bytes_per_line; | ||
| 1986 | bits += bytes_per_line; | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | cursor = be_create_pixmap_cursor (bitmap, info->x, info->y); | ||
| 1990 | BBitmap_free (bitmap); | ||
| 1991 | |||
| 1992 | return cursor; | ||
| 1993 | } | ||
| 1994 | |||
| 1995 | /* Free all cursors on F that were allocated specifically for the | ||
| 1996 | frame. */ | ||
| 1997 | void | ||
| 1998 | haiku_free_custom_cursors (struct frame *f) | ||
| 1999 | { | ||
| 2000 | struct user_cursor_info *cursor; | ||
| 2001 | struct haiku_output *output; | ||
| 2002 | struct haiku_display_info *dpyinfo; | ||
| 2003 | Emacs_Cursor *frame_cursor; | ||
| 2004 | Emacs_Cursor *display_cursor; | ||
| 2005 | int i; | ||
| 2006 | |||
| 2007 | output = FRAME_OUTPUT_DATA (f); | ||
| 2008 | dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 2009 | |||
| 2010 | for (i = 0; i < ARRAYELTS (custom_cursors); ++i) | ||
| 2011 | { | ||
| 2012 | cursor = &custom_cursors[i]; | ||
| 2013 | frame_cursor = (Emacs_Cursor *) ((char *) output | ||
| 2014 | + cursor->output_offset); | ||
| 2015 | display_cursor = (Emacs_Cursor *) ((char *) dpyinfo | ||
| 2016 | + cursor->default_offset); | ||
| 2017 | |||
| 2018 | if (*frame_cursor != *display_cursor && *frame_cursor) | ||
| 2019 | { | ||
| 2020 | if (output->current_cursor == *frame_cursor) | ||
| 2021 | output->current_cursor = *display_cursor; | ||
| 2022 | |||
| 2023 | be_delete_cursor (*frame_cursor); | ||
| 2024 | } | ||
| 2025 | |||
| 2026 | *frame_cursor = *display_cursor; | ||
| 2027 | } | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static void | ||
| 2031 | haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | ||
| 2032 | { | ||
| 2033 | struct haiku_output *output; | ||
| 2034 | Emacs_Cursor *frame_cursor, old, *recolored; | ||
| 2035 | int i, n, rc; | ||
| 2036 | bool color_specified_p; | ||
| 2037 | Emacs_Color color; | ||
| 2038 | |||
| 2039 | CHECK_STRING (arg); | ||
| 2040 | color_specified_p = true; | ||
| 2041 | |||
| 2042 | if (!strcmp (SSDATA (arg), "font-color")) | ||
| 2043 | color_specified_p = false; | ||
| 2044 | else | ||
| 2045 | rc = haiku_get_color (SSDATA (arg), &color); | ||
| 2046 | |||
| 2047 | if (color_specified_p && rc) | ||
| 2048 | signal_error ("Undefined color", arg); | ||
| 2049 | |||
| 2050 | output = FRAME_OUTPUT_DATA (f); | ||
| 2051 | |||
| 2052 | /* This will also reset all the cursors back to their default | ||
| 2053 | values. */ | ||
| 2054 | haiku_free_custom_cursors (f); | ||
| 2055 | |||
| 2056 | for (i = 0; i < ARRAYELTS (custom_cursors); ++i) | ||
| 2057 | { | ||
| 2058 | frame_cursor = (Emacs_Cursor *) ((char *) output | ||
| 2059 | + custom_cursors[i].output_offset); | ||
| 2060 | old = *frame_cursor; | ||
| 2061 | |||
| 2062 | if (custom_cursors[i].lisp_cursor | ||
| 2063 | && FIXNUMP (*custom_cursors[i].lisp_cursor)) | ||
| 2064 | { | ||
| 2065 | if (!RANGED_FIXNUMP (0, *custom_cursors[i].lisp_cursor, | ||
| 2066 | 28)) /* 28 is the largest Haiku cursor ID. */ | ||
| 2067 | signal_error ("Invalid cursor", | ||
| 2068 | *custom_cursors[i].lisp_cursor); | ||
| 2069 | |||
| 2070 | n = XFIXNUM (*custom_cursors[i].lisp_cursor); | ||
| 2071 | |||
| 2072 | if (color_specified_p && cursor_bitmaps_for_id[n].bits) | ||
| 2073 | { | ||
| 2074 | recolored | ||
| 2075 | = haiku_create_colored_cursor (&cursor_bitmaps_for_id[n], | ||
| 2076 | color.pixel, | ||
| 2077 | FRAME_BACKGROUND_PIXEL (f)); | ||
| 2078 | |||
| 2079 | if (recolored) | ||
| 2080 | { | ||
| 2081 | *frame_cursor = recolored; | ||
| 2082 | continue; | ||
| 2083 | } | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | /* Create and set the custom cursor. */ | ||
| 2087 | *frame_cursor = be_create_cursor_from_id (n); | ||
| 2088 | } | ||
| 2089 | else if (color_specified_p && cursor_bitmaps[i].bits) | ||
| 2090 | { | ||
| 2091 | recolored | ||
| 2092 | = haiku_create_colored_cursor (&cursor_bitmaps[i], color.pixel, | ||
| 2093 | FRAME_BACKGROUND_PIXEL (f)); | ||
| 2094 | |||
| 2095 | if (recolored) | ||
| 2096 | *frame_cursor = recolored; | ||
| 2097 | } | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | /* This function can be called before the frame's window is | ||
| 2101 | created. */ | ||
| 2102 | if (FRAME_HAIKU_WINDOW (f)) | ||
| 2103 | { | ||
| 2104 | if (output->current_cursor == old | ||
| 2105 | && old != *frame_cursor) | ||
| 2106 | { | ||
| 2107 | output->current_cursor = *frame_cursor; | ||
| 2108 | |||
| 2109 | BView_set_view_cursor (FRAME_HAIKU_VIEW (f), | ||
| 2110 | *frame_cursor); | ||
| 2111 | } | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | update_face_from_frame_parameter (f, Qmouse_color, arg); | ||
| 2115 | } | ||
| 2116 | |||
| 1795 | 2117 | ||
| 1796 | 2118 | ||
| 1797 | DEFUN ("haiku-set-mouse-absolute-pixel-position", | 2119 | DEFUN ("haiku-set-mouse-absolute-pixel-position", |
| @@ -1890,34 +2212,28 @@ DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, | |||
| 1890 | } | 2212 | } |
| 1891 | 2213 | ||
| 1892 | DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, | 2214 | DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, |
| 1893 | 1, 3, 0, | 2215 | 1, 3, 0, doc: /* SKIP: real doc in xfns.c. */) |
| 1894 | doc: /* SKIP: real doc in xfns.c. */) | ||
| 1895 | (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed) | 2216 | (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed) |
| 1896 | { | 2217 | { |
| 1897 | struct haiku_display_info *dpyinfo; | ||
| 1898 | CHECK_STRING (display); | 2218 | CHECK_STRING (display); |
| 1899 | 2219 | ||
| 1900 | if (NILP (Fstring_equal (display, build_string ("be")))) | 2220 | if (NILP (Fstring_equal (display, build_string ("be")))) |
| 1901 | { | 2221 | { |
| 1902 | if (!NILP (must_succeed)) | 2222 | if (!NILP (must_succeed)) |
| 1903 | fatal ("Bad display"); | 2223 | fatal ("Invalid display %s", SDATA (display)); |
| 1904 | else | 2224 | else |
| 1905 | error ("Bad display"); | 2225 | signal_error ("Invalid display", display); |
| 1906 | } | 2226 | } |
| 1907 | 2227 | ||
| 1908 | if (x_display_list) | 2228 | if (x_display_list) |
| 1909 | return Qnil; | ||
| 1910 | |||
| 1911 | dpyinfo = haiku_term_init (); | ||
| 1912 | |||
| 1913 | if (!dpyinfo) | ||
| 1914 | { | 2229 | { |
| 1915 | if (!NILP (must_succeed)) | 2230 | if (!NILP (must_succeed)) |
| 1916 | fatal ("Display not responding"); | 2231 | fatal ("A display is already open"); |
| 1917 | else | 2232 | else |
| 1918 | error ("Display not responding"); | 2233 | error ("A display is already open"); |
| 1919 | } | 2234 | } |
| 1920 | 2235 | ||
| 2236 | haiku_term_init (); | ||
| 1921 | return Qnil; | 2237 | return Qnil; |
| 1922 | } | 2238 | } |
| 1923 | 2239 | ||
| @@ -1944,7 +2260,7 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_heigh | |||
| 1944 | check_haiku_display_info (terminal); | 2260 | check_haiku_display_info (terminal); |
| 1945 | 2261 | ||
| 1946 | be_get_screen_dimensions (&width, &height); | 2262 | be_get_screen_dimensions (&width, &height); |
| 1947 | return make_fixnum (width); | 2263 | return make_fixnum (height); |
| 1948 | } | 2264 | } |
| 1949 | 2265 | ||
| 1950 | DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, | 2266 | DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, |
| @@ -2039,6 +2355,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, | |||
| 2039 | else | 2355 | else |
| 2040 | CHECK_FIXNUM (dy); | 2356 | CHECK_FIXNUM (dy); |
| 2041 | 2357 | ||
| 2358 | tip_dx = dx; | ||
| 2359 | tip_dy = dy; | ||
| 2360 | |||
| 2042 | if (use_system_tooltips) | 2361 | if (use_system_tooltips) |
| 2043 | { | 2362 | { |
| 2044 | int root_x, root_y; | 2363 | int root_x, root_y; |
| @@ -2579,6 +2898,7 @@ Frames are listed from topmost (first) to bottommost (last). */) | |||
| 2579 | 2898 | ||
| 2580 | if (NILP (sel)) | 2899 | if (NILP (sel)) |
| 2581 | return frames; | 2900 | return frames; |
| 2901 | |||
| 2582 | return Fcons (sel, frames); | 2902 | return Fcons (sel, frames); |
| 2583 | } | 2903 | } |
| 2584 | 2904 | ||
| @@ -2683,6 +3003,57 @@ call this function yourself. */) | |||
| 2683 | return Qnil; | 3003 | return Qnil; |
| 2684 | } | 3004 | } |
| 2685 | 3005 | ||
| 3006 | DEFUN ("haiku-display-monitor-attributes-list", | ||
| 3007 | Fhaiku_display_monitor_attributes_list, | ||
| 3008 | Shaiku_display_monitor_attributes_list, | ||
| 3009 | 0, 1, 0, | ||
| 3010 | doc: /* Return a list of physical monitor attributes on the display TERMINAL. | ||
| 3011 | |||
| 3012 | The optional argument TERMINAL specifies which display to ask about. | ||
| 3013 | TERMINAL should be a terminal object, a frame or a display name (a string). | ||
| 3014 | If omitted or nil, that stands for the selected frame's display. | ||
| 3015 | |||
| 3016 | Internal use only, use `display-monitor-attributes-list' instead. */) | ||
| 3017 | (Lisp_Object terminal) | ||
| 3018 | { | ||
| 3019 | struct MonitorInfo monitor; | ||
| 3020 | struct haiku_display_info *dpyinfo; | ||
| 3021 | Lisp_Object frames, tail, tem; | ||
| 3022 | |||
| 3023 | dpyinfo = check_haiku_display_info (terminal); | ||
| 3024 | frames = Qnil; | ||
| 3025 | |||
| 3026 | FOR_EACH_FRAME (tail, tem) | ||
| 3027 | { | ||
| 3028 | maybe_quit (); | ||
| 3029 | |||
| 3030 | if (FRAME_HAIKU_P (XFRAME (tem)) | ||
| 3031 | && !FRAME_TOOLTIP_P (XFRAME (tem))) | ||
| 3032 | frames = Fcons (tem, frames); | ||
| 3033 | } | ||
| 3034 | |||
| 3035 | monitor.geom.x = 0; | ||
| 3036 | monitor.geom.y = 0; | ||
| 3037 | be_get_screen_dimensions ((int *) &monitor.geom.width, | ||
| 3038 | (int *) &monitor.geom.height); | ||
| 3039 | |||
| 3040 | monitor.mm_width = (monitor.geom.width | ||
| 3041 | / (dpyinfo->resx / 25.4)); | ||
| 3042 | monitor.mm_height = (monitor.geom.height | ||
| 3043 | / (dpyinfo->resy / 25.4)); | ||
| 3044 | monitor.name = (char *) "BeOS monitor"; | ||
| 3045 | |||
| 3046 | if (!be_get_explicit_workarea ((int *) &monitor.work.x, | ||
| 3047 | (int *) &monitor.work.y, | ||
| 3048 | (int *) &monitor.work.width, | ||
| 3049 | (int *) &monitor.work.height)) | ||
| 3050 | monitor.work = monitor.geom; | ||
| 3051 | |||
| 3052 | return make_monitor_attribute_list (&monitor, 1, 0, | ||
| 3053 | make_vector (1, frames), | ||
| 3054 | "fallback"); | ||
| 3055 | } | ||
| 3056 | |||
| 2686 | frame_parm_handler haiku_frame_parm_handlers[] = | 3057 | frame_parm_handler haiku_frame_parm_handlers[] = |
| 2687 | { | 3058 | { |
| 2688 | gui_set_autoraise, | 3059 | gui_set_autoraise, |
| @@ -2701,7 +3072,7 @@ frame_parm_handler haiku_frame_parm_handlers[] = | |||
| 2701 | gui_set_right_divider_width, | 3072 | gui_set_right_divider_width, |
| 2702 | gui_set_bottom_divider_width, | 3073 | gui_set_bottom_divider_width, |
| 2703 | haiku_set_menu_bar_lines, | 3074 | haiku_set_menu_bar_lines, |
| 2704 | NULL, /* set mouse color */ | 3075 | haiku_set_mouse_color, |
| 2705 | haiku_explicitly_set_name, | 3076 | haiku_explicitly_set_name, |
| 2706 | gui_set_scroll_bar_width, | 3077 | gui_set_scroll_bar_width, |
| 2707 | gui_set_scroll_bar_height, | 3078 | gui_set_scroll_bar_height, |
| @@ -2751,6 +3122,9 @@ syms_of_haikufns (void) | |||
| 2751 | DEFSYM (Qstatic_color, "static-color"); | 3122 | DEFSYM (Qstatic_color, "static-color"); |
| 2752 | DEFSYM (Qstatic_gray, "static-gray"); | 3123 | DEFSYM (Qstatic_gray, "static-gray"); |
| 2753 | DEFSYM (Qtrue_color, "true-color"); | 3124 | DEFSYM (Qtrue_color, "true-color"); |
| 3125 | DEFSYM (Qmono, "mono"); | ||
| 3126 | DEFSYM (Qgrayscale, "grayscale"); | ||
| 3127 | DEFSYM (Qcolor, "color"); | ||
| 2754 | 3128 | ||
| 2755 | defsubr (&Sx_hide_tip); | 3129 | defsubr (&Sx_hide_tip); |
| 2756 | defsubr (&Sxw_display_color_p); | 3130 | defsubr (&Sxw_display_color_p); |
| @@ -2785,6 +3159,7 @@ syms_of_haikufns (void) | |||
| 2785 | defsubr (&Sx_display_save_under); | 3159 | defsubr (&Sx_display_save_under); |
| 2786 | defsubr (&Shaiku_frame_restack); | 3160 | defsubr (&Shaiku_frame_restack); |
| 2787 | defsubr (&Shaiku_save_session_reply); | 3161 | defsubr (&Shaiku_save_session_reply); |
| 3162 | defsubr (&Shaiku_display_monitor_attributes_list); | ||
| 2788 | 3163 | ||
| 2789 | tip_timer = Qnil; | 3164 | tip_timer = Qnil; |
| 2790 | staticpro (&tip_timer); | 3165 | staticpro (&tip_timer); |
| @@ -2796,6 +3171,10 @@ syms_of_haikufns (void) | |||
| 2796 | staticpro (&tip_last_string); | 3171 | staticpro (&tip_last_string); |
| 2797 | tip_last_parms = Qnil; | 3172 | tip_last_parms = Qnil; |
| 2798 | staticpro (&tip_last_parms); | 3173 | staticpro (&tip_last_parms); |
| 3174 | tip_dx = Qnil; | ||
| 3175 | staticpro (&tip_dx); | ||
| 3176 | tip_dy = Qnil; | ||
| 3177 | staticpro (&tip_dy); | ||
| 2799 | 3178 | ||
| 2800 | DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, | 3179 | DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, |
| 2801 | doc: /* SKIP: real doc in xfns.c. */); | 3180 | doc: /* SKIP: real doc in xfns.c. */); |
| @@ -2805,6 +3184,19 @@ syms_of_haikufns (void) | |||
| 2805 | doc: /* SKIP: real doc in xfns.c. */); | 3184 | doc: /* SKIP: real doc in xfns.c. */); |
| 2806 | Vx_cursor_fore_pixel = Qnil; | 3185 | Vx_cursor_fore_pixel = Qnil; |
| 2807 | 3186 | ||
| 3187 | DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape, | ||
| 3188 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 3189 | Vx_pointer_shape = Qnil; | ||
| 3190 | |||
| 3191 | DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape, | ||
| 3192 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 3193 | Vx_hourglass_pointer_shape = Qnil; | ||
| 3194 | |||
| 3195 | DEFVAR_LISP ("x-sensitive-text-pointer-shape", | ||
| 3196 | Vx_sensitive_text_pointer_shape, | ||
| 3197 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 3198 | Vx_sensitive_text_pointer_shape = Qnil; | ||
| 3199 | |||
| 2808 | DEFVAR_LISP ("haiku-allowed-ui-colors", Vhaiku_allowed_ui_colors, | 3200 | DEFVAR_LISP ("haiku-allowed-ui-colors", Vhaiku_allowed_ui_colors, |
| 2809 | doc: /* Vector of UI colors that Emacs can look up from the system. | 3201 | doc: /* Vector of UI colors that Emacs can look up from the system. |
| 2810 | If this is set up incorrectly, Emacs can crash when encoutering an | 3202 | If this is set up incorrectly, Emacs can crash when encoutering an |
diff --git a/src/haikufont.c b/src/haikufont.c index e0db086aa00..54f11c6e413 100644 --- a/src/haikufont.c +++ b/src/haikufont.c | |||
| @@ -1084,8 +1084,8 @@ haikufont_draw (struct glyph_string *s, int from, int to, | |||
| 1084 | s->first_glyph->slice.glyphless.lower_yoff | 1084 | s->first_glyph->slice.glyphless.lower_yoff |
| 1085 | - s->first_glyph->slice.glyphless.upper_yoff; | 1085 | - s->first_glyph->slice.glyphless.upper_yoff; |
| 1086 | 1086 | ||
| 1087 | BView_SetHighColor (view, background); | 1087 | haiku_draw_background_rect (s, s->face, x, y - ascent, |
| 1088 | BView_FillRectangle (view, x, y - ascent, s->width, height); | 1088 | s->width, height); |
| 1089 | s->background_filled_p = 1; | 1089 | s->background_filled_p = 1; |
| 1090 | } | 1090 | } |
| 1091 | 1091 | ||
diff --git a/src/haikugui.h b/src/haikugui.h index a6cf3a4e6ce..0dc127e6b63 100644 --- a/src/haikugui.h +++ b/src/haikugui.h | |||
| @@ -95,4 +95,109 @@ typedef haiku Drawable; | |||
| 95 | typedef haiku Window; | 95 | typedef haiku Window; |
| 96 | typedef int Display; | 96 | typedef int Display; |
| 97 | 97 | ||
| 98 | /* Cursor bitmaps. These are only used to create colored cursors when | ||
| 99 | the user specifies a mouse color. */ | ||
| 100 | |||
| 101 | MAYBE_UNUSED static unsigned char cross_ptr_bits[] = | ||
| 102 | { | ||
| 103 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, | ||
| 104 | 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, | ||
| 105 | 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, | ||
| 106 | 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, | ||
| 107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf0, 0x1f, 0x00, 0x00, | ||
| 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 110 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, | ||
| 111 | 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, | ||
| 112 | 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, | ||
| 113 | 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 114 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 115 | }; | ||
| 116 | |||
| 117 | MAYBE_UNUSED static unsigned char cross_ptrmask_bits[] = | ||
| 118 | { | ||
| 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, | ||
| 120 | 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, | ||
| 121 | 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, | ||
| 122 | 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, | ||
| 123 | 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 124 | 0x00, 0xfc, 0x07, 0xf0, 0x1f, 0xfe, 0x0f, 0xf8, 0x3f, 0xfc, 0x07, | ||
| 125 | 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 126 | 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, | ||
| 127 | 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, | ||
| 128 | 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, | ||
| 129 | 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, | ||
| 130 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 131 | }; | ||
| 132 | |||
| 133 | MAYBE_UNUSED static unsigned char ibeam_ptr_bits[] = | ||
| 134 | { | ||
| 135 | 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, | ||
| 136 | 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, | ||
| 137 | 0xc0, 0x01, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00 | ||
| 138 | }; | ||
| 139 | |||
| 140 | MAYBE_UNUSED static unsigned char ibeam_ptrmask_bits[] = | ||
| 141 | { | ||
| 142 | 0x00, 0x00, 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0xe0, 0x03, 0xe0, | ||
| 143 | 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, | ||
| 144 | 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0x00, 0x00 | ||
| 145 | }; | ||
| 146 | |||
| 147 | MAYBE_UNUSED static unsigned char hand_ptr_bits[] = | ||
| 148 | { | ||
| 149 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xa0, 0x02, 0xa0, | ||
| 150 | 0x02, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, | ||
| 151 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 152 | }; | ||
| 153 | |||
| 154 | MAYBE_UNUSED static unsigned char hand_ptrmask_bits[] = | ||
| 155 | { | ||
| 156 | 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xf0, 0x07, 0xf0, 0x07, 0xf8, | ||
| 157 | 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, | ||
| 158 | 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 159 | }; | ||
| 160 | |||
| 161 | MAYBE_UNUSED static unsigned char horizd_ptr_bits[] = | ||
| 162 | { | ||
| 163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x28, | ||
| 164 | 0x0a, 0xf4, 0x17, 0x02, 0x20, 0xf4, 0x17, 0x28, 0x0a, 0x10, 0x04, | ||
| 165 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 166 | }; | ||
| 167 | |||
| 168 | MAYBE_UNUSED static unsigned char horizd_ptrmask_bits[] = | ||
| 169 | { | ||
| 170 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x38, | ||
| 171 | 0x0e, 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0x38, 0x0e, 0x10, 0x04, | ||
| 172 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 173 | }; | ||
| 174 | |||
| 175 | MAYBE_UNUSED static unsigned char vertd_ptr_bits[] = | ||
| 176 | { | ||
| 177 | 0x00, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, 0x50, 0x05, 0x60, | ||
| 178 | 0x03, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x60, 0x03, 0x50, 0x05, | ||
| 179 | 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x00, 0x00 | ||
| 180 | }; | ||
| 181 | |||
| 182 | MAYBE_UNUSED static unsigned char vertd_ptrmask_bits[] = | ||
| 183 | { | ||
| 184 | 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xe0, | ||
| 185 | 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, | ||
| 186 | 0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00 | ||
| 187 | }; | ||
| 188 | |||
| 189 | MAYBE_UNUSED static unsigned char hourglass_bits[] = | ||
| 190 | { | ||
| 191 | 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x24, | ||
| 192 | 0x10, 0x44, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x88, 0x08, | ||
| 193 | 0x10, 0x04, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 | ||
| 194 | }; | ||
| 195 | |||
| 196 | MAYBE_UNUSED static unsigned char hourglass_mask_bits[] = | ||
| 197 | { | ||
| 198 | 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, | ||
| 199 | 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xf8, 0x0f, | ||
| 200 | 0xf0, 0x07, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 | ||
| 201 | }; | ||
| 202 | |||
| 98 | #endif /* _HAIKU_GUI_H_ */ | 203 | #endif /* _HAIKU_GUI_H_ */ |
diff --git a/src/haikumenu.c b/src/haikumenu.c index 9779c34a998..5729bed4a9b 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c | |||
| @@ -35,26 +35,35 @@ int popup_activated_p = 0; | |||
| 35 | 35 | ||
| 36 | static void | 36 | static void |
| 37 | digest_menu_items (void *first_menu, int start, int menu_items_used, | 37 | digest_menu_items (void *first_menu, int start, int menu_items_used, |
| 38 | int mbar_p) | 38 | bool is_menu_bar) |
| 39 | { | 39 | { |
| 40 | void **menus, **panes; | 40 | void **menus, **panes; |
| 41 | ssize_t menu_len = (menu_items_used + 1 - start) * sizeof *menus; | 41 | ssize_t menu_len; |
| 42 | ssize_t pane_len = (menu_items_used + 1 - start) * sizeof *panes; | 42 | ssize_t pane_len; |
| 43 | int i, menu_depth; | ||
| 44 | void *menu, *window, *view; | ||
| 45 | Lisp_Object pane_name, prefix; | ||
| 46 | const char *pane_string; | ||
| 47 | Lisp_Object item_name, enable, descrip, def, selected, help; | ||
| 43 | 48 | ||
| 44 | menus = alloca (menu_len); | 49 | USE_SAFE_ALLOCA; |
| 45 | panes = alloca (pane_len); | ||
| 46 | 50 | ||
| 47 | int i = start, menu_depth = 0; | 51 | menu_len = (menu_items_used + 1 - start) * sizeof *menus; |
| 52 | pane_len = (menu_items_used + 1 - start) * sizeof *panes; | ||
| 53 | menu = first_menu; | ||
| 48 | 54 | ||
| 55 | i = start; | ||
| 56 | menu_depth = 0; | ||
| 57 | |||
| 58 | menus = SAFE_ALLOCA (menu_len); | ||
| 59 | panes = SAFE_ALLOCA (pane_len); | ||
| 49 | memset (menus, 0, menu_len); | 60 | memset (menus, 0, menu_len); |
| 50 | memset (panes, 0, pane_len); | 61 | memset (panes, 0, pane_len); |
| 51 | |||
| 52 | void *menu = first_menu; | ||
| 53 | |||
| 54 | menus[0] = first_menu; | 62 | menus[0] = first_menu; |
| 55 | 63 | ||
| 56 | void *window = NULL; | 64 | window = NULL; |
| 57 | void *view = NULL; | 65 | view = NULL; |
| 66 | |||
| 58 | if (FRAMEP (Vmenu_updating_frame) && | 67 | if (FRAMEP (Vmenu_updating_frame) && |
| 59 | FRAME_LIVE_P (XFRAME (Vmenu_updating_frame)) && | 68 | FRAME_LIVE_P (XFRAME (Vmenu_updating_frame)) && |
| 60 | FRAME_HAIKU_P (XFRAME (Vmenu_updating_frame))) | 69 | FRAME_HAIKU_P (XFRAME (Vmenu_updating_frame))) |
| @@ -83,9 +92,6 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, | |||
| 83 | i += 1; | 92 | i += 1; |
| 84 | else if (EQ (AREF (menu_items, i), Qt)) | 93 | else if (EQ (AREF (menu_items, i), Qt)) |
| 85 | { | 94 | { |
| 86 | Lisp_Object pane_name, prefix; | ||
| 87 | const char *pane_string; | ||
| 88 | |||
| 89 | if (menu_items_n_panes == 1) | 95 | if (menu_items_n_panes == 1) |
| 90 | { | 96 | { |
| 91 | i += MENU_ITEMS_PANE_LENGTH; | 97 | i += MENU_ITEMS_PANE_LENGTH; |
| @@ -116,7 +122,6 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, | |||
| 116 | } | 122 | } |
| 117 | else | 123 | else |
| 118 | { | 124 | { |
| 119 | Lisp_Object item_name, enable, descrip, def, selected, help; | ||
| 120 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); | 125 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); |
| 121 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); | 126 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); |
| 122 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); | 127 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); |
| @@ -144,7 +149,7 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, | |||
| 144 | menu = BMenu_new_submenu (menu, SSDATA (item_name), !NILP (enable)); | 149 | menu = BMenu_new_submenu (menu, SSDATA (item_name), !NILP (enable)); |
| 145 | else if (NILP (def) && menu_separator_name_p (SSDATA (item_name))) | 150 | else if (NILP (def) && menu_separator_name_p (SSDATA (item_name))) |
| 146 | BMenu_add_separator (menu); | 151 | BMenu_add_separator (menu); |
| 147 | else if (!mbar_p) | 152 | else if (!is_menu_bar) |
| 148 | { | 153 | { |
| 149 | if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode))) | 154 | if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode))) |
| 150 | BMenu_add_item (menu, SSDATA (item_name), | 155 | BMenu_add_item (menu, SSDATA (item_name), |
| @@ -178,6 +183,8 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, | |||
| 178 | 183 | ||
| 179 | if (view) | 184 | if (view) |
| 180 | BView_draw_unlock (view); | 185 | BView_draw_unlock (view); |
| 186 | |||
| 187 | SAFE_FREE (); | ||
| 181 | } | 188 | } |
| 182 | 189 | ||
| 183 | static Lisp_Object | 190 | static Lisp_Object |
| @@ -376,12 +383,18 @@ Lisp_Object | |||
| 376 | haiku_menu_show (struct frame *f, int x, int y, int menuflags, | 383 | haiku_menu_show (struct frame *f, int x, int y, int menuflags, |
| 377 | Lisp_Object title, const char **error_name) | 384 | Lisp_Object title, const char **error_name) |
| 378 | { | 385 | { |
| 379 | int i = 0, submenu_depth = 0; | 386 | int i, submenu_depth, j; |
| 380 | void *view = FRAME_HAIKU_VIEW (f); | 387 | void *view, *menu; |
| 381 | void *menu; | 388 | Lisp_Object *subprefix_stack; |
| 389 | Lisp_Object prefix, entry; | ||
| 382 | 390 | ||
| 383 | Lisp_Object *subprefix_stack = | 391 | USE_SAFE_ALLOCA; |
| 384 | alloca (menu_items_used * sizeof (Lisp_Object)); | 392 | |
| 393 | view = FRAME_HAIKU_VIEW (f); | ||
| 394 | i = 0; | ||
| 395 | submenu_depth = 0; | ||
| 396 | subprefix_stack | ||
| 397 | = SAFE_ALLOCA (menu_items_used * sizeof (Lisp_Object)); | ||
| 385 | 398 | ||
| 386 | eassert (FRAME_HAIKU_P (f)); | 399 | eassert (FRAME_HAIKU_P (f)); |
| 387 | 400 | ||
| @@ -390,6 +403,8 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 390 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) | 403 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) |
| 391 | { | 404 | { |
| 392 | *error_name = "Empty menu"; | 405 | *error_name = "Empty menu"; |
| 406 | |||
| 407 | SAFE_FREE (); | ||
| 393 | return Qnil; | 408 | return Qnil; |
| 394 | } | 409 | } |
| 395 | 410 | ||
| @@ -417,8 +432,6 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 417 | 432 | ||
| 418 | if (menu_item_selection) | 433 | if (menu_item_selection) |
| 419 | { | 434 | { |
| 420 | Lisp_Object prefix, entry; | ||
| 421 | |||
| 422 | prefix = entry = Qnil; | 435 | prefix = entry = Qnil; |
| 423 | i = 0; | 436 | i = 0; |
| 424 | while (i < menu_items_used) | 437 | while (i < menu_items_used) |
| @@ -452,8 +465,6 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 452 | { | 465 | { |
| 453 | if (menuflags & MENU_KEYMAPS) | 466 | if (menuflags & MENU_KEYMAPS) |
| 454 | { | 467 | { |
| 455 | int j; | ||
| 456 | |||
| 457 | entry = list1 (entry); | 468 | entry = list1 (entry); |
| 458 | if (!NILP (prefix)) | 469 | if (!NILP (prefix)) |
| 459 | entry = Fcons (prefix, entry); | 470 | entry = Fcons (prefix, entry); |
| @@ -464,6 +475,8 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 464 | block_input (); | 475 | block_input (); |
| 465 | BPopUpMenu_delete (menu); | 476 | BPopUpMenu_delete (menu); |
| 466 | unblock_input (); | 477 | unblock_input (); |
| 478 | |||
| 479 | SAFE_FREE (); | ||
| 467 | return entry; | 480 | return entry; |
| 468 | } | 481 | } |
| 469 | i += MENU_ITEMS_ITEM_LENGTH; | 482 | i += MENU_ITEMS_ITEM_LENGTH; |
| @@ -480,6 +493,8 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 480 | block_input (); | 493 | block_input (); |
| 481 | BPopUpMenu_delete (menu); | 494 | BPopUpMenu_delete (menu); |
| 482 | unblock_input (); | 495 | unblock_input (); |
| 496 | |||
| 497 | SAFE_FREE (); | ||
| 483 | return Qnil; | 498 | return Qnil; |
| 484 | } | 499 | } |
| 485 | 500 | ||
| @@ -728,7 +743,7 @@ run_menu_bar_help_event (struct frame *f, int mb_idx) | |||
| 728 | 743 | ||
| 729 | vec = f->menu_bar_vector; | 744 | vec = f->menu_bar_vector; |
| 730 | if ((mb_idx + MENU_ITEMS_ITEM_HELP) >= ASIZE (vec)) | 745 | if ((mb_idx + MENU_ITEMS_ITEM_HELP) >= ASIZE (vec)) |
| 731 | emacs_abort (); | 746 | return; |
| 732 | 747 | ||
| 733 | help = AREF (vec, mb_idx + MENU_ITEMS_ITEM_HELP); | 748 | help = AREF (vec, mb_idx + MENU_ITEMS_ITEM_HELP); |
| 734 | if (STRINGP (help) || NILP (help)) | 749 | if (STRINGP (help) || NILP (help)) |
diff --git a/src/haikuselect.c b/src/haikuselect.c index a186acc66ff..8a7b6f2e0b1 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c | |||
| @@ -33,8 +33,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 33 | the nested event loop inside be_drag_message. */ | 33 | the nested event loop inside be_drag_message. */ |
| 34 | struct frame *haiku_dnd_frame; | 34 | struct frame *haiku_dnd_frame; |
| 35 | 35 | ||
| 36 | /* Whether or not to move the tip frame during drag-and-drop. */ | ||
| 37 | bool haiku_dnd_follow_tooltip; | ||
| 38 | |||
| 36 | static void haiku_lisp_to_message (Lisp_Object, void *); | 39 | static void haiku_lisp_to_message (Lisp_Object, void *); |
| 37 | 40 | ||
| 41 | static enum haiku_clipboard | ||
| 42 | haiku_get_clipboard_name (Lisp_Object clipboard) | ||
| 43 | { | ||
| 44 | if (EQ (clipboard, QPRIMARY)) | ||
| 45 | return CLIPBOARD_PRIMARY; | ||
| 46 | |||
| 47 | if (EQ (clipboard, QSECONDARY)) | ||
| 48 | return CLIPBOARD_SECONDARY; | ||
| 49 | |||
| 50 | if (EQ (clipboard, QCLIPBOARD)) | ||
| 51 | return CLIPBOARD_CLIPBOARD; | ||
| 52 | |||
| 53 | signal_error ("Invalid clipboard", clipboard); | ||
| 54 | } | ||
| 55 | |||
| 38 | DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, | 56 | DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, |
| 39 | 2, 2, 0, | 57 | 2, 2, 0, |
| 40 | doc: /* Retrieve content typed as NAME from the clipboard | 58 | doc: /* Retrieve content typed as NAME from the clipboard |
| @@ -53,22 +71,15 @@ message in the format accepted by `haiku-drag-message', which see. */) | |||
| 53 | int rc; | 71 | int rc; |
| 54 | 72 | ||
| 55 | CHECK_SYMBOL (clipboard); | 73 | CHECK_SYMBOL (clipboard); |
| 56 | 74 | clipboard_name = haiku_get_clipboard_name (clipboard); | |
| 57 | if (!EQ (clipboard, QPRIMARY) && !EQ (clipboard, QSECONDARY) | ||
| 58 | && !EQ (clipboard, QCLIPBOARD)) | ||
| 59 | signal_error ("Invalid clipboard", clipboard); | ||
| 60 | 75 | ||
| 61 | if (!NILP (name)) | 76 | if (!NILP (name)) |
| 62 | { | 77 | { |
| 63 | CHECK_STRING (name); | 78 | CHECK_STRING (name); |
| 64 | 79 | ||
| 65 | block_input (); | 80 | block_input (); |
| 66 | if (EQ (clipboard, QPRIMARY)) | 81 | dat = be_find_clipboard_data (clipboard_name, |
| 67 | dat = BClipboard_find_primary_selection_data (SSDATA (name), &len); | 82 | SSDATA (name), &len); |
| 68 | else if (EQ (clipboard, QSECONDARY)) | ||
| 69 | dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len); | ||
| 70 | else | ||
| 71 | dat = BClipboard_find_system_data (SSDATA (name), &len); | ||
| 72 | unblock_input (); | 83 | unblock_input (); |
| 73 | 84 | ||
| 74 | if (!dat) | 85 | if (!dat) |
| @@ -83,18 +94,11 @@ message in the format accepted by `haiku-drag-message', which see. */) | |||
| 83 | Qforeign_selection, Qt, str); | 94 | Qforeign_selection, Qt, str); |
| 84 | 95 | ||
| 85 | block_input (); | 96 | block_input (); |
| 86 | BClipboard_free_data (dat); | 97 | free (dat); |
| 87 | unblock_input (); | 98 | unblock_input (); |
| 88 | } | 99 | } |
| 89 | else | 100 | else |
| 90 | { | 101 | { |
| 91 | if (EQ (clipboard, QPRIMARY)) | ||
| 92 | clipboard_name = CLIPBOARD_PRIMARY; | ||
| 93 | else if (EQ (clipboard, QSECONDARY)) | ||
| 94 | clipboard_name = CLIPBOARD_SECONDARY; | ||
| 95 | else | ||
| 96 | clipboard_name = CLIPBOARD_CLIPBOARD; | ||
| 97 | |||
| 98 | block_input (); | 102 | block_input (); |
| 99 | rc = be_lock_clipboard_message (clipboard_name, &message, false); | 103 | rc = be_lock_clipboard_message (clipboard_name, &message, false); |
| 100 | unblock_input (); | 104 | unblock_input (); |
| @@ -139,16 +143,12 @@ In that case, the arguments after NAME are ignored. */) | |||
| 139 | int rc; | 143 | int rc; |
| 140 | void *message; | 144 | void *message; |
| 141 | 145 | ||
| 146 | CHECK_SYMBOL (clipboard); | ||
| 147 | clipboard_name = haiku_get_clipboard_name (clipboard); | ||
| 148 | |||
| 142 | if (CONSP (name) || NILP (name)) | 149 | if (CONSP (name) || NILP (name)) |
| 143 | { | 150 | { |
| 144 | if (EQ (clipboard, QPRIMARY)) | 151 | be_update_clipboard_count (clipboard_name); |
| 145 | clipboard_name = CLIPBOARD_PRIMARY; | ||
| 146 | else if (EQ (clipboard, QSECONDARY)) | ||
| 147 | clipboard_name = CLIPBOARD_SECONDARY; | ||
| 148 | else if (EQ (clipboard, QCLIPBOARD)) | ||
| 149 | clipboard_name = CLIPBOARD_CLIPBOARD; | ||
| 150 | else | ||
| 151 | signal_error ("Invalid clipboard", clipboard); | ||
| 152 | 152 | ||
| 153 | rc = be_lock_clipboard_message (clipboard_name, | 153 | rc = be_lock_clipboard_message (clipboard_name, |
| 154 | &message, true); | 154 | &message, true); |
| @@ -164,7 +164,6 @@ In that case, the arguments after NAME are ignored. */) | |||
| 164 | return unbind_to (ref, Qnil); | 164 | return unbind_to (ref, Qnil); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | CHECK_SYMBOL (clipboard); | ||
| 168 | CHECK_STRING (name); | 167 | CHECK_STRING (name); |
| 169 | if (!NILP (data)) | 168 | if (!NILP (data)) |
| 170 | CHECK_STRING (data); | 169 | CHECK_STRING (data); |
| @@ -172,20 +171,8 @@ In that case, the arguments after NAME are ignored. */) | |||
| 172 | dat = !NILP (data) ? SSDATA (data) : NULL; | 171 | dat = !NILP (data) ? SSDATA (data) : NULL; |
| 173 | len = !NILP (data) ? SBYTES (data) : 0; | 172 | len = !NILP (data) ? SBYTES (data) : 0; |
| 174 | 173 | ||
| 175 | if (EQ (clipboard, QPRIMARY)) | 174 | be_set_clipboard_data (clipboard_name, SSDATA (name), dat, len, |
| 176 | BClipboard_set_primary_selection_data (SSDATA (name), dat, len, | 175 | !NILP (clear)); |
| 177 | !NILP (clear)); | ||
| 178 | else if (EQ (clipboard, QSECONDARY)) | ||
| 179 | BClipboard_set_secondary_selection_data (SSDATA (name), dat, len, | ||
| 180 | !NILP (clear)); | ||
| 181 | else if (EQ (clipboard, QCLIPBOARD)) | ||
| 182 | BClipboard_set_system_data (SSDATA (name), dat, len, !NILP (clear)); | ||
| 183 | else | ||
| 184 | { | ||
| 185 | unblock_input (); | ||
| 186 | signal_error ("Bad clipboard", clipboard); | ||
| 187 | } | ||
| 188 | |||
| 189 | return Qnil; | 176 | return Qnil; |
| 190 | } | 177 | } |
| 191 | 178 | ||
| @@ -193,27 +180,15 @@ DEFUN ("haiku-selection-owner-p", Fhaiku_selection_owner_p, Shaiku_selection_own | |||
| 193 | 0, 1, 0, | 180 | 0, 1, 0, |
| 194 | doc: /* Whether the current Emacs process owns the given SELECTION. | 181 | doc: /* Whether the current Emacs process owns the given SELECTION. |
| 195 | The arg should be the name of the selection in question, typically one | 182 | The arg should be the name of the selection in question, typically one |
| 196 | of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. For | 183 | of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) |
| 197 | convenience, the symbol nil is the same as `PRIMARY', and t is the | ||
| 198 | same as `SECONDARY'. */) | ||
| 199 | (Lisp_Object selection) | 184 | (Lisp_Object selection) |
| 200 | { | 185 | { |
| 201 | bool value; | 186 | bool value; |
| 202 | 187 | enum haiku_clipboard name; | |
| 203 | if (NILP (selection)) | ||
| 204 | selection = QPRIMARY; | ||
| 205 | else if (EQ (selection, Qt)) | ||
| 206 | selection = QSECONDARY; | ||
| 207 | 188 | ||
| 208 | block_input (); | 189 | block_input (); |
| 209 | if (EQ (selection, QPRIMARY)) | 190 | name = haiku_get_clipboard_name (selection); |
| 210 | value = BClipboard_owns_primary (); | 191 | value = be_clipboard_owner_p (name); |
| 211 | else if (EQ (selection, QSECONDARY)) | ||
| 212 | value = BClipboard_owns_secondary (); | ||
| 213 | else if (EQ (selection, QCLIPBOARD)) | ||
| 214 | value = BClipboard_owns_clipboard (); | ||
| 215 | else | ||
| 216 | value = false; | ||
| 217 | unblock_input (); | 192 | unblock_input (); |
| 218 | 193 | ||
| 219 | return value ? Qt : Qnil; | 194 | return value ? Qt : Qnil; |
| @@ -275,7 +250,7 @@ haiku_message_to_lisp (void *message) | |||
| 275 | if (!pbuf) | 250 | if (!pbuf) |
| 276 | memory_full (SIZE_MAX); | 251 | memory_full (SIZE_MAX); |
| 277 | 252 | ||
| 278 | t1 = build_string (pbuf); | 253 | t1 = DECODE_FILE (build_string (pbuf)); |
| 279 | 254 | ||
| 280 | free (pbuf); | 255 | free (pbuf); |
| 281 | break; | 256 | break; |
| @@ -320,6 +295,14 @@ haiku_message_to_lisp (void *message) | |||
| 320 | t1 = make_int ((intmax_t) *(ssize_t *) buf); | 295 | t1 = make_int ((intmax_t) *(ssize_t *) buf); |
| 321 | break; | 296 | break; |
| 322 | 297 | ||
| 298 | case 'DBLE': | ||
| 299 | t1 = make_float (*(double *) buf); | ||
| 300 | break; | ||
| 301 | |||
| 302 | case 'FLOT': | ||
| 303 | t1 = make_float (*(float *) buf); | ||
| 304 | break; | ||
| 305 | |||
| 323 | default: | 306 | default: |
| 324 | t1 = make_uninit_string (buf_size); | 307 | t1 = make_uninit_string (buf_size); |
| 325 | memcpy (SDATA (t1), buf, buf_size); | 308 | memcpy (SDATA (t1), buf, buf_size); |
| @@ -378,6 +361,14 @@ haiku_message_to_lisp (void *message) | |||
| 378 | t2 = Qpoint; | 361 | t2 = Qpoint; |
| 379 | break; | 362 | break; |
| 380 | 363 | ||
| 364 | case 'DBLE': | ||
| 365 | t2 = Qdouble; | ||
| 366 | break; | ||
| 367 | |||
| 368 | case 'FLOT': | ||
| 369 | t2 = Qfloat; | ||
| 370 | break; | ||
| 371 | |||
| 381 | default: | 372 | default: |
| 382 | t2 = make_int (type_code); | 373 | t2 = make_int (type_code); |
| 383 | } | 374 | } |
| @@ -423,6 +414,10 @@ lisp_to_type_code (Lisp_Object obj) | |||
| 423 | return 'SSZT'; | 414 | return 'SSZT'; |
| 424 | else if (EQ (obj, Qpoint)) | 415 | else if (EQ (obj, Qpoint)) |
| 425 | return 'BPNT'; | 416 | return 'BPNT'; |
| 417 | else if (EQ (obj, Qfloat)) | ||
| 418 | return 'FLOT'; | ||
| 419 | else if (EQ (obj, Qdouble)) | ||
| 420 | return 'DBLE'; | ||
| 426 | else | 421 | else |
| 427 | return -1; | 422 | return -1; |
| 428 | } | 423 | } |
| @@ -441,7 +436,8 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 441 | ssize_t ssizet_data; | 436 | ssize_t ssizet_data; |
| 442 | intmax_t t4; | 437 | intmax_t t4; |
| 443 | uintmax_t t5; | 438 | uintmax_t t5; |
| 444 | float t6, t7; | 439 | float t6, t7, float_data; |
| 440 | double double_data; | ||
| 445 | int rc; | 441 | int rc; |
| 446 | specpdl_ref ref; | 442 | specpdl_ref ref; |
| 447 | 443 | ||
| @@ -526,7 +522,8 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 526 | case 'RREF': | 522 | case 'RREF': |
| 527 | CHECK_STRING (data); | 523 | CHECK_STRING (data); |
| 528 | 524 | ||
| 529 | if (be_add_refs_data (message, SSDATA (name), SSDATA (data)) | 525 | if (be_add_refs_data (message, SSDATA (name), |
| 526 | SSDATA (ENCODE_FILE (data))) | ||
| 530 | && haiku_signal_invalid_refs) | 527 | && haiku_signal_invalid_refs) |
| 531 | signal_error ("Invalid file name", data); | 528 | signal_error ("Invalid file name", data); |
| 532 | break; | 529 | break; |
| @@ -544,6 +541,30 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 544 | signal_error ("Invalid point", data); | 541 | signal_error ("Invalid point", data); |
| 545 | break; | 542 | break; |
| 546 | 543 | ||
| 544 | case 'FLOT': | ||
| 545 | CHECK_NUMBER (data); | ||
| 546 | float_data = XFLOATINT (data); | ||
| 547 | |||
| 548 | rc = be_add_message_data (message, SSDATA (name), | ||
| 549 | type_code, &float_data, | ||
| 550 | sizeof float_data); | ||
| 551 | |||
| 552 | if (rc) | ||
| 553 | signal_error ("Failed to add float", data); | ||
| 554 | break; | ||
| 555 | |||
| 556 | case 'DBLE': | ||
| 557 | CHECK_NUMBER (data); | ||
| 558 | double_data = XFLOATINT (data); | ||
| 559 | |||
| 560 | rc = be_add_message_data (message, SSDATA (name), | ||
| 561 | type_code, &double_data, | ||
| 562 | sizeof double_data); | ||
| 563 | |||
| 564 | if (rc) | ||
| 565 | signal_error ("Failed to add double", data); | ||
| 566 | break; | ||
| 567 | |||
| 547 | case 'SHRT': | 568 | case 'SHRT': |
| 548 | if (!TYPE_RANGED_FIXNUMP (int16, data)) | 569 | if (!TYPE_RANGED_FIXNUMP (int16, data)) |
| 549 | signal_error ("Invalid value", data); | 570 | signal_error ("Invalid value", data); |
| @@ -737,7 +758,7 @@ haiku_unwind_drag_message (void *message) | |||
| 737 | } | 758 | } |
| 738 | 759 | ||
| 739 | DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message, | 760 | DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message, |
| 740 | 2, 3, 0, | 761 | 2, 4, 0, |
| 741 | doc: /* Begin dragging MESSAGE from FRAME. | 762 | doc: /* Begin dragging MESSAGE from FRAME. |
| 742 | 763 | ||
| 743 | MESSAGE an alist of strings, denoting message field names, to a list | 764 | MESSAGE an alist of strings, denoting message field names, to a list |
| @@ -758,6 +779,10 @@ system. If TYPE is `ssize_t', then DATA is an integer that can hold | |||
| 758 | values from -1 to the maximum value of the C data type `ssize_t' on | 779 | values from -1 to the maximum value of the C data type `ssize_t' on |
| 759 | the current system. If TYPE is `point', then DATA is a cons of float | 780 | the current system. If TYPE is `point', then DATA is a cons of float |
| 760 | values describing the X and Y coordinates of an on-screen location. | 781 | values describing the X and Y coordinates of an on-screen location. |
| 782 | If TYPE is `float', then DATA is a low-precision floating point | ||
| 783 | number, whose exact precision is not guaranteed. If TYPE is `double', | ||
| 784 | then DATA is a floating point number that can represent any value a | ||
| 785 | Lisp float can represent. | ||
| 761 | 786 | ||
| 762 | If the field name is not a string but the symbol `type', then it | 787 | If the field name is not a string but the symbol `type', then it |
| 763 | associates to a 32-bit unsigned integer describing the type of the | 788 | associates to a 32-bit unsigned integer describing the type of the |
| @@ -767,8 +792,12 @@ FRAME is a window system frame that must be visible, from which the | |||
| 767 | drag will originate. | 792 | drag will originate. |
| 768 | 793 | ||
| 769 | ALLOW-SAME-FRAME, if nil or not specified, means that MESSAGE will be | 794 | ALLOW-SAME-FRAME, if nil or not specified, means that MESSAGE will be |
| 770 | ignored if it is dropped on top of FRAME. */) | 795 | ignored if it is dropped on top of FRAME. |
| 771 | (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame) | 796 | |
| 797 | FOLLOW-TOOLTIP, if non-nil, will cause any non-system tooltip | ||
| 798 | currently being displayed to move along with the mouse pointer. */) | ||
| 799 | (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame, | ||
| 800 | Lisp_Object follow_tooltip) | ||
| 772 | { | 801 | { |
| 773 | specpdl_ref idx; | 802 | specpdl_ref idx; |
| 774 | void *be_message; | 803 | void *be_message; |
| @@ -782,23 +811,167 @@ ignored if it is dropped on top of FRAME. */) | |||
| 782 | error ("Frame is invisible"); | 811 | error ("Frame is invisible"); |
| 783 | 812 | ||
| 784 | haiku_dnd_frame = f; | 813 | haiku_dnd_frame = f; |
| 814 | haiku_dnd_follow_tooltip = !NILP (follow_tooltip); | ||
| 785 | be_message = be_create_simple_message (); | 815 | be_message = be_create_simple_message (); |
| 786 | 816 | ||
| 787 | record_unwind_protect_ptr (haiku_unwind_drag_message, be_message); | 817 | record_unwind_protect_ptr (haiku_unwind_drag_message, be_message); |
| 788 | haiku_lisp_to_message (message, be_message); | 818 | haiku_lisp_to_message (message, be_message); |
| 819 | |||
| 789 | rc = be_drag_message (FRAME_HAIKU_VIEW (f), be_message, | 820 | rc = be_drag_message (FRAME_HAIKU_VIEW (f), be_message, |
| 790 | !NILP (allow_same_frame), | 821 | !NILP (allow_same_frame), |
| 791 | block_input, unblock_input, | 822 | block_input, unblock_input, |
| 792 | process_pending_signals, | 823 | process_pending_signals, |
| 793 | haiku_should_quit_drag); | 824 | haiku_should_quit_drag); |
| 794 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | ||
| 795 | 825 | ||
| 826 | /* Don't clear the mouse grab if the user decided to quit instead | ||
| 827 | of the drop finishing. */ | ||
| 796 | if (rc) | 828 | if (rc) |
| 797 | quit (); | 829 | quit (); |
| 798 | 830 | ||
| 831 | /* Now dismiss the tooltip, since the drop presumably succeeded. */ | ||
| 832 | if (!NILP (follow_tooltip)) | ||
| 833 | Fx_hide_tip (); | ||
| 834 | |||
| 835 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | ||
| 836 | |||
| 799 | return unbind_to (idx, Qnil); | 837 | return unbind_to (idx, Qnil); |
| 800 | } | 838 | } |
| 801 | 839 | ||
| 840 | DEFUN ("haiku-roster-launch", Fhaiku_roster_launch, Shaiku_roster_launch, | ||
| 841 | 2, 2, 0, | ||
| 842 | doc: /* Launch an application associated with FILE-OR-TYPE. | ||
| 843 | Return the process ID of any process created, the symbol | ||
| 844 | `already-running' if ARGS was sent to a program that's already | ||
| 845 | running, or nil if launching the application failed because no | ||
| 846 | application was found for FILE-OR-TYPE. | ||
| 847 | |||
| 848 | Signal an error if FILE-OR-TYPE is invalid, or if ARGS is a message | ||
| 849 | but the application doesn't accept messages. | ||
| 850 | |||
| 851 | FILE-OR-TYPE can either be a string denoting a MIME type, or a list | ||
| 852 | with one argument FILE, denoting a file whose associated application | ||
| 853 | will be launched. | ||
| 854 | |||
| 855 | ARGS can either be a vector of strings containing the arguments that | ||
| 856 | will be passed to the application, or a system message in the form | ||
| 857 | accepted by `haiku-drag-message' that will be sent to the application | ||
| 858 | after it starts. */) | ||
| 859 | (Lisp_Object file_or_type, Lisp_Object args) | ||
| 860 | { | ||
| 861 | char **cargs; | ||
| 862 | char *type, *file; | ||
| 863 | team_id team_id; | ||
| 864 | status_t rc; | ||
| 865 | ptrdiff_t i, nargs; | ||
| 866 | Lisp_Object tem, canonical; | ||
| 867 | void *message; | ||
| 868 | specpdl_ref depth; | ||
| 869 | |||
| 870 | type = NULL; | ||
| 871 | file = NULL; | ||
| 872 | cargs = NULL; | ||
| 873 | message = NULL; | ||
| 874 | nargs = 0; | ||
| 875 | depth = SPECPDL_INDEX (); | ||
| 876 | |||
| 877 | USE_SAFE_ALLOCA; | ||
| 878 | |||
| 879 | if (STRINGP (file_or_type)) | ||
| 880 | SAFE_ALLOCA_STRING (type, file_or_type); | ||
| 881 | else | ||
| 882 | { | ||
| 883 | CHECK_LIST (file_or_type); | ||
| 884 | tem = XCAR (file_or_type); | ||
| 885 | canonical = Fexpand_file_name (tem, Qnil); | ||
| 886 | |||
| 887 | CHECK_STRING (tem); | ||
| 888 | SAFE_ALLOCA_STRING (file, ENCODE_FILE (canonical)); | ||
| 889 | CHECK_LIST_END (XCDR (file_or_type), file_or_type); | ||
| 890 | } | ||
| 891 | |||
| 892 | if (VECTORP (args)) | ||
| 893 | { | ||
| 894 | nargs = ASIZE (args); | ||
| 895 | cargs = SAFE_ALLOCA (nargs * sizeof *cargs); | ||
| 896 | |||
| 897 | for (i = 0; i < nargs; ++i) | ||
| 898 | { | ||
| 899 | tem = AREF (args, i); | ||
| 900 | CHECK_STRING (tem); | ||
| 901 | maybe_quit (); | ||
| 902 | |||
| 903 | cargs[i] = SAFE_ALLOCA (SBYTES (tem) + 1); | ||
| 904 | memcpy (cargs[i], SDATA (tem), SBYTES (tem) + 1); | ||
| 905 | } | ||
| 906 | } | ||
| 907 | else | ||
| 908 | { | ||
| 909 | message = be_create_simple_message (); | ||
| 910 | |||
| 911 | record_unwind_protect_ptr (BMessage_delete, message); | ||
| 912 | haiku_lisp_to_message (args, message); | ||
| 913 | } | ||
| 914 | |||
| 915 | block_input (); | ||
| 916 | rc = be_roster_launch (type, file, cargs, nargs, message, | ||
| 917 | &team_id); | ||
| 918 | unblock_input (); | ||
| 919 | |||
| 920 | /* `be_roster_launch' can potentially take a while in IO, but | ||
| 921 | signals from async input will interrupt that operation. If the | ||
| 922 | user wanted to quit, act like it. */ | ||
| 923 | maybe_quit (); | ||
| 924 | |||
| 925 | if (rc == B_OK) | ||
| 926 | return SAFE_FREE_UNBIND_TO (depth, | ||
| 927 | make_uint (team_id)); | ||
| 928 | else if (rc == B_ALREADY_RUNNING) | ||
| 929 | return Qalready_running; | ||
| 930 | else if (rc == B_BAD_VALUE) | ||
| 931 | signal_error ("Invalid type or bad arguments", | ||
| 932 | list2 (file_or_type, args)); | ||
| 933 | |||
| 934 | return SAFE_FREE_UNBIND_TO (depth, Qnil); | ||
| 935 | } | ||
| 936 | |||
| 937 | static void | ||
| 938 | haiku_dnd_compute_tip_xy (int *root_x, int *root_y) | ||
| 939 | { | ||
| 940 | int min_x, min_y, max_x, max_y; | ||
| 941 | int width, height; | ||
| 942 | |||
| 943 | width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame)); | ||
| 944 | height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame)); | ||
| 945 | |||
| 946 | min_x = 0; | ||
| 947 | min_y = 0; | ||
| 948 | be_get_screen_dimensions (&max_x, &max_y); | ||
| 949 | |||
| 950 | if (*root_y + XFIXNUM (tip_dy) <= min_y) | ||
| 951 | *root_y = min_y; /* Can happen for negative dy */ | ||
| 952 | else if (*root_y + XFIXNUM (tip_dy) + height <= max_y) | ||
| 953 | /* It fits below the pointer */ | ||
| 954 | *root_y += XFIXNUM (tip_dy); | ||
| 955 | else if (height + XFIXNUM (tip_dy) + min_y <= *root_y) | ||
| 956 | /* It fits above the pointer. */ | ||
| 957 | *root_y -= height + XFIXNUM (tip_dy); | ||
| 958 | else | ||
| 959 | /* Put it on the top. */ | ||
| 960 | *root_y = min_y; | ||
| 961 | |||
| 962 | if (*root_x + XFIXNUM (tip_dx) <= min_x) | ||
| 963 | *root_x = 0; /* Can happen for negative dx */ | ||
| 964 | else if (*root_x + XFIXNUM (tip_dx) + width <= max_x) | ||
| 965 | /* It fits to the right of the pointer. */ | ||
| 966 | *root_x += XFIXNUM (tip_dx); | ||
| 967 | else if (width + XFIXNUM (tip_dx) + min_x <= *root_x) | ||
| 968 | /* It fits to the left of the pointer. */ | ||
| 969 | *root_x -= width + XFIXNUM (tip_dx); | ||
| 970 | else | ||
| 971 | /* Put it left justified on the screen -- it ought to fit that way. */ | ||
| 972 | *root_x = min_x; | ||
| 973 | } | ||
| 974 | |||
| 802 | static Lisp_Object | 975 | static Lisp_Object |
| 803 | haiku_note_drag_motion_1 (void *data) | 976 | haiku_note_drag_motion_1 (void *data) |
| 804 | { | 977 | { |
| @@ -817,6 +990,26 @@ haiku_note_drag_motion_2 (enum nonlocal_exit exit, Lisp_Object error) | |||
| 817 | void | 990 | void |
| 818 | haiku_note_drag_motion (void) | 991 | haiku_note_drag_motion (void) |
| 819 | { | 992 | { |
| 993 | struct frame *tip_f; | ||
| 994 | int x, y; | ||
| 995 | |||
| 996 | if (FRAMEP (tip_frame) && haiku_dnd_follow_tooltip | ||
| 997 | && FIXNUMP (tip_dx) && FIXNUMP (tip_dy)) | ||
| 998 | { | ||
| 999 | tip_f = XFRAME (tip_frame); | ||
| 1000 | |||
| 1001 | if (FRAME_LIVE_P (tip_f) && FRAME_VISIBLE_P (tip_f)) | ||
| 1002 | { | ||
| 1003 | BView_get_mouse (FRAME_HAIKU_VIEW (haiku_dnd_frame), | ||
| 1004 | &x, &y); | ||
| 1005 | BView_convert_to_screen (FRAME_HAIKU_VIEW (haiku_dnd_frame), | ||
| 1006 | &x, &y); | ||
| 1007 | |||
| 1008 | haiku_dnd_compute_tip_xy (&x, &y); | ||
| 1009 | BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), x, y); | ||
| 1010 | } | ||
| 1011 | } | ||
| 1012 | |||
| 820 | internal_catch_all (haiku_note_drag_motion_1, NULL, | 1013 | internal_catch_all (haiku_note_drag_motion_1, NULL, |
| 821 | haiku_note_drag_motion_2); | 1014 | haiku_note_drag_motion_2); |
| 822 | } | 1015 | } |
| @@ -855,11 +1048,15 @@ used to retrieve the current position of the mouse. */); | |||
| 855 | DEFSYM (Qsize_t, "size_t"); | 1048 | DEFSYM (Qsize_t, "size_t"); |
| 856 | DEFSYM (Qssize_t, "ssize_t"); | 1049 | DEFSYM (Qssize_t, "ssize_t"); |
| 857 | DEFSYM (Qpoint, "point"); | 1050 | DEFSYM (Qpoint, "point"); |
| 1051 | DEFSYM (Qfloat, "float"); | ||
| 1052 | DEFSYM (Qdouble, "double"); | ||
| 1053 | DEFSYM (Qalready_running, "already-running"); | ||
| 858 | 1054 | ||
| 859 | defsubr (&Shaiku_selection_data); | 1055 | defsubr (&Shaiku_selection_data); |
| 860 | defsubr (&Shaiku_selection_put); | 1056 | defsubr (&Shaiku_selection_put); |
| 861 | defsubr (&Shaiku_selection_owner_p); | 1057 | defsubr (&Shaiku_selection_owner_p); |
| 862 | defsubr (&Shaiku_drag_message); | 1058 | defsubr (&Shaiku_drag_message); |
| 1059 | defsubr (&Shaiku_roster_launch); | ||
| 863 | 1060 | ||
| 864 | haiku_dnd_frame = NULL; | 1061 | haiku_dnd_frame = NULL; |
| 865 | } | 1062 | } |
diff --git a/src/haikuselect.h b/src/haikuselect.h index d4f331a9ccb..e9a2f2dd77d 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h | |||
| @@ -37,31 +37,17 @@ enum haiku_clipboard | |||
| 37 | #ifdef __cplusplus | 37 | #ifdef __cplusplus |
| 38 | extern "C" | 38 | extern "C" |
| 39 | { | 39 | { |
| 40 | /* Also declared in haikuterm.h for use in emacs.c. */ | ||
| 40 | extern void init_haiku_select (void); | 41 | extern void init_haiku_select (void); |
| 41 | #endif | 42 | #endif |
| 42 | /* Whether or not the selection was recently changed. */ | 43 | /* Whether or not the selection was recently changed. */ |
| 43 | 44 | ||
| 44 | /* Find a string with the MIME type TYPE in the system clipboard. */ | 45 | extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, ssize_t *); |
| 45 | extern char *BClipboard_find_system_data (const char *, ssize_t *); | 46 | extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const char *, |
| 46 | extern char *BClipboard_find_primary_selection_data (const char *, ssize_t *); | 47 | ssize_t, bool); |
| 47 | extern char *BClipboard_find_secondary_selection_data (const char *, ssize_t *); | 48 | extern void be_get_clipboard_targets (enum haiku_clipboard, char **, int); |
| 48 | 49 | extern bool be_clipboard_owner_p (enum haiku_clipboard); | |
| 49 | extern void BClipboard_set_system_data (const char *, const char *, ssize_t, bool); | 50 | extern void be_update_clipboard_count (enum haiku_clipboard); |
| 50 | extern void BClipboard_set_primary_selection_data (const char *, const char *, | ||
| 51 | ssize_t, bool); | ||
| 52 | extern void BClipboard_set_secondary_selection_data (const char *, const char *, | ||
| 53 | ssize_t, bool); | ||
| 54 | |||
| 55 | extern void BClipboard_system_targets (char **, int); | ||
| 56 | extern void BClipboard_primary_targets (char **, int); | ||
| 57 | extern void BClipboard_secondary_targets (char **, int); | ||
| 58 | |||
| 59 | extern bool BClipboard_owns_clipboard (void); | ||
| 60 | extern bool BClipboard_owns_primary (void); | ||
| 61 | extern bool BClipboard_owns_secondary (void); | ||
| 62 | |||
| 63 | /* Free the returned data. */ | ||
| 64 | extern void BClipboard_free_data (void *); | ||
| 65 | 51 | ||
| 66 | extern int be_enum_message (void *, int32 *, int32, int32 *, const char **); | 52 | extern int be_enum_message (void *, int32 *, int32, int32 *, const char **); |
| 67 | extern int be_get_message_data (void *, const char *, int32, int32, | 53 | extern int be_get_message_data (void *, const char *, int32, int32, |
diff --git a/src/haikuterm.c b/src/haikuterm.c index ced16d9f09b..365b23cd92c 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c | |||
| @@ -43,17 +43,24 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 43 | /* Minimum and maximum values used for Haiku scroll bars. */ | 43 | /* Minimum and maximum values used for Haiku scroll bars. */ |
| 44 | #define BE_SB_MAX 12000000 | 44 | #define BE_SB_MAX 12000000 |
| 45 | 45 | ||
| 46 | struct haiku_display_info *x_display_list = NULL; | 46 | /* The single Haiku display (if any). */ |
| 47 | extern frame_parm_handler haiku_frame_parm_handlers[]; | 47 | struct haiku_display_info *x_display_list; |
| 48 | 48 | ||
| 49 | /* This is used to determine when to evict the font lookup cache, | 49 | /* This is used to determine when to evict the font lookup cache, |
| 50 | which we do every 50 updates. */ | 50 | which we do every 50 updates. */ |
| 51 | static int up_to_date_count; | 51 | static int up_to_date_count; |
| 52 | 52 | ||
| 53 | /* List of defined fringe bitmaps. */ | ||
| 53 | static void **fringe_bmps; | 54 | static void **fringe_bmps; |
| 54 | static int max_fringe_bmp = 0; | ||
| 55 | 55 | ||
| 56 | /* The amount of fringe bitmaps in that list. */ | ||
| 57 | static int max_fringe_bmp; | ||
| 58 | |||
| 59 | /* Alist of resources to their values. */ | ||
| 56 | static Lisp_Object rdb; | 60 | static Lisp_Object rdb; |
| 61 | |||
| 62 | /* Non-zero means that a HELP_EVENT has been generated since Emacs | ||
| 63 | start. */ | ||
| 57 | static bool any_help_event_p; | 64 | static bool any_help_event_p; |
| 58 | 65 | ||
| 59 | char * | 66 | char * |
| @@ -89,14 +96,9 @@ static void | |||
| 89 | haiku_coords_from_parent (struct frame *f, int *x, int *y) | 96 | haiku_coords_from_parent (struct frame *f, int *x, int *y) |
| 90 | { | 97 | { |
| 91 | struct frame *p = FRAME_PARENT_FRAME (f); | 98 | struct frame *p = FRAME_PARENT_FRAME (f); |
| 92 | eassert (p); | ||
| 93 | 99 | ||
| 94 | for (struct frame *parent = p; parent; | 100 | *x -= FRAME_OUTPUT_DATA (p)->frame_x; |
| 95 | parent = FRAME_PARENT_FRAME (parent)) | 101 | *y -= FRAME_OUTPUT_DATA (p)->frame_y; |
| 96 | { | ||
| 97 | *x -= parent->left_pos; | ||
| 98 | *y -= parent->top_pos; | ||
| 99 | } | ||
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | static void | 104 | static void |
| @@ -115,7 +117,8 @@ haiku_delete_terminal (struct terminal *terminal) | |||
| 115 | } | 117 | } |
| 116 | 118 | ||
| 117 | static const char * | 119 | static const char * |
| 118 | get_string_resource (void *ignored, const char *name, const char *class) | 120 | haiku_get_string_resource (void *ignored, const char *name, |
| 121 | const char *class) | ||
| 119 | { | 122 | { |
| 120 | const char *native; | 123 | const char *native; |
| 121 | 124 | ||
| @@ -196,6 +199,8 @@ haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst) | |||
| 196 | { | 199 | { |
| 197 | BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y, | 200 | BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y, |
| 198 | s->width, s->height); | 201 | s->width, s->height); |
| 202 | BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), s->x, | ||
| 203 | s->y, s->width, s->height); | ||
| 199 | } | 204 | } |
| 200 | 205 | ||
| 201 | static void | 206 | static void |
| @@ -511,6 +516,9 @@ haiku_scroll_bar_from_widget (void *scroll_bar, void *window) | |||
| 511 | if (!frame) | 516 | if (!frame) |
| 512 | return NULL; | 517 | return NULL; |
| 513 | 518 | ||
| 519 | if (!scroll_bar) | ||
| 520 | return NULL; | ||
| 521 | |||
| 514 | if (!NILP (FRAME_SCROLL_BARS (frame))) | 522 | if (!NILP (FRAME_SCROLL_BARS (frame))) |
| 515 | { | 523 | { |
| 516 | for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem); | 524 | for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem); |
| @@ -567,20 +575,24 @@ haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor) | |||
| 567 | } | 575 | } |
| 568 | 576 | ||
| 569 | static bool | 577 | static bool |
| 570 | haiku_defined_color (struct frame *f, | 578 | haiku_defined_color (struct frame *f, const char *name, |
| 571 | const char *name, | 579 | Emacs_Color *color, bool alloc, bool make_index) |
| 572 | Emacs_Color *color, | ||
| 573 | bool alloc, | ||
| 574 | bool make_index) | ||
| 575 | { | 580 | { |
| 576 | return !haiku_get_color (name, color); | 581 | int rc; |
| 582 | |||
| 583 | rc = !haiku_get_color (name, color); | ||
| 584 | |||
| 585 | if (rc && f->gamma && alloc) | ||
| 586 | gamma_correct (f, color); | ||
| 587 | |||
| 588 | return rc; | ||
| 577 | } | 589 | } |
| 578 | 590 | ||
| 579 | /* Adapted from xterm `x_draw_box_rect'. */ | 591 | /* Adapted from xterm `x_draw_box_rect'. */ |
| 580 | static void | 592 | static void |
| 581 | haiku_draw_box_rect (struct glyph_string *s, | 593 | haiku_draw_box_rect (struct glyph_string *s, int left_x, int top_y, |
| 582 | int left_x, int top_y, int right_x, int bottom_y, int hwidth, | 594 | int right_x, int bottom_y, int hwidth, int vwidth, |
| 583 | int vwidth, bool left_p, bool right_p, struct haiku_rect *clip_rect) | 595 | bool left_p, bool right_p, struct haiku_rect *clip_rect) |
| 584 | { | 596 | { |
| 585 | void *view = FRAME_HAIKU_VIEW (s->f); | 597 | void *view = FRAME_HAIKU_VIEW (s->f); |
| 586 | struct face *face = s->face; | 598 | struct face *face = s->face; |
| @@ -604,13 +616,19 @@ static void | |||
| 604 | haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w, | 616 | haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w, |
| 605 | uint32_t *rgbout_b) | 617 | uint32_t *rgbout_b) |
| 606 | { | 618 | { |
| 607 | struct face *face = s->face; | ||
| 608 | double h, cs, l; | 619 | double h, cs, l; |
| 609 | uint32_t rgbin; | 620 | uint32_t rgbin; |
| 610 | struct haiku_output *di; | 621 | struct haiku_output *di; |
| 611 | 622 | ||
| 612 | rgbin = (face->use_box_color_for_shadows_p | 623 | if (s->face->use_box_color_for_shadows_p) |
| 613 | ? face->box_color : face->background); | 624 | rgbin = s->face->box_color; |
| 625 | else if (s->first_glyph->type == IMAGE_GLYPH | ||
| 626 | && s->img->pixmap | ||
| 627 | && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) | ||
| 628 | rgbin = IMAGE_BACKGROUND (s->img, s->f, 0); | ||
| 629 | else | ||
| 630 | rgbin = s->face->background; | ||
| 631 | |||
| 614 | di = FRAME_OUTPUT_DATA (s->f); | 632 | di = FRAME_OUTPUT_DATA (s->f); |
| 615 | 633 | ||
| 616 | if (s->hl == DRAW_CURSOR) | 634 | if (s->hl == DRAW_CURSOR) |
| @@ -632,30 +650,35 @@ haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w, | |||
| 632 | } | 650 | } |
| 633 | 651 | ||
| 634 | static void | 652 | static void |
| 635 | haiku_draw_relief_rect (struct glyph_string *s, | 653 | haiku_draw_relief_rect (struct glyph_string *s, int left_x, int top_y, |
| 636 | int left_x, int top_y, int right_x, int bottom_y, | 654 | int right_x, int bottom_y, int hwidth, int vwidth, |
| 637 | int hwidth, int vwidth, bool raised_p, bool top_p, | 655 | bool raised_p, bool top_p, bool bot_p, bool left_p, |
| 638 | bool bot_p, bool left_p, bool right_p, | 656 | bool right_p, struct haiku_rect *clip_rect) |
| 639 | struct haiku_rect *clip_rect, bool fancy_p) | ||
| 640 | { | 657 | { |
| 641 | uint32_t color_white, color_black; | 658 | uint32_t color_white, color_black; |
| 642 | void *view; | 659 | void *view; |
| 643 | 660 | ||
| 661 | view = FRAME_HAIKU_VIEW (s->f); | ||
| 644 | haiku_calculate_relief_colors (s, &color_white, &color_black); | 662 | haiku_calculate_relief_colors (s, &color_white, &color_black); |
| 645 | 663 | ||
| 646 | view = FRAME_HAIKU_VIEW (s->f); | ||
| 647 | BView_SetHighColor (view, raised_p ? color_white : color_black); | 664 | BView_SetHighColor (view, raised_p ? color_white : color_black); |
| 665 | |||
| 648 | if (clip_rect) | 666 | if (clip_rect) |
| 649 | { | 667 | { |
| 650 | BView_StartClip (view); | 668 | BView_StartClip (view); |
| 651 | haiku_clip_to_string (s); | 669 | haiku_clip_to_string (s); |
| 652 | BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width, | 670 | BView_ClipToRect (view, clip_rect->x, clip_rect->y, |
| 653 | clip_rect->height); | 671 | clip_rect->width, clip_rect->height); |
| 654 | } | 672 | } |
| 673 | |||
| 655 | if (top_p) | 674 | if (top_p) |
| 656 | BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth); | 675 | BView_FillRectangle (view, left_x, top_y, |
| 676 | right_x - left_x + 1, hwidth); | ||
| 677 | |||
| 657 | if (left_p) | 678 | if (left_p) |
| 658 | BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1); | 679 | BView_FillRectangle (view, left_x, top_y, |
| 680 | vwidth, bottom_y - top_y + 1); | ||
| 681 | |||
| 659 | BView_SetHighColor (view, !raised_p ? color_white : color_black); | 682 | BView_SetHighColor (view, !raised_p ? color_white : color_black); |
| 660 | 683 | ||
| 661 | if (bot_p) | 684 | if (bot_p) |
| @@ -696,10 +719,10 @@ haiku_draw_relief_rect (struct glyph_string *s, | |||
| 696 | if (vwidth > 1 && right_p) | 719 | if (vwidth > 1 && right_p) |
| 697 | BView_StrokeLine (view, right_x, top_y, right_x, bottom_y); | 720 | BView_StrokeLine (view, right_x, top_y, right_x, bottom_y); |
| 698 | 721 | ||
| 699 | BView_SetHighColor (view, s->face->background); | 722 | BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (s->f)); |
| 700 | 723 | ||
| 701 | /* Omit corner pixels. */ | 724 | /* Omit corner pixels. */ |
| 702 | if (hwidth > 1 || vwidth > 1) | 725 | if (hwidth > 1 && vwidth > 1) |
| 703 | { | 726 | { |
| 704 | if (left_p && top_p) | 727 | if (left_p && top_p) |
| 705 | BView_FillRectangle (view, left_x, top_y, 1, 1); | 728 | BView_FillRectangle (view, left_x, top_y, 1, 1); |
| @@ -716,21 +739,40 @@ haiku_draw_relief_rect (struct glyph_string *s, | |||
| 716 | } | 739 | } |
| 717 | 740 | ||
| 718 | static void | 741 | static void |
| 742 | haiku_get_scale_factor (int *scale_x, int *scale_y) | ||
| 743 | { | ||
| 744 | struct haiku_display_info *dpyinfo = x_display_list; | ||
| 745 | |||
| 746 | if (dpyinfo->resx > 96) | ||
| 747 | *scale_x = floor (dpyinfo->resx / 96); | ||
| 748 | if (dpyinfo->resy > 96) | ||
| 749 | *scale_y = floor (dpyinfo->resy / 96); | ||
| 750 | } | ||
| 751 | |||
| 752 | static void | ||
| 719 | haiku_draw_underwave (struct glyph_string *s, int width, int x) | 753 | haiku_draw_underwave (struct glyph_string *s, int width, int x) |
| 720 | { | 754 | { |
| 721 | int wave_height = 3, wave_length = 2; | 755 | int wave_height, wave_length; |
| 722 | int y, dx, dy, odd, xmax; | 756 | int y, dx, dy, odd, xmax, scale_x, scale_y; |
| 723 | float ax, ay, bx, by; | 757 | float ax, ay, bx, by; |
| 724 | void *view = FRAME_HAIKU_VIEW (s->f); | 758 | void *view; |
| 759 | |||
| 760 | scale_x = 1; | ||
| 761 | scale_y = 1; | ||
| 762 | haiku_get_scale_factor (&scale_x, &scale_y); | ||
| 763 | wave_height = 3 * scale_y; | ||
| 764 | wave_length = 2 * scale_x; | ||
| 725 | 765 | ||
| 726 | dx = wave_length; | 766 | dx = wave_length; |
| 727 | dy = wave_height - 1; | 767 | dy = wave_height - 1; |
| 728 | y = s->ybase - wave_height + 3; | 768 | y = s->ybase - wave_height + 3; |
| 729 | xmax = x + width; | 769 | xmax = x + width; |
| 770 | view = FRAME_HAIKU_VIEW (s->f); | ||
| 730 | 771 | ||
| 731 | BView_StartClip (view); | 772 | BView_StartClip (view); |
| 732 | haiku_clip_to_string (s); | 773 | haiku_clip_to_string (s); |
| 733 | BView_ClipToRect (view, x, y, width, wave_height); | 774 | BView_ClipToRect (view, x, y, width, wave_height); |
| 775 | |||
| 734 | ax = x - ((int) (x) % dx) + (float) 0.5; | 776 | ax = x - ((int) (x) % dx) + (float) 0.5; |
| 735 | bx = ax + dx; | 777 | bx = ax + dx; |
| 736 | odd = (int) (ax / dx) % 2; | 778 | odd = (int) (ax / dx) % 2; |
| @@ -741,6 +783,8 @@ haiku_draw_underwave (struct glyph_string *s, int width, int x) | |||
| 741 | else | 783 | else |
| 742 | by += dy; | 784 | by += dy; |
| 743 | 785 | ||
| 786 | BView_SetPenSize (view, scale_y); | ||
| 787 | |||
| 744 | while (ax <= xmax) | 788 | while (ax <= xmax) |
| 745 | { | 789 | { |
| 746 | BView_StrokeLine (view, ax, ay, bx, by); | 790 | BView_StrokeLine (view, ax, ay, bx, by); |
| @@ -748,6 +792,8 @@ haiku_draw_underwave (struct glyph_string *s, int width, int x) | |||
| 748 | bx += dx, by = y + 0.5 + odd * dy; | 792 | bx += dx, by = y + 0.5 + odd * dy; |
| 749 | odd = !odd; | 793 | odd = !odd; |
| 750 | } | 794 | } |
| 795 | |||
| 796 | BView_SetPenSize (view, 1); | ||
| 751 | BView_EndClip (view); | 797 | BView_EndClip (view); |
| 752 | } | 798 | } |
| 753 | 799 | ||
| @@ -809,13 +855,13 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, | |||
| 809 | val = (WINDOW_BUFFER_LOCAL_VALUE | 855 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 810 | (Qx_underline_at_descent_line, s->w)); | 856 | (Qx_underline_at_descent_line, s->w)); |
| 811 | underline_at_descent_line | 857 | underline_at_descent_line |
| 812 | = (!(NILP (val) || EQ (val, Qunbound)) | 858 | = (!(NILP (val) || BASE_EQ (val, Qunbound)) |
| 813 | || s->face->underline_at_descent_line_p); | 859 | || s->face->underline_at_descent_line_p); |
| 814 | 860 | ||
| 815 | val = (WINDOW_BUFFER_LOCAL_VALUE | 861 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 816 | (Qx_use_underline_position_properties, s->w)); | 862 | (Qx_use_underline_position_properties, s->w)); |
| 817 | use_underline_position_properties | 863 | use_underline_position_properties |
| 818 | = !(NILP (val) || EQ (val, Qunbound)); | 864 | = !(NILP (val) || BASE_EQ (val, Qunbound)); |
| 819 | 865 | ||
| 820 | /* Get the underline thickness. Default is 1 pixel. */ | 866 | /* Get the underline thickness. Default is 1 pixel. */ |
| 821 | if (font && font->underline_thickness > 0) | 867 | if (font && font->underline_thickness > 0) |
| @@ -958,15 +1004,16 @@ haiku_draw_string_box (struct glyph_string *s) | |||
| 958 | else | 1004 | else |
| 959 | haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth, | 1005 | haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth, |
| 960 | vwidth, raised_p, true, true, left_p, right_p, | 1006 | vwidth, raised_p, true, true, left_p, right_p, |
| 961 | NULL, 1); | 1007 | NULL); |
| 962 | } | 1008 | } |
| 963 | 1009 | ||
| 964 | static void | 1010 | static void |
| 965 | haiku_draw_plain_background (struct glyph_string *s, struct face *face, | 1011 | haiku_draw_plain_background (struct glyph_string *s, struct face *face, |
| 966 | int box_line_hwidth, int box_line_vwidth) | 1012 | int x, int y, int width, int height) |
| 967 | { | 1013 | { |
| 968 | void *view = FRAME_HAIKU_VIEW (s->f); | 1014 | void *view = FRAME_HAIKU_VIEW (s->f); |
| 969 | unsigned long cursor_color; | 1015 | unsigned long cursor_color; |
| 1016 | |||
| 970 | if (s->hl == DRAW_CURSOR) | 1017 | if (s->hl == DRAW_CURSOR) |
| 971 | { | 1018 | { |
| 972 | haiku_merge_cursor_foreground (s, NULL, &cursor_color); | 1019 | haiku_merge_cursor_foreground (s, NULL, &cursor_color); |
| @@ -975,18 +1022,92 @@ haiku_draw_plain_background (struct glyph_string *s, struct face *face, | |||
| 975 | else | 1022 | else |
| 976 | BView_SetHighColor (view, face->background_defaulted_p ? | 1023 | BView_SetHighColor (view, face->background_defaulted_p ? |
| 977 | FRAME_BACKGROUND_PIXEL (s->f) : | 1024 | FRAME_BACKGROUND_PIXEL (s->f) : |
| 978 | face->background); | 1025 | face->background); |
| 1026 | |||
| 1027 | BView_FillRectangle (view, x, y, width, height); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | static struct haiku_bitmap_record * | ||
| 1031 | haiku_get_bitmap_rec (struct frame *f, ptrdiff_t id) | ||
| 1032 | { | ||
| 1033 | return &FRAME_DISPLAY_INFO (f)->bitmaps[id - 1]; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static void | ||
| 1037 | haiku_update_bitmap_rec (struct haiku_bitmap_record *rec, | ||
| 1038 | uint32_t new_foreground, | ||
| 1039 | uint32_t new_background) | ||
| 1040 | { | ||
| 1041 | char *bits; | ||
| 1042 | int x, y, bytes_per_line; | ||
| 1043 | |||
| 1044 | if (new_foreground == rec->stipple_foreground | ||
| 1045 | && new_background == rec->stipple_background) | ||
| 1046 | return; | ||
| 1047 | |||
| 1048 | bits = rec->stipple_bits; | ||
| 1049 | bytes_per_line = (rec->width + 7) / 8; | ||
| 1050 | |||
| 1051 | for (y = 0; y < rec->height; y++) | ||
| 1052 | { | ||
| 1053 | for (x = 0; x < rec->width; x++) | ||
| 1054 | haiku_put_pixel (rec->img, x, y, | ||
| 1055 | ((bits[x / 8] >> (x % 8)) & 1 | ||
| 1056 | ? new_foreground : new_background)); | ||
| 1057 | |||
| 1058 | bits += bytes_per_line; | ||
| 1059 | } | ||
| 979 | 1060 | ||
| 980 | BView_FillRectangle (view, s->x, | 1061 | rec->stipple_foreground = new_foreground; |
| 981 | s->y + box_line_hwidth, | 1062 | rec->stipple_background = new_background; |
| 982 | s->background_width, | ||
| 983 | s->height - 2 * box_line_hwidth); | ||
| 984 | } | 1063 | } |
| 985 | 1064 | ||
| 986 | static void | 1065 | static void |
| 987 | haiku_draw_stipple_background (struct glyph_string *s, struct face *face, | 1066 | haiku_draw_stipple_background (struct glyph_string *s, struct face *face, |
| 988 | int box_line_hwidth, int box_line_vwidth) | 1067 | int x, int y, int width, int height, |
| 1068 | bool explicit_colors_p, | ||
| 1069 | uint32 explicit_background, | ||
| 1070 | uint32 explicit_foreground) | ||
| 989 | { | 1071 | { |
| 1072 | struct haiku_bitmap_record *rec; | ||
| 1073 | unsigned long foreground, background; | ||
| 1074 | void *view; | ||
| 1075 | |||
| 1076 | view = FRAME_HAIKU_VIEW (s->f); | ||
| 1077 | rec = haiku_get_bitmap_rec (s->f, s->face->stipple); | ||
| 1078 | |||
| 1079 | if (explicit_colors_p) | ||
| 1080 | { | ||
| 1081 | background = explicit_background; | ||
| 1082 | foreground = explicit_foreground; | ||
| 1083 | } | ||
| 1084 | else if (s->hl == DRAW_CURSOR) | ||
| 1085 | haiku_merge_cursor_foreground (s, &foreground, &background); | ||
| 1086 | else | ||
| 1087 | { | ||
| 1088 | foreground = s->face->foreground; | ||
| 1089 | background = s->face->background; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | haiku_update_bitmap_rec (rec, foreground, background); | ||
| 1093 | |||
| 1094 | BView_StartClip (view); | ||
| 1095 | haiku_clip_to_string (s); | ||
| 1096 | BView_ClipToRect (view, x, y, width, height); | ||
| 1097 | BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1, | ||
| 1098 | 0, 0, x + width, y + height); | ||
| 1099 | BView_EndClip (view); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | void | ||
| 1103 | haiku_draw_background_rect (struct glyph_string *s, struct face *face, | ||
| 1104 | int x, int y, int width, int height) | ||
| 1105 | { | ||
| 1106 | if (!s->stippled_p) | ||
| 1107 | haiku_draw_plain_background (s, face, x, y, width, height); | ||
| 1108 | else | ||
| 1109 | haiku_draw_stipple_background (s, face, x, y, width, height, | ||
| 1110 | false, 0, 0); | ||
| 990 | } | 1111 | } |
| 991 | 1112 | ||
| 992 | static void | 1113 | static void |
| @@ -1002,12 +1123,10 @@ haiku_maybe_draw_background (struct glyph_string *s, int force_p) | |||
| 1002 | || FONT_TOO_HIGH (s->font) | 1123 | || FONT_TOO_HIGH (s->font) |
| 1003 | || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) | 1124 | || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) |
| 1004 | { | 1125 | { |
| 1005 | if (!face->stipple) | 1126 | haiku_draw_background_rect (s, s->face, s->x, s->y + box_line_width, |
| 1006 | haiku_draw_plain_background (s, face, box_line_width, | 1127 | s->background_width, |
| 1007 | box_vline_width); | 1128 | s->height - 2 * box_line_width); |
| 1008 | else | 1129 | |
| 1009 | haiku_draw_stipple_background (s, face, box_line_width, | ||
| 1010 | box_vline_width); | ||
| 1011 | s->background_filled_p = 1; | 1130 | s->background_filled_p = 1; |
| 1012 | } | 1131 | } |
| 1013 | } | 1132 | } |
| @@ -1182,9 +1301,8 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s) | |||
| 1182 | static void | 1301 | static void |
| 1183 | haiku_draw_stretch_glyph_string (struct glyph_string *s) | 1302 | haiku_draw_stretch_glyph_string (struct glyph_string *s) |
| 1184 | { | 1303 | { |
| 1185 | eassert (s->first_glyph->type == STRETCH_GLYPH); | ||
| 1186 | |||
| 1187 | struct face *face = s->face; | 1304 | struct face *face = s->face; |
| 1305 | uint32_t bkg; | ||
| 1188 | 1306 | ||
| 1189 | if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p) | 1307 | if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p) |
| 1190 | { | 1308 | { |
| @@ -1232,9 +1350,11 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 1232 | int y = s->y; | 1350 | int y = s->y; |
| 1233 | int w = background_width - width, h = s->height; | 1351 | int w = background_width - width, h = s->height; |
| 1234 | 1352 | ||
| 1353 | /* Draw stipples manually because we want the background | ||
| 1354 | part of a stretch glyph to have a stipple even if the | ||
| 1355 | cursor is visible on top. */ | ||
| 1235 | if (!face->stipple) | 1356 | if (!face->stipple) |
| 1236 | { | 1357 | { |
| 1237 | uint32_t bkg; | ||
| 1238 | if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) | 1358 | if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) |
| 1239 | haiku_mouse_face_colors (s, NULL, &bkg); | 1359 | haiku_mouse_face_colors (s, NULL, &bkg); |
| 1240 | else | 1360 | else |
| @@ -1243,6 +1363,16 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 1243 | BView_SetHighColor (view, bkg); | 1363 | BView_SetHighColor (view, bkg); |
| 1244 | BView_FillRectangle (view, x, y, w, h); | 1364 | BView_FillRectangle (view, x, y, w, h); |
| 1245 | } | 1365 | } |
| 1366 | else | ||
| 1367 | { | ||
| 1368 | if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) | ||
| 1369 | haiku_mouse_face_colors (s, NULL, &bkg); | ||
| 1370 | else | ||
| 1371 | bkg = face->background; | ||
| 1372 | |||
| 1373 | haiku_draw_stipple_background (s, s->face, x, y, w, h, | ||
| 1374 | true, bkg, face->foreground); | ||
| 1375 | } | ||
| 1246 | } | 1376 | } |
| 1247 | } | 1377 | } |
| 1248 | else if (!s->background_filled_p) | 1378 | else if (!s->background_filled_p) |
| @@ -1260,17 +1390,8 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 1260 | } | 1390 | } |
| 1261 | 1391 | ||
| 1262 | if (background_width > 0) | 1392 | if (background_width > 0) |
| 1263 | { | 1393 | haiku_draw_background_rect (s, s->face, s->x, s->y, |
| 1264 | void *view = FRAME_HAIKU_VIEW (s->f); | 1394 | background_width, s->height); |
| 1265 | unsigned long bkg; | ||
| 1266 | if (s->hl == DRAW_CURSOR) | ||
| 1267 | haiku_merge_cursor_foreground (s, NULL, &bkg); | ||
| 1268 | else | ||
| 1269 | bkg = s->face->background; | ||
| 1270 | |||
| 1271 | BView_SetHighColor (view, bkg); | ||
| 1272 | BView_FillRectangle (view, x, s->y, background_width, s->height); | ||
| 1273 | } | ||
| 1274 | } | 1395 | } |
| 1275 | s->background_filled_p = 1; | 1396 | s->background_filled_p = 1; |
| 1276 | } | 1397 | } |
| @@ -1504,19 +1625,20 @@ haiku_draw_image_relief (struct glyph_string *s) | |||
| 1504 | 1625 | ||
| 1505 | get_glyph_string_clip_rect (s, &r); | 1626 | get_glyph_string_clip_rect (s, &r); |
| 1506 | haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p, | 1627 | haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p, |
| 1507 | top_p, bot_p, left_p, right_p, &r, 0); | 1628 | top_p, bot_p, left_p, right_p, &r); |
| 1508 | } | 1629 | } |
| 1509 | 1630 | ||
| 1510 | static void | 1631 | static void |
| 1511 | haiku_draw_image_glyph_string (struct glyph_string *s) | 1632 | haiku_draw_image_glyph_string (struct glyph_string *s) |
| 1512 | { | 1633 | { |
| 1513 | struct face *face = s->face; | 1634 | struct face *face = s->face; |
| 1514 | 1635 | void *view, *bitmap, *mask; | |
| 1515 | int box_line_hwidth = max (face->box_vertical_line_width, 0); | 1636 | int box_line_hwidth = max (face->box_vertical_line_width, 0); |
| 1516 | int box_line_vwidth = max (face->box_horizontal_line_width, 0); | 1637 | int box_line_vwidth = max (face->box_horizontal_line_width, 0); |
| 1517 | 1638 | int x, y, height, width, relief; | |
| 1518 | int x, y; | 1639 | struct haiku_rect nr; |
| 1519 | int height, width; | 1640 | Emacs_Rectangle cr, ir, r; |
| 1641 | unsigned long background; | ||
| 1520 | 1642 | ||
| 1521 | height = s->height; | 1643 | height = s->height; |
| 1522 | if (s->slice.y == 0) | 1644 | if (s->slice.y == 0) |
| @@ -1537,19 +1659,22 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1537 | if (s->slice.y == 0) | 1659 | if (s->slice.y == 0) |
| 1538 | y += box_line_vwidth; | 1660 | y += box_line_vwidth; |
| 1539 | 1661 | ||
| 1540 | void *view = FRAME_HAIKU_VIEW (s->f); | 1662 | view = FRAME_HAIKU_VIEW (s->f); |
| 1541 | void *bitmap = s->img->pixmap; | 1663 | bitmap = s->img->pixmap; |
| 1542 | 1664 | ||
| 1665 | /* TODO: implement stipples for images with masks. */ | ||
| 1543 | s->stippled_p = face->stipple != 0; | 1666 | s->stippled_p = face->stipple != 0; |
| 1544 | 1667 | ||
| 1545 | BView_SetHighColor (view, face->background); | 1668 | if (s->hl == DRAW_CURSOR) |
| 1669 | haiku_merge_cursor_foreground (s, NULL, &background); | ||
| 1670 | else | ||
| 1671 | background = face->background; | ||
| 1672 | |||
| 1673 | BView_SetHighColor (view, background); | ||
| 1546 | BView_FillRectangle (view, x, y, width, height); | 1674 | BView_FillRectangle (view, x, y, width, height); |
| 1547 | 1675 | ||
| 1548 | if (bitmap) | 1676 | if (bitmap) |
| 1549 | { | 1677 | { |
| 1550 | struct haiku_rect nr; | ||
| 1551 | Emacs_Rectangle cr, ir, r; | ||
| 1552 | |||
| 1553 | get_glyph_string_clip_rect (s, &nr); | 1678 | get_glyph_string_clip_rect (s, &nr); |
| 1554 | CONVERT_TO_EMACS_RECT (cr, nr); | 1679 | CONVERT_TO_EMACS_RECT (cr, nr); |
| 1555 | x = s->x; | 1680 | x = s->x; |
| @@ -1571,7 +1696,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1571 | ir.height = s->slice.height; | 1696 | ir.height = s->slice.height; |
| 1572 | r = ir; | 1697 | r = ir; |
| 1573 | 1698 | ||
| 1574 | void *mask = s->img->mask; | 1699 | mask = s->img->mask; |
| 1575 | 1700 | ||
| 1576 | if (gui_intersect_rectangles (&cr, &ir, &r)) | 1701 | if (gui_intersect_rectangles (&cr, &ir, &r)) |
| 1577 | { | 1702 | { |
| @@ -1605,11 +1730,25 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1605 | BBitmap_free (bitmap); | 1730 | BBitmap_free (bitmap); |
| 1606 | } | 1731 | } |
| 1607 | 1732 | ||
| 1608 | if (s->hl == DRAW_CURSOR) | 1733 | if (!s->img->mask) |
| 1609 | { | 1734 | { |
| 1610 | BView_SetPenSize (view, 1); | 1735 | /* When the image has a mask, we can expect that at |
| 1611 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel); | 1736 | least part of a mouse highlight or a block cursor will |
| 1612 | BView_StrokeRectangle (view, r.x, r.y, r.width, r.height); | 1737 | be visible. If the image doesn't have a mask, make |
| 1738 | a block cursor visible by drawing a rectangle around | ||
| 1739 | the image. I believe it's looking better if we do | ||
| 1740 | nothing here for mouse-face. */ | ||
| 1741 | |||
| 1742 | if (s->hl == DRAW_CURSOR) | ||
| 1743 | { | ||
| 1744 | relief = eabs (s->img->relief); | ||
| 1745 | |||
| 1746 | BView_SetPenSize (view, 1); | ||
| 1747 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel); | ||
| 1748 | BView_StrokeRectangle (view, x - relief, y - relief, | ||
| 1749 | s->slice.width + relief * 2, | ||
| 1750 | s->slice.height + relief * 2); | ||
| 1751 | } | ||
| 1613 | } | 1752 | } |
| 1614 | } | 1753 | } |
| 1615 | 1754 | ||
| @@ -1622,16 +1761,14 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1622 | static void | 1761 | static void |
| 1623 | haiku_draw_glyph_string (struct glyph_string *s) | 1762 | haiku_draw_glyph_string (struct glyph_string *s) |
| 1624 | { | 1763 | { |
| 1625 | void *view; | 1764 | void *view = FRAME_HAIKU_VIEW (s->f);; |
| 1765 | struct face *face = s->face; | ||
| 1626 | 1766 | ||
| 1627 | block_input (); | 1767 | block_input (); |
| 1628 | view = FRAME_HAIKU_VIEW (s->f); | ||
| 1629 | BView_draw_lock (view, false, 0, 0, 0, 0); | 1768 | BView_draw_lock (view, false, 0, 0, 0, 0); |
| 1630 | prepare_face_for_display (s->f, s->face); | 1769 | prepare_face_for_display (s->f, s->face); |
| 1631 | 1770 | ||
| 1632 | struct face *face = s->face; | 1771 | s->stippled_p = s->hl != DRAW_CURSOR && face->stipple; |
| 1633 | if (face != s->face) | ||
| 1634 | prepare_face_for_display (s->f, face); | ||
| 1635 | 1772 | ||
| 1636 | if (s->next && s->right_overhang && !s->for_overlaps) | 1773 | if (s->next && s->right_overhang && !s->for_overlaps) |
| 1637 | { | 1774 | { |
| @@ -1643,13 +1780,16 @@ haiku_draw_glyph_string (struct glyph_string *s) | |||
| 1643 | width += next->width, next = next->next) | 1780 | width += next->width, next = next->next) |
| 1644 | if (next->first_glyph->type != IMAGE_GLYPH) | 1781 | if (next->first_glyph->type != IMAGE_GLYPH) |
| 1645 | { | 1782 | { |
| 1646 | prepare_face_for_display (s->f, s->next->face); | 1783 | prepare_face_for_display (s->f, next->face); |
| 1647 | haiku_start_clip (s->next); | 1784 | next->stippled_p |
| 1648 | haiku_clip_to_string (s->next); | 1785 | = next->hl != DRAW_CURSOR && next->face->stipple; |
| 1786 | |||
| 1787 | haiku_start_clip (next); | ||
| 1788 | haiku_clip_to_string (next); | ||
| 1649 | if (next->first_glyph->type != STRETCH_GLYPH) | 1789 | if (next->first_glyph->type != STRETCH_GLYPH) |
| 1650 | haiku_maybe_draw_background (s->next, 1); | 1790 | haiku_maybe_draw_background (next, true); |
| 1651 | else | 1791 | else |
| 1652 | haiku_draw_stretch_glyph_string (s->next); | 1792 | haiku_draw_stretch_glyph_string (next); |
| 1653 | haiku_end_clip (s); | 1793 | haiku_end_clip (s); |
| 1654 | } | 1794 | } |
| 1655 | } | 1795 | } |
| @@ -1774,8 +1914,21 @@ haiku_draw_glyph_string (struct glyph_string *s) | |||
| 1774 | } | 1914 | } |
| 1775 | } | 1915 | } |
| 1776 | } | 1916 | } |
| 1917 | |||
| 1777 | haiku_end_clip (s); | 1918 | haiku_end_clip (s); |
| 1778 | BView_draw_unlock (view); | 1919 | BView_draw_unlock (view); |
| 1920 | |||
| 1921 | /* Set the stipple_p flag indicating whether or not a stipple was | ||
| 1922 | drawn in s->row. That is the case either when s is a stretch | ||
| 1923 | glyph string and s->face->stipple is not NULL, or when | ||
| 1924 | s->face->stipple exists and s->hl is not DRAW_CURSOR, and s is | ||
| 1925 | not an image. This is different from X. */ | ||
| 1926 | if (s->first_glyph->type != IMAGE_GLYPH | ||
| 1927 | && s->face->stipple | ||
| 1928 | && (s->first_glyph->type == STRETCH_GLYPH | ||
| 1929 | || s->hl != DRAW_CURSOR)) | ||
| 1930 | s->row->stipple_p = true; | ||
| 1931 | |||
| 1779 | unblock_input (); | 1932 | unblock_input (); |
| 1780 | } | 1933 | } |
| 1781 | 1934 | ||
| @@ -1811,8 +1964,9 @@ haiku_after_update_window_line (struct window *w, | |||
| 1811 | void *view = FRAME_HAIKU_VIEW (f); | 1964 | void *view = FRAME_HAIKU_VIEW (f); |
| 1812 | BView_draw_lock (view, false, 0, 0, 0, 0); | 1965 | BView_draw_lock (view, false, 0, 0, 0, 0); |
| 1813 | BView_StartClip (view); | 1966 | BView_StartClip (view); |
| 1814 | BView_SetHighColor (view, face->background_defaulted_p ? | 1967 | BView_SetHighColor (view, (face->background_defaulted_p |
| 1815 | FRAME_BACKGROUND_PIXEL (f) : face->background); | 1968 | ? FRAME_BACKGROUND_PIXEL (f) |
| 1969 | : face->background)); | ||
| 1816 | BView_FillRectangle (view, 0, y, width, height); | 1970 | BView_FillRectangle (view, 0, y, width, height); |
| 1817 | BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width, | 1971 | BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width, |
| 1818 | y, width, height); | 1972 | y, width, height); |
| @@ -1847,7 +2001,7 @@ haiku_set_window_size (struct frame *f, bool change_gravity, | |||
| 1847 | /* Only do this if the fullscreen status has actually been | 2001 | /* Only do this if the fullscreen status has actually been |
| 1848 | applied. */ | 2002 | applied. */ |
| 1849 | && f->want_fullscreen == FULLSCREEN_NONE | 2003 | && f->want_fullscreen == FULLSCREEN_NONE |
| 1850 | /* And if the configury during frame completion has been | 2004 | /* And if the configury during frame creation has been |
| 1851 | completed. Otherwise, there will be no valid "old size" to | 2005 | completed. Otherwise, there will be no valid "old size" to |
| 1852 | go back to. */ | 2006 | go back to. */ |
| 1853 | && FRAME_OUTPUT_DATA (f)->configury_done) | 2007 | && FRAME_OUTPUT_DATA (f)->configury_done) |
| @@ -1858,134 +2012,215 @@ haiku_set_window_size (struct frame *f, bool change_gravity, | |||
| 1858 | if (FRAME_HAIKU_WINDOW (f)) | 2012 | if (FRAME_HAIKU_WINDOW (f)) |
| 1859 | { | 2013 | { |
| 1860 | block_input (); | 2014 | block_input (); |
| 1861 | BWindow_resize (FRAME_HAIKU_WINDOW (f), width, height); | 2015 | BWindow_resize (FRAME_HAIKU_WINDOW (f), |
| 2016 | width, height); | ||
| 2017 | |||
| 2018 | if (FRAME_VISIBLE_P (f) | ||
| 2019 | && (width != FRAME_PIXEL_WIDTH (f) | ||
| 2020 | || height != FRAME_PIXEL_HEIGHT (f))) | ||
| 2021 | haiku_wait_for_event (f, FRAME_RESIZED); | ||
| 1862 | unblock_input (); | 2022 | unblock_input (); |
| 1863 | } | 2023 | } |
| 2024 | |||
| 2025 | do_pending_window_change (false); | ||
| 1864 | } | 2026 | } |
| 1865 | 2027 | ||
| 1866 | static void | 2028 | static void |
| 1867 | haiku_draw_window_cursor (struct window *w, | 2029 | haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row) |
| 1868 | struct glyph_row *glyph_row, | ||
| 1869 | int x, int y, | ||
| 1870 | enum text_cursor_kinds cursor_type, | ||
| 1871 | int cursor_width, bool on_p, bool active_p) | ||
| 1872 | { | 2030 | { |
| 1873 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 2031 | struct frame *f; |
| 1874 | struct face *face; | 2032 | int x, y, wd, h; |
| 1875 | struct glyph *phys_cursor_glyph; | ||
| 1876 | struct glyph *cursor_glyph; | 2033 | struct glyph *cursor_glyph; |
| 2034 | uint32_t foreground; | ||
| 2035 | void *view; | ||
| 1877 | 2036 | ||
| 1878 | void *view = FRAME_HAIKU_VIEW (f); | 2037 | f = XFRAME (WINDOW_FRAME (w)); |
| 1879 | 2038 | view = FRAME_HAIKU_VIEW (f); | |
| 1880 | int fx, fy, h, cursor_height; | ||
| 1881 | 2039 | ||
| 1882 | if (!on_p) | 2040 | /* Get the glyph the cursor is on. If we can't tell because |
| 2041 | the current matrix is invalid or such, give up. */ | ||
| 2042 | cursor_glyph = get_phys_cursor_glyph (w); | ||
| 2043 | if (cursor_glyph == NULL) | ||
| 1883 | return; | 2044 | return; |
| 1884 | 2045 | ||
| 1885 | if (cursor_type == NO_CURSOR) | 2046 | /* Compute frame-relative coordinates for phys cursor. */ |
| 1886 | { | 2047 | get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); |
| 1887 | w->phys_cursor_width = 0; | 2048 | wd = w->phys_cursor_width; |
| 1888 | return; | ||
| 1889 | } | ||
| 1890 | 2049 | ||
| 1891 | w->phys_cursor_on_p = true; | 2050 | /* The foreground of cursor_gc is typically the same as the normal |
| 1892 | w->phys_cursor_type = cursor_type; | 2051 | background color, which can cause the cursor box to be invisible. */ |
| 2052 | foreground = FRAME_CURSOR_COLOR (f).pixel; | ||
| 1893 | 2053 | ||
| 1894 | phys_cursor_glyph = get_phys_cursor_glyph (w); | 2054 | /* When on R2L character, show cursor at the right edge of the |
| 2055 | glyph, unless the cursor box is as wide as the glyph or wider | ||
| 2056 | (the latter happens when x-stretch-cursor is non-nil). */ | ||
| 2057 | if ((cursor_glyph->resolved_level & 1) != 0 | ||
| 2058 | && cursor_glyph->pixel_width > wd) | ||
| 2059 | x += cursor_glyph->pixel_width - wd; | ||
| 1895 | 2060 | ||
| 1896 | if (!phys_cursor_glyph) | 2061 | /* Set clipping, draw the rectangle, and reset clipping again. |
| 1897 | { | 2062 | This also marks the region as invalidated. */ |
| 1898 | if (glyph_row->exact_window_width_line_p | 2063 | |
| 1899 | && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) | 2064 | BView_draw_lock (view, true, x, y, wd, h); |
| 1900 | { | 2065 | BView_StartClip (view); |
| 1901 | glyph_row->cursor_in_fringe_p = 1; | 2066 | haiku_clip_to_row (w, row, TEXT_AREA); |
| 1902 | draw_fringe_bitmap (w, glyph_row, 0); | ||
| 1903 | } | ||
| 1904 | return; | ||
| 1905 | } | ||
| 1906 | 2067 | ||
| 1907 | get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h); | 2068 | /* Now set the foreground color and pen size. */ |
| 2069 | BView_SetHighColor (view, foreground); | ||
| 2070 | BView_SetPenSize (view, 1); | ||
| 1908 | 2071 | ||
| 1909 | if (cursor_type == BAR_CURSOR) | 2072 | /* Actually draw the rectangle. */ |
| 2073 | BView_StrokeRectangle (view, x, y, wd, h); | ||
| 2074 | |||
| 2075 | /* Reset clipping. */ | ||
| 2076 | BView_EndClip (view); | ||
| 2077 | BView_draw_unlock (view); | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | static void | ||
| 2081 | haiku_draw_bar_cursor (struct window *w, struct glyph_row *row, | ||
| 2082 | int width, enum text_cursor_kinds kind) | ||
| 2083 | { | ||
| 2084 | struct frame *f; | ||
| 2085 | struct glyph *cursor_glyph; | ||
| 2086 | struct glyph_row *r; | ||
| 2087 | struct face *face; | ||
| 2088 | uint32_t foreground; | ||
| 2089 | void *view; | ||
| 2090 | int x, y, dummy_x, dummy_y, dummy_h; | ||
| 2091 | |||
| 2092 | f = XFRAME (w->frame); | ||
| 2093 | |||
| 2094 | /* If cursor is out of bounds, don't draw garbage. This can happen | ||
| 2095 | in mini-buffer windows when switching between echo area glyphs | ||
| 2096 | and mini-buffer. */ | ||
| 2097 | cursor_glyph = get_phys_cursor_glyph (w); | ||
| 2098 | if (cursor_glyph == NULL) | ||
| 2099 | return; | ||
| 2100 | |||
| 2101 | /* If on an image, draw like a normal cursor. That's usually better | ||
| 2102 | visible than drawing a bar, esp. if the image is large so that | ||
| 2103 | the bar might not be in the window. */ | ||
| 2104 | if (cursor_glyph->type == IMAGE_GLYPH) | ||
| 1910 | { | 2105 | { |
| 1911 | if (cursor_width < 1) | 2106 | r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); |
| 1912 | cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); | 2107 | draw_phys_cursor_glyph (w, r, DRAW_CURSOR); |
| 1913 | if (cursor_width < w->phys_cursor_width) | ||
| 1914 | w->phys_cursor_width = cursor_width; | ||
| 1915 | } | 2108 | } |
| 1916 | else if (cursor_type == HBAR_CURSOR) | 2109 | else |
| 1917 | { | 2110 | { |
| 1918 | cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width; | 2111 | view = FRAME_HAIKU_VIEW (f); |
| 1919 | if (cursor_height > glyph_row->height) | 2112 | face = FACE_FROM_ID (f, cursor_glyph->face_id); |
| 1920 | cursor_height = glyph_row->height; | ||
| 1921 | if (h > cursor_height) | ||
| 1922 | fy += h - cursor_height; | ||
| 1923 | h = cursor_height; | ||
| 1924 | } | ||
| 1925 | 2113 | ||
| 1926 | BView_draw_lock (view, false, 0, 0, 0, 0); | 2114 | /* If the glyph's background equals the color we normally draw |
| 1927 | BView_StartClip (view); | 2115 | the bars cursor in, the bar cursor in its normal color is |
| 2116 | invisible. Use the glyph's foreground color instead in this | ||
| 2117 | case, on the assumption that the glyph's colors are chosen so | ||
| 2118 | that the glyph is legible. */ | ||
| 2119 | if (face->background == FRAME_CURSOR_COLOR (f).pixel) | ||
| 2120 | foreground = face->foreground; | ||
| 2121 | else | ||
| 2122 | foreground = FRAME_CURSOR_COLOR (f).pixel; | ||
| 1928 | 2123 | ||
| 1929 | if (cursor_type == BAR_CURSOR) | 2124 | BView_draw_lock (view, false, 0, 0, 0, 0); |
| 1930 | { | 2125 | BView_StartClip (view); |
| 1931 | cursor_glyph = get_phys_cursor_glyph (w); | 2126 | BView_SetHighColor (view, foreground); |
| 1932 | face = FACE_FROM_ID (f, cursor_glyph->face_id); | 2127 | haiku_clip_to_row (w, row, TEXT_AREA); |
| 1933 | } | ||
| 1934 | 2128 | ||
| 1935 | /* If the glyph's background equals the color we normally draw the | 2129 | if (kind == BAR_CURSOR) |
| 1936 | bar cursor in, our cursor in its normal color is invisible. Use | 2130 | { |
| 1937 | the glyph's foreground color instead in this case, on the | 2131 | x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); |
| 1938 | assumption that the glyph's colors are chosen so that the glyph | 2132 | y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); |
| 1939 | is legible. */ | ||
| 1940 | 2133 | ||
| 1941 | /* xterm.c only does this for bar cursors, and nobody has | 2134 | if (width < 0) |
| 1942 | complained, so it would be best to do that here as well. */ | 2135 | width = FRAME_CURSOR_WIDTH (f); |
| 1943 | if (cursor_type == BAR_CURSOR | 2136 | width = min (cursor_glyph->pixel_width, width); |
| 1944 | && face->background == FRAME_CURSOR_COLOR (f).pixel) | ||
| 1945 | BView_SetHighColor (view, face->foreground); | ||
| 1946 | else | ||
| 1947 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (f).pixel); | ||
| 1948 | haiku_clip_to_row (w, glyph_row, TEXT_AREA); | ||
| 1949 | 2137 | ||
| 1950 | switch (cursor_type) | 2138 | w->phys_cursor_width = width; |
| 1951 | { | 2139 | |
| 1952 | default: | 2140 | /* If the character under cursor is R2L, draw the bar cursor |
| 1953 | case DEFAULT_CURSOR: | 2141 | on the right of its glyph, rather than on the left. */ |
| 1954 | case NO_CURSOR: | 2142 | if ((cursor_glyph->resolved_level & 1) != 0) |
| 1955 | break; | 2143 | x += cursor_glyph->pixel_width - width; |
| 1956 | case HBAR_CURSOR: | 2144 | |
| 1957 | BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h); | 2145 | BView_FillRectangle (view, x, y, width, row->height); |
| 1958 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2146 | BView_invalidate_region (view, x, y, width, row->height); |
| 1959 | break; | 2147 | } |
| 1960 | case BAR_CURSOR: | 2148 | else /* HBAR_CURSOR */ |
| 1961 | if (cursor_glyph->resolved_level & 1) | ||
| 1962 | { | 2149 | { |
| 1963 | BView_FillRectangle (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width, | 2150 | x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); |
| 1964 | fy, w->phys_cursor_width, h); | 2151 | y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + |
| 1965 | BView_invalidate_region (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width, | 2152 | row->height - width); |
| 1966 | fy, w->phys_cursor_width, h); | 2153 | |
| 2154 | if (width < 0) | ||
| 2155 | width = row->height; | ||
| 2156 | |||
| 2157 | width = min (row->height, width); | ||
| 2158 | |||
| 2159 | get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x, | ||
| 2160 | &dummy_y, &dummy_h); | ||
| 2161 | |||
| 2162 | if ((cursor_glyph->resolved_level & 1) != 0 | ||
| 2163 | && cursor_glyph->pixel_width > w->phys_cursor_width - 1) | ||
| 2164 | x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; | ||
| 2165 | |||
| 2166 | BView_FillRectangle (view, x, y, w->phys_cursor_width - 1, | ||
| 2167 | width); | ||
| 2168 | BView_invalidate_region (view, x, y, w->phys_cursor_width - 1, | ||
| 2169 | width); | ||
| 1967 | } | 2170 | } |
| 1968 | else | ||
| 1969 | BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h); | ||
| 1970 | 2171 | ||
| 1971 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2172 | BView_EndClip (view); |
| 1972 | break; | 2173 | BView_draw_unlock (view); |
| 1973 | case HOLLOW_BOX_CURSOR: | 2174 | } |
| 1974 | if (phys_cursor_glyph->type != IMAGE_GLYPH) | 2175 | } |
| 2176 | |||
| 2177 | static void | ||
| 2178 | haiku_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | ||
| 2179 | int x, int y, enum text_cursor_kinds cursor_type, | ||
| 2180 | int cursor_width, bool on_p, bool active_p) | ||
| 2181 | { | ||
| 2182 | if (on_p) | ||
| 2183 | { | ||
| 2184 | w->phys_cursor_type = cursor_type; | ||
| 2185 | w->phys_cursor_on_p = true; | ||
| 2186 | |||
| 2187 | if (glyph_row->exact_window_width_line_p | ||
| 2188 | && (glyph_row->reversed_p | ||
| 2189 | ? (w->phys_cursor.hpos < 0) | ||
| 2190 | : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]))) | ||
| 1975 | { | 2191 | { |
| 1976 | BView_SetPenSize (view, 1); | 2192 | glyph_row->cursor_in_fringe_p = true; |
| 1977 | BView_StrokeRectangle (view, fx, fy, w->phys_cursor_width, h); | 2193 | draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p); |
| 1978 | } | 2194 | } |
| 1979 | else | 2195 | else |
| 1980 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 2196 | { |
| 2197 | switch (cursor_type) | ||
| 2198 | { | ||
| 2199 | case HOLLOW_BOX_CURSOR: | ||
| 2200 | haiku_draw_hollow_cursor (w, glyph_row); | ||
| 2201 | break; | ||
| 1981 | 2202 | ||
| 1982 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2203 | case FILLED_BOX_CURSOR: |
| 1983 | break; | 2204 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
| 1984 | case FILLED_BOX_CURSOR: | 2205 | break; |
| 1985 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 2206 | |
| 2207 | case BAR_CURSOR: | ||
| 2208 | haiku_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); | ||
| 2209 | break; | ||
| 2210 | |||
| 2211 | case HBAR_CURSOR: | ||
| 2212 | haiku_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); | ||
| 2213 | break; | ||
| 2214 | |||
| 2215 | case NO_CURSOR: | ||
| 2216 | w->phys_cursor_width = 0; | ||
| 2217 | break; | ||
| 2218 | |||
| 2219 | default: | ||
| 2220 | emacs_abort (); | ||
| 2221 | } | ||
| 2222 | } | ||
| 1986 | } | 2223 | } |
| 1987 | BView_EndClip (view); | ||
| 1988 | BView_draw_unlock (view); | ||
| 1989 | } | 2224 | } |
| 1990 | 2225 | ||
| 1991 | static void | 2226 | static void |
| @@ -2072,19 +2307,25 @@ haiku_draw_vertical_window_border (struct window *w, | |||
| 2072 | static void | 2307 | static void |
| 2073 | haiku_set_scroll_bar_default_width (struct frame *f) | 2308 | haiku_set_scroll_bar_default_width (struct frame *f) |
| 2074 | { | 2309 | { |
| 2075 | int unit = FRAME_COLUMN_WIDTH (f); | 2310 | int unit, size; |
| 2076 | FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = BScrollBar_default_size (0) + 1; | 2311 | |
| 2077 | FRAME_CONFIG_SCROLL_BAR_COLS (f) = | 2312 | unit = FRAME_COLUMN_WIDTH (f); |
| 2078 | (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit; | 2313 | size = BScrollBar_default_size (0) + 1; |
| 2314 | |||
| 2315 | FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = size; | ||
| 2316 | FRAME_CONFIG_SCROLL_BAR_COLS (f) = (size + unit - 1) / unit; | ||
| 2079 | } | 2317 | } |
| 2080 | 2318 | ||
| 2081 | static void | 2319 | static void |
| 2082 | haiku_set_scroll_bar_default_height (struct frame *f) | 2320 | haiku_set_scroll_bar_default_height (struct frame *f) |
| 2083 | { | 2321 | { |
| 2084 | int height = FRAME_LINE_HEIGHT (f); | 2322 | int height, size; |
| 2085 | FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = BScrollBar_default_size (1) + 1; | 2323 | |
| 2086 | FRAME_CONFIG_SCROLL_BAR_LINES (f) = | 2324 | height = FRAME_LINE_HEIGHT (f); |
| 2087 | (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height; | 2325 | size = BScrollBar_default_size (true) + 1; |
| 2326 | |||
| 2327 | FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = size; | ||
| 2328 | FRAME_CONFIG_SCROLL_BAR_LINES (f) = (size + height - 1) / height; | ||
| 2088 | } | 2329 | } |
| 2089 | 2330 | ||
| 2090 | static void | 2331 | static void |
| @@ -2266,15 +2507,17 @@ static struct scroll_bar * | |||
| 2266 | haiku_scroll_bar_create (struct window *w, int left, int top, | 2507 | haiku_scroll_bar_create (struct window *w, int left, int top, |
| 2267 | int width, int height, bool horizontal_p) | 2508 | int width, int height, bool horizontal_p) |
| 2268 | { | 2509 | { |
| 2269 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 2510 | struct frame *f; |
| 2270 | Lisp_Object barobj; | 2511 | Lisp_Object barobj; |
| 2512 | struct scroll_bar *bar; | ||
| 2513 | void *scroll_bar; | ||
| 2514 | void *view; | ||
| 2271 | 2515 | ||
| 2272 | void *sb = NULL; | 2516 | f = XFRAME (WINDOW_FRAME (w)); |
| 2273 | void *vw = FRAME_HAIKU_VIEW (f); | 2517 | view = FRAME_HAIKU_VIEW (f); |
| 2274 | 2518 | ||
| 2275 | block_input (); | 2519 | block_input (); |
| 2276 | struct scroll_bar *bar | 2520 | bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); |
| 2277 | = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); | ||
| 2278 | 2521 | ||
| 2279 | XSETWINDOW (bar->window, w); | 2522 | XSETWINDOW (bar->window, w); |
| 2280 | bar->top = top; | 2523 | bar->top = top; |
| @@ -2287,15 +2530,14 @@ haiku_scroll_bar_create (struct window *w, int left, int top, | |||
| 2287 | bar->update = -1; | 2530 | bar->update = -1; |
| 2288 | bar->horizontal = horizontal_p; | 2531 | bar->horizontal = horizontal_p; |
| 2289 | 2532 | ||
| 2290 | sb = BScrollBar_make_for_view (vw, horizontal_p, | 2533 | scroll_bar = be_make_scroll_bar_for_view (view, horizontal_p, |
| 2291 | left, top, left + width - 1, | 2534 | left, top, left + width - 1, |
| 2292 | top + height - 1, bar); | 2535 | top + height - 1); |
| 2293 | 2536 | BView_publish_scroll_bar (view, left, top, width, height); | |
| 2294 | BView_publish_scroll_bar (vw, left, top, width, height); | ||
| 2295 | 2537 | ||
| 2296 | bar->next = FRAME_SCROLL_BARS (f); | 2538 | bar->next = FRAME_SCROLL_BARS (f); |
| 2297 | bar->prev = Qnil; | 2539 | bar->prev = Qnil; |
| 2298 | bar->scroll_bar = sb; | 2540 | bar->scroll_bar = scroll_bar; |
| 2299 | XSETVECTOR (barobj, bar); | 2541 | XSETVECTOR (barobj, bar); |
| 2300 | fset_scroll_bars (f, barobj); | 2542 | fset_scroll_bars (f, barobj); |
| 2301 | 2543 | ||
| @@ -2309,18 +2551,20 @@ haiku_scroll_bar_create (struct window *w, int left, int top, | |||
| 2309 | static void | 2551 | static void |
| 2310 | haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) | 2552 | haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) |
| 2311 | { | 2553 | { |
| 2312 | eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)); | ||
| 2313 | Lisp_Object barobj; | 2554 | Lisp_Object barobj; |
| 2314 | struct scroll_bar *bar; | 2555 | struct scroll_bar *bar; |
| 2315 | int top, height, left, width; | 2556 | int top, height, left, width; |
| 2316 | int window_x, window_width; | 2557 | int window_x, window_width; |
| 2558 | void *view; | ||
| 2317 | 2559 | ||
| 2560 | eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)); | ||
| 2318 | /* Get window dimensions. */ | 2561 | /* Get window dimensions. */ |
| 2319 | window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); | 2562 | window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); |
| 2320 | left = window_x; | 2563 | left = window_x; |
| 2321 | width = window_width; | 2564 | width = window_width; |
| 2322 | top = WINDOW_SCROLL_BAR_AREA_Y (w); | 2565 | top = WINDOW_SCROLL_BAR_AREA_Y (w); |
| 2323 | height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w); | 2566 | height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w); |
| 2567 | view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); | ||
| 2324 | 2568 | ||
| 2325 | block_input (); | 2569 | block_input (); |
| 2326 | 2570 | ||
| @@ -2335,15 +2579,15 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p | |||
| 2335 | { | 2579 | { |
| 2336 | bar = XSCROLL_BAR (w->horizontal_scroll_bar); | 2580 | bar = XSCROLL_BAR (w->horizontal_scroll_bar); |
| 2337 | 2581 | ||
| 2338 | if (bar->left != left || bar->top != top || | 2582 | if (bar->left != left || bar->top != top |
| 2339 | bar->width != width || bar->height != height) | 2583 | || bar->width != width || bar->height != height) |
| 2340 | { | 2584 | { |
| 2341 | void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); | ||
| 2342 | BView_forget_scroll_bar (view, bar->left, bar->top, | 2585 | BView_forget_scroll_bar (view, bar->left, bar->top, |
| 2343 | bar->width, bar->height); | 2586 | bar->width, bar->height); |
| 2344 | BView_move_frame (bar->scroll_bar, left, top, | 2587 | BView_move_frame (bar->scroll_bar, left, top, |
| 2345 | left + width - 1, top + height - 1); | 2588 | left + width - 1, top + height - 1); |
| 2346 | BView_publish_scroll_bar (view, left, top, width, height); | 2589 | BView_publish_scroll_bar (view, left, top, width, height); |
| 2590 | |||
| 2347 | bar->left = left; | 2591 | bar->left = left; |
| 2348 | bar->top = top; | 2592 | bar->top = top; |
| 2349 | bar->width = width; | 2593 | bar->width = width; |
| @@ -2360,14 +2604,15 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p | |||
| 2360 | } | 2604 | } |
| 2361 | 2605 | ||
| 2362 | static void | 2606 | static void |
| 2363 | haiku_set_vertical_scroll_bar (struct window *w, | 2607 | haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position) |
| 2364 | int portion, int whole, int position) | ||
| 2365 | { | 2608 | { |
| 2366 | eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); | ||
| 2367 | Lisp_Object barobj; | 2609 | Lisp_Object barobj; |
| 2368 | struct scroll_bar *bar; | 2610 | struct scroll_bar *bar; |
| 2369 | int top, height, left, width; | 2611 | int top, height, left, width; |
| 2370 | int window_y, window_height; | 2612 | int window_y, window_height; |
| 2613 | void *view; | ||
| 2614 | |||
| 2615 | eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); | ||
| 2371 | 2616 | ||
| 2372 | /* Get window dimensions. */ | 2617 | /* Get window dimensions. */ |
| 2373 | window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); | 2618 | window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); |
| @@ -2377,8 +2622,10 @@ haiku_set_vertical_scroll_bar (struct window *w, | |||
| 2377 | /* Compute the left edge and the width of the scroll bar area. */ | 2622 | /* Compute the left edge and the width of the scroll bar area. */ |
| 2378 | left = WINDOW_SCROLL_BAR_AREA_X (w); | 2623 | left = WINDOW_SCROLL_BAR_AREA_X (w); |
| 2379 | width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); | 2624 | width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); |
| 2380 | block_input (); | ||
| 2381 | 2625 | ||
| 2626 | view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); | ||
| 2627 | |||
| 2628 | block_input (); | ||
| 2382 | if (NILP (w->vertical_scroll_bar)) | 2629 | if (NILP (w->vertical_scroll_bar)) |
| 2383 | { | 2630 | { |
| 2384 | bar = haiku_scroll_bar_create (w, left, top, width, height, false); | 2631 | bar = haiku_scroll_bar_create (w, left, top, width, height, false); |
| @@ -2389,15 +2636,15 @@ haiku_set_vertical_scroll_bar (struct window *w, | |||
| 2389 | { | 2636 | { |
| 2390 | bar = XSCROLL_BAR (w->vertical_scroll_bar); | 2637 | bar = XSCROLL_BAR (w->vertical_scroll_bar); |
| 2391 | 2638 | ||
| 2392 | if (bar->left != left || bar->top != top || | 2639 | if (bar->left != left || bar->top != top |
| 2393 | bar->width != width || bar->height != height) | 2640 | || bar->width != width || bar->height != height) |
| 2394 | { | 2641 | { |
| 2395 | void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); | ||
| 2396 | BView_forget_scroll_bar (view, bar->left, bar->top, | 2642 | BView_forget_scroll_bar (view, bar->left, bar->top, |
| 2397 | bar->width, bar->height); | 2643 | bar->width, bar->height); |
| 2398 | BView_move_frame (bar->scroll_bar, left, top, | 2644 | BView_move_frame (bar->scroll_bar, left, top, |
| 2399 | left + width - 1, top + height - 1); | 2645 | left + width - 1, top + height - 1); |
| 2400 | BView_publish_scroll_bar (view, left, top, width, height); | 2646 | BView_publish_scroll_bar (view, left, top, width, height); |
| 2647 | |||
| 2401 | bar->left = left; | 2648 | bar->left = left; |
| 2402 | bar->top = top; | 2649 | bar->top = top; |
| 2403 | bar->width = width; | 2650 | bar->width = width; |
| @@ -2418,25 +2665,57 @@ static void | |||
| 2418 | haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | 2665 | haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row, |
| 2419 | struct draw_fringe_bitmap_params *p) | 2666 | struct draw_fringe_bitmap_params *p) |
| 2420 | { | 2667 | { |
| 2421 | void *view = FRAME_HAIKU_VIEW (XFRAME (WINDOW_FRAME (w))); | 2668 | struct face *face; |
| 2422 | struct face *face = p->face; | 2669 | struct frame *f; |
| 2670 | struct haiku_bitmap_record *rec; | ||
| 2671 | void *view, *bitmap; | ||
| 2672 | uint32 col; | ||
| 2673 | |||
| 2674 | f = XFRAME (WINDOW_FRAME (w)); | ||
| 2675 | view = FRAME_HAIKU_VIEW (f); | ||
| 2676 | face = p->face; | ||
| 2423 | 2677 | ||
| 2424 | block_input (); | 2678 | block_input (); |
| 2425 | BView_draw_lock (view, true, p->x, p->y, p->wd, p->h); | 2679 | BView_draw_lock (view, true, 0, 0, 0, 0); |
| 2426 | BView_StartClip (view); | 2680 | BView_StartClip (view); |
| 2427 | 2681 | ||
| 2682 | if (p->wd && p->h) | ||
| 2683 | BView_invalidate_region (view, p->x, p->y, p->wd, p->h); | ||
| 2684 | |||
| 2428 | haiku_clip_to_row (w, row, ANY_AREA); | 2685 | haiku_clip_to_row (w, row, ANY_AREA); |
| 2686 | |||
| 2429 | if (p->bx >= 0 && !p->overlay_p) | 2687 | if (p->bx >= 0 && !p->overlay_p) |
| 2430 | { | 2688 | { |
| 2431 | BView_SetHighColor (view, face->background); | 2689 | BView_invalidate_region (view, p->bx, p->by, p->nx, p->ny); |
| 2432 | BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny); | 2690 | |
| 2691 | if (!face->stipple) | ||
| 2692 | { | ||
| 2693 | BView_SetHighColor (view, face->background); | ||
| 2694 | BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny); | ||
| 2695 | } | ||
| 2696 | else | ||
| 2697 | { | ||
| 2698 | rec = haiku_get_bitmap_rec (f, face->stipple); | ||
| 2699 | haiku_update_bitmap_rec (rec, face->foreground, | ||
| 2700 | face->background); | ||
| 2701 | |||
| 2702 | BView_StartClip (view); | ||
| 2703 | haiku_clip_to_row (w, row, ANY_AREA); | ||
| 2704 | BView_ClipToRect (view, p->bx, p->by, p->nx, p->ny); | ||
| 2705 | BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1, | ||
| 2706 | 0, 0, FRAME_PIXEL_WIDTH (f), | ||
| 2707 | FRAME_PIXEL_HEIGHT (f)); | ||
| 2708 | BView_EndClip (view); | ||
| 2709 | |||
| 2710 | row->stipple_p = true; | ||
| 2711 | } | ||
| 2433 | } | 2712 | } |
| 2434 | 2713 | ||
| 2435 | if (p->which | 2714 | if (p->which |
| 2436 | && p->which < max_fringe_bmp | 2715 | && p->which < max_fringe_bmp |
| 2437 | && p->which < max_used_fringe_bitmap) | 2716 | && p->which < max_used_fringe_bitmap) |
| 2438 | { | 2717 | { |
| 2439 | void *bitmap = fringe_bmps[p->which]; | 2718 | bitmap = fringe_bmps[p->which]; |
| 2440 | 2719 | ||
| 2441 | if (!bitmap) | 2720 | if (!bitmap) |
| 2442 | { | 2721 | { |
| @@ -2450,8 +2729,6 @@ haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2450 | bitmap = fringe_bmps[p->which]; | 2729 | bitmap = fringe_bmps[p->which]; |
| 2451 | } | 2730 | } |
| 2452 | 2731 | ||
| 2453 | uint32_t col; | ||
| 2454 | |||
| 2455 | if (!p->cursor_p) | 2732 | if (!p->cursor_p) |
| 2456 | col = face->foreground; | 2733 | col = face->foreground; |
| 2457 | else if (p->overlay_p) | 2734 | else if (p->overlay_p) |
| @@ -2610,7 +2887,7 @@ haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 2610 | x_display_list->last_mouse_glyph_frame = f1; | 2887 | x_display_list->last_mouse_glyph_frame = f1; |
| 2611 | 2888 | ||
| 2612 | *bar_window = Qnil; | 2889 | *bar_window = Qnil; |
| 2613 | *part = scroll_bar_above_handle; | 2890 | *part = scroll_bar_nowhere; |
| 2614 | 2891 | ||
| 2615 | /* If track-mouse is `drag-source' and the mouse pointer is | 2892 | /* If track-mouse is `drag-source' and the mouse pointer is |
| 2616 | certain to not be actually under the chosen frame, return | 2893 | certain to not be actually under the chosen frame, return |
| @@ -2659,20 +2936,13 @@ haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) | |||
| 2659 | } | 2936 | } |
| 2660 | 2937 | ||
| 2661 | static void | 2938 | static void |
| 2662 | haiku_update_window_end (struct window *w, bool cursor_on_p, | ||
| 2663 | bool mouse_face_overwritten_p) | ||
| 2664 | { | ||
| 2665 | |||
| 2666 | } | ||
| 2667 | |||
| 2668 | static void | ||
| 2669 | haiku_default_font_parameter (struct frame *f, Lisp_Object parms) | 2939 | haiku_default_font_parameter (struct frame *f, Lisp_Object parms) |
| 2670 | { | 2940 | { |
| 2671 | struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 2941 | struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 2672 | Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, | 2942 | Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, |
| 2673 | RES_TYPE_STRING); | 2943 | RES_TYPE_STRING); |
| 2674 | Lisp_Object font = Qnil; | 2944 | Lisp_Object font = Qnil; |
| 2675 | if (EQ (font_param, Qunbound)) | 2945 | if (BASE_EQ (font_param, Qunbound)) |
| 2676 | font_param = Qnil; | 2946 | font_param = Qnil; |
| 2677 | 2947 | ||
| 2678 | if (NILP (font_param)) | 2948 | if (NILP (font_param)) |
| @@ -2733,8 +3003,8 @@ static struct redisplay_interface haiku_redisplay_interface = | |||
| 2733 | gui_clear_end_of_line, | 3003 | gui_clear_end_of_line, |
| 2734 | haiku_scroll_run, | 3004 | haiku_scroll_run, |
| 2735 | haiku_after_update_window_line, | 3005 | haiku_after_update_window_line, |
| 2736 | NULL, | 3006 | NULL, /* update_window_begin */ |
| 2737 | haiku_update_window_end, | 3007 | NULL, /* update_window_end */ |
| 2738 | haiku_flush, | 3008 | haiku_flush, |
| 2739 | gui_clear_window_mouse_face, | 3009 | gui_clear_window_mouse_face, |
| 2740 | gui_get_glyph_overhangs, | 3010 | gui_get_glyph_overhangs, |
| @@ -2750,7 +3020,7 @@ static struct redisplay_interface haiku_redisplay_interface = | |||
| 2750 | haiku_draw_window_cursor, | 3020 | haiku_draw_window_cursor, |
| 2751 | haiku_draw_vertical_window_border, | 3021 | haiku_draw_vertical_window_border, |
| 2752 | haiku_draw_window_divider, | 3022 | haiku_draw_window_divider, |
| 2753 | 0, /* shift glyphs for insert */ | 3023 | NULL, /* shift glyphs for insert */ |
| 2754 | haiku_show_hourglass, | 3024 | haiku_show_hourglass, |
| 2755 | haiku_hide_hourglass, | 3025 | haiku_hide_hourglass, |
| 2756 | haiku_default_font_parameter, | 3026 | haiku_default_font_parameter, |
| @@ -2759,11 +3029,20 @@ static struct redisplay_interface haiku_redisplay_interface = | |||
| 2759 | static void | 3029 | static void |
| 2760 | haiku_make_fullscreen_consistent (struct frame *f) | 3030 | haiku_make_fullscreen_consistent (struct frame *f) |
| 2761 | { | 3031 | { |
| 2762 | Lisp_Object lval = get_frame_param (f, Qfullscreen); | 3032 | Lisp_Object lval; |
| 2763 | 3033 | struct haiku_output *output; | |
| 2764 | if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p) | 3034 | |
| 3035 | output = FRAME_OUTPUT_DATA (f); | ||
| 3036 | |||
| 3037 | if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH) | ||
| 3038 | lval = Qfullboth; | ||
| 3039 | else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH) | ||
| 3040 | lval = Qfullwidth; | ||
| 3041 | else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT) | ||
| 3042 | lval = Qfullheight; | ||
| 3043 | else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED) | ||
| 2765 | lval = Qmaximized; | 3044 | lval = Qmaximized; |
| 2766 | else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p) | 3045 | else |
| 2767 | lval = Qnil; | 3046 | lval = Qnil; |
| 2768 | 3047 | ||
| 2769 | store_frame_param (f, Qfullscreen, lval); | 3048 | store_frame_param (f, Qfullscreen, lval); |
| @@ -2778,7 +3057,7 @@ haiku_flush_dirty_back_buffer_on (struct frame *f) | |||
| 2778 | haiku_flip_buffers (f); | 3057 | haiku_flip_buffers (f); |
| 2779 | } | 3058 | } |
| 2780 | 3059 | ||
| 2781 | /* N.B. that support for TYPE must be explictly added to | 3060 | /* N.B. that support for TYPE must be explicitly added to |
| 2782 | haiku_read_socket. */ | 3061 | haiku_read_socket. */ |
| 2783 | void | 3062 | void |
| 2784 | haiku_wait_for_event (struct frame *f, int type) | 3063 | haiku_wait_for_event (struct frame *f, int type) |
| @@ -2816,7 +3095,7 @@ static int | |||
| 2816 | haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | 3095 | haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) |
| 2817 | { | 3096 | { |
| 2818 | int message_count; | 3097 | int message_count; |
| 2819 | static void *buf; | 3098 | void *buf; |
| 2820 | ssize_t b_size; | 3099 | ssize_t b_size; |
| 2821 | int button_or_motion_p, do_help; | 3100 | int button_or_motion_p, do_help; |
| 2822 | enum haiku_event_type type; | 3101 | enum haiku_event_type type; |
| @@ -2825,11 +3104,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 2825 | message_count = 0; | 3104 | message_count = 0; |
| 2826 | button_or_motion_p = 0; | 3105 | button_or_motion_p = 0; |
| 2827 | do_help = 0; | 3106 | do_help = 0; |
| 2828 | buf = NULL; | 3107 | |
| 3108 | buf = alloca (200); | ||
| 2829 | 3109 | ||
| 2830 | block_input (); | 3110 | block_input (); |
| 2831 | if (!buf) | ||
| 2832 | buf = xmalloc (200); | ||
| 2833 | haiku_read_size (&b_size, false); | 3111 | haiku_read_size (&b_size, false); |
| 2834 | while (b_size >= 0) | 3112 | while (b_size >= 0) |
| 2835 | { | 3113 | { |
| @@ -2868,8 +3146,12 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 2868 | if (!f) | 3146 | if (!f) |
| 2869 | continue; | 3147 | continue; |
| 2870 | 3148 | ||
| 2871 | int width = lrint (b->px_widthf); | 3149 | int width = lrint (b->width); |
| 2872 | int height = lrint (b->px_heightf); | 3150 | int height = lrint (b->height); |
| 3151 | |||
| 3152 | if (FRAME_OUTPUT_DATA (f)->wait_for_event_type | ||
| 3153 | == FRAME_RESIZED) | ||
| 3154 | FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1; | ||
| 2873 | 3155 | ||
| 2874 | if (FRAME_TOOLTIP_P (f)) | 3156 | if (FRAME_TOOLTIP_P (f)) |
| 2875 | { | 3157 | { |
| @@ -2899,6 +3181,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 2899 | cancel_mouse_face (f); | 3181 | cancel_mouse_face (f); |
| 2900 | haiku_clear_under_internal_border (f); | 3182 | haiku_clear_under_internal_border (f); |
| 2901 | } | 3183 | } |
| 3184 | |||
| 2902 | break; | 3185 | break; |
| 2903 | } | 3186 | } |
| 2904 | case FRAME_EXPOSED: | 3187 | case FRAME_EXPOSED: |
| @@ -3006,10 +3289,18 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3006 | if (FRAME_TOOLTIP_P (f)) | 3289 | if (FRAME_TOOLTIP_P (f)) |
| 3007 | { | 3290 | { |
| 3008 | /* Dismiss the tooltip if the mouse moves onto a | 3291 | /* Dismiss the tooltip if the mouse moves onto a |
| 3009 | tooltip frame. FIXME: for some reason we don't get | 3292 | tooltip frame (except when drag-and-drop is in |
| 3010 | leave notification events for this. */ | 3293 | progress and we are trying to move the tooltip |
| 3011 | 3294 | along with the mouse pointer). FIXME: for some | |
| 3012 | if (any_help_event_p) | 3295 | reason we don't get leave notification events for |
| 3296 | this. */ | ||
| 3297 | |||
| 3298 | if (any_help_event_p | ||
| 3299 | && !(be_drag_and_drop_in_progress () | ||
| 3300 | && haiku_dnd_follow_tooltip) | ||
| 3301 | && !((EQ (track_mouse, Qdrag_source) | ||
| 3302 | || EQ (track_mouse, Qdropping)) | ||
| 3303 | && gui_mouse_grabbed (x_display_list))) | ||
| 3013 | do_help = -1; | 3304 | do_help = -1; |
| 3014 | break; | 3305 | break; |
| 3015 | } | 3306 | } |
| @@ -3056,7 +3347,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3056 | 3347 | ||
| 3057 | haiku_new_focus_frame (x_display_list->focused_frame); | 3348 | haiku_new_focus_frame (x_display_list->focused_frame); |
| 3058 | 3349 | ||
| 3059 | if (any_help_event_p) | 3350 | if (any_help_event_p |
| 3351 | && !((EQ (track_mouse, Qdrag_source) | ||
| 3352 | || EQ (track_mouse, Qdropping)) | ||
| 3353 | && gui_mouse_grabbed (x_display_list))) | ||
| 3060 | do_help = -1; | 3354 | do_help = -1; |
| 3061 | } | 3355 | } |
| 3062 | else | 3356 | else |
| @@ -3081,18 +3375,17 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3081 | previous_help_echo_string = help_echo_string; | 3375 | previous_help_echo_string = help_echo_string; |
| 3082 | help_echo_string = Qnil; | 3376 | help_echo_string = Qnil; |
| 3083 | 3377 | ||
| 3084 | /* A LeaveNotify event (well, the closest equivalent on Haiku, which | 3378 | /* A crossing event might be sent out-of-order with |
| 3085 | is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might | 3379 | regard to motion events from other windows, such as |
| 3086 | be sent out-of-order with regards to motion events from other | 3380 | when the mouse pointer rapidly moves from an |
| 3087 | windows, such as when the mouse pointer rapidly moves from an | 3381 | undecorated child frame to its parent. This can |
| 3088 | undecorated child frame to its parent. This can cause a failure to | 3382 | cause a failure to clear the mouse face on the |
| 3089 | clear the mouse face on the former if an event for the latter is | 3383 | former if an event for the latter is read by Emacs |
| 3090 | read by Emacs first and ends up showing the mouse face there. | 3384 | first and ends up showing the mouse face there. |
| 3091 | 3385 | ||
| 3092 | In case the `movement_locker' (also see the comment | 3386 | Work around the problem by clearing the mouse face |
| 3093 | there) doesn't take care of the problem, work | 3387 | now if it is currently shown on a different |
| 3094 | around it by clearing the mouse face now, if it is | 3388 | frame. */ |
| 3095 | currently shown on a different frame. */ | ||
| 3096 | 3389 | ||
| 3097 | if (hlinfo->mouse_face_hidden | 3390 | if (hlinfo->mouse_face_hidden |
| 3098 | || (f != hlinfo->mouse_face_mouse_frame | 3391 | || (f != hlinfo->mouse_face_mouse_frame |
| @@ -3181,13 +3474,13 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3181 | Lisp_Object tab_bar_arg = Qnil; | 3474 | Lisp_Object tab_bar_arg = Qnil; |
| 3182 | int tab_bar_p = 0, tool_bar_p = 0; | 3475 | int tab_bar_p = 0, tool_bar_p = 0; |
| 3183 | bool up_okay_p = false; | 3476 | bool up_okay_p = false; |
| 3477 | struct scroll_bar *bar; | ||
| 3184 | 3478 | ||
| 3185 | if (popup_activated_p || !f) | 3479 | if (popup_activated_p || !f) |
| 3186 | continue; | 3480 | continue; |
| 3187 | 3481 | ||
| 3188 | struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 3189 | |||
| 3190 | inev.modifiers = haiku_modifiers_to_emacs (b->modifiers); | 3482 | inev.modifiers = haiku_modifiers_to_emacs (b->modifiers); |
| 3483 | bar = haiku_scroll_bar_from_widget (b->scroll_bar, b->window); | ||
| 3191 | 3484 | ||
| 3192 | x_display_list->last_mouse_glyph_frame = 0; | 3485 | x_display_list->last_mouse_glyph_frame = 0; |
| 3193 | x_display_list->last_mouse_movement_time = b->time / 1000; | 3486 | x_display_list->last_mouse_movement_time = b->time / 1000; |
| @@ -3235,34 +3528,64 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3235 | if (type == BUTTON_UP) | 3528 | if (type == BUTTON_UP) |
| 3236 | { | 3529 | { |
| 3237 | inev.modifiers |= up_modifier; | 3530 | inev.modifiers |= up_modifier; |
| 3238 | up_okay_p = (dpyinfo->grabbed & (1 << b->btn_no)); | 3531 | up_okay_p = (x_display_list->grabbed & (1 << b->btn_no)); |
| 3239 | dpyinfo->grabbed &= ~(1 << b->btn_no); | 3532 | x_display_list->grabbed &= ~(1 << b->btn_no); |
| 3240 | } | 3533 | } |
| 3241 | else | 3534 | else |
| 3242 | { | 3535 | { |
| 3243 | up_okay_p = true; | 3536 | up_okay_p = true; |
| 3244 | inev.modifiers |= down_modifier; | 3537 | inev.modifiers |= down_modifier; |
| 3245 | dpyinfo->last_mouse_frame = f; | 3538 | x_display_list->last_mouse_frame = f; |
| 3246 | dpyinfo->grabbed |= (1 << b->btn_no); | 3539 | x_display_list->grabbed |= (1 << b->btn_no); |
| 3247 | if (f && !tab_bar_p) | 3540 | if (f && !tab_bar_p) |
| 3248 | f->last_tab_bar_item = -1; | 3541 | f->last_tab_bar_item = -1; |
| 3249 | if (f && !tool_bar_p) | 3542 | if (f && !tool_bar_p) |
| 3250 | f->last_tool_bar_item = -1; | 3543 | f->last_tool_bar_item = -1; |
| 3251 | } | 3544 | } |
| 3252 | 3545 | ||
| 3253 | if (up_okay_p | 3546 | if (bar) |
| 3254 | && !(tab_bar_p && NILP (tab_bar_arg)) | 3547 | { |
| 3255 | && !tool_bar_p) | 3548 | inev.kind = (bar->horizontal |
| 3549 | ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT | ||
| 3550 | : SCROLL_BAR_CLICK_EVENT); | ||
| 3551 | inev.part = (bar->horizontal | ||
| 3552 | ? scroll_bar_horizontal_handle | ||
| 3553 | : scroll_bar_handle); | ||
| 3554 | } | ||
| 3555 | else if (up_okay_p | ||
| 3556 | && !(tab_bar_p && NILP (tab_bar_arg)) | ||
| 3557 | && !tool_bar_p) | ||
| 3256 | inev.kind = MOUSE_CLICK_EVENT; | 3558 | inev.kind = MOUSE_CLICK_EVENT; |
| 3559 | |||
| 3257 | inev.arg = tab_bar_arg; | 3560 | inev.arg = tab_bar_arg; |
| 3258 | inev.code = b->btn_no; | 3561 | inev.code = b->btn_no; |
| 3259 | 3562 | ||
| 3260 | f->mouse_moved = false; | 3563 | f->mouse_moved = false; |
| 3261 | 3564 | ||
| 3262 | XSETINT (inev.x, b->x); | 3565 | if (bar) |
| 3263 | XSETINT (inev.y, b->y); | 3566 | { |
| 3567 | if (bar->horizontal) | ||
| 3568 | { | ||
| 3569 | XSETINT (inev.x, min (max (0, b->x - bar->left), | ||
| 3570 | bar->width)); | ||
| 3571 | XSETINT (inev.y, bar->width); | ||
| 3572 | } | ||
| 3573 | else | ||
| 3574 | { | ||
| 3575 | XSETINT (inev.x, min (max (0, b->y - bar->top), | ||
| 3576 | bar->height)); | ||
| 3577 | XSETINT (inev.y, bar->height); | ||
| 3578 | } | ||
| 3579 | |||
| 3580 | inev.frame_or_window = bar->window; | ||
| 3581 | } | ||
| 3582 | else | ||
| 3583 | { | ||
| 3584 | XSETINT (inev.x, b->x); | ||
| 3585 | XSETINT (inev.y, b->y); | ||
| 3586 | XSETFRAME (inev.frame_or_window, f); | ||
| 3587 | } | ||
| 3264 | 3588 | ||
| 3265 | XSETFRAME (inev.frame_or_window, f); | ||
| 3266 | break; | 3589 | break; |
| 3267 | } | 3590 | } |
| 3268 | case ICONIFICATION: | 3591 | case ICONIFICATION: |
| @@ -3279,7 +3602,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3279 | SET_FRAME_ICONIFIED (f, 0); | 3602 | SET_FRAME_ICONIFIED (f, 0); |
| 3280 | inev.kind = DEICONIFY_EVENT; | 3603 | inev.kind = DEICONIFY_EVENT; |
| 3281 | 3604 | ||
| 3282 | |||
| 3283 | /* Haiku doesn't expose frames on deiconification, but | 3605 | /* Haiku doesn't expose frames on deiconification, but |
| 3284 | if we are double-buffered, the previous screen | 3606 | if we are double-buffered, the previous screen |
| 3285 | contents should have been preserved. */ | 3607 | contents should have been preserved. */ |
| @@ -3303,30 +3625,36 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3303 | { | 3625 | { |
| 3304 | struct haiku_move_event *b = buf; | 3626 | struct haiku_move_event *b = buf; |
| 3305 | struct frame *f = haiku_window_to_frame (b->window); | 3627 | struct frame *f = haiku_window_to_frame (b->window); |
| 3628 | int top, left; | ||
| 3629 | struct frame *p; | ||
| 3306 | 3630 | ||
| 3307 | if (!f) | 3631 | if (!f) |
| 3308 | continue; | 3632 | continue; |
| 3309 | 3633 | ||
| 3634 | FRAME_OUTPUT_DATA (f)->frame_x = b->x; | ||
| 3635 | FRAME_OUTPUT_DATA (f)->frame_y = b->y; | ||
| 3636 | |||
| 3310 | if (FRAME_PARENT_FRAME (f)) | 3637 | if (FRAME_PARENT_FRAME (f)) |
| 3311 | haiku_coords_from_parent (f, &b->x, &b->y); | 3638 | haiku_coords_from_parent (f, &b->x, &b->y); |
| 3312 | 3639 | ||
| 3313 | if (b->x != f->left_pos || b->y != f->top_pos) | 3640 | left = b->x - b->decorator_width; |
| 3641 | top = b->y - b->decorator_height; | ||
| 3642 | |||
| 3643 | if (left != f->left_pos || top != f->top_pos) | ||
| 3314 | { | 3644 | { |
| 3315 | inev.kind = MOVE_FRAME_EVENT; | 3645 | inev.kind = MOVE_FRAME_EVENT; |
| 3316 | 3646 | ||
| 3317 | XSETINT (inev.x, b->x); | 3647 | XSETINT (inev.x, left); |
| 3318 | XSETINT (inev.y, b->y); | 3648 | XSETINT (inev.y, top); |
| 3319 | 3649 | ||
| 3320 | f->left_pos = b->x; | 3650 | f->left_pos = left; |
| 3321 | f->top_pos = b->y; | 3651 | f->top_pos = top; |
| 3322 | 3652 | ||
| 3323 | struct frame *p; | 3653 | p = FRAME_PARENT_FRAME (f); |
| 3324 | 3654 | ||
| 3325 | if ((p = FRAME_PARENT_FRAME (f))) | 3655 | if (p) |
| 3326 | { | 3656 | EmacsWindow_move_weak_child (FRAME_HAIKU_WINDOW (p), |
| 3327 | void *window = FRAME_HAIKU_WINDOW (p); | 3657 | b->window, left, top); |
| 3328 | EmacsWindow_move_weak_child (window, b->window, b->x, b->y); | ||
| 3329 | } | ||
| 3330 | 3658 | ||
| 3331 | XSETFRAME (inev.frame_or_window, f); | 3659 | XSETFRAME (inev.frame_or_window, f); |
| 3332 | } | 3660 | } |
| @@ -3357,8 +3685,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3357 | inev.kind = (bar->horizontal | 3685 | inev.kind = (bar->horizontal |
| 3358 | ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : | 3686 | ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : |
| 3359 | SCROLL_BAR_CLICK_EVENT); | 3687 | SCROLL_BAR_CLICK_EVENT); |
| 3360 | inev.part = bar->horizontal ? | 3688 | inev.part = (bar->horizontal |
| 3361 | scroll_bar_horizontal_handle : scroll_bar_handle; | 3689 | ? scroll_bar_horizontal_handle |
| 3690 | : scroll_bar_handle); | ||
| 3362 | 3691 | ||
| 3363 | if (bar->horizontal) | 3692 | if (bar->horizontal) |
| 3364 | { | 3693 | { |
| @@ -3594,14 +3923,17 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3594 | case ZOOM_EVENT: | 3923 | case ZOOM_EVENT: |
| 3595 | { | 3924 | { |
| 3596 | struct haiku_zoom_event *b = buf; | 3925 | struct haiku_zoom_event *b = buf; |
| 3597 | |||
| 3598 | struct frame *f = haiku_window_to_frame (b->window); | 3926 | struct frame *f = haiku_window_to_frame (b->window); |
| 3599 | 3927 | ||
| 3600 | if (!f) | 3928 | if (!f) |
| 3601 | continue; | 3929 | continue; |
| 3602 | 3930 | ||
| 3603 | FRAME_OUTPUT_DATA (f)->zoomed_p = b->zoomed; | 3931 | if (b->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED) |
| 3604 | haiku_make_fullscreen_consistent (f); | 3932 | f->want_fullscreen = FULLSCREEN_NONE; |
| 3933 | else | ||
| 3934 | f->want_fullscreen = FULLSCREEN_MAXIMIZED; | ||
| 3935 | |||
| 3936 | FRAME_TERMINAL (f)->fullscreen_hook (f); | ||
| 3605 | break; | 3937 | break; |
| 3606 | } | 3938 | } |
| 3607 | case DRAG_AND_DROP_EVENT: | 3939 | case DRAG_AND_DROP_EVENT: |
| @@ -3625,6 +3957,15 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3625 | BMessage_delete (b->message); | 3957 | BMessage_delete (b->message); |
| 3626 | break; | 3958 | break; |
| 3627 | } | 3959 | } |
| 3960 | case SCREEN_CHANGED_EVENT: | ||
| 3961 | { | ||
| 3962 | struct haiku_screen_changed_event *b = buf; | ||
| 3963 | |||
| 3964 | inev.kind = MONITORS_CHANGED_EVENT; | ||
| 3965 | XSETTERMINAL (inev.arg, x_display_list->terminal); | ||
| 3966 | inev.timestamp = b->when / 1000; | ||
| 3967 | break; | ||
| 3968 | } | ||
| 3628 | case APP_QUIT_REQUESTED_EVENT: | 3969 | case APP_QUIT_REQUESTED_EVENT: |
| 3629 | inev.kind = SAVE_SESSION_EVENT; | 3970 | inev.kind = SAVE_SESSION_EVENT; |
| 3630 | inev.arg = Qt; | 3971 | inev.arg = Qt; |
| @@ -3685,6 +4026,21 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3685 | return message_count; | 4026 | return message_count; |
| 3686 | } | 4027 | } |
| 3687 | 4028 | ||
| 4029 | static Lisp_Object | ||
| 4030 | haiku_get_focus_frame (struct frame *f) | ||
| 4031 | { | ||
| 4032 | Lisp_Object lisp_focus; | ||
| 4033 | struct frame *focus; | ||
| 4034 | |||
| 4035 | focus = FRAME_DISPLAY_INFO (f)->focused_frame; | ||
| 4036 | |||
| 4037 | if (!focus) | ||
| 4038 | return Qnil; | ||
| 4039 | |||
| 4040 | XSETFRAME (lisp_focus, focus); | ||
| 4041 | return lisp_focus; | ||
| 4042 | } | ||
| 4043 | |||
| 3688 | static void | 4044 | static void |
| 3689 | haiku_frame_rehighlight (struct frame *frame) | 4045 | haiku_frame_rehighlight (struct frame *frame) |
| 3690 | { | 4046 | { |
| @@ -3833,6 +4189,8 @@ haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p) | |||
| 3833 | static void | 4189 | static void |
| 3834 | haiku_fullscreen (struct frame *f) | 4190 | haiku_fullscreen (struct frame *f) |
| 3835 | { | 4191 | { |
| 4192 | enum haiku_fullscreen_mode mode; | ||
| 4193 | |||
| 3836 | /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is | 4194 | /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is |
| 3837 | being created, and its regular width and height have not yet been | 4195 | being created, and its regular width and height have not yet been |
| 3838 | set. This function will be called again by haiku_create_frame, | 4196 | set. This function will be called again by haiku_create_frame, |
| @@ -3841,18 +4199,22 @@ haiku_fullscreen (struct frame *f) | |||
| 3841 | return; | 4199 | return; |
| 3842 | 4200 | ||
| 3843 | if (f->want_fullscreen == FULLSCREEN_MAXIMIZED) | 4201 | if (f->want_fullscreen == FULLSCREEN_MAXIMIZED) |
| 3844 | BWindow_zoom (FRAME_HAIKU_WINDOW (f)); | 4202 | mode = FULLSCREEN_MODE_MAXIMIZED; |
| 3845 | else if (f->want_fullscreen == FULLSCREEN_BOTH) | 4203 | else if (f->want_fullscreen == FULLSCREEN_BOTH) |
| 3846 | EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1); | 4204 | mode = FULLSCREEN_MODE_BOTH; |
| 4205 | else if (f->want_fullscreen == FULLSCREEN_WIDTH) | ||
| 4206 | mode = FULLSCREEN_MODE_WIDTH; | ||
| 4207 | else if (f->want_fullscreen == FULLSCREEN_HEIGHT) | ||
| 4208 | mode = FULLSCREEN_MODE_HEIGHT; | ||
| 3847 | else | 4209 | else |
| 3848 | { | 4210 | mode = FULLSCREEN_MODE_NONE; |
| 3849 | EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0); | ||
| 3850 | EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f)); | ||
| 3851 | } | ||
| 3852 | 4211 | ||
| 3853 | f->want_fullscreen = FULLSCREEN_NONE; | 4212 | f->want_fullscreen = FULLSCREEN_NONE; |
| 4213 | be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode); | ||
| 4214 | FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode; | ||
| 3854 | 4215 | ||
| 3855 | haiku_update_size_hints (f); | 4216 | haiku_update_size_hints (f); |
| 4217 | haiku_make_fullscreen_consistent (f); | ||
| 3856 | } | 4218 | } |
| 3857 | 4219 | ||
| 3858 | static struct terminal * | 4220 | static struct terminal * |
| @@ -3873,7 +4235,7 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo) | |||
| 3873 | terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible; | 4235 | terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible; |
| 3874 | terminal->set_frame_offset_hook = haiku_set_offset; | 4236 | terminal->set_frame_offset_hook = haiku_set_offset; |
| 3875 | terminal->delete_terminal_hook = haiku_delete_terminal; | 4237 | terminal->delete_terminal_hook = haiku_delete_terminal; |
| 3876 | terminal->get_string_resource_hook = get_string_resource; | 4238 | terminal->get_string_resource_hook = haiku_get_string_resource; |
| 3877 | terminal->set_new_font_hook = haiku_new_font; | 4239 | terminal->set_new_font_hook = haiku_new_font; |
| 3878 | terminal->defined_color_hook = haiku_defined_color; | 4240 | terminal->defined_color_hook = haiku_defined_color; |
| 3879 | terminal->set_window_size_hook = haiku_set_window_size; | 4241 | terminal->set_window_size_hook = haiku_set_window_size; |
| @@ -3904,6 +4266,7 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo) | |||
| 3904 | terminal->fullscreen_hook = haiku_fullscreen; | 4266 | terminal->fullscreen_hook = haiku_fullscreen; |
| 3905 | terminal->toolkit_position_hook = haiku_toolkit_position; | 4267 | terminal->toolkit_position_hook = haiku_toolkit_position; |
| 3906 | terminal->activate_menubar_hook = haiku_activate_menubar; | 4268 | terminal->activate_menubar_hook = haiku_activate_menubar; |
| 4269 | terminal->get_focus_frame = haiku_get_focus_frame; | ||
| 3907 | 4270 | ||
| 3908 | return terminal; | 4271 | return terminal; |
| 3909 | } | 4272 | } |
| @@ -3959,34 +4322,24 @@ haiku_term_init (void) | |||
| 3959 | 4322 | ||
| 3960 | gui_init_fringe (terminal->rif); | 4323 | gui_init_fringe (terminal->rif); |
| 3961 | 4324 | ||
| 3962 | #define ASSIGN_CURSOR(cursor, be_cursor) (dpyinfo->cursor = be_cursor) | 4325 | #define ASSIGN_CURSOR(cursor, cursor_id) \ |
| 3963 | ASSIGN_CURSOR (text_cursor, BCursor_create_i_beam ()); | 4326 | (dpyinfo->cursor = be_create_cursor_from_id (cursor_id)) |
| 3964 | ASSIGN_CURSOR (nontext_cursor, BCursor_create_default ()); | 4327 | ASSIGN_CURSOR (text_cursor, CURSOR_ID_I_BEAM); |
| 3965 | ASSIGN_CURSOR (modeline_cursor, BCursor_create_modeline ()); | 4328 | ASSIGN_CURSOR (nontext_cursor, CURSOR_ID_SYSTEM_DEFAULT); |
| 3966 | ASSIGN_CURSOR (hand_cursor, BCursor_create_grab ()); | 4329 | ASSIGN_CURSOR (modeline_cursor, CURSOR_ID_CONTEXT_MENU); |
| 3967 | ASSIGN_CURSOR (hourglass_cursor, BCursor_create_progress_cursor ()); | 4330 | ASSIGN_CURSOR (hand_cursor, CURSOR_ID_GRAB); |
| 3968 | ASSIGN_CURSOR (horizontal_drag_cursor, | 4331 | ASSIGN_CURSOR (hourglass_cursor, CURSOR_ID_PROGRESS); |
| 3969 | BCursor_from_id (CURSOR_ID_RESIZE_EAST_WEST)); | 4332 | ASSIGN_CURSOR (horizontal_drag_cursor, CURSOR_ID_RESIZE_EAST_WEST); |
| 3970 | ASSIGN_CURSOR (vertical_drag_cursor, | 4333 | ASSIGN_CURSOR (vertical_drag_cursor, CURSOR_ID_RESIZE_NORTH_SOUTH); |
| 3971 | BCursor_from_id (CURSOR_ID_RESIZE_NORTH_SOUTH)); | 4334 | ASSIGN_CURSOR (left_edge_cursor, CURSOR_ID_RESIZE_WEST); |
| 3972 | ASSIGN_CURSOR (left_edge_cursor, | 4335 | ASSIGN_CURSOR (top_left_corner_cursor, CURSOR_ID_RESIZE_NORTH_WEST); |
| 3973 | BCursor_from_id (CURSOR_ID_RESIZE_WEST)); | 4336 | ASSIGN_CURSOR (top_edge_cursor, CURSOR_ID_RESIZE_NORTH); |
| 3974 | ASSIGN_CURSOR (top_left_corner_cursor, | 4337 | ASSIGN_CURSOR (top_right_corner_cursor, CURSOR_ID_RESIZE_NORTH_EAST); |
| 3975 | BCursor_from_id (CURSOR_ID_RESIZE_NORTH_WEST)); | 4338 | ASSIGN_CURSOR (right_edge_cursor, CURSOR_ID_RESIZE_EAST); |
| 3976 | ASSIGN_CURSOR (top_edge_cursor, | 4339 | ASSIGN_CURSOR (bottom_right_corner_cursor, CURSOR_ID_RESIZE_SOUTH_EAST); |
| 3977 | BCursor_from_id (CURSOR_ID_RESIZE_NORTH)); | 4340 | ASSIGN_CURSOR (bottom_edge_cursor, CURSOR_ID_RESIZE_SOUTH); |
| 3978 | ASSIGN_CURSOR (top_right_corner_cursor, | 4341 | ASSIGN_CURSOR (bottom_left_corner_cursor, CURSOR_ID_RESIZE_SOUTH_WEST); |
| 3979 | BCursor_from_id (CURSOR_ID_RESIZE_NORTH_EAST)); | 4342 | ASSIGN_CURSOR (no_cursor, CURSOR_ID_NO_CURSOR); |
| 3980 | ASSIGN_CURSOR (right_edge_cursor, | ||
| 3981 | BCursor_from_id (CURSOR_ID_RESIZE_EAST)); | ||
| 3982 | ASSIGN_CURSOR (bottom_right_corner_cursor, | ||
| 3983 | BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_EAST)); | ||
| 3984 | ASSIGN_CURSOR (bottom_edge_cursor, | ||
| 3985 | BCursor_from_id (CURSOR_ID_RESIZE_SOUTH)); | ||
| 3986 | ASSIGN_CURSOR (bottom_left_corner_cursor, | ||
| 3987 | BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_WEST)); | ||
| 3988 | ASSIGN_CURSOR (no_cursor, | ||
| 3989 | BCursor_from_id (CURSOR_ID_NO_CURSOR)); | ||
| 3990 | #undef ASSIGN_CURSOR | 4343 | #undef ASSIGN_CURSOR |
| 3991 | 4344 | ||
| 3992 | system_name = Fsystem_name (); | 4345 | system_name = Fsystem_name (); |
| @@ -4082,9 +4435,15 @@ mark_haiku_display (void) | |||
| 4082 | void | 4435 | void |
| 4083 | haiku_scroll_bar_remove (struct scroll_bar *bar) | 4436 | haiku_scroll_bar_remove (struct scroll_bar *bar) |
| 4084 | { | 4437 | { |
| 4438 | void *view; | ||
| 4439 | struct frame *f; | ||
| 4440 | |||
| 4441 | f = WINDOW_XFRAME (XWINDOW (bar->window)); | ||
| 4442 | view = FRAME_HAIKU_VIEW (f); | ||
| 4443 | |||
| 4085 | block_input (); | 4444 | block_input (); |
| 4086 | void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (XWINDOW (bar->window))); | 4445 | BView_forget_scroll_bar (view, bar->left, bar->top, |
| 4087 | BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height); | 4446 | bar->width, bar->height); |
| 4088 | BScrollBar_delete (bar->scroll_bar); | 4447 | BScrollBar_delete (bar->scroll_bar); |
| 4089 | expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)), | 4448 | expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)), |
| 4090 | bar->left, bar->top, bar->width, bar->height); | 4449 | bar->left, bar->top, bar->width, bar->height); |
| @@ -4093,7 +4452,6 @@ haiku_scroll_bar_remove (struct scroll_bar *bar) | |||
| 4093 | wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); | 4452 | wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); |
| 4094 | else | 4453 | else |
| 4095 | wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); | 4454 | wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); |
| 4096 | |||
| 4097 | unblock_input (); | 4455 | unblock_input (); |
| 4098 | }; | 4456 | }; |
| 4099 | 4457 | ||
| @@ -4101,6 +4459,22 @@ void | |||
| 4101 | haiku_set_offset (struct frame *frame, int x, int y, | 4459 | haiku_set_offset (struct frame *frame, int x, int y, |
| 4102 | int change_gravity) | 4460 | int change_gravity) |
| 4103 | { | 4461 | { |
| 4462 | Lisp_Object lframe; | ||
| 4463 | |||
| 4464 | /* Don't allow moving a fullscreen frame: the semantics of that are | ||
| 4465 | unclear. */ | ||
| 4466 | |||
| 4467 | XSETFRAME (lframe, frame); | ||
| 4468 | if (EQ (Fframe_parameter (lframe, Qfullscreen), Qfullboth) | ||
| 4469 | /* Only do this if the fullscreen status has actually been | ||
| 4470 | applied. */ | ||
| 4471 | && frame->want_fullscreen == FULLSCREEN_NONE | ||
| 4472 | /* And if the configury during frame creation has been | ||
| 4473 | completed. Otherwise, there will be no valid "old position" | ||
| 4474 | to go back to. */ | ||
| 4475 | && FRAME_OUTPUT_DATA (frame)->configury_done) | ||
| 4476 | return; | ||
| 4477 | |||
| 4104 | if (change_gravity > 0) | 4478 | if (change_gravity > 0) |
| 4105 | { | 4479 | { |
| 4106 | frame->top_pos = y; | 4480 | frame->top_pos = y; |
| @@ -4160,7 +4534,7 @@ haiku_merge_cursor_foreground (struct glyph_string *s, | |||
| 4160 | foreground = s->face->foreground; | 4534 | foreground = s->face->foreground; |
| 4161 | 4535 | ||
| 4162 | if (background == s->face->background | 4536 | if (background == s->face->background |
| 4163 | || foreground == s->face->foreground) | 4537 | && foreground == s->face->foreground) |
| 4164 | { | 4538 | { |
| 4165 | background = s->face->foreground; | 4539 | background = s->face->foreground; |
| 4166 | foreground = s->face->background; | 4540 | foreground = s->face->background; |
diff --git a/src/haikuterm.h b/src/haikuterm.h index 30b474b1e1d..ea20289b5d1 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h | |||
| @@ -52,6 +52,10 @@ struct haiku_bitmap_record | |||
| 52 | char *file; | 52 | char *file; |
| 53 | int refcount; | 53 | int refcount; |
| 54 | int height, width, depth; | 54 | int height, width, depth; |
| 55 | |||
| 56 | uint32_t stipple_foreground; | ||
| 57 | uint32_t stipple_background; | ||
| 58 | void *stipple_bits; | ||
| 55 | }; | 59 | }; |
| 56 | 60 | ||
| 57 | struct haiku_display_info | 61 | struct haiku_display_info |
| @@ -156,13 +160,16 @@ struct haiku_output | |||
| 156 | int fontset; | 160 | int fontset; |
| 157 | int baseline_offset; | 161 | int baseline_offset; |
| 158 | 162 | ||
| 159 | bool_bf zoomed_p : 1; | 163 | /* Whether or not the hourglass cursor is currently being |
| 164 | displayed. */ | ||
| 160 | bool_bf hourglass_p : 1; | 165 | bool_bf hourglass_p : 1; |
| 166 | |||
| 167 | /* Whether or not the menu bar is open. */ | ||
| 161 | bool_bf menu_bar_open_p : 1; | 168 | bool_bf menu_bar_open_p : 1; |
| 162 | 169 | ||
| 163 | /* Whether or not there is data in a back buffer that hasn't been | 170 | /* Whether or not there is data in a back buffer that hasn't been |
| 164 | displayed yet. */ | 171 | displayed yet. */ |
| 165 | bool dirty_p; | 172 | bool_bf dirty_p : 1; |
| 166 | 173 | ||
| 167 | struct font *font; | 174 | struct font *font; |
| 168 | 175 | ||
| @@ -192,6 +199,15 @@ struct haiku_output | |||
| 192 | They are changed only when a different background is involved. | 199 | They are changed only when a different background is involved. |
| 193 | -1 means no color has been computed. */ | 200 | -1 means no color has been computed. */ |
| 194 | long relief_background; | 201 | long relief_background; |
| 202 | |||
| 203 | /* The absolute position of this frame. This differs from left_pos | ||
| 204 | and top_pos in that the decorator and parent frames are not taken | ||
| 205 | into account. */ | ||
| 206 | int frame_x, frame_y; | ||
| 207 | |||
| 208 | /* The current fullscreen mode of this frame. This should be `enum | ||
| 209 | haiku_fullscreen_mode', but that isn't available here. */ | ||
| 210 | int fullscreen_mode; | ||
| 195 | }; | 211 | }; |
| 196 | 212 | ||
| 197 | struct x_output | 213 | struct x_output |
| @@ -203,7 +219,13 @@ extern struct haiku_display_info *x_display_list; | |||
| 203 | extern struct font_driver const haikufont_driver; | 219 | extern struct font_driver const haikufont_driver; |
| 204 | 220 | ||
| 205 | extern Lisp_Object tip_frame; | 221 | extern Lisp_Object tip_frame; |
| 222 | extern Lisp_Object tip_dx; | ||
| 223 | extern Lisp_Object tip_dy; | ||
| 224 | |||
| 206 | extern struct frame *haiku_dnd_frame; | 225 | extern struct frame *haiku_dnd_frame; |
| 226 | extern bool haiku_dnd_follow_tooltip; | ||
| 227 | |||
| 228 | extern frame_parm_handler haiku_frame_parm_handlers[]; | ||
| 207 | 229 | ||
| 208 | struct scroll_bar | 230 | struct scroll_bar |
| 209 | { | 231 | { |
| @@ -298,6 +320,7 @@ extern void haiku_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); | |||
| 298 | extern void haiku_set_internal_border_width (struct frame *, Lisp_Object, Lisp_Object); | 320 | extern void haiku_set_internal_border_width (struct frame *, Lisp_Object, Lisp_Object); |
| 299 | extern void haiku_change_tab_bar_height (struct frame *, int); | 321 | extern void haiku_change_tab_bar_height (struct frame *, int); |
| 300 | extern void haiku_change_tool_bar_height (struct frame *, int); | 322 | extern void haiku_change_tool_bar_height (struct frame *, int); |
| 323 | extern void haiku_free_custom_cursors (struct frame *); | ||
| 301 | 324 | ||
| 302 | extern void haiku_query_color (uint32_t, Emacs_Color *); | 325 | extern void haiku_query_color (uint32_t, Emacs_Color *); |
| 303 | 326 | ||
| @@ -323,6 +346,9 @@ extern int haiku_load_image (struct frame *, struct image *, | |||
| 323 | extern void syms_of_haikuimage (void); | 346 | extern void syms_of_haikuimage (void); |
| 324 | #endif | 347 | #endif |
| 325 | 348 | ||
| 349 | extern void haiku_draw_background_rect (struct glyph_string *, struct face *, | ||
| 350 | int, int, int, int); | ||
| 351 | |||
| 326 | #ifdef USE_BE_CAIRO | 352 | #ifdef USE_BE_CAIRO |
| 327 | extern cairo_t *haiku_begin_cr_clip (struct frame *, struct glyph_string *); | 353 | extern cairo_t *haiku_begin_cr_clip (struct frame *, struct glyph_string *); |
| 328 | 354 | ||
diff --git a/src/image.c b/src/image.c index e4b56e29cff..058c1755704 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -542,12 +542,26 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 542 | #endif /* HAVE_PGTK */ | 542 | #endif /* HAVE_PGTK */ |
| 543 | 543 | ||
| 544 | #ifdef HAVE_HAIKU | 544 | #ifdef HAVE_HAIKU |
| 545 | void *bitmap = BBitmap_new (width, height, 1); | 545 | void *bitmap, *stipple; |
| 546 | int bytes_per_line, x, y; | ||
| 547 | |||
| 548 | bitmap = BBitmap_new (width, height, false); | ||
| 546 | 549 | ||
| 547 | if (!bitmap) | 550 | if (!bitmap) |
| 548 | return -1; | 551 | return -1; |
| 549 | 552 | ||
| 550 | BBitmap_import_mono_bits (bitmap, bits, width, height); | 553 | bytes_per_line = (width + 7) / 8; |
| 554 | stipple = xmalloc (height * bytes_per_line); | ||
| 555 | memcpy (stipple, bits, height * bytes_per_line); | ||
| 556 | |||
| 557 | for (y = 0; y < height; y++) | ||
| 558 | { | ||
| 559 | for (x = 0; x < width; x++) | ||
| 560 | PUT_PIXEL (bitmap, x, y, ((bits[8] >> (x % 8)) & 1 | ||
| 561 | ? f->foreground_pixel | ||
| 562 | : f->background_pixel)); | ||
| 563 | bits += bytes_per_line; | ||
| 564 | } | ||
| 551 | #endif | 565 | #endif |
| 552 | 566 | ||
| 553 | id = image_allocate_bitmap_record (f); | 567 | id = image_allocate_bitmap_record (f); |
| @@ -567,6 +581,11 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 567 | #ifdef HAVE_HAIKU | 581 | #ifdef HAVE_HAIKU |
| 568 | dpyinfo->bitmaps[id - 1].img = bitmap; | 582 | dpyinfo->bitmaps[id - 1].img = bitmap; |
| 569 | dpyinfo->bitmaps[id - 1].depth = 1; | 583 | dpyinfo->bitmaps[id - 1].depth = 1; |
| 584 | dpyinfo->bitmaps[id - 1].stipple_bits = stipple; | ||
| 585 | dpyinfo->bitmaps[id - 1].stipple_foreground | ||
| 586 | = f->foreground_pixel & 0xffffffff; | ||
| 587 | dpyinfo->bitmaps[id - 1].stipple_background | ||
| 588 | = f->background_pixel & 0xffffffff; | ||
| 570 | #endif | 589 | #endif |
| 571 | 590 | ||
| 572 | dpyinfo->bitmaps[id - 1].file = NULL; | 591 | dpyinfo->bitmaps[id - 1].file = NULL; |
| @@ -592,24 +611,55 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 592 | return id; | 611 | return id; |
| 593 | } | 612 | } |
| 594 | 613 | ||
| 614 | #if defined HAVE_HAIKU || defined HAVE_NS | ||
| 615 | static char *slurp_file (int, ptrdiff_t *); | ||
| 616 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); | ||
| 617 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, | ||
| 618 | int *, int *, char **, bool); | ||
| 619 | #endif | ||
| 620 | |||
| 595 | /* Create bitmap from file FILE for frame F. */ | 621 | /* Create bitmap from file FILE for frame F. */ |
| 596 | 622 | ||
| 597 | ptrdiff_t | 623 | ptrdiff_t |
| 598 | image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | 624 | image_create_bitmap_from_file (struct frame *f, Lisp_Object file) |
| 599 | { | 625 | { |
| 600 | #if defined (HAVE_NTGUI) || defined (HAVE_HAIKU) | 626 | #if defined (HAVE_NTGUI) |
| 601 | return -1; /* W32_TODO : bitmap support */ | 627 | return -1; /* W32_TODO : bitmap support */ |
| 602 | #else | 628 | #else |
| 603 | Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); | 629 | Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 604 | #endif | 630 | #endif |
| 605 | 631 | ||
| 606 | #ifdef HAVE_NS | 632 | #ifdef HAVE_NS |
| 607 | ptrdiff_t id; | 633 | ptrdiff_t id, size; |
| 608 | void *bitmap = ns_image_from_file (file); | 634 | int fd, width, height, rc; |
| 635 | char *contents, *data; | ||
| 636 | void *bitmap; | ||
| 609 | 637 | ||
| 610 | if (!bitmap) | 638 | if (!STRINGP (image_find_image_fd (file, &fd))) |
| 639 | return -1; | ||
| 640 | |||
| 641 | contents = slurp_file (fd, &size); | ||
| 642 | |||
| 643 | if (!contents) | ||
| 644 | return -1; | ||
| 645 | |||
| 646 | rc = xbm_read_bitmap_data (f, contents, contents + size, | ||
| 647 | &width, &height, &data, 0); | ||
| 648 | |||
| 649 | if (!rc) | ||
| 650 | { | ||
| 651 | xfree (contents); | ||
| 611 | return -1; | 652 | return -1; |
| 653 | } | ||
| 612 | 654 | ||
| 655 | bitmap = ns_image_from_XBM (data, width, height, 0, 0); | ||
| 656 | |||
| 657 | if (!bitmap) | ||
| 658 | { | ||
| 659 | xfree (contents); | ||
| 660 | xfree (data); | ||
| 661 | return -1; | ||
| 662 | } | ||
| 613 | 663 | ||
| 614 | id = image_allocate_bitmap_record (f); | 664 | id = image_allocate_bitmap_record (f); |
| 615 | dpyinfo->bitmaps[id - 1].img = bitmap; | 665 | dpyinfo->bitmaps[id - 1].img = bitmap; |
| @@ -618,6 +668,9 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 618 | dpyinfo->bitmaps[id - 1].depth = 1; | 668 | dpyinfo->bitmaps[id - 1].depth = 1; |
| 619 | dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap); | 669 | dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap); |
| 620 | dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap); | 670 | dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap); |
| 671 | |||
| 672 | xfree (contents); | ||
| 673 | xfree (data); | ||
| 621 | return id; | 674 | return id; |
| 622 | #endif | 675 | #endif |
| 623 | 676 | ||
| @@ -637,7 +690,6 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 637 | dpyinfo->bitmaps[id - 1].img = bitmap; | 690 | dpyinfo->bitmaps[id - 1].img = bitmap; |
| 638 | dpyinfo->bitmaps[id - 1].refcount = 1; | 691 | dpyinfo->bitmaps[id - 1].refcount = 1; |
| 639 | dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); | 692 | dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); |
| 640 | //dpyinfo->bitmaps[id - 1].depth = 1; | ||
| 641 | dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); | 693 | dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); |
| 642 | dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); | 694 | dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); |
| 643 | dpyinfo->bitmaps[id - 1].pattern | 695 | dpyinfo->bitmaps[id - 1].pattern |
| @@ -692,6 +744,89 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 692 | 744 | ||
| 693 | return id; | 745 | return id; |
| 694 | #endif /* HAVE_X_WINDOWS */ | 746 | #endif /* HAVE_X_WINDOWS */ |
| 747 | |||
| 748 | #ifdef HAVE_HAIKU | ||
| 749 | ptrdiff_t id, size; | ||
| 750 | int fd, width, height, rc, bytes_per_line, x, y; | ||
| 751 | char *contents, *data, *tmp; | ||
| 752 | void *bitmap; | ||
| 753 | Lisp_Object found; | ||
| 754 | |||
| 755 | /* Look for an existing bitmap with the same name. */ | ||
| 756 | for (id = 0; id < dpyinfo->bitmaps_last; ++id) | ||
| 757 | { | ||
| 758 | if (dpyinfo->bitmaps[id].refcount | ||
| 759 | && dpyinfo->bitmaps[id].file | ||
| 760 | && !strcmp (dpyinfo->bitmaps[id].file, SSDATA (file))) | ||
| 761 | { | ||
| 762 | ++dpyinfo->bitmaps[id].refcount; | ||
| 763 | return id + 1; | ||
| 764 | } | ||
| 765 | } | ||
| 766 | |||
| 767 | /* Search bitmap-file-path for the file, if appropriate. */ | ||
| 768 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, | ||
| 769 | make_fixnum (R_OK), false, false) | ||
| 770 | < 0) | ||
| 771 | return -1; | ||
| 772 | |||
| 773 | if (!STRINGP (image_find_image_fd (file, &fd)) | ||
| 774 | && !STRINGP (image_find_image_fd (found, &fd))) | ||
| 775 | return -1; | ||
| 776 | |||
| 777 | contents = slurp_file (fd, &size); | ||
| 778 | |||
| 779 | if (!contents) | ||
| 780 | return -1; | ||
| 781 | |||
| 782 | rc = xbm_read_bitmap_data (f, contents, contents + size, | ||
| 783 | &width, &height, &data, 0); | ||
| 784 | |||
| 785 | if (!rc) | ||
| 786 | { | ||
| 787 | xfree (contents); | ||
| 788 | return -1; | ||
| 789 | } | ||
| 790 | |||
| 791 | bitmap = BBitmap_new (width, height, false); | ||
| 792 | |||
| 793 | if (!bitmap) | ||
| 794 | { | ||
| 795 | xfree (contents); | ||
| 796 | xfree (data); | ||
| 797 | return -1; | ||
| 798 | } | ||
| 799 | |||
| 800 | id = image_allocate_bitmap_record (f); | ||
| 801 | |||
| 802 | dpyinfo->bitmaps[id - 1].img = bitmap; | ||
| 803 | dpyinfo->bitmaps[id - 1].depth = 1; | ||
| 804 | dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); | ||
| 805 | dpyinfo->bitmaps[id - 1].height = height; | ||
| 806 | dpyinfo->bitmaps[id - 1].width = width; | ||
| 807 | dpyinfo->bitmaps[id - 1].refcount = 1; | ||
| 808 | dpyinfo->bitmaps[id - 1].stipple_foreground | ||
| 809 | = f->foreground_pixel & 0xffffffff; | ||
| 810 | dpyinfo->bitmaps[id - 1].stipple_background | ||
| 811 | = f->background_pixel & 0xffffffff; | ||
| 812 | dpyinfo->bitmaps[id - 1].stipple_bits = data; | ||
| 813 | |||
| 814 | bytes_per_line = (width + 7) / 8; | ||
| 815 | tmp = data; | ||
| 816 | |||
| 817 | for (y = 0; y < height; y++) | ||
| 818 | { | ||
| 819 | for (x = 0; x < width; x++) | ||
| 820 | PUT_PIXEL (bitmap, x, y, ((tmp[x / 8] >> (x % 8)) & 1 | ||
| 821 | ? f->foreground_pixel | ||
| 822 | : f->background_pixel)); | ||
| 823 | |||
| 824 | tmp += bytes_per_line; | ||
| 825 | } | ||
| 826 | |||
| 827 | xfree (contents); | ||
| 828 | return id; | ||
| 829 | #endif | ||
| 695 | } | 830 | } |
| 696 | 831 | ||
| 697 | /* Free bitmap B. */ | 832 | /* Free bitmap B. */ |
| @@ -724,6 +859,9 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) | |||
| 724 | 859 | ||
| 725 | #ifdef HAVE_HAIKU | 860 | #ifdef HAVE_HAIKU |
| 726 | BBitmap_free (bm->img); | 861 | BBitmap_free (bm->img); |
| 862 | |||
| 863 | if (bm->stipple_bits) | ||
| 864 | xfree (bm->stipple_bits); | ||
| 727 | #endif | 865 | #endif |
| 728 | 866 | ||
| 729 | if (bm->file) | 867 | if (bm->file) |
| @@ -6169,7 +6307,7 @@ image_edge_detection (struct frame *f, struct image *img, | |||
| 6169 | } | 6307 | } |
| 6170 | 6308 | ||
| 6171 | 6309 | ||
| 6172 | #if defined HAVE_X_WINDOWS || defined USE_CAIRO | 6310 | #if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_HAIKU |
| 6173 | static void | 6311 | static void |
| 6174 | image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap, | 6312 | image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap, |
| 6175 | int x, int y, unsigned int width, unsigned int height, | 6313 | int x, int y, unsigned int width, unsigned int height, |
| @@ -6203,9 +6341,11 @@ image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap, | |||
| 6203 | XDrawLine (dpy, pixmap, gc, x, y, x + width - 1, y + height - 1); | 6341 | XDrawLine (dpy, pixmap, gc, x, y, x + width - 1, y + height - 1); |
| 6204 | XDrawLine (dpy, pixmap, gc, x, y + height - 1, x + width - 1, y); | 6342 | XDrawLine (dpy, pixmap, gc, x, y + height - 1, x + width - 1, y); |
| 6205 | XFreeGC (dpy, gc); | 6343 | XFreeGC (dpy, gc); |
| 6206 | #endif /* HAVE_X_WINDOWS */ | 6344 | #elif HAVE_HAIKU |
| 6345 | be_draw_cross_on_pixmap (pixmap, x, y, width, height, color); | ||
| 6346 | #endif | ||
| 6207 | } | 6347 | } |
| 6208 | #endif /* HAVE_X_WINDOWS || USE_CAIRO */ | 6348 | #endif /* HAVE_X_WINDOWS || USE_CAIRO || HAVE_HAIKU */ |
| 6209 | 6349 | ||
| 6210 | /* Transform image IMG on frame F so that it looks disabled. */ | 6350 | /* Transform image IMG on frame F so that it looks disabled. */ |
| 6211 | 6351 | ||
| @@ -6247,25 +6387,23 @@ image_disable_image (struct frame *f, struct image *img) | |||
| 6247 | { | 6387 | { |
| 6248 | #ifndef HAVE_NTGUI | 6388 | #ifndef HAVE_NTGUI |
| 6249 | #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ | 6389 | #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ |
| 6250 | #ifndef HAVE_HAIKU | ||
| 6251 | 6390 | ||
| 6252 | #ifndef USE_CAIRO | 6391 | #if !defined USE_CAIRO && !defined HAVE_HAIKU |
| 6253 | #define CrossForeground(f) BLACK_PIX_DEFAULT (f) | 6392 | #define CrossForeground(f) BLACK_PIX_DEFAULT (f) |
| 6254 | #define MaskForeground(f) WHITE_PIX_DEFAULT (f) | 6393 | #define MaskForeground(f) WHITE_PIX_DEFAULT (f) |
| 6255 | #else /* USE_CAIRO */ | 6394 | #else /* USE_CAIRO || HAVE_HAIKU */ |
| 6256 | #define CrossForeground(f) 0 | 6395 | #define CrossForeground(f) 0 |
| 6257 | #define MaskForeground(f) PIX_MASK_DRAW | 6396 | #define MaskForeground(f) PIX_MASK_DRAW |
| 6258 | #endif /* USE_CAIRO */ | 6397 | #endif /* USE_CAIRO || HAVE_HAIKU */ |
| 6259 | 6398 | ||
| 6260 | #ifndef USE_CAIRO | 6399 | #if !defined USE_CAIRO && !defined HAVE_HAIKU |
| 6261 | image_sync_to_pixmaps (f, img); | 6400 | image_sync_to_pixmaps (f, img); |
| 6262 | #endif /* !USE_CAIRO */ | 6401 | #endif /* !USE_CAIRO && !HAVE_HAIKU */ |
| 6263 | image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height, | 6402 | image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height, |
| 6264 | CrossForeground (f)); | 6403 | CrossForeground (f)); |
| 6265 | if (img->mask) | 6404 | if (img->mask) |
| 6266 | image_pixmap_draw_cross (f, img->mask, 0, 0, img->width, img->height, | 6405 | image_pixmap_draw_cross (f, img->mask, 0, 0, img->width, img->height, |
| 6267 | MaskForeground (f)); | 6406 | MaskForeground (f)); |
| 6268 | #endif /* !HAVE_HAIKU */ | ||
| 6269 | #endif /* !HAVE_NS */ | 6407 | #endif /* !HAVE_NS */ |
| 6270 | #else | 6408 | #else |
| 6271 | HDC hdc, bmpdc; | 6409 | HDC hdc, bmpdc; |
| @@ -8970,7 +9108,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 8970 | goto gif_error; | 9108 | goto gif_error; |
| 8971 | } | 9109 | } |
| 8972 | 9110 | ||
| 8973 | /* It's an animated image, so initalize the cache. */ | 9111 | /* It's an animated image, so initialize the cache. */ |
| 8974 | if (cache && !cache->handle) | 9112 | if (cache && !cache->handle) |
| 8975 | { | 9113 | { |
| 8976 | cache->handle = gif; | 9114 | cache->handle = gif; |
diff --git a/src/indent.c b/src/indent.c index acbb9dc9723..51f6f414de3 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -1204,7 +1204,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, | |||
| 1204 | /* Negative width means use all available text columns. */ | 1204 | /* Negative width means use all available text columns. */ |
| 1205 | if (width < 0) | 1205 | if (width < 0) |
| 1206 | { | 1206 | { |
| 1207 | width = window_body_width (win, 0); | 1207 | width = window_body_width (win, WINDOW_BODY_IN_CANONICAL_CHARS); |
| 1208 | /* We must make room for continuation marks if we don't have fringes. */ | 1208 | /* We must make room for continuation marks if we don't have fringes. */ |
| 1209 | #ifdef HAVE_WINDOW_SYSTEM | 1209 | #ifdef HAVE_WINDOW_SYSTEM |
| 1210 | if (!FRAME_WINDOW_P (XFRAME (win->frame))) | 1210 | if (!FRAME_WINDOW_P (XFRAME (win->frame))) |
| @@ -1814,7 +1814,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) | |||
| 1814 | ? window_internal_height (w) | 1814 | ? window_internal_height (w) |
| 1815 | : XFIXNUM (XCDR (topos))), | 1815 | : XFIXNUM (XCDR (topos))), |
| 1816 | (NILP (topos) | 1816 | (NILP (topos) |
| 1817 | ? (window_body_width (w, 0) | 1817 | ? (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) |
| 1818 | - ( | 1818 | - ( |
| 1819 | #ifdef HAVE_WINDOW_SYSTEM | 1819 | #ifdef HAVE_WINDOW_SYSTEM |
| 1820 | FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 : | 1820 | FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 : |
diff --git a/src/intervals.c b/src/intervals.c index 687b237b9ea..9e28637d6bc 100644 --- a/src/intervals.c +++ b/src/intervals.c | |||
| @@ -121,7 +121,6 @@ copy_properties (INTERVAL source, INTERVAL target) | |||
| 121 | { | 121 | { |
| 122 | if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target)) | 122 | if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target)) |
| 123 | return; | 123 | return; |
| 124 | eassume (source && target); | ||
| 125 | 124 | ||
| 126 | COPY_INTERVAL_CACHE (source, target); | 125 | COPY_INTERVAL_CACHE (source, target); |
| 127 | set_interval_plist (target, Fcopy_sequence (source->plist)); | 126 | set_interval_plist (target, Fcopy_sequence (source->plist)); |
diff --git a/src/intervals.h b/src/intervals.h index 484fca2e756..0ce581208e3 100644 --- a/src/intervals.h +++ b/src/intervals.h | |||
| @@ -251,7 +251,7 @@ extern void traverse_intervals_noorder (INTERVAL, | |||
| 251 | void (*) (INTERVAL, void *), void *); | 251 | void (*) (INTERVAL, void *), void *); |
| 252 | extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t) | 252 | extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t) |
| 253 | ATTRIBUTE_RETURNS_NONNULL; | 253 | ATTRIBUTE_RETURNS_NONNULL; |
| 254 | extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t); | 254 | extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t) ATTRIBUTE_RETURNS_NONNULL; |
| 255 | extern INTERVAL find_interval (INTERVAL, ptrdiff_t); | 255 | extern INTERVAL find_interval (INTERVAL, ptrdiff_t); |
| 256 | extern INTERVAL next_interval (INTERVAL); | 256 | extern INTERVAL next_interval (INTERVAL); |
| 257 | extern INTERVAL previous_interval (INTERVAL); | 257 | extern INTERVAL previous_interval (INTERVAL); |
diff --git a/src/json.c b/src/json.c index 957f91b46bb..4b3fabb3eb3 100644 --- a/src/json.c +++ b/src/json.c | |||
| @@ -364,7 +364,7 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp, | |||
| 364 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 364 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 365 | { | 365 | { |
| 366 | Lisp_Object key = HASH_KEY (h, i); | 366 | Lisp_Object key = HASH_KEY (h, i); |
| 367 | if (!EQ (key, Qunbound)) | 367 | if (!BASE_EQ (key, Qunbound)) |
| 368 | { | 368 | { |
| 369 | CHECK_STRING (key); | 369 | CHECK_STRING (key); |
| 370 | Lisp_Object ekey = json_encode (key); | 370 | Lisp_Object ekey = json_encode (key); |
diff --git a/src/keyboard.c b/src/keyboard.c index 70908120cb0..55d710ed627 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -95,8 +95,6 @@ volatile int interrupt_input_blocked; | |||
| 95 | The maybe_quit function checks this. */ | 95 | The maybe_quit function checks this. */ |
| 96 | volatile bool pending_signals; | 96 | volatile bool pending_signals; |
| 97 | 97 | ||
| 98 | enum { KBD_BUFFER_SIZE = 4096 }; | ||
| 99 | |||
| 100 | KBOARD *initial_kboard; | 98 | KBOARD *initial_kboard; |
| 101 | KBOARD *current_kboard; | 99 | KBOARD *current_kboard; |
| 102 | static KBOARD *all_kboards; | 100 | static KBOARD *all_kboards; |
| @@ -290,14 +288,14 @@ bool input_was_pending; | |||
| 290 | 288 | ||
| 291 | /* Circular buffer for pre-read keyboard input. */ | 289 | /* Circular buffer for pre-read keyboard input. */ |
| 292 | 290 | ||
| 293 | static union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE]; | 291 | union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE]; |
| 294 | 292 | ||
| 295 | /* Pointer to next available character in kbd_buffer. | 293 | /* Pointer to next available character in kbd_buffer. |
| 296 | If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. */ | 294 | If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. */ |
| 297 | static union buffered_input_event *kbd_fetch_ptr; | 295 | union buffered_input_event *kbd_fetch_ptr; |
| 298 | 296 | ||
| 299 | /* Pointer to next place to store character in kbd_buffer. */ | 297 | /* Pointer to next place to store character in kbd_buffer. */ |
| 300 | static union buffered_input_event *kbd_store_ptr; | 298 | union buffered_input_event *kbd_store_ptr; |
| 301 | 299 | ||
| 302 | /* The above pair of variables forms a "queue empty" flag. When we | 300 | /* The above pair of variables forms a "queue empty" flag. When we |
| 303 | enqueue a non-hook event, we increment kbd_store_ptr. When we | 301 | enqueue a non-hook event, we increment kbd_store_ptr. When we |
| @@ -391,14 +389,6 @@ next_kbd_event (union buffered_input_event *ptr) | |||
| 391 | return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1; | 389 | return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1; |
| 392 | } | 390 | } |
| 393 | 391 | ||
| 394 | #ifdef HAVE_X11 | ||
| 395 | static union buffered_input_event * | ||
| 396 | prev_kbd_event (union buffered_input_event *ptr) | ||
| 397 | { | ||
| 398 | return ptr == kbd_buffer ? kbd_buffer + KBD_BUFFER_SIZE - 1 : ptr - 1; | ||
| 399 | } | ||
| 400 | #endif | ||
| 401 | |||
| 402 | /* Like EVENT_START, but assume EVENT is an event. | 392 | /* Like EVENT_START, but assume EVENT is an event. |
| 403 | This pacifies gcc -Wnull-dereference, which might otherwise | 393 | This pacifies gcc -Wnull-dereference, which might otherwise |
| 404 | complain about earlier checks that EVENT is indeed an event. */ | 394 | complain about earlier checks that EVENT is indeed an event. */ |
| @@ -3530,6 +3520,11 @@ readable_events (int flags) | |||
| 3530 | return 1; | 3520 | return 1; |
| 3531 | } | 3521 | } |
| 3532 | 3522 | ||
| 3523 | #ifdef HAVE_X_WINDOWS | ||
| 3524 | if (x_detect_pending_selection_requests ()) | ||
| 3525 | return 1; | ||
| 3526 | #endif | ||
| 3527 | |||
| 3533 | if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ()) | 3528 | if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ()) |
| 3534 | return 1; | 3529 | return 1; |
| 3535 | if (single_kboard) | 3530 | if (single_kboard) |
| @@ -3701,25 +3696,6 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event, | |||
| 3701 | Vquit_flag = Vthrow_on_input; | 3696 | Vquit_flag = Vthrow_on_input; |
| 3702 | } | 3697 | } |
| 3703 | 3698 | ||
| 3704 | |||
| 3705 | #ifdef HAVE_X11 | ||
| 3706 | |||
| 3707 | /* Put a selection input event back in the head of the event queue. */ | ||
| 3708 | |||
| 3709 | void | ||
| 3710 | kbd_buffer_unget_event (struct selection_input_event *event) | ||
| 3711 | { | ||
| 3712 | /* Don't let the very last slot in the buffer become full, */ | ||
| 3713 | union buffered_input_event *kp = prev_kbd_event (kbd_fetch_ptr); | ||
| 3714 | if (kp != kbd_store_ptr) | ||
| 3715 | { | ||
| 3716 | kp->sie = *event; | ||
| 3717 | kbd_fetch_ptr = kp; | ||
| 3718 | } | ||
| 3719 | } | ||
| 3720 | |||
| 3721 | #endif | ||
| 3722 | |||
| 3723 | /* Limit help event positions to this range, to avoid overflow problems. */ | 3699 | /* Limit help event positions to this range, to avoid overflow problems. */ |
| 3724 | #define INPUT_EVENT_POS_MAX \ | 3700 | #define INPUT_EVENT_POS_MAX \ |
| 3725 | ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ | 3701 | ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ |
| @@ -3876,6 +3852,11 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 3876 | struct timespec *end_time) | 3852 | struct timespec *end_time) |
| 3877 | { | 3853 | { |
| 3878 | Lisp_Object obj, str; | 3854 | Lisp_Object obj, str; |
| 3855 | #ifdef HAVE_X_WINDOWS | ||
| 3856 | bool had_pending_selection_requests; | ||
| 3857 | |||
| 3858 | had_pending_selection_requests = false; | ||
| 3859 | #endif | ||
| 3879 | 3860 | ||
| 3880 | #ifdef subprocesses | 3861 | #ifdef subprocesses |
| 3881 | if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) | 3862 | if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) |
| @@ -3928,10 +3909,18 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 3928 | #if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) | 3909 | #if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) |
| 3929 | gobble_input (); | 3910 | gobble_input (); |
| 3930 | #endif | 3911 | #endif |
| 3912 | |||
| 3931 | if (kbd_fetch_ptr != kbd_store_ptr) | 3913 | if (kbd_fetch_ptr != kbd_store_ptr) |
| 3932 | break; | 3914 | break; |
| 3933 | if (some_mouse_moved ()) | 3915 | if (some_mouse_moved ()) |
| 3934 | break; | 3916 | break; |
| 3917 | #ifdef HAVE_X_WINDOWS | ||
| 3918 | if (x_detect_pending_selection_requests ()) | ||
| 3919 | { | ||
| 3920 | had_pending_selection_requests = true; | ||
| 3921 | break; | ||
| 3922 | } | ||
| 3923 | #endif | ||
| 3935 | if (end_time) | 3924 | if (end_time) |
| 3936 | { | 3925 | { |
| 3937 | struct timespec now = current_timespec (); | 3926 | struct timespec now = current_timespec (); |
| @@ -3968,6 +3957,16 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 3968 | gobble_input (); | 3957 | gobble_input (); |
| 3969 | } | 3958 | } |
| 3970 | 3959 | ||
| 3960 | #ifdef HAVE_X_WINDOWS | ||
| 3961 | /* Handle pending selection requests. This can happen if Emacs | ||
| 3962 | enters a recursive edit inside a nested event loop (probably | ||
| 3963 | because the debugger opened) or someone called | ||
| 3964 | `read-char'. */ | ||
| 3965 | |||
| 3966 | if (had_pending_selection_requests) | ||
| 3967 | x_handle_pending_selection_requests (); | ||
| 3968 | #endif | ||
| 3969 | |||
| 3971 | if (CONSP (Vunread_command_events)) | 3970 | if (CONSP (Vunread_command_events)) |
| 3972 | { | 3971 | { |
| 3973 | Lisp_Object first; | 3972 | Lisp_Object first; |
| @@ -4022,6 +4021,11 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4022 | kbd_fetch_ptr = next_kbd_event (event); | 4021 | kbd_fetch_ptr = next_kbd_event (event); |
| 4023 | input_pending = readable_events (0); | 4022 | input_pending = readable_events (0); |
| 4024 | 4023 | ||
| 4024 | /* This means this event was already handled in | ||
| 4025 | `x_dnd_begin_drag_and_drop'. */ | ||
| 4026 | if (event->ie.modifiers < x_dnd_unsupported_event_level) | ||
| 4027 | break; | ||
| 4028 | |||
| 4025 | f = XFRAME (event->ie.frame_or_window); | 4029 | f = XFRAME (event->ie.frame_or_window); |
| 4026 | 4030 | ||
| 4027 | if (!FRAME_LIVE_P (f)) | 4031 | if (!FRAME_LIVE_P (f)) |
| @@ -4029,14 +4033,20 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4029 | 4033 | ||
| 4030 | if (!NILP (Vx_dnd_unsupported_drop_function)) | 4034 | if (!NILP (Vx_dnd_unsupported_drop_function)) |
| 4031 | { | 4035 | { |
| 4032 | if (!NILP (call6 (Vx_dnd_unsupported_drop_function, | 4036 | if (!NILP (call7 (Vx_dnd_unsupported_drop_function, |
| 4033 | XCAR (XCDR (event->ie.arg)), event->ie.x, | 4037 | XCAR (XCDR (event->ie.arg)), event->ie.x, |
| 4034 | event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), | 4038 | event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), |
| 4035 | make_uint (event->ie.code), | 4039 | make_uint (event->ie.code), |
| 4036 | event->ie.frame_or_window))) | 4040 | event->ie.frame_or_window, |
| 4041 | make_int (event->ie.timestamp)))) | ||
| 4037 | break; | 4042 | break; |
| 4038 | } | 4043 | } |
| 4039 | 4044 | ||
| 4045 | /* `x-dnd-unsupported-drop-function' could have deleted the | ||
| 4046 | event frame. */ | ||
| 4047 | if (!FRAME_LIVE_P (f)) | ||
| 4048 | break; | ||
| 4049 | |||
| 4040 | x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), | 4050 | x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), |
| 4041 | event->ie.frame_or_window, | 4051 | event->ie.frame_or_window, |
| 4042 | XCAR (event->ie.arg), | 4052 | XCAR (event->ie.arg), |
| @@ -4049,6 +4059,18 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4049 | } | 4059 | } |
| 4050 | #endif | 4060 | #endif |
| 4051 | 4061 | ||
| 4062 | case MONITORS_CHANGED_EVENT: | ||
| 4063 | { | ||
| 4064 | kbd_fetch_ptr = next_kbd_event (event); | ||
| 4065 | input_pending = readable_events (0); | ||
| 4066 | |||
| 4067 | CALLN (Frun_hook_with_args, | ||
| 4068 | Qdisplay_monitors_changed_functions, | ||
| 4069 | event->ie.arg); | ||
| 4070 | |||
| 4071 | break; | ||
| 4072 | } | ||
| 4073 | |||
| 4052 | #ifdef HAVE_EXT_MENU_BAR | 4074 | #ifdef HAVE_EXT_MENU_BAR |
| 4053 | case MENU_BAR_ACTIVATE_EVENT: | 4075 | case MENU_BAR_ACTIVATE_EVENT: |
| 4054 | { | 4076 | { |
| @@ -4324,6 +4346,10 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4324 | ? movement_frame->last_mouse_device | 4346 | ? movement_frame->last_mouse_device |
| 4325 | : virtual_core_pointer_name); | 4347 | : virtual_core_pointer_name); |
| 4326 | } | 4348 | } |
| 4349 | #ifdef HAVE_X_WINDOWS | ||
| 4350 | else if (had_pending_selection_requests) | ||
| 4351 | obj = Qnil; | ||
| 4352 | #endif | ||
| 4327 | else | 4353 | else |
| 4328 | /* We were promised by the above while loop that there was | 4354 | /* We were promised by the above while loop that there was |
| 4329 | something for us to read! */ | 4355 | something for us to read! */ |
| @@ -7220,7 +7246,10 @@ lucid_event_type_list_p (Lisp_Object object) | |||
| 7220 | If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal | 7246 | If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal |
| 7221 | events (FOCUS_IN_EVENT). | 7247 | events (FOCUS_IN_EVENT). |
| 7222 | If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse | 7248 | If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse |
| 7223 | movements and toolkit scroll bar thumb drags. */ | 7249 | movements and toolkit scroll bar thumb drags. |
| 7250 | |||
| 7251 | On X, this also returns if the selection event chain is full, since | ||
| 7252 | that's also "keyboard input". */ | ||
| 7224 | 7253 | ||
| 7225 | static bool | 7254 | static bool |
| 7226 | get_input_pending (int flags) | 7255 | get_input_pending (int flags) |
| @@ -12600,6 +12629,8 @@ See also `pre-command-hook'. */); | |||
| 12600 | DEFSYM (Qtouchscreen_end, "touchscreen-end"); | 12629 | DEFSYM (Qtouchscreen_end, "touchscreen-end"); |
| 12601 | DEFSYM (Qtouchscreen_update, "touchscreen-update"); | 12630 | DEFSYM (Qtouchscreen_update, "touchscreen-update"); |
| 12602 | DEFSYM (Qpinch, "pinch"); | 12631 | DEFSYM (Qpinch, "pinch"); |
| 12632 | DEFSYM (Qdisplay_monitors_changed_functions, | ||
| 12633 | "display-monitors-changed-functions"); | ||
| 12603 | 12634 | ||
| 12604 | DEFSYM (Qcoding, "coding"); | 12635 | DEFSYM (Qcoding, "coding"); |
| 12605 | 12636 | ||
| @@ -12840,6 +12871,14 @@ Called with three arguments: | |||
| 12840 | - the context (a string which normally goes at the start of the message), | 12871 | - the context (a string which normally goes at the start of the message), |
| 12841 | - the Lisp function within which the error was signaled. | 12872 | - the Lisp function within which the error was signaled. |
| 12842 | 12873 | ||
| 12874 | For instance, to make error messages stand out more in the echo area, | ||
| 12875 | you could say something like: | ||
| 12876 | |||
| 12877 | (setq command-error-function | ||
| 12878 | (lambda (data _ _) | ||
| 12879 | (message "%s" (propertize (error-message-string data) | ||
| 12880 | \\='face \\='error)))) | ||
| 12881 | |||
| 12843 | Also see `set-message-function' (which controls how non-error messages | 12882 | Also see `set-message-function' (which controls how non-error messages |
| 12844 | are displayed). */); | 12883 | are displayed). */); |
| 12845 | Vcommand_error_function = intern ("command-error-default-function"); | 12884 | Vcommand_error_function = intern ("command-error-default-function"); |
| @@ -12854,11 +12893,12 @@ and tool-bar buttons. */); | |||
| 12854 | 12893 | ||
| 12855 | DEFVAR_LISP ("select-active-regions", | 12894 | DEFVAR_LISP ("select-active-regions", |
| 12856 | Vselect_active_regions, | 12895 | Vselect_active_regions, |
| 12857 | doc: /* If non-nil, an active region automatically sets the primary selection. | 12896 | doc: /* If non-nil, any active region automatically sets the primary selection. |
| 12858 | If the value is `only', only temporarily active regions (usually made | 12897 | This variable only has an effect when Transient Mark mode is enabled. |
| 12859 | by mouse-dragging or shift-selection) set the window selection. | ||
| 12860 | 12898 | ||
| 12861 | This takes effect only when Transient Mark mode is enabled. */); | 12899 | If the value is `only', only temporarily active regions (usually made |
| 12900 | by mouse-dragging or shift-selection) set the window system's primary | ||
| 12901 | selection. */); | ||
| 12862 | Vselect_active_regions = Qt; | 12902 | Vselect_active_regions = Qt; |
| 12863 | 12903 | ||
| 12864 | DEFVAR_LISP ("saved-region-selection", | 12904 | DEFVAR_LISP ("saved-region-selection", |
| @@ -12943,6 +12983,15 @@ Otherwise, a wheel event will be sent every time the mouse wheel is | |||
| 12943 | moved. */); | 12983 | moved. */); |
| 12944 | mwheel_coalesce_scroll_events = true; | 12984 | mwheel_coalesce_scroll_events = true; |
| 12945 | 12985 | ||
| 12986 | DEFVAR_LISP ("display-monitors-changed-functions", Vdisplay_monitors_changed_functions, | ||
| 12987 | doc: /* Abnormal hook run when the monitor configuration changes. | ||
| 12988 | This can happen if a monitor is rotated, moved, plugged in or removed | ||
| 12989 | from a multi-monitor setup, if the primary monitor changes, or if the | ||
| 12990 | resolution of a monitor changes. The hook should accept a single | ||
| 12991 | argument, which is the terminal on which the monitor configuration | ||
| 12992 | changed. */); | ||
| 12993 | Vdisplay_monitors_changed_functions = Qnil; | ||
| 12994 | |||
| 12946 | pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); | 12995 | pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); |
| 12947 | } | 12996 | } |
| 12948 | 12997 | ||
diff --git a/src/keyboard.h b/src/keyboard.h index cd5f677b963..6ae2dc9c4c6 100644 --- a/src/keyboard.h +++ b/src/keyboard.h | |||
| @@ -358,6 +358,11 @@ enum menu_item_idx | |||
| 358 | MENU_ITEMS_ITEM_LENGTH | 358 | MENU_ITEMS_ITEM_LENGTH |
| 359 | }; | 359 | }; |
| 360 | 360 | ||
| 361 | enum | ||
| 362 | { | ||
| 363 | KBD_BUFFER_SIZE = 4096 | ||
| 364 | }; | ||
| 365 | |||
| 361 | extern void unuse_menu_items (void); | 366 | extern void unuse_menu_items (void); |
| 362 | 367 | ||
| 363 | /* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU | 368 | /* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU |
| @@ -419,6 +424,10 @@ extern void unuse_menu_items (void); | |||
| 419 | happens. */ | 424 | happens. */ |
| 420 | extern struct timespec *input_available_clear_time; | 425 | extern struct timespec *input_available_clear_time; |
| 421 | 426 | ||
| 427 | extern union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE]; | ||
| 428 | extern union buffered_input_event *kbd_fetch_ptr; | ||
| 429 | extern union buffered_input_event *kbd_store_ptr; | ||
| 430 | |||
| 422 | extern bool ignore_mouse_drag_p; | 431 | extern bool ignore_mouse_drag_p; |
| 423 | 432 | ||
| 424 | extern Lisp_Object parse_modifiers (Lisp_Object); | 433 | extern Lisp_Object parse_modifiers (Lisp_Object); |
| @@ -472,9 +481,6 @@ kbd_buffer_store_event_hold (struct input_event *event, | |||
| 472 | kbd_buffer_store_buffered_event ((union buffered_input_event *) event, | 481 | kbd_buffer_store_buffered_event ((union buffered_input_event *) event, |
| 473 | hold_quit); | 482 | hold_quit); |
| 474 | } | 483 | } |
| 475 | #ifdef HAVE_X11 | ||
| 476 | extern void kbd_buffer_unget_event (struct selection_input_event *); | ||
| 477 | #endif | ||
| 478 | extern void poll_for_input_1 (void); | 484 | extern void poll_for_input_1 (void); |
| 479 | extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object, | 485 | extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object, |
| 480 | Lisp_Object); | 486 | Lisp_Object); |
diff --git a/src/keymap.c b/src/keymap.c index da0a52bd2c1..c8b01eed6fd 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -395,7 +395,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, | |||
| 395 | if (noinherit || NILP (retval)) | 395 | if (noinherit || NILP (retval)) |
| 396 | /* If NOINHERIT, stop here, the rest is inherited. */ | 396 | /* If NOINHERIT, stop here, the rest is inherited. */ |
| 397 | break; | 397 | break; |
| 398 | else if (!EQ (retval, Qunbound)) | 398 | else if (!BASE_EQ (retval, Qunbound)) |
| 399 | { | 399 | { |
| 400 | Lisp_Object parent_entry; | 400 | Lisp_Object parent_entry; |
| 401 | eassert (KEYMAPP (retval)); | 401 | eassert (KEYMAPP (retval)); |
| @@ -454,7 +454,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, | |||
| 454 | } | 454 | } |
| 455 | 455 | ||
| 456 | /* If we found a binding, clean it up and return it. */ | 456 | /* If we found a binding, clean it up and return it. */ |
| 457 | if (!EQ (val, Qunbound)) | 457 | if (!BASE_EQ (val, Qunbound)) |
| 458 | { | 458 | { |
| 459 | if (EQ (val, Qt)) | 459 | if (EQ (val, Qt)) |
| 460 | /* A Qt binding is just like an explicit nil binding | 460 | /* A Qt binding is just like an explicit nil binding |
| @@ -466,12 +466,12 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, | |||
| 466 | 466 | ||
| 467 | if (!KEYMAPP (val)) | 467 | if (!KEYMAPP (val)) |
| 468 | { | 468 | { |
| 469 | if (NILP (retval) || EQ (retval, Qunbound)) | 469 | if (NILP (retval) || BASE_EQ (retval, Qunbound)) |
| 470 | retval = val; | 470 | retval = val; |
| 471 | if (!NILP (val)) | 471 | if (!NILP (val)) |
| 472 | break; /* Shadows everything that follows. */ | 472 | break; /* Shadows everything that follows. */ |
| 473 | } | 473 | } |
| 474 | else if (NILP (retval) || EQ (retval, Qunbound)) | 474 | else if (NILP (retval) || BASE_EQ (retval, Qunbound)) |
| 475 | retval = val; | 475 | retval = val; |
| 476 | else if (CONSP (retval_tail)) | 476 | else if (CONSP (retval_tail)) |
| 477 | { | 477 | { |
| @@ -487,7 +487,8 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, | |||
| 487 | maybe_quit (); | 487 | maybe_quit (); |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | return EQ (Qunbound, retval) ? get_keyelt (t_binding, autoload) : retval; | 490 | return BASE_EQ (Qunbound, retval) |
| 491 | ? get_keyelt (t_binding, autoload) : retval; | ||
| 491 | } | 492 | } |
| 492 | } | 493 | } |
| 493 | 494 | ||
| @@ -496,7 +497,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, | |||
| 496 | bool t_ok, bool noinherit, bool autoload) | 497 | bool t_ok, bool noinherit, bool autoload) |
| 497 | { | 498 | { |
| 498 | Lisp_Object val = access_keymap_1 (map, idx, t_ok, noinherit, autoload); | 499 | Lisp_Object val = access_keymap_1 (map, idx, t_ok, noinherit, autoload); |
| 499 | return EQ (val, Qunbound) ? Qnil : val; | 500 | return BASE_EQ (val, Qunbound) ? Qnil : val; |
| 500 | } | 501 | } |
| 501 | 502 | ||
| 502 | static void | 503 | static void |
| @@ -1550,7 +1551,7 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr) | |||
| 1550 | for ( ; CONSP (alist); alist = XCDR (alist)) | 1551 | for ( ; CONSP (alist); alist = XCDR (alist)) |
| 1551 | if ((assoc = XCAR (alist), CONSP (assoc)) | 1552 | if ((assoc = XCAR (alist), CONSP (assoc)) |
| 1552 | && (var = XCAR (assoc), SYMBOLP (var)) | 1553 | && (var = XCAR (assoc), SYMBOLP (var)) |
| 1553 | && (val = find_symbol_value (var), !EQ (val, Qunbound)) | 1554 | && (val = find_symbol_value (var), !BASE_EQ (val, Qunbound)) |
| 1554 | && !NILP (val)) | 1555 | && !NILP (val)) |
| 1555 | { | 1556 | { |
| 1556 | Lisp_Object temp; | 1557 | Lisp_Object temp; |
diff --git a/src/lisp.h b/src/lisp.h index 8832e76b447..361a3f63b28 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -621,7 +621,6 @@ extern Lisp_Object char_table_ref (Lisp_Object, int) ATTRIBUTE_PURE; | |||
| 621 | extern void char_table_set (Lisp_Object, int, Lisp_Object); | 621 | extern void char_table_set (Lisp_Object, int, Lisp_Object); |
| 622 | 622 | ||
| 623 | /* Defined in data.c. */ | 623 | /* Defined in data.c. */ |
| 624 | extern bool symbols_with_pos_enabled; | ||
| 625 | extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); | 624 | extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); |
| 626 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); | 625 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); |
| 627 | extern Lisp_Object default_value (Lisp_Object symbol); | 626 | extern Lisp_Object default_value (Lisp_Object symbol); |
| @@ -2097,19 +2096,17 @@ XSUB_CHAR_TABLE (Lisp_Object a) | |||
| 2097 | INLINE Lisp_Object | 2096 | INLINE Lisp_Object |
| 2098 | CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx) | 2097 | CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx) |
| 2099 | { | 2098 | { |
| 2100 | struct Lisp_Char_Table *tbl = NULL; | 2099 | for (struct Lisp_Char_Table *tbl = XCHAR_TABLE (ct); ; |
| 2101 | Lisp_Object val; | 2100 | tbl = XCHAR_TABLE (tbl->parent)) |
| 2102 | do | ||
| 2103 | { | 2101 | { |
| 2104 | tbl = tbl ? XCHAR_TABLE (tbl->parent) : XCHAR_TABLE (ct); | 2102 | Lisp_Object val = (SUB_CHAR_TABLE_P (tbl->ascii) |
| 2105 | val = (! SUB_CHAR_TABLE_P (tbl->ascii) ? tbl->ascii | 2103 | ? XSUB_CHAR_TABLE (tbl->ascii)->contents[idx] |
| 2106 | : XSUB_CHAR_TABLE (tbl->ascii)->contents[idx]); | 2104 | : tbl->ascii); |
| 2107 | if (NILP (val)) | 2105 | if (NILP (val)) |
| 2108 | val = tbl->defalt; | 2106 | val = tbl->defalt; |
| 2107 | if (!NILP (val) || NILP (tbl->parent)) | ||
| 2108 | return val; | ||
| 2109 | } | 2109 | } |
| 2110 | while (NILP (val) && ! NILP (tbl->parent)); | ||
| 2111 | |||
| 2112 | return val; | ||
| 2113 | } | 2110 | } |
| 2114 | 2111 | ||
| 2115 | /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII | 2112 | /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII |
| @@ -3639,6 +3636,10 @@ struct handler | |||
| 3639 | struct bc_frame *act_rec; | 3636 | struct bc_frame *act_rec; |
| 3640 | int poll_suppress_count; | 3637 | int poll_suppress_count; |
| 3641 | int interrupt_input_blocked; | 3638 | int interrupt_input_blocked; |
| 3639 | |||
| 3640 | #ifdef HAVE_X_WINDOWS | ||
| 3641 | int x_error_handler_depth; | ||
| 3642 | #endif | ||
| 3642 | }; | 3643 | }; |
| 3643 | 3644 | ||
| 3644 | extern Lisp_Object memory_signal_data; | 3645 | extern Lisp_Object memory_signal_data; |
| @@ -4492,6 +4493,7 @@ extern void dir_warning (const char *, Lisp_Object); | |||
| 4492 | extern void init_obarray_once (void); | 4493 | extern void init_obarray_once (void); |
| 4493 | extern void init_lread (void); | 4494 | extern void init_lread (void); |
| 4494 | extern void syms_of_lread (void); | 4495 | extern void syms_of_lread (void); |
| 4496 | extern void mark_lread (void); | ||
| 4495 | 4497 | ||
| 4496 | INLINE Lisp_Object | 4498 | INLINE Lisp_Object |
| 4497 | intern (const char *str) | 4499 | intern (const char *str) |
| @@ -5098,9 +5100,7 @@ extern void syms_of_w32cygwinx (void); | |||
| 5098 | extern Lisp_Object Vface_alternative_font_family_alist; | 5100 | extern Lisp_Object Vface_alternative_font_family_alist; |
| 5099 | extern Lisp_Object Vface_alternative_font_registry_alist; | 5101 | extern Lisp_Object Vface_alternative_font_registry_alist; |
| 5100 | extern void syms_of_xfaces (void); | 5102 | extern void syms_of_xfaces (void); |
| 5101 | #ifdef HAVE_PDUMPER | ||
| 5102 | extern void init_xfaces (void); | 5103 | extern void init_xfaces (void); |
| 5103 | #endif | ||
| 5104 | 5104 | ||
| 5105 | #ifdef HAVE_X_WINDOWS | 5105 | #ifdef HAVE_X_WINDOWS |
| 5106 | /* Defined in xfns.c. */ | 5106 | /* Defined in xfns.c. */ |
| @@ -5503,7 +5503,7 @@ struct for_each_tail_internal | |||
| 5503 | intended for use only by the above macros. | 5503 | intended for use only by the above macros. |
| 5504 | 5504 | ||
| 5505 | Use Brent’s teleporting tortoise-hare algorithm. See: | 5505 | Use Brent’s teleporting tortoise-hare algorithm. See: |
| 5506 | Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190 | 5506 | Brent RP. BIT. 1980;20(2):176-184. doi:10.1007/BF01933190 |
| 5507 | https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf | 5507 | https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf |
| 5508 | 5508 | ||
| 5509 | This macro uses maybe_quit because of an excess of caution. The | 5509 | This macro uses maybe_quit because of an excess of caution. The |
| @@ -5520,7 +5520,7 @@ struct for_each_tail_internal | |||
| 5520 | || ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \ | 5520 | || ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \ |
| 5521 | || (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \ | 5521 | || (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \ |
| 5522 | li.tortoise = (tail), false)) \ | 5522 | li.tortoise = (tail), false)) \ |
| 5523 | && EQ (tail, li.tortoise)) \ | 5523 | && BASE_EQ (tail, li.tortoise)) \ |
| 5524 | ? (cycle) : (void) 0)) | 5524 | ? (cycle) : (void) 0)) |
| 5525 | 5525 | ||
| 5526 | /* Do a `for' loop over alist values. */ | 5526 | /* Do a `for' loop over alist values. */ |
diff --git a/src/lread.c b/src/lread.c index f1ffdef04e4..dfabe75113e 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -656,10 +656,6 @@ struct subst | |||
| 656 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, | 656 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, |
| 657 | Lisp_Object, bool); | 657 | Lisp_Object, bool); |
| 658 | static Lisp_Object read0 (Lisp_Object, bool); | 658 | static Lisp_Object read0 (Lisp_Object, bool); |
| 659 | static Lisp_Object read1 (Lisp_Object, int *, bool, bool); | ||
| 660 | |||
| 661 | static Lisp_Object read_list (bool, Lisp_Object, bool); | ||
| 662 | static Lisp_Object read_vector (Lisp_Object, bool, bool); | ||
| 663 | 659 | ||
| 664 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); | 660 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); |
| 665 | static void substitute_in_interval (INTERVAL, void *); | 661 | static void substitute_in_interval (INTERVAL, void *); |
| @@ -940,7 +936,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) | |||
| 940 | ch = READCHAR; | 936 | ch = READCHAR; |
| 941 | if (ch == '\n') ch = READCHAR; | 937 | if (ch == '\n') ch = READCHAR; |
| 942 | /* It is OK to leave the position after a #! line, since | 938 | /* It is OK to leave the position after a #! line, since |
| 943 | that is what read1 does. */ | 939 | that is what read0 does. */ |
| 944 | } | 940 | } |
| 945 | 941 | ||
| 946 | if (ch != ';') | 942 | if (ch != ';') |
| @@ -1248,10 +1244,9 @@ Return t if the file exists and loads successfully. */) | |||
| 1248 | CHECK_STRING (file); | 1244 | CHECK_STRING (file); |
| 1249 | 1245 | ||
| 1250 | /* If file name is magic, call the handler. */ | 1246 | /* If file name is magic, call the handler. */ |
| 1251 | /* This shouldn't be necessary any more now that `openp' handles it right. | 1247 | handler = Ffind_file_name_handler (file, Qload); |
| 1252 | handler = Ffind_file_name_handler (file, Qload); | 1248 | if (!NILP (handler)) |
| 1253 | if (!NILP (handler)) | 1249 | return call5 (handler, Qload, file, noerror, nomessage, nosuffix); |
| 1254 | return call5 (handler, Qload, file, noerror, nomessage, nosuffix); */ | ||
| 1255 | 1250 | ||
| 1256 | /* The presence of this call is the result of a historical accident: | 1251 | /* The presence of this call is the result of a historical accident: |
| 1257 | it used to be in every file-operation and when it got removed | 1252 | it used to be in every file-operation and when it got removed |
| @@ -2221,7 +2216,7 @@ readevalloop (Lisp_Object readcharfun, | |||
| 2221 | lexical environment, otherwise, turn off lexical binding. */ | 2216 | lexical environment, otherwise, turn off lexical binding. */ |
| 2222 | lex_bound = find_symbol_value (Qlexical_binding); | 2217 | lex_bound = find_symbol_value (Qlexical_binding); |
| 2223 | specbind (Qinternal_interpreter_environment, | 2218 | specbind (Qinternal_interpreter_environment, |
| 2224 | (NILP (lex_bound) || EQ (lex_bound, Qunbound) | 2219 | (NILP (lex_bound) || BASE_EQ (lex_bound, Qunbound) |
| 2225 | ? Qnil : list1 (Qt))); | 2220 | ? Qnil : list1 (Qt))); |
| 2226 | specbind (Qmacroexp__dynvars, Vmacroexp__dynvars); | 2221 | specbind (Qmacroexp__dynvars, Vmacroexp__dynvars); |
| 2227 | 2222 | ||
| @@ -2286,6 +2281,7 @@ readevalloop (Lisp_Object readcharfun, | |||
| 2286 | if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' | 2281 | if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' |
| 2287 | || c == NO_BREAK_SPACE) | 2282 | || c == NO_BREAK_SPACE) |
| 2288 | goto read_next; | 2283 | goto read_next; |
| 2284 | UNREAD (c); | ||
| 2289 | 2285 | ||
| 2290 | if (! HASH_TABLE_P (read_objects_map) | 2286 | if (! HASH_TABLE_P (read_objects_map) |
| 2291 | || XHASH_TABLE (read_objects_map)->count) | 2287 | || XHASH_TABLE (read_objects_map)->count) |
| @@ -2300,12 +2296,9 @@ readevalloop (Lisp_Object readcharfun, | |||
| 2300 | DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD, | 2296 | DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD, |
| 2301 | Qnil, false); | 2297 | Qnil, false); |
| 2302 | if (!NILP (Vpurify_flag) && c == '(') | 2298 | if (!NILP (Vpurify_flag) && c == '(') |
| 2303 | { | 2299 | val = read0 (readcharfun, false); |
| 2304 | val = read_list (0, readcharfun, false); | ||
| 2305 | } | ||
| 2306 | else | 2300 | else |
| 2307 | { | 2301 | { |
| 2308 | UNREAD (c); | ||
| 2309 | if (!NILP (readfun)) | 2302 | if (!NILP (readfun)) |
| 2310 | { | 2303 | { |
| 2311 | val = call1 (readfun, readcharfun); | 2304 | val = call1 (readfun, readcharfun); |
| @@ -2349,7 +2342,7 @@ readevalloop (Lisp_Object readcharfun, | |||
| 2349 | { | 2342 | { |
| 2350 | Vvalues = Fcons (val, Vvalues); | 2343 | Vvalues = Fcons (val, Vvalues); |
| 2351 | if (EQ (Vstandard_output, Qt)) | 2344 | if (EQ (Vstandard_output, Qt)) |
| 2352 | Fprin1 (val, Qnil); | 2345 | Fprin1 (val, Qnil, Qnil); |
| 2353 | else | 2346 | else |
| 2354 | Fprint (val, Qnil); | 2347 | Fprint (val, Qnil); |
| 2355 | } | 2348 | } |
| @@ -2582,24 +2575,6 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end, | |||
| 2582 | return retval; | 2575 | return retval; |
| 2583 | } | 2576 | } |
| 2584 | 2577 | ||
| 2585 | |||
| 2586 | /* Use this for recursive reads, in contexts where internal tokens | ||
| 2587 | are not allowed. */ | ||
| 2588 | |||
| 2589 | static Lisp_Object | ||
| 2590 | read0 (Lisp_Object readcharfun, bool locate_syms) | ||
| 2591 | { | ||
| 2592 | register Lisp_Object val; | ||
| 2593 | int c; | ||
| 2594 | |||
| 2595 | val = read1 (readcharfun, &c, 0, locate_syms); | ||
| 2596 | if (!c) | ||
| 2597 | return val; | ||
| 2598 | |||
| 2599 | invalid_syntax_lisp (Fmake_string (make_fixnum (1), make_fixnum (c), Qnil), | ||
| 2600 | readcharfun); | ||
| 2601 | } | ||
| 2602 | |||
| 2603 | /* Grow a read buffer BUF that contains OFFSET useful bytes of data, | 2578 | /* Grow a read buffer BUF that contains OFFSET useful bytes of data, |
| 2604 | by at least MAX_MULTIBYTE_LENGTH bytes. Update *BUF_ADDR and | 2579 | by at least MAX_MULTIBYTE_LENGTH bytes. Update *BUF_ADDR and |
| 2605 | *BUF_SIZE accordingly; 0 <= OFFSET <= *BUF_SIZE. If *BUF_ADDR is | 2580 | *BUF_SIZE accordingly; 0 <= OFFSET <= *BUF_SIZE. If *BUF_ADDR is |
| @@ -2658,7 +2633,7 @@ enum { UNICODE_CHARACTER_NAME_LENGTH_BOUND = 200 }; | |||
| 2658 | If the escape sequence forces unibyte, return eight-bit char. */ | 2633 | If the escape sequence forces unibyte, return eight-bit char. */ |
| 2659 | 2634 | ||
| 2660 | static int | 2635 | static int |
| 2661 | read_escape (Lisp_Object readcharfun, bool stringp) | 2636 | read_escape (Lisp_Object readcharfun) |
| 2662 | { | 2637 | { |
| 2663 | int c = READCHAR; | 2638 | int c = READCHAR; |
| 2664 | /* \u allows up to four hex digits, \U up to eight. Default to the | 2639 | /* \u allows up to four hex digits, \U up to eight. Default to the |
| @@ -2688,12 +2663,10 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2688 | return '\t'; | 2663 | return '\t'; |
| 2689 | case 'v': | 2664 | case 'v': |
| 2690 | return '\v'; | 2665 | return '\v'; |
| 2666 | |||
| 2691 | case '\n': | 2667 | case '\n': |
| 2692 | return -1; | 2668 | /* ?\LF is an error; it's probably a user mistake. */ |
| 2693 | case ' ': | 2669 | error ("Invalid escape character syntax"); |
| 2694 | if (stringp) | ||
| 2695 | return -1; | ||
| 2696 | return ' '; | ||
| 2697 | 2670 | ||
| 2698 | case 'M': | 2671 | case 'M': |
| 2699 | c = READCHAR; | 2672 | c = READCHAR; |
| @@ -2701,7 +2674,7 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2701 | error ("Invalid escape character syntax"); | 2674 | error ("Invalid escape character syntax"); |
| 2702 | c = READCHAR; | 2675 | c = READCHAR; |
| 2703 | if (c == '\\') | 2676 | if (c == '\\') |
| 2704 | c = read_escape (readcharfun, 0); | 2677 | c = read_escape (readcharfun); |
| 2705 | return c | meta_modifier; | 2678 | return c | meta_modifier; |
| 2706 | 2679 | ||
| 2707 | case 'S': | 2680 | case 'S': |
| @@ -2710,7 +2683,7 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2710 | error ("Invalid escape character syntax"); | 2683 | error ("Invalid escape character syntax"); |
| 2711 | c = READCHAR; | 2684 | c = READCHAR; |
| 2712 | if (c == '\\') | 2685 | if (c == '\\') |
| 2713 | c = read_escape (readcharfun, 0); | 2686 | c = read_escape (readcharfun); |
| 2714 | return c | shift_modifier; | 2687 | return c | shift_modifier; |
| 2715 | 2688 | ||
| 2716 | case 'H': | 2689 | case 'H': |
| @@ -2719,7 +2692,7 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2719 | error ("Invalid escape character syntax"); | 2692 | error ("Invalid escape character syntax"); |
| 2720 | c = READCHAR; | 2693 | c = READCHAR; |
| 2721 | if (c == '\\') | 2694 | if (c == '\\') |
| 2722 | c = read_escape (readcharfun, 0); | 2695 | c = read_escape (readcharfun); |
| 2723 | return c | hyper_modifier; | 2696 | return c | hyper_modifier; |
| 2724 | 2697 | ||
| 2725 | case 'A': | 2698 | case 'A': |
| @@ -2728,19 +2701,19 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2728 | error ("Invalid escape character syntax"); | 2701 | error ("Invalid escape character syntax"); |
| 2729 | c = READCHAR; | 2702 | c = READCHAR; |
| 2730 | if (c == '\\') | 2703 | if (c == '\\') |
| 2731 | c = read_escape (readcharfun, 0); | 2704 | c = read_escape (readcharfun); |
| 2732 | return c | alt_modifier; | 2705 | return c | alt_modifier; |
| 2733 | 2706 | ||
| 2734 | case 's': | 2707 | case 's': |
| 2735 | c = READCHAR; | 2708 | c = READCHAR; |
| 2736 | if (stringp || c != '-') | 2709 | if (c != '-') |
| 2737 | { | 2710 | { |
| 2738 | UNREAD (c); | 2711 | UNREAD (c); |
| 2739 | return ' '; | 2712 | return ' '; |
| 2740 | } | 2713 | } |
| 2741 | c = READCHAR; | 2714 | c = READCHAR; |
| 2742 | if (c == '\\') | 2715 | if (c == '\\') |
| 2743 | c = read_escape (readcharfun, 0); | 2716 | c = read_escape (readcharfun); |
| 2744 | return c | super_modifier; | 2717 | return c | super_modifier; |
| 2745 | 2718 | ||
| 2746 | case 'C': | 2719 | case 'C': |
| @@ -2751,7 +2724,7 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2751 | case '^': | 2724 | case '^': |
| 2752 | c = READCHAR; | 2725 | c = READCHAR; |
| 2753 | if (c == '\\') | 2726 | if (c == '\\') |
| 2754 | c = read_escape (readcharfun, 0); | 2727 | c = read_escape (readcharfun); |
| 2755 | if ((c & ~CHAR_MODIFIER_MASK) == '?') | 2728 | if ((c & ~CHAR_MODIFIER_MASK) == '?') |
| 2756 | return 0177 | (c & CHAR_MODIFIER_MASK); | 2729 | return 0177 | (c & CHAR_MODIFIER_MASK); |
| 2757 | else if (! ASCII_CHAR_P ((c & ~CHAR_MODIFIER_MASK))) | 2730 | else if (! ASCII_CHAR_P ((c & ~CHAR_MODIFIER_MASK))) |
| @@ -2902,8 +2875,8 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2902 | invalid_syntax ("Empty character name", readcharfun); | 2875 | invalid_syntax ("Empty character name", readcharfun); |
| 2903 | name[length] = '\0'; | 2876 | name[length] = '\0'; |
| 2904 | 2877 | ||
| 2905 | /* character_name_to_code can invoke read1, recursively. | 2878 | /* character_name_to_code can invoke read0, recursively. |
| 2906 | This is why read1's buffer is not static. */ | 2879 | This is why read0's buffer is not static. */ |
| 2907 | return character_name_to_code (name, length, readcharfun); | 2880 | return character_name_to_code (name, length, readcharfun); |
| 2908 | } | 2881 | } |
| 2909 | 2882 | ||
| @@ -2932,20 +2905,17 @@ digit_to_number (int character, int base) | |||
| 2932 | return digit < base ? digit : -1; | 2905 | return digit < base ? digit : -1; |
| 2933 | } | 2906 | } |
| 2934 | 2907 | ||
| 2935 | static char const invalid_radix_integer_format[] = "integer, radix %"pI"d"; | 2908 | /* Size of the fixed-size buffer used during reading. |
| 2936 | 2909 | It should be at least big enough for `invalid_radix_integer' but | |
| 2937 | /* Small, as read1 is recursive (Bug#31995). But big enough to hold | 2910 | can usefully be much bigger than that. */ |
| 2938 | the invalid_radix_integer string. */ | 2911 | enum { stackbufsize = 1024 }; |
| 2939 | enum { stackbufsize = max (64, | ||
| 2940 | (sizeof invalid_radix_integer_format | ||
| 2941 | - sizeof "%"pI"d" | ||
| 2942 | + INT_STRLEN_BOUND (EMACS_INT) + 1)) }; | ||
| 2943 | 2912 | ||
| 2944 | static void | 2913 | static void |
| 2945 | invalid_radix_integer (EMACS_INT radix, char stackbuf[VLA_ELEMS (stackbufsize)], | 2914 | invalid_radix_integer (EMACS_INT radix, char stackbuf[VLA_ELEMS (stackbufsize)], |
| 2946 | Lisp_Object readcharfun) | 2915 | Lisp_Object readcharfun) |
| 2947 | { | 2916 | { |
| 2948 | sprintf (stackbuf, invalid_radix_integer_format, radix); | 2917 | int n = snprintf (stackbuf, stackbufsize, "integer, radix %"pI"d", radix); |
| 2918 | eassert (n < stackbufsize); | ||
| 2949 | invalid_syntax (stackbuf, readcharfun); | 2919 | invalid_syntax (stackbuf, readcharfun); |
| 2950 | } | 2920 | } |
| 2951 | 2921 | ||
| @@ -3011,780 +2981,1110 @@ read_integer (Lisp_Object readcharfun, int radix, | |||
| 3011 | *p = '\0'; | 2981 | *p = '\0'; |
| 3012 | return unbind_to (count, string_to_number (read_buffer, radix, NULL)); | 2982 | return unbind_to (count, string_to_number (read_buffer, radix, NULL)); |
| 3013 | } | 2983 | } |
| 2984 | |||
| 3014 | 2985 | ||
| 3015 | /* If the next token is ')' or ']' or '.', we store that character | 2986 | /* Read a character literal (preceded by `?'). */ |
| 3016 | in *PCH and the return value is not interesting. Else, we store | ||
| 3017 | zero in *PCH and we read and return one lisp object. | ||
| 3018 | |||
| 3019 | FIRST_IN_LIST is true if this is the first element of a list. | ||
| 3020 | LOCATE_SYMS true means read symbol occurrences as symbols with | ||
| 3021 | position. */ | ||
| 3022 | |||
| 3023 | static Lisp_Object | 2987 | static Lisp_Object |
| 3024 | read1 (Lisp_Object readcharfun, int *pch, bool first_in_list, bool locate_syms) | 2988 | read_char_literal (Lisp_Object readcharfun) |
| 3025 | { | 2989 | { |
| 3026 | int c; | 2990 | int ch = READCHAR; |
| 3027 | bool uninterned_symbol = false; | 2991 | if (ch < 0) |
| 3028 | bool skip_shorthand = false; | 2992 | end_of_file_error (); |
| 3029 | bool multibyte; | ||
| 3030 | char stackbuf[stackbufsize]; | ||
| 3031 | current_thread->stack_top = stackbuf; | ||
| 3032 | 2993 | ||
| 3033 | *pch = 0; | 2994 | /* Accept `single space' syntax like (list ? x) where the |
| 2995 | whitespace character is SPC or TAB. | ||
| 2996 | Other literal whitespace like NL, CR, and FF are not accepted, | ||
| 2997 | as there are well-established escape sequences for these. */ | ||
| 2998 | if (ch == ' ' || ch == '\t') | ||
| 2999 | return make_fixnum (ch); | ||
| 3034 | 3000 | ||
| 3035 | retry: | 3001 | if ( ch == '(' || ch == ')' || ch == '[' || ch == ']' |
| 3002 | || ch == '"' || ch == ';') | ||
| 3003 | { | ||
| 3004 | CHECK_LIST (Vlread_unescaped_character_literals); | ||
| 3005 | Lisp_Object char_obj = make_fixed_natnum (ch); | ||
| 3006 | if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals))) | ||
| 3007 | Vlread_unescaped_character_literals = | ||
| 3008 | Fcons (char_obj, Vlread_unescaped_character_literals); | ||
| 3009 | } | ||
| 3036 | 3010 | ||
| 3037 | c = READCHAR_REPORT_MULTIBYTE (&multibyte); | 3011 | if (ch == '\\') |
| 3038 | if (c < 0) | 3012 | ch = read_escape (readcharfun); |
| 3039 | end_of_file_error (); | ||
| 3040 | 3013 | ||
| 3041 | switch (c) | 3014 | int modifiers = ch & CHAR_MODIFIER_MASK; |
| 3042 | { | 3015 | ch &= ~CHAR_MODIFIER_MASK; |
| 3043 | case '(': | 3016 | if (CHAR_BYTE8_P (ch)) |
| 3044 | return read_list (0, readcharfun, locate_syms); | 3017 | ch = CHAR_TO_BYTE8 (ch); |
| 3018 | ch |= modifiers; | ||
| 3045 | 3019 | ||
| 3046 | case '[': | 3020 | int nch = READCHAR; |
| 3047 | return read_vector (readcharfun, 0, locate_syms); | 3021 | UNREAD (nch); |
| 3022 | if (nch <= 32 | ||
| 3023 | || nch == '"' || nch == '\'' || nch == ';' || nch == '(' | ||
| 3024 | || nch == ')' || nch == '[' || nch == ']' || nch == '#' | ||
| 3025 | || nch == '?' || nch == '`' || nch == ',' || nch == '.') | ||
| 3026 | return make_fixnum (ch); | ||
| 3048 | 3027 | ||
| 3049 | case ')': | 3028 | invalid_syntax ("?", readcharfun); |
| 3050 | case ']': | 3029 | } |
| 3051 | { | ||
| 3052 | *pch = c; | ||
| 3053 | return Qnil; | ||
| 3054 | } | ||
| 3055 | 3030 | ||
| 3056 | case '#': | 3031 | /* Read a string literal (preceded by '"'). */ |
| 3057 | c = READCHAR; | 3032 | static Lisp_Object |
| 3058 | if (c == 's') | 3033 | read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)], |
| 3034 | Lisp_Object readcharfun) | ||
| 3035 | { | ||
| 3036 | char *read_buffer = stackbuf; | ||
| 3037 | ptrdiff_t read_buffer_size = stackbufsize; | ||
| 3038 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 3039 | char *heapbuf = NULL; | ||
| 3040 | char *p = read_buffer; | ||
| 3041 | char *end = read_buffer + read_buffer_size; | ||
| 3042 | /* True if we saw an escape sequence specifying | ||
| 3043 | a multibyte character. */ | ||
| 3044 | bool force_multibyte = false; | ||
| 3045 | /* True if we saw an escape sequence specifying | ||
| 3046 | a single-byte character. */ | ||
| 3047 | bool force_singlebyte = false; | ||
| 3048 | bool cancel = false; | ||
| 3049 | ptrdiff_t nchars = 0; | ||
| 3050 | |||
| 3051 | int ch; | ||
| 3052 | while ((ch = READCHAR) >= 0 && ch != '\"') | ||
| 3053 | { | ||
| 3054 | if (end - p < MAX_MULTIBYTE_LENGTH) | ||
| 3059 | { | 3055 | { |
| 3060 | c = READCHAR; | 3056 | ptrdiff_t offset = p - read_buffer; |
| 3061 | if (c == '(') | 3057 | read_buffer = grow_read_buffer (read_buffer, offset, |
| 3058 | &heapbuf, &read_buffer_size, | ||
| 3059 | count); | ||
| 3060 | p = read_buffer + offset; | ||
| 3061 | end = read_buffer + read_buffer_size; | ||
| 3062 | } | ||
| 3063 | |||
| 3064 | if (ch == '\\') | ||
| 3065 | { | ||
| 3066 | /* First apply string-specific escape rules: */ | ||
| 3067 | ch = READCHAR; | ||
| 3068 | switch (ch) | ||
| 3062 | { | 3069 | { |
| 3063 | /* Accept extended format for hash tables (extensible to | 3070 | case 's': |
| 3064 | other types), e.g. | 3071 | /* `\s' is always a space in strings. */ |
| 3065 | #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ | 3072 | ch = ' '; |
| 3066 | Lisp_Object tmp = read_list (0, readcharfun, false); | 3073 | break; |
| 3067 | Lisp_Object head = CAR_SAFE (tmp); | 3074 | case ' ': |
| 3068 | Lisp_Object data = Qnil; | 3075 | case '\n': |
| 3069 | Lisp_Object val = Qnil; | 3076 | /* `\SPC' and `\LF' generate no characters at all. */ |
| 3070 | /* The size is 2 * number of allowed keywords to | 3077 | if (p == read_buffer) |
| 3071 | make-hash-table. */ | 3078 | cancel = true; |
| 3072 | Lisp_Object params[12]; | 3079 | continue; |
| 3073 | Lisp_Object ht; | 3080 | default: |
| 3074 | Lisp_Object key = Qnil; | 3081 | UNREAD (ch); |
| 3075 | int param_count = 0; | 3082 | ch = read_escape (readcharfun); |
| 3076 | 3083 | break; | |
| 3077 | if (!EQ (head, Qhash_table)) | 3084 | } |
| 3085 | |||
| 3086 | int modifiers = ch & CHAR_MODIFIER_MASK; | ||
| 3087 | ch &= ~CHAR_MODIFIER_MASK; | ||
| 3088 | |||
| 3089 | if (CHAR_BYTE8_P (ch)) | ||
| 3090 | force_singlebyte = true; | ||
| 3091 | else if (! ASCII_CHAR_P (ch)) | ||
| 3092 | force_multibyte = true; | ||
| 3093 | else /* I.e. ASCII_CHAR_P (ch). */ | ||
| 3094 | { | ||
| 3095 | /* Allow `\C-SPC' and `\^SPC'. This is done here because | ||
| 3096 | the literals ?\C-SPC and ?\^SPC (rather inconsistently) | ||
| 3097 | yield (' ' | CHAR_CTL); see bug#55738. */ | ||
| 3098 | if (modifiers == CHAR_CTL && ch == ' ') | ||
| 3099 | { | ||
| 3100 | ch = 0; | ||
| 3101 | modifiers = 0; | ||
| 3102 | } | ||
| 3103 | if (modifiers & CHAR_SHIFT) | ||
| 3078 | { | 3104 | { |
| 3079 | ptrdiff_t size = XFIXNUM (Flength (tmp)); | 3105 | /* Shift modifier is valid only with [A-Za-z]. */ |
| 3080 | Lisp_Object record = Fmake_record (CAR_SAFE (tmp), | 3106 | if (ch >= 'A' && ch <= 'Z') |
| 3081 | make_fixnum (size - 1), | 3107 | modifiers &= ~CHAR_SHIFT; |
| 3082 | Qnil); | 3108 | else if (ch >= 'a' && ch <= 'z') |
| 3083 | for (int i = 1; i < size; i++) | ||
| 3084 | { | 3109 | { |
| 3085 | tmp = Fcdr (tmp); | 3110 | ch -= ('a' - 'A'); |
| 3086 | ASET (record, i, Fcar (tmp)); | 3111 | modifiers &= ~CHAR_SHIFT; |
| 3087 | } | 3112 | } |
| 3088 | return record; | ||
| 3089 | } | 3113 | } |
| 3090 | 3114 | ||
| 3091 | tmp = CDR_SAFE (tmp); | 3115 | if (modifiers & CHAR_META) |
| 3116 | { | ||
| 3117 | /* Move the meta bit to the right place for a | ||
| 3118 | string. */ | ||
| 3119 | modifiers &= ~CHAR_META; | ||
| 3120 | ch = BYTE8_TO_CHAR (ch | 0x80); | ||
| 3121 | force_singlebyte = true; | ||
| 3122 | } | ||
| 3123 | } | ||
| 3092 | 3124 | ||
| 3093 | /* This is repetitive but fast and simple. */ | 3125 | /* Any modifiers remaining are invalid. */ |
| 3094 | params[param_count] = QCsize; | 3126 | if (modifiers) |
| 3095 | params[param_count + 1] = Fplist_get (tmp, Qsize); | 3127 | invalid_syntax ("Invalid modifier in string", readcharfun); |
| 3096 | if (!NILP (params[param_count + 1])) | 3128 | p += CHAR_STRING (ch, (unsigned char *) p); |
| 3097 | param_count += 2; | 3129 | } |
| 3130 | else | ||
| 3131 | { | ||
| 3132 | p += CHAR_STRING (ch, (unsigned char *) p); | ||
| 3133 | if (CHAR_BYTE8_P (ch)) | ||
| 3134 | force_singlebyte = true; | ||
| 3135 | else if (! ASCII_CHAR_P (ch)) | ||
| 3136 | force_multibyte = true; | ||
| 3137 | } | ||
| 3138 | nchars++; | ||
| 3139 | } | ||
| 3098 | 3140 | ||
| 3099 | params[param_count] = QCtest; | 3141 | if (ch < 0) |
| 3100 | params[param_count + 1] = Fplist_get (tmp, Qtest); | 3142 | end_of_file_error (); |
| 3101 | if (!NILP (params[param_count + 1])) | ||
| 3102 | param_count += 2; | ||
| 3103 | 3143 | ||
| 3104 | params[param_count] = QCweakness; | 3144 | /* If purifying, and string starts with \ newline, |
| 3105 | params[param_count + 1] = Fplist_get (tmp, Qweakness); | 3145 | return zero instead. This is for doc strings |
| 3106 | if (!NILP (params[param_count + 1])) | 3146 | that we are really going to find in etc/DOC.nn.nn. */ |
| 3107 | param_count += 2; | 3147 | if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel) |
| 3148 | { | ||
| 3149 | unbind_to (count, Qnil); | ||
| 3150 | return make_fixnum (0); | ||
| 3151 | } | ||
| 3108 | 3152 | ||
| 3109 | params[param_count] = QCrehash_size; | 3153 | if (!force_multibyte && force_singlebyte) |
| 3110 | params[param_count + 1] = Fplist_get (tmp, Qrehash_size); | 3154 | { |
| 3111 | if (!NILP (params[param_count + 1])) | 3155 | /* READ_BUFFER contains raw 8-bit bytes and no multibyte |
| 3112 | param_count += 2; | 3156 | forms. Convert it to unibyte. */ |
| 3157 | nchars = str_as_unibyte ((unsigned char *) read_buffer, | ||
| 3158 | p - read_buffer); | ||
| 3159 | p = read_buffer + nchars; | ||
| 3160 | } | ||
| 3113 | 3161 | ||
| 3114 | params[param_count] = QCrehash_threshold; | 3162 | Lisp_Object obj = make_specified_string (read_buffer, nchars, p - read_buffer, |
| 3115 | params[param_count + 1] = Fplist_get (tmp, Qrehash_threshold); | 3163 | (force_multibyte |
| 3116 | if (!NILP (params[param_count + 1])) | 3164 | || (p - read_buffer != nchars))); |
| 3117 | param_count += 2; | 3165 | return unbind_to (count, obj); |
| 3166 | } | ||
| 3118 | 3167 | ||
| 3119 | params[param_count] = QCpurecopy; | 3168 | /* Make a hash table from the constructor plist. */ |
| 3120 | params[param_count + 1] = Fplist_get (tmp, Qpurecopy); | 3169 | static Lisp_Object |
| 3121 | if (!NILP (params[param_count + 1])) | 3170 | hash_table_from_plist (Lisp_Object plist) |
| 3122 | param_count += 2; | 3171 | { |
| 3172 | Lisp_Object params[12]; | ||
| 3173 | Lisp_Object *par = params; | ||
| 3174 | |||
| 3175 | /* This is repetitive but fast and simple. */ | ||
| 3176 | #define ADDPARAM(name) \ | ||
| 3177 | do { \ | ||
| 3178 | Lisp_Object val = Fplist_get (plist, Q ## name); \ | ||
| 3179 | if (!NILP (val)) \ | ||
| 3180 | { \ | ||
| 3181 | *par++ = QC ## name; \ | ||
| 3182 | *par++ = val; \ | ||
| 3183 | } \ | ||
| 3184 | } while (0) | ||
| 3185 | |||
| 3186 | ADDPARAM (size); | ||
| 3187 | ADDPARAM (test); | ||
| 3188 | ADDPARAM (weakness); | ||
| 3189 | ADDPARAM (rehash_size); | ||
| 3190 | ADDPARAM (rehash_threshold); | ||
| 3191 | ADDPARAM (purecopy); | ||
| 3192 | |||
| 3193 | Lisp_Object data = Fplist_get (plist, Qdata); | ||
| 3194 | |||
| 3195 | /* Now use params to make a new hash table and fill it. */ | ||
| 3196 | Lisp_Object ht = Fmake_hash_table (par - params, params); | ||
| 3197 | |||
| 3198 | Lisp_Object last = data; | ||
| 3199 | FOR_EACH_TAIL_SAFE (data) | ||
| 3200 | { | ||
| 3201 | Lisp_Object key = XCAR (data); | ||
| 3202 | data = XCDR (data); | ||
| 3203 | if (!CONSP (data)) | ||
| 3204 | break; | ||
| 3205 | Lisp_Object val = XCAR (data); | ||
| 3206 | last = XCDR (data); | ||
| 3207 | Fputhash (key, val, ht); | ||
| 3208 | } | ||
| 3209 | if (!NILP (last)) | ||
| 3210 | error ("Hash table data is not a list of even length"); | ||
| 3123 | 3211 | ||
| 3124 | /* This is the hash table data. */ | 3212 | return ht; |
| 3125 | data = Fplist_get (tmp, Qdata); | 3213 | } |
| 3126 | 3214 | ||
| 3127 | /* Now use params to make a new hash table and fill it. */ | 3215 | static Lisp_Object |
| 3128 | ht = Fmake_hash_table (param_count, params); | 3216 | record_from_list (Lisp_Object elems) |
| 3217 | { | ||
| 3218 | ptrdiff_t size = list_length (elems); | ||
| 3219 | Lisp_Object obj = Fmake_record (XCAR (elems), | ||
| 3220 | make_fixnum (size - 1), | ||
| 3221 | Qnil); | ||
| 3222 | Lisp_Object tl = XCDR (elems); | ||
| 3223 | for (int i = 1; i < size; i++) | ||
| 3224 | { | ||
| 3225 | ASET (obj, i, XCAR (tl)); | ||
| 3226 | tl = XCDR (tl); | ||
| 3227 | } | ||
| 3228 | return obj; | ||
| 3229 | } | ||
| 3129 | 3230 | ||
| 3130 | Lisp_Object last = data; | 3231 | /* Turn a reversed list into a vector. */ |
| 3131 | FOR_EACH_TAIL_SAFE (data) | 3232 | static Lisp_Object |
| 3132 | { | 3233 | vector_from_rev_list (Lisp_Object elems) |
| 3133 | key = XCAR (data); | 3234 | { |
| 3134 | data = XCDR (data); | 3235 | ptrdiff_t size = list_length (elems); |
| 3135 | if (!CONSP (data)) | 3236 | Lisp_Object obj = make_nil_vector (size); |
| 3136 | break; | 3237 | Lisp_Object *vec = XVECTOR (obj)->contents; |
| 3137 | val = XCAR (data); | 3238 | for (ptrdiff_t i = size - 1; i >= 0; i--) |
| 3138 | last = XCDR (data); | 3239 | { |
| 3139 | Fputhash (key, val, ht); | 3240 | vec[i] = XCAR (elems); |
| 3140 | } | 3241 | Lisp_Object next = XCDR (elems); |
| 3141 | if (!NILP (last)) | 3242 | free_cons (XCONS (elems)); |
| 3142 | error ("Hash table data is not a list of even length"); | 3243 | elems = next; |
| 3244 | } | ||
| 3245 | return obj; | ||
| 3246 | } | ||
| 3143 | 3247 | ||
| 3144 | return ht; | 3248 | static Lisp_Object |
| 3145 | } | 3249 | bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) |
| 3146 | UNREAD (c); | 3250 | { |
| 3147 | invalid_syntax ("#", readcharfun); | 3251 | Lisp_Object obj = vector_from_rev_list (elems); |
| 3148 | } | 3252 | Lisp_Object *vec = XVECTOR (obj)->contents; |
| 3149 | if (c == '^') | 3253 | ptrdiff_t size = ASIZE (obj); |
| 3150 | { | 3254 | |
| 3151 | c = READCHAR; | 3255 | if (!(size >= COMPILED_STACK_DEPTH + 1 && size <= COMPILED_INTERACTIVE + 1 |
| 3152 | if (c == '[') | 3256 | && (FIXNUMP (vec[COMPILED_ARGLIST]) |
| 3153 | { | 3257 | || CONSP (vec[COMPILED_ARGLIST]) |
| 3154 | Lisp_Object tmp; | 3258 | || NILP (vec[COMPILED_ARGLIST])) |
| 3155 | tmp = read_vector (readcharfun, 0, false); | 3259 | && FIXNATP (vec[COMPILED_STACK_DEPTH]))) |
| 3156 | if (ASIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS) | 3260 | invalid_syntax ("Invalid byte-code object", readcharfun); |
| 3157 | error ("Invalid size char-table"); | 3261 | |
| 3158 | XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE); | 3262 | if (load_force_doc_strings |
| 3159 | return tmp; | 3263 | && NILP (vec[COMPILED_CONSTANTS]) |
| 3160 | } | 3264 | && STRINGP (vec[COMPILED_BYTECODE])) |
| 3161 | else if (c == '^') | 3265 | { |
| 3162 | { | 3266 | /* Lazily-loaded bytecode is represented by the constant slot being nil |
| 3163 | c = READCHAR; | 3267 | and the bytecode slot a (lazily loaded) string containing the |
| 3164 | if (c == '[') | 3268 | print representation of (BYTECODE . CONSTANTS). Unpack the |
| 3165 | { | 3269 | pieces by coerceing the string to unibyte and reading the result. */ |
| 3166 | /* Sub char-table can't be read as a regular | 3270 | Lisp_Object enc = vec[COMPILED_BYTECODE]; |
| 3167 | vector because of a two C integer fields. */ | 3271 | Lisp_Object pair = Fread (Fcons (enc, readcharfun)); |
| 3168 | Lisp_Object tbl, tmp = read_list (1, readcharfun, false); | 3272 | if (!CONSP (pair)) |
| 3169 | ptrdiff_t size = list_length (tmp); | 3273 | invalid_syntax ("Invalid byte-code object", readcharfun); |
| 3170 | int i, depth, min_char; | 3274 | |
| 3171 | struct Lisp_Cons *cell; | 3275 | vec[COMPILED_BYTECODE] = XCAR (pair); |
| 3172 | 3276 | vec[COMPILED_CONSTANTS] = XCDR (pair); | |
| 3173 | if (size == 0) | 3277 | } |
| 3174 | error ("Zero-sized sub char-table"); | 3278 | |
| 3175 | 3279 | if (!((STRINGP (vec[COMPILED_BYTECODE]) | |
| 3176 | if (! RANGED_FIXNUMP (1, XCAR (tmp), 3)) | 3280 | && VECTORP (vec[COMPILED_CONSTANTS])) |
| 3177 | error ("Invalid depth in sub char-table"); | 3281 | || CONSP (vec[COMPILED_BYTECODE]))) |
| 3178 | depth = XFIXNUM (XCAR (tmp)); | 3282 | invalid_syntax ("Invalid byte-code object", readcharfun); |
| 3179 | if (chartab_size[depth] != size - 2) | 3283 | |
| 3180 | error ("Invalid size in sub char-table"); | 3284 | if (STRINGP (vec[COMPILED_BYTECODE])) |
| 3181 | cell = XCONS (tmp), tmp = XCDR (tmp), size--; | 3285 | { |
| 3182 | free_cons (cell); | 3286 | if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE])) |
| 3183 | |||
| 3184 | if (! RANGED_FIXNUMP (0, XCAR (tmp), MAX_CHAR)) | ||
| 3185 | error ("Invalid minimum character in sub-char-table"); | ||
| 3186 | min_char = XFIXNUM (XCAR (tmp)); | ||
| 3187 | cell = XCONS (tmp), tmp = XCDR (tmp), size--; | ||
| 3188 | free_cons (cell); | ||
| 3189 | |||
| 3190 | tbl = make_uninit_sub_char_table (depth, min_char); | ||
| 3191 | for (i = 0; i < size; i++) | ||
| 3192 | { | ||
| 3193 | XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (tmp); | ||
| 3194 | cell = XCONS (tmp), tmp = XCDR (tmp); | ||
| 3195 | free_cons (cell); | ||
| 3196 | } | ||
| 3197 | return tbl; | ||
| 3198 | } | ||
| 3199 | invalid_syntax ("#^^", readcharfun); | ||
| 3200 | } | ||
| 3201 | invalid_syntax ("#^", readcharfun); | ||
| 3202 | } | ||
| 3203 | if (c == '&') | ||
| 3204 | { | 3287 | { |
| 3205 | Lisp_Object length; | 3288 | /* BYTESTR must have been produced by Emacs 20.2 or earlier |
| 3206 | length = read1 (readcharfun, pch, first_in_list, false); | 3289 | because it produced a raw 8-bit string for byte-code and |
| 3207 | c = READCHAR; | 3290 | now such a byte-code string is loaded as multibyte with |
| 3208 | if (c == '"') | 3291 | raw 8-bit characters converted to multibyte form. |
| 3209 | { | 3292 | Convert them back to the original unibyte form. */ |
| 3210 | Lisp_Object tmp, val; | 3293 | vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]); |
| 3211 | EMACS_INT size_in_chars = bool_vector_bytes (XFIXNAT (length)); | ||
| 3212 | unsigned char *data; | ||
| 3213 | |||
| 3214 | UNREAD (c); | ||
| 3215 | tmp = read1 (readcharfun, pch, first_in_list, false); | ||
| 3216 | if (STRING_MULTIBYTE (tmp) | ||
| 3217 | || (size_in_chars != SCHARS (tmp) | ||
| 3218 | /* We used to print 1 char too many | ||
| 3219 | when the number of bits was a multiple of 8. | ||
| 3220 | Accept such input in case it came from an old | ||
| 3221 | version. */ | ||
| 3222 | && ! (XFIXNAT (length) | ||
| 3223 | == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR))) | ||
| 3224 | invalid_syntax ("#&...", readcharfun); | ||
| 3225 | |||
| 3226 | val = make_uninit_bool_vector (XFIXNAT (length)); | ||
| 3227 | data = bool_vector_uchar_data (val); | ||
| 3228 | memcpy (data, SDATA (tmp), size_in_chars); | ||
| 3229 | /* Clear the extraneous bits in the last byte. */ | ||
| 3230 | if (XFIXNUM (length) != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR) | ||
| 3231 | data[size_in_chars - 1] | ||
| 3232 | &= (1 << (XFIXNUM (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | ||
| 3233 | return val; | ||
| 3234 | } | ||
| 3235 | invalid_syntax ("#&...", readcharfun); | ||
| 3236 | } | 3294 | } |
| 3237 | if (c == '[') | 3295 | // Bytecode must be immovable. |
| 3238 | { | 3296 | pin_string (vec[COMPILED_BYTECODE]); |
| 3239 | /* Accept compiled functions at read-time so that we don't have to | 3297 | } |
| 3240 | build them using function calls. */ | ||
| 3241 | Lisp_Object tmp; | ||
| 3242 | struct Lisp_Vector *vec; | ||
| 3243 | tmp = read_vector (readcharfun, 1, false); | ||
| 3244 | vec = XVECTOR (tmp); | ||
| 3245 | if (! (COMPILED_STACK_DEPTH < ASIZE (tmp) | ||
| 3246 | && (FIXNUMP (AREF (tmp, COMPILED_ARGLIST)) | ||
| 3247 | || CONSP (AREF (tmp, COMPILED_ARGLIST)) | ||
| 3248 | || NILP (AREF (tmp, COMPILED_ARGLIST))) | ||
| 3249 | && ((STRINGP (AREF (tmp, COMPILED_BYTECODE)) | ||
| 3250 | && VECTORP (AREF (tmp, COMPILED_CONSTANTS))) | ||
| 3251 | || CONSP (AREF (tmp, COMPILED_BYTECODE))) | ||
| 3252 | && FIXNATP (AREF (tmp, COMPILED_STACK_DEPTH)))) | ||
| 3253 | invalid_syntax ("Invalid byte-code object", readcharfun); | ||
| 3254 | |||
| 3255 | if (STRINGP (AREF (tmp, COMPILED_BYTECODE))) | ||
| 3256 | { | ||
| 3257 | if (STRING_MULTIBYTE (AREF (tmp, COMPILED_BYTECODE))) | ||
| 3258 | { | ||
| 3259 | /* BYTESTR must have been produced by Emacs 20.2 or earlier | ||
| 3260 | because it produced a raw 8-bit string for byte-code and | ||
| 3261 | now such a byte-code string is loaded as multibyte with | ||
| 3262 | raw 8-bit characters converted to multibyte form. | ||
| 3263 | Convert them back to the original unibyte form. */ | ||
| 3264 | ASET (tmp, COMPILED_BYTECODE, | ||
| 3265 | Fstring_as_unibyte (AREF (tmp, COMPILED_BYTECODE))); | ||
| 3266 | } | ||
| 3267 | // Bytecode must be immovable. | ||
| 3268 | pin_string (AREF (tmp, COMPILED_BYTECODE)); | ||
| 3269 | } | ||
| 3270 | 3298 | ||
| 3271 | XSETPVECTYPE (vec, PVEC_COMPILED); | 3299 | XSETPVECTYPE (XVECTOR (obj), PVEC_COMPILED); |
| 3272 | return tmp; | 3300 | return obj; |
| 3273 | } | 3301 | } |
| 3274 | if (c == '(') | ||
| 3275 | { | ||
| 3276 | Lisp_Object tmp; | ||
| 3277 | int ch; | ||
| 3278 | |||
| 3279 | /* Read the string itself. */ | ||
| 3280 | tmp = read1 (readcharfun, &ch, 0, false); | ||
| 3281 | if (ch != 0 || !STRINGP (tmp)) | ||
| 3282 | invalid_syntax ("#", readcharfun); | ||
| 3283 | /* Read the intervals and their properties. */ | ||
| 3284 | while (1) | ||
| 3285 | { | ||
| 3286 | Lisp_Object beg, end, plist; | ||
| 3287 | 3302 | ||
| 3288 | beg = read1 (readcharfun, &ch, 0, false); | 3303 | static Lisp_Object |
| 3289 | end = plist = Qnil; | 3304 | char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) |
| 3290 | if (ch == ')') | 3305 | { |
| 3291 | break; | 3306 | Lisp_Object obj = vector_from_rev_list (elems); |
| 3292 | if (ch == 0) | 3307 | if (ASIZE (obj) < CHAR_TABLE_STANDARD_SLOTS) |
| 3293 | end = read1 (readcharfun, &ch, 0, false); | 3308 | invalid_syntax ("Invalid size char-table", readcharfun); |
| 3294 | if (ch == 0) | 3309 | XSETPVECTYPE (XVECTOR (obj), PVEC_CHAR_TABLE); |
| 3295 | plist = read1 (readcharfun, &ch, 0, false); | 3310 | return obj; |
| 3296 | if (ch) | ||
| 3297 | invalid_syntax ("Invalid string property list", readcharfun); | ||
| 3298 | Fset_text_properties (beg, end, plist, tmp); | ||
| 3299 | } | ||
| 3300 | 3311 | ||
| 3301 | return tmp; | 3312 | } |
| 3302 | } | ||
| 3303 | 3313 | ||
| 3304 | /* #@NUMBER is used to skip NUMBER following bytes. | 3314 | static Lisp_Object |
| 3305 | That's used in .elc files to skip over doc strings | 3315 | sub_char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) |
| 3306 | and function definitions. */ | 3316 | { |
| 3307 | if (c == '@') | 3317 | /* A sub-char-table can't be read as a regular vector because of two |
| 3318 | C integer fields. */ | ||
| 3319 | elems = Fnreverse (elems); | ||
| 3320 | ptrdiff_t size = list_length (elems); | ||
| 3321 | if (size < 2) | ||
| 3322 | error ("Invalid size of sub-char-table"); | ||
| 3323 | |||
| 3324 | if (!RANGED_FIXNUMP (1, XCAR (elems), 3)) | ||
| 3325 | error ("Invalid depth in sub-char-table"); | ||
| 3326 | int depth = XFIXNUM (XCAR (elems)); | ||
| 3327 | |||
| 3328 | if (chartab_size[depth] != size - 2) | ||
| 3329 | error ("Invalid size in sub-char-table"); | ||
| 3330 | elems = XCDR (elems); | ||
| 3331 | |||
| 3332 | if (!RANGED_FIXNUMP (0, XCAR (elems), MAX_CHAR)) | ||
| 3333 | error ("Invalid minimum character in sub-char-table"); | ||
| 3334 | int min_char = XFIXNUM (XCAR (elems)); | ||
| 3335 | elems = XCDR (elems); | ||
| 3336 | |||
| 3337 | Lisp_Object tbl = make_uninit_sub_char_table (depth, min_char); | ||
| 3338 | for (int i = 0; i < size - 2; i++) | ||
| 3339 | { | ||
| 3340 | XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (elems); | ||
| 3341 | elems = XCDR (elems); | ||
| 3342 | } | ||
| 3343 | return tbl; | ||
| 3344 | } | ||
| 3345 | |||
| 3346 | static Lisp_Object | ||
| 3347 | string_props_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | ||
| 3348 | { | ||
| 3349 | elems = Fnreverse (elems); | ||
| 3350 | if (NILP (elems) || !STRINGP (XCAR (elems))) | ||
| 3351 | invalid_syntax ("#", readcharfun); | ||
| 3352 | Lisp_Object obj = XCAR (elems); | ||
| 3353 | for (Lisp_Object tl = XCDR (elems); !NILP (tl);) | ||
| 3354 | { | ||
| 3355 | Lisp_Object beg = XCAR (tl); | ||
| 3356 | tl = XCDR (tl); | ||
| 3357 | if (NILP (tl)) | ||
| 3358 | invalid_syntax ("Invalid string property list", readcharfun); | ||
| 3359 | Lisp_Object end = XCAR (tl); | ||
| 3360 | tl = XCDR (tl); | ||
| 3361 | if (NILP (tl)) | ||
| 3362 | invalid_syntax ("Invalid string property list", readcharfun); | ||
| 3363 | Lisp_Object plist = XCAR (tl); | ||
| 3364 | tl = XCDR (tl); | ||
| 3365 | Fset_text_properties (beg, end, plist, obj); | ||
| 3366 | } | ||
| 3367 | return obj; | ||
| 3368 | } | ||
| 3369 | |||
| 3370 | /* Read a bool vector (preceded by "#&"). */ | ||
| 3371 | static Lisp_Object | ||
| 3372 | read_bool_vector (char stackbuf[VLA_ELEMS (stackbufsize)], | ||
| 3373 | Lisp_Object readcharfun) | ||
| 3374 | { | ||
| 3375 | ptrdiff_t length = 0; | ||
| 3376 | for (;;) | ||
| 3377 | { | ||
| 3378 | int c = READCHAR; | ||
| 3379 | if (c < '0' || c > '9') | ||
| 3308 | { | 3380 | { |
| 3309 | enum { extra = 100 }; | 3381 | if (c != '"') |
| 3310 | ptrdiff_t i, nskip = 0, digits = 0; | 3382 | invalid_syntax ("#&", readcharfun); |
| 3383 | break; | ||
| 3384 | } | ||
| 3385 | if (INT_MULTIPLY_WRAPV (length, 10, &length) | ||
| 3386 | | INT_ADD_WRAPV (length, c - '0', &length)) | ||
| 3387 | invalid_syntax ("#&", readcharfun); | ||
| 3388 | } | ||
| 3311 | 3389 | ||
| 3312 | /* Read a decimal integer. */ | 3390 | ptrdiff_t size_in_chars = bool_vector_bytes (length); |
| 3313 | while ((c = READCHAR) >= 0 | 3391 | Lisp_Object str = read_string_literal (stackbuf, readcharfun); |
| 3314 | && c >= '0' && c <= '9') | 3392 | if (STRING_MULTIBYTE (str) |
| 3315 | { | 3393 | || !(size_in_chars == SCHARS (str) |
| 3316 | if ((STRING_BYTES_BOUND - extra) / 10 <= nskip) | 3394 | /* We used to print 1 char too many when the number of bits |
| 3317 | string_overflow (); | 3395 | was a multiple of 8. Accept such input in case it came |
| 3318 | digits++; | 3396 | from an old version. */ |
| 3319 | nskip *= 10; | 3397 | || length == (SCHARS (str) - 1) * BOOL_VECTOR_BITS_PER_CHAR)) |
| 3320 | nskip += c - '0'; | 3398 | invalid_syntax ("#&...", readcharfun); |
| 3321 | if (digits == 2 && nskip == 0) | 3399 | |
| 3322 | { /* We've just seen #@00, which means "skip to end". */ | 3400 | Lisp_Object obj = make_uninit_bool_vector (length); |
| 3323 | skip_dyn_eof (readcharfun); | 3401 | unsigned char *data = bool_vector_uchar_data (obj); |
| 3324 | return Qnil; | 3402 | memcpy (data, SDATA (str), size_in_chars); |
| 3325 | } | 3403 | /* Clear the extraneous bits in the last byte. */ |
| 3326 | } | 3404 | if (length != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR) |
| 3405 | data[size_in_chars - 1] &= (1 << (length % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | ||
| 3406 | return obj; | ||
| 3407 | } | ||
| 3408 | |||
| 3409 | /* Skip (and optionally remember) a lazily-loaded string | ||
| 3410 | preceded by "#@". */ | ||
| 3411 | static void | ||
| 3412 | skip_lazy_string (Lisp_Object readcharfun) | ||
| 3413 | { | ||
| 3414 | ptrdiff_t nskip = 0; | ||
| 3415 | ptrdiff_t digits = 0; | ||
| 3416 | for (;;) | ||
| 3417 | { | ||
| 3418 | int c = READCHAR; | ||
| 3419 | if (c < '0' || c > '9') | ||
| 3420 | { | ||
| 3327 | if (nskip > 0) | 3421 | if (nskip > 0) |
| 3328 | /* We can't use UNREAD here, because in the code below we side-step | 3422 | /* We can't use UNREAD here, because in the code below we side-step |
| 3329 | READCHAR. Instead, assume the first char after #@NNN occupies | 3423 | READCHAR. Instead, assume the first char after #@NNN occupies |
| 3330 | a single byte, which is the case normally since it's just | 3424 | a single byte, which is the case normally since it's just |
| 3331 | a space. */ | 3425 | a space. */ |
| 3332 | nskip--; | 3426 | nskip--; |
| 3333 | else | 3427 | else |
| 3334 | UNREAD (c); | 3428 | UNREAD (c); |
| 3335 | 3429 | break; | |
| 3336 | if (load_force_doc_strings | ||
| 3337 | && (FROM_FILE_P (readcharfun))) | ||
| 3338 | { | ||
| 3339 | /* If we are supposed to force doc strings into core right now, | ||
| 3340 | record the last string that we skipped, | ||
| 3341 | and record where in the file it comes from. */ | ||
| 3342 | |||
| 3343 | /* But first exchange saved_doc_string | ||
| 3344 | with prev_saved_doc_string, so we save two strings. */ | ||
| 3345 | { | ||
| 3346 | char *temp = saved_doc_string; | ||
| 3347 | ptrdiff_t temp_size = saved_doc_string_size; | ||
| 3348 | file_offset temp_pos = saved_doc_string_position; | ||
| 3349 | ptrdiff_t temp_len = saved_doc_string_length; | ||
| 3350 | |||
| 3351 | saved_doc_string = prev_saved_doc_string; | ||
| 3352 | saved_doc_string_size = prev_saved_doc_string_size; | ||
| 3353 | saved_doc_string_position = prev_saved_doc_string_position; | ||
| 3354 | saved_doc_string_length = prev_saved_doc_string_length; | ||
| 3355 | |||
| 3356 | prev_saved_doc_string = temp; | ||
| 3357 | prev_saved_doc_string_size = temp_size; | ||
| 3358 | prev_saved_doc_string_position = temp_pos; | ||
| 3359 | prev_saved_doc_string_length = temp_len; | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | if (saved_doc_string_size == 0) | ||
| 3363 | { | ||
| 3364 | saved_doc_string = xmalloc (nskip + extra); | ||
| 3365 | saved_doc_string_size = nskip + extra; | ||
| 3366 | } | ||
| 3367 | if (nskip > saved_doc_string_size) | ||
| 3368 | { | ||
| 3369 | saved_doc_string = xrealloc (saved_doc_string, nskip + extra); | ||
| 3370 | saved_doc_string_size = nskip + extra; | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | FILE *instream = infile->stream; | ||
| 3374 | saved_doc_string_position = (file_tell (instream) | ||
| 3375 | - infile->lookahead); | ||
| 3376 | |||
| 3377 | /* Copy that many bytes into saved_doc_string. */ | ||
| 3378 | i = 0; | ||
| 3379 | for (int n = min (nskip, infile->lookahead); 0 < n; n--) | ||
| 3380 | saved_doc_string[i++] | ||
| 3381 | = c = infile->buf[--infile->lookahead]; | ||
| 3382 | block_input (); | ||
| 3383 | for (; i < nskip && 0 <= c; i++) | ||
| 3384 | saved_doc_string[i] = c = getc (instream); | ||
| 3385 | unblock_input (); | ||
| 3386 | |||
| 3387 | saved_doc_string_length = i; | ||
| 3388 | } | ||
| 3389 | else | ||
| 3390 | /* Skip that many bytes. */ | ||
| 3391 | skip_dyn_bytes (readcharfun, nskip); | ||
| 3392 | |||
| 3393 | goto retry; | ||
| 3394 | } | 3430 | } |
| 3395 | if (c == '!') | 3431 | if (INT_MULTIPLY_WRAPV (nskip, 10, &nskip) |
| 3432 | | INT_ADD_WRAPV (nskip, c - '0', &nskip)) | ||
| 3433 | invalid_syntax ("#@", readcharfun); | ||
| 3434 | digits++; | ||
| 3435 | if (digits == 2 && nskip == 0) | ||
| 3396 | { | 3436 | { |
| 3397 | /* #! appears at the beginning of an executable file. | 3437 | /* #@00 means "skip to end" */ |
| 3398 | Skip the first line. */ | 3438 | skip_dyn_eof (readcharfun); |
| 3399 | while (c != '\n' && c >= 0) | 3439 | return; |
| 3400 | c = READCHAR; | ||
| 3401 | goto retry; | ||
| 3402 | } | 3440 | } |
| 3403 | if (c == '$') | 3441 | } |
| 3404 | return Vload_file_name; | 3442 | |
| 3405 | if (c == '\'') | 3443 | if (load_force_doc_strings && FROM_FILE_P (readcharfun)) |
| 3406 | return list2 (Qfunction, read0 (readcharfun, locate_syms)); | 3444 | { |
| 3407 | /* #:foo is the uninterned symbol named foo. */ | 3445 | /* If we are supposed to force doc strings into core right now, |
| 3408 | if (c == ':') | 3446 | record the last string that we skipped, |
| 3447 | and record where in the file it comes from. */ | ||
| 3448 | |||
| 3449 | /* But first exchange saved_doc_string | ||
| 3450 | with prev_saved_doc_string, so we save two strings. */ | ||
| 3451 | { | ||
| 3452 | char *temp = saved_doc_string; | ||
| 3453 | ptrdiff_t temp_size = saved_doc_string_size; | ||
| 3454 | file_offset temp_pos = saved_doc_string_position; | ||
| 3455 | ptrdiff_t temp_len = saved_doc_string_length; | ||
| 3456 | |||
| 3457 | saved_doc_string = prev_saved_doc_string; | ||
| 3458 | saved_doc_string_size = prev_saved_doc_string_size; | ||
| 3459 | saved_doc_string_position = prev_saved_doc_string_position; | ||
| 3460 | saved_doc_string_length = prev_saved_doc_string_length; | ||
| 3461 | |||
| 3462 | prev_saved_doc_string = temp; | ||
| 3463 | prev_saved_doc_string_size = temp_size; | ||
| 3464 | prev_saved_doc_string_position = temp_pos; | ||
| 3465 | prev_saved_doc_string_length = temp_len; | ||
| 3466 | } | ||
| 3467 | |||
| 3468 | enum { extra = 100 }; | ||
| 3469 | if (saved_doc_string_size == 0) | ||
| 3409 | { | 3470 | { |
| 3410 | uninterned_symbol = true; | 3471 | saved_doc_string = xmalloc (nskip + extra); |
| 3411 | read_hash_prefixed_symbol: | 3472 | saved_doc_string_size = nskip + extra; |
| 3412 | c = READCHAR; | ||
| 3413 | if (!(c > 040 | ||
| 3414 | && c != NO_BREAK_SPACE | ||
| 3415 | && (c >= 0200 | ||
| 3416 | || strchr ("\"';()[]#`,", c) == NULL))) | ||
| 3417 | { | ||
| 3418 | /* No symbol character follows, this is the empty | ||
| 3419 | symbol. */ | ||
| 3420 | UNREAD (c); | ||
| 3421 | return Fmake_symbol (empty_unibyte_string); | ||
| 3422 | } | ||
| 3423 | goto read_symbol; | ||
| 3424 | } | 3473 | } |
| 3425 | /* #_foo is really the symbol foo, regardless of shorthands */ | 3474 | if (nskip > saved_doc_string_size) |
| 3426 | if (c == '_') | ||
| 3427 | { | 3475 | { |
| 3428 | skip_shorthand = true; | 3476 | saved_doc_string = xrealloc (saved_doc_string, nskip + extra); |
| 3429 | goto read_hash_prefixed_symbol; | 3477 | saved_doc_string_size = nskip + extra; |
| 3430 | } | 3478 | } |
| 3431 | /* ## is the empty symbol. */ | ||
| 3432 | if (c == '#') | ||
| 3433 | return Fintern (empty_unibyte_string, Qnil); | ||
| 3434 | 3479 | ||
| 3435 | if (c >= '0' && c <= '9') | 3480 | FILE *instream = infile->stream; |
| 3436 | { | 3481 | saved_doc_string_position = (file_tell (instream) - infile->lookahead); |
| 3437 | EMACS_INT n = c - '0'; | ||
| 3438 | bool overflow = false; | ||
| 3439 | 3482 | ||
| 3440 | /* Read a non-negative integer. */ | 3483 | /* Copy that many bytes into saved_doc_string. */ |
| 3441 | while ('0' <= (c = READCHAR) && c <= '9') | 3484 | ptrdiff_t i = 0; |
| 3442 | { | 3485 | int c = 0; |
| 3443 | overflow |= INT_MULTIPLY_WRAPV (n, 10, &n); | 3486 | for (int n = min (nskip, infile->lookahead); n > 0; n--) |
| 3444 | overflow |= INT_ADD_WRAPV (n, c - '0', &n); | 3487 | saved_doc_string[i++] = c = infile->buf[--infile->lookahead]; |
| 3445 | } | 3488 | block_input (); |
| 3489 | for (; i < nskip && c >= 0; i++) | ||
| 3490 | saved_doc_string[i] = c = getc (instream); | ||
| 3491 | unblock_input (); | ||
| 3446 | 3492 | ||
| 3447 | if (!overflow) | 3493 | saved_doc_string_length = i; |
| 3448 | { | 3494 | } |
| 3449 | if (c == 'r' || c == 'R') | 3495 | else |
| 3450 | { | 3496 | /* Skip that many bytes. */ |
| 3451 | if (! (2 <= n && n <= 36)) | 3497 | skip_dyn_bytes (readcharfun, nskip); |
| 3452 | invalid_radix_integer (n, stackbuf, readcharfun); | 3498 | } |
| 3453 | return read_integer (readcharfun, n, stackbuf); | ||
| 3454 | } | ||
| 3455 | 3499 | ||
| 3456 | if (n <= MOST_POSITIVE_FIXNUM && ! NILP (Vread_circle)) | ||
| 3457 | { | ||
| 3458 | /* Reader forms that can reuse previously read objects. */ | ||
| 3459 | 3500 | ||
| 3460 | /* #n=object returns object, but associates it with | 3501 | /* Length of prefix only consisting of symbol constituent characters. */ |
| 3461 | n for #n#. */ | 3502 | static ptrdiff_t |
| 3462 | if (c == '=') | 3503 | symbol_char_span (const char *s) |
| 3463 | { | 3504 | { |
| 3464 | /* Make a placeholder for #n# to use temporarily. */ | 3505 | const char *p = s; |
| 3465 | /* Note: We used to use AUTO_CONS to allocate | 3506 | while ( *p == '^' || *p == '*' || *p == '+' || *p == '-' || *p == '/' |
| 3466 | placeholder, but that is a bad idea, since it | 3507 | || *p == '<' || *p == '=' || *p == '>' || *p == '_' || *p == '|') |
| 3467 | will place a stack-allocated cons cell into | 3508 | p++; |
| 3468 | the list in read_objects_map, which is a | 3509 | return p - s; |
| 3469 | staticpro'd global variable, and thus each of | 3510 | } |
| 3470 | its elements is marked during each GC. A | ||
| 3471 | stack-allocated object will become garbled | ||
| 3472 | when its stack slot goes out of scope, and | ||
| 3473 | some other function reuses it for entirely | ||
| 3474 | different purposes, which will cause crashes | ||
| 3475 | in GC. */ | ||
| 3476 | Lisp_Object placeholder = Fcons (Qnil, Qnil); | ||
| 3477 | struct Lisp_Hash_Table *h | ||
| 3478 | = XHASH_TABLE (read_objects_map); | ||
| 3479 | Lisp_Object number = make_fixnum (n), hash; | ||
| 3480 | |||
| 3481 | ptrdiff_t i = hash_lookup (h, number, &hash); | ||
| 3482 | if (i >= 0) | ||
| 3483 | /* Not normal, but input could be malformed. */ | ||
| 3484 | set_hash_value_slot (h, i, placeholder); | ||
| 3485 | else | ||
| 3486 | hash_put (h, number, placeholder, hash); | ||
| 3487 | |||
| 3488 | /* Read the object itself. */ | ||
| 3489 | Lisp_Object tem = read0 (readcharfun, locate_syms); | ||
| 3490 | |||
| 3491 | if (CONSP (tem)) | ||
| 3492 | { | ||
| 3493 | if (BASE_EQ (tem, placeholder)) | ||
| 3494 | /* Catch silly games like #1=#1# */ | ||
| 3495 | invalid_syntax ("nonsensical self-reference", | ||
| 3496 | readcharfun); | ||
| 3497 | 3511 | ||
| 3498 | /* Optimisation: since the placeholder is already | 3512 | static void |
| 3499 | a cons, repurpose it as the actual value. | 3513 | skip_space_and_comments (Lisp_Object readcharfun) |
| 3500 | This allows us to skip the substition below, | 3514 | { |
| 3501 | since the placeholder is already referenced | 3515 | int c; |
| 3502 | inside TEM at the appropriate places. */ | 3516 | do |
| 3503 | Fsetcar (placeholder, XCAR (tem)); | 3517 | { |
| 3504 | Fsetcdr (placeholder, XCDR (tem)); | 3518 | c = READCHAR; |
| 3505 | 3519 | if (c == ';') | |
| 3506 | struct Lisp_Hash_Table *h2 | 3520 | do |
| 3507 | = XHASH_TABLE (read_objects_completed); | 3521 | c = READCHAR; |
| 3508 | ptrdiff_t i = hash_lookup (h2, placeholder, &hash); | 3522 | while (c >= 0 && c != '\n'); |
| 3509 | eassert (i < 0); | 3523 | if (c < 0) |
| 3510 | hash_put (h2, placeholder, Qnil, hash); | 3524 | end_of_file_error (); |
| 3511 | return placeholder; | 3525 | } |
| 3512 | } | 3526 | while (c <= 32 || c == NO_BREAK_SPACE); |
| 3513 | 3527 | UNREAD (c); | |
| 3514 | /* If it can be recursive, remember it for | 3528 | } |
| 3515 | future substitutions. */ | ||
| 3516 | if (! SYMBOLP (tem) | ||
| 3517 | && ! NUMBERP (tem) | ||
| 3518 | && ! (STRINGP (tem) && !string_intervals (tem))) | ||
| 3519 | { | ||
| 3520 | struct Lisp_Hash_Table *h2 | ||
| 3521 | = XHASH_TABLE (read_objects_completed); | ||
| 3522 | i = hash_lookup (h2, tem, &hash); | ||
| 3523 | eassert (i < 0); | ||
| 3524 | hash_put (h2, tem, Qnil, hash); | ||
| 3525 | } | ||
| 3526 | |||
| 3527 | /* Now put it everywhere the placeholder was... */ | ||
| 3528 | Flread__substitute_object_in_subtree | ||
| 3529 | (tem, placeholder, read_objects_completed); | ||
| 3530 | |||
| 3531 | /* ...and #n# will use the real value from now on. */ | ||
| 3532 | i = hash_lookup (h, number, &hash); | ||
| 3533 | eassert (i >= 0); | ||
| 3534 | set_hash_value_slot (h, i, tem); | ||
| 3535 | |||
| 3536 | return tem; | ||
| 3537 | } | ||
| 3538 | 3529 | ||
| 3539 | /* #n# returns a previously read object. */ | 3530 | /* When an object is read, the type of the top read stack entry indicates |
| 3540 | if (c == '#') | 3531 | the syntactic context. */ |
| 3541 | { | 3532 | enum read_entry_type |
| 3542 | struct Lisp_Hash_Table *h | 3533 | { |
| 3543 | = XHASH_TABLE (read_objects_map); | 3534 | /* preceding syntactic context */ |
| 3544 | ptrdiff_t i = hash_lookup (h, make_fixnum (n), NULL); | 3535 | RE_list_start, /* "(" */ |
| 3545 | if (i >= 0) | 3536 | |
| 3546 | return HASH_VALUE (h, i); | 3537 | RE_list, /* "(" (+ OBJECT) */ |
| 3547 | } | 3538 | RE_list_dot, /* "(" (+ OBJECT) "." */ |
| 3548 | } | 3539 | |
| 3549 | } | 3540 | RE_vector, /* "[" (* OBJECT) */ |
| 3550 | /* Fall through to error message. */ | 3541 | RE_record, /* "#s(" (* OBJECT) */ |
| 3542 | RE_char_table, /* "#^[" (* OBJECT) */ | ||
| 3543 | RE_sub_char_table, /* "#^^[" (* OBJECT) */ | ||
| 3544 | RE_byte_code, /* "#[" (* OBJECT) */ | ||
| 3545 | RE_string_props, /* "#(" (* OBJECT) */ | ||
| 3546 | |||
| 3547 | RE_special, /* "'" | "#'" | "`" | "," | ",@" */ | ||
| 3548 | |||
| 3549 | RE_numbered, /* "#" (+ DIGIT) "=" */ | ||
| 3550 | }; | ||
| 3551 | |||
| 3552 | struct read_stack_entry | ||
| 3553 | { | ||
| 3554 | enum read_entry_type type; | ||
| 3555 | union { | ||
| 3556 | /* RE_list, RE_list_dot */ | ||
| 3557 | struct { | ||
| 3558 | Lisp_Object head; /* first cons of list */ | ||
| 3559 | Lisp_Object tail; /* last cons of list */ | ||
| 3560 | } list; | ||
| 3561 | |||
| 3562 | /* RE_vector, RE_record, RE_char_table, RE_sub_char_table, | ||
| 3563 | RE_byte_code, RE_string_props */ | ||
| 3564 | struct { | ||
| 3565 | Lisp_Object elems; /* list of elements in reverse order */ | ||
| 3566 | bool old_locate_syms; /* old value of locate_syms */ | ||
| 3567 | } vector; | ||
| 3568 | |||
| 3569 | /* RE_special */ | ||
| 3570 | struct { | ||
| 3571 | Lisp_Object symbol; /* symbol from special syntax */ | ||
| 3572 | } special; | ||
| 3573 | |||
| 3574 | /* RE_numbered */ | ||
| 3575 | struct { | ||
| 3576 | Lisp_Object number; /* number as a fixnum */ | ||
| 3577 | Lisp_Object placeholder; /* placeholder object */ | ||
| 3578 | } numbered; | ||
| 3579 | } u; | ||
| 3580 | }; | ||
| 3581 | |||
| 3582 | struct read_stack | ||
| 3583 | { | ||
| 3584 | struct read_stack_entry *stack; /* base of stack */ | ||
| 3585 | ptrdiff_t size; /* allocated size in entries */ | ||
| 3586 | ptrdiff_t sp; /* current number of entries */ | ||
| 3587 | }; | ||
| 3588 | |||
| 3589 | static struct read_stack rdstack = {NULL, 0, 0}; | ||
| 3590 | |||
| 3591 | void | ||
| 3592 | mark_lread (void) | ||
| 3593 | { | ||
| 3594 | /* Mark the read stack, which may contain data not otherwise traced */ | ||
| 3595 | for (ptrdiff_t i = 0; i < rdstack.sp; i++) | ||
| 3596 | { | ||
| 3597 | struct read_stack_entry *e = &rdstack.stack[i]; | ||
| 3598 | switch (e->type) | ||
| 3599 | { | ||
| 3600 | case RE_list_start: | ||
| 3601 | break; | ||
| 3602 | case RE_list: | ||
| 3603 | case RE_list_dot: | ||
| 3604 | mark_object (e->u.list.head); | ||
| 3605 | mark_object (e->u.list.tail); | ||
| 3606 | break; | ||
| 3607 | case RE_vector: | ||
| 3608 | case RE_record: | ||
| 3609 | case RE_char_table: | ||
| 3610 | case RE_sub_char_table: | ||
| 3611 | case RE_byte_code: | ||
| 3612 | case RE_string_props: | ||
| 3613 | mark_object (e->u.vector.elems); | ||
| 3614 | break; | ||
| 3615 | case RE_special: | ||
| 3616 | mark_object (e->u.special.symbol); | ||
| 3617 | break; | ||
| 3618 | case RE_numbered: | ||
| 3619 | mark_object (e->u.numbered.number); | ||
| 3620 | mark_object (e->u.numbered.placeholder); | ||
| 3621 | break; | ||
| 3551 | } | 3622 | } |
| 3552 | else if (c == 'x' || c == 'X') | 3623 | } |
| 3553 | return read_integer (readcharfun, 16, stackbuf); | 3624 | } |
| 3554 | else if (c == 'o' || c == 'O') | ||
| 3555 | return read_integer (readcharfun, 8, stackbuf); | ||
| 3556 | else if (c == 'b' || c == 'B') | ||
| 3557 | return read_integer (readcharfun, 2, stackbuf); | ||
| 3558 | |||
| 3559 | char acm_buf[15]; /* FIXME!!! 2021-11-27. */ | ||
| 3560 | sprintf (acm_buf, "#%c", c); | ||
| 3561 | invalid_syntax (acm_buf, readcharfun); | ||
| 3562 | UNREAD (c); | ||
| 3563 | invalid_syntax ("#", readcharfun); | ||
| 3564 | 3625 | ||
| 3565 | case ';': | 3626 | static inline struct read_stack_entry * |
| 3566 | while ((c = READCHAR) >= 0 && c != '\n'); | 3627 | read_stack_top (void) |
| 3567 | goto retry; | 3628 | { |
| 3629 | eassume (rdstack.sp > 0); | ||
| 3630 | return &rdstack.stack[rdstack.sp - 1]; | ||
| 3631 | } | ||
| 3568 | 3632 | ||
| 3569 | case '\'': | 3633 | static inline struct read_stack_entry * |
| 3570 | return list2 (Qquote, read0 (readcharfun, locate_syms)); | 3634 | read_stack_pop (void) |
| 3635 | { | ||
| 3636 | eassume (rdstack.sp > 0); | ||
| 3637 | return &rdstack.stack[--rdstack.sp]; | ||
| 3638 | } | ||
| 3571 | 3639 | ||
| 3572 | case '`': | 3640 | static inline bool |
| 3573 | return list2 (Qbackquote, read0 (readcharfun, locate_syms)); | 3641 | read_stack_empty_p (ptrdiff_t base_sp) |
| 3642 | { | ||
| 3643 | return rdstack.sp <= base_sp; | ||
| 3644 | } | ||
| 3574 | 3645 | ||
| 3575 | case ',': | 3646 | NO_INLINE static void |
| 3576 | { | 3647 | grow_read_stack (void) |
| 3577 | Lisp_Object comma_type = Qnil; | 3648 | { |
| 3578 | Lisp_Object value; | 3649 | struct read_stack *rs = &rdstack; |
| 3579 | int ch = READCHAR; | 3650 | eassert (rs->sp == rs->size); |
| 3651 | rs->stack = xpalloc (rs->stack, &rs->size, 1, -1, sizeof *rs->stack); | ||
| 3652 | eassert (rs->sp < rs->size); | ||
| 3653 | } | ||
| 3580 | 3654 | ||
| 3581 | if (ch == '@') | 3655 | static inline void |
| 3582 | comma_type = Qcomma_at; | 3656 | read_stack_push (struct read_stack_entry e) |
| 3583 | else | 3657 | { |
| 3584 | { | 3658 | if (rdstack.sp >= rdstack.size) |
| 3585 | if (ch >= 0) UNREAD (ch); | 3659 | grow_read_stack (); |
| 3586 | comma_type = Qcomma; | 3660 | rdstack.stack[rdstack.sp++] = e; |
| 3587 | } | 3661 | } |
| 3588 | 3662 | ||
| 3589 | value = read0 (readcharfun, locate_syms); | ||
| 3590 | return list2 (comma_type, value); | ||
| 3591 | } | ||
| 3592 | case '?': | ||
| 3593 | { | ||
| 3594 | int modifiers; | ||
| 3595 | int next_char; | ||
| 3596 | bool ok; | ||
| 3597 | 3663 | ||
| 3598 | c = READCHAR; | 3664 | /* Read a Lisp object. |
| 3599 | if (c < 0) | 3665 | If LOCATE_SYMS is true, symbols are read with position. */ |
| 3600 | end_of_file_error (); | 3666 | static Lisp_Object |
| 3601 | 3667 | read0 (Lisp_Object readcharfun, bool locate_syms) | |
| 3602 | /* Accept `single space' syntax like (list ? x) where the | 3668 | { |
| 3603 | whitespace character is SPC or TAB. | 3669 | char stackbuf[stackbufsize]; |
| 3604 | Other literal whitespace like NL, CR, and FF are not accepted, | 3670 | char *read_buffer = stackbuf; |
| 3605 | as there are well-established escape sequences for these. */ | 3671 | ptrdiff_t read_buffer_size = sizeof stackbuf; |
| 3606 | if (c == ' ' || c == '\t') | 3672 | char *heapbuf = NULL; |
| 3607 | return make_fixnum (c); | 3673 | specpdl_ref count = SPECPDL_INDEX (); |
| 3608 | 3674 | ||
| 3609 | if (c == '(' || c == ')' || c == '[' || c == ']' | 3675 | ptrdiff_t base_sp = rdstack.sp; |
| 3610 | || c == '"' || c == ';') | 3676 | |
| 3677 | bool uninterned_symbol; | ||
| 3678 | bool skip_shorthand; | ||
| 3679 | |||
| 3680 | /* Read an object into `obj'. */ | ||
| 3681 | read_obj: ; | ||
| 3682 | Lisp_Object obj; | ||
| 3683 | bool multibyte; | ||
| 3684 | int c = READCHAR_REPORT_MULTIBYTE (&multibyte); | ||
| 3685 | if (c < 0) | ||
| 3686 | end_of_file_error (); | ||
| 3687 | |||
| 3688 | switch (c) | ||
| 3689 | { | ||
| 3690 | case '(': | ||
| 3691 | read_stack_push ((struct read_stack_entry) {.type = RE_list_start}); | ||
| 3692 | goto read_obj; | ||
| 3693 | |||
| 3694 | case ')': | ||
| 3695 | if (read_stack_empty_p (base_sp)) | ||
| 3696 | invalid_syntax (")", readcharfun); | ||
| 3697 | switch (read_stack_top ()->type) | ||
| 3698 | { | ||
| 3699 | case RE_list_start: | ||
| 3700 | read_stack_pop (); | ||
| 3701 | obj = Qnil; | ||
| 3702 | break; | ||
| 3703 | case RE_list: | ||
| 3704 | obj = read_stack_pop ()->u.list.head; | ||
| 3705 | break; | ||
| 3706 | case RE_record: | ||
| 3611 | { | 3707 | { |
| 3612 | CHECK_LIST (Vlread_unescaped_character_literals); | 3708 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; |
| 3613 | Lisp_Object char_obj = make_fixed_natnum (c); | 3709 | Lisp_Object elems = Fnreverse (read_stack_pop ()->u.vector.elems); |
| 3614 | if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals))) | 3710 | if (NILP (elems)) |
| 3615 | Vlread_unescaped_character_literals = | 3711 | invalid_syntax ("#s", readcharfun); |
| 3616 | Fcons (char_obj, Vlread_unescaped_character_literals); | 3712 | |
| 3713 | if (BASE_EQ (XCAR (elems), Qhash_table)) | ||
| 3714 | obj = hash_table_from_plist (XCDR (elems)); | ||
| 3715 | else | ||
| 3716 | obj = record_from_list (elems); | ||
| 3717 | break; | ||
| 3617 | } | 3718 | } |
| 3719 | case RE_string_props: | ||
| 3720 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; | ||
| 3721 | obj = string_props_from_rev_list (read_stack_pop () ->u.vector.elems, | ||
| 3722 | readcharfun); | ||
| 3723 | break; | ||
| 3724 | default: | ||
| 3725 | invalid_syntax (")", readcharfun); | ||
| 3726 | } | ||
| 3727 | break; | ||
| 3618 | 3728 | ||
| 3619 | if (c == '\\') | 3729 | case '[': |
| 3620 | c = read_escape (readcharfun, 0); | 3730 | read_stack_push ((struct read_stack_entry) { |
| 3621 | modifiers = c & CHAR_MODIFIER_MASK; | 3731 | .type = RE_vector, |
| 3622 | c &= ~CHAR_MODIFIER_MASK; | 3732 | .u.vector.elems = Qnil, |
| 3623 | if (CHAR_BYTE8_P (c)) | 3733 | .u.vector.old_locate_syms = locate_syms, |
| 3624 | c = CHAR_TO_BYTE8 (c); | 3734 | }); |
| 3625 | c |= modifiers; | 3735 | /* FIXME: should vectors be read with locate_syms=false? */ |
| 3626 | 3736 | goto read_obj; | |
| 3627 | next_char = READCHAR; | ||
| 3628 | ok = (next_char <= 040 | ||
| 3629 | || (next_char < 0200 | ||
| 3630 | && strchr ("\"';()[]#?`,.", next_char) != NULL)); | ||
| 3631 | UNREAD (next_char); | ||
| 3632 | if (ok) | ||
| 3633 | return make_fixnum (c); | ||
| 3634 | |||
| 3635 | invalid_syntax ("?", readcharfun); | ||
| 3636 | } | ||
| 3637 | 3737 | ||
| 3638 | case '"': | 3738 | case ']': |
| 3739 | if (read_stack_empty_p (base_sp)) | ||
| 3740 | invalid_syntax ("]", readcharfun); | ||
| 3741 | switch (read_stack_top ()->type) | ||
| 3742 | { | ||
| 3743 | case RE_vector: | ||
| 3744 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; | ||
| 3745 | obj = vector_from_rev_list (read_stack_pop ()->u.vector.elems); | ||
| 3746 | break; | ||
| 3747 | case RE_byte_code: | ||
| 3748 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; | ||
| 3749 | obj = bytecode_from_rev_list (read_stack_pop ()->u.vector.elems, | ||
| 3750 | readcharfun); | ||
| 3751 | break; | ||
| 3752 | case RE_char_table: | ||
| 3753 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; | ||
| 3754 | obj = char_table_from_rev_list (read_stack_pop ()->u.vector.elems, | ||
| 3755 | readcharfun); | ||
| 3756 | break; | ||
| 3757 | case RE_sub_char_table: | ||
| 3758 | locate_syms = read_stack_top ()->u.vector.old_locate_syms; | ||
| 3759 | obj = sub_char_table_from_rev_list (read_stack_pop ()->u.vector.elems, | ||
| 3760 | readcharfun); | ||
| 3761 | break; | ||
| 3762 | default: | ||
| 3763 | invalid_syntax ("]", readcharfun); | ||
| 3764 | break; | ||
| 3765 | } | ||
| 3766 | break; | ||
| 3767 | |||
| 3768 | case '#': | ||
| 3639 | { | 3769 | { |
| 3640 | specpdl_ref count = SPECPDL_INDEX (); | 3770 | int ch = READCHAR; |
| 3641 | char *read_buffer = stackbuf; | 3771 | switch (ch) |
| 3642 | ptrdiff_t read_buffer_size = sizeof stackbuf; | ||
| 3643 | char *heapbuf = NULL; | ||
| 3644 | char *p = read_buffer; | ||
| 3645 | char *end = read_buffer + read_buffer_size; | ||
| 3646 | int ch; | ||
| 3647 | /* True if we saw an escape sequence specifying | ||
| 3648 | a multibyte character. */ | ||
| 3649 | bool force_multibyte = false; | ||
| 3650 | /* True if we saw an escape sequence specifying | ||
| 3651 | a single-byte character. */ | ||
| 3652 | bool force_singlebyte = false; | ||
| 3653 | bool cancel = false; | ||
| 3654 | ptrdiff_t nchars = 0; | ||
| 3655 | |||
| 3656 | while ((ch = READCHAR) >= 0 | ||
| 3657 | && ch != '\"') | ||
| 3658 | { | 3772 | { |
| 3659 | if (end - p < MAX_MULTIBYTE_LENGTH) | 3773 | case '\'': |
| 3774 | /* #'X -- special syntax for (function X) */ | ||
| 3775 | read_stack_push ((struct read_stack_entry) { | ||
| 3776 | .type = RE_special, | ||
| 3777 | .u.special.symbol = Qfunction, | ||
| 3778 | }); | ||
| 3779 | goto read_obj; | ||
| 3780 | |||
| 3781 | case '#': | ||
| 3782 | /* ## -- the empty symbol */ | ||
| 3783 | obj = Fintern (empty_unibyte_string, Qnil); | ||
| 3784 | break; | ||
| 3785 | |||
| 3786 | case 's': | ||
| 3787 | /* #s(...) -- a record or hash-table */ | ||
| 3788 | ch = READCHAR; | ||
| 3789 | if (ch != '(') | ||
| 3660 | { | 3790 | { |
| 3661 | ptrdiff_t offset = p - read_buffer; | 3791 | UNREAD (ch); |
| 3662 | read_buffer = grow_read_buffer (read_buffer, offset, | 3792 | invalid_syntax ("#s", readcharfun); |
| 3663 | &heapbuf, &read_buffer_size, | ||
| 3664 | count); | ||
| 3665 | p = read_buffer + offset; | ||
| 3666 | end = read_buffer + read_buffer_size; | ||
| 3667 | } | 3793 | } |
| 3794 | read_stack_push ((struct read_stack_entry) { | ||
| 3795 | .type = RE_record, | ||
| 3796 | .u.vector.elems = Qnil, | ||
| 3797 | .u.vector.old_locate_syms = locate_syms, | ||
| 3798 | }); | ||
| 3799 | locate_syms = false; | ||
| 3800 | goto read_obj; | ||
| 3801 | |||
| 3802 | case '^': | ||
| 3803 | /* #^[...] -- char-table | ||
| 3804 | #^^[...] -- sub-char-table */ | ||
| 3805 | ch = READCHAR; | ||
| 3806 | if (ch == '^') | ||
| 3807 | { | ||
| 3808 | ch = READCHAR; | ||
| 3809 | if (ch == '[') | ||
| 3810 | { | ||
| 3811 | read_stack_push ((struct read_stack_entry) { | ||
| 3812 | .type = RE_sub_char_table, | ||
| 3813 | .u.vector.elems = Qnil, | ||
| 3814 | .u.vector.old_locate_syms = locate_syms, | ||
| 3815 | }); | ||
| 3816 | locate_syms = false; | ||
| 3817 | goto read_obj; | ||
| 3818 | } | ||
| 3819 | else | ||
| 3820 | { | ||
| 3821 | UNREAD (ch); | ||
| 3822 | invalid_syntax ("#^^", readcharfun); | ||
| 3823 | } | ||
| 3824 | } | ||
| 3825 | else if (ch == '[') | ||
| 3826 | { | ||
| 3827 | read_stack_push ((struct read_stack_entry) { | ||
| 3828 | .type = RE_char_table, | ||
| 3829 | .u.vector.elems = Qnil, | ||
| 3830 | .u.vector.old_locate_syms = locate_syms, | ||
| 3831 | }); | ||
| 3832 | locate_syms = false; | ||
| 3833 | goto read_obj; | ||
| 3834 | } | ||
| 3835 | else | ||
| 3836 | { | ||
| 3837 | UNREAD (ch); | ||
| 3838 | invalid_syntax ("#^", readcharfun); | ||
| 3839 | } | ||
| 3840 | |||
| 3841 | case '(': | ||
| 3842 | /* #(...) -- string with properties */ | ||
| 3843 | read_stack_push ((struct read_stack_entry) { | ||
| 3844 | .type = RE_string_props, | ||
| 3845 | .u.vector.elems = Qnil, | ||
| 3846 | .u.vector.old_locate_syms = locate_syms, | ||
| 3847 | }); | ||
| 3848 | locate_syms = false; | ||
| 3849 | goto read_obj; | ||
| 3850 | |||
| 3851 | case '[': | ||
| 3852 | /* #[...] -- byte-code */ | ||
| 3853 | read_stack_push ((struct read_stack_entry) { | ||
| 3854 | .type = RE_byte_code, | ||
| 3855 | .u.vector.elems = Qnil, | ||
| 3856 | .u.vector.old_locate_syms = locate_syms, | ||
| 3857 | }); | ||
| 3858 | locate_syms = false; | ||
| 3859 | goto read_obj; | ||
| 3860 | |||
| 3861 | case '&': | ||
| 3862 | /* #&N"..." -- bool-vector */ | ||
| 3863 | obj = read_bool_vector (stackbuf, readcharfun); | ||
| 3864 | break; | ||
| 3865 | |||
| 3866 | case '!': | ||
| 3867 | /* #! appears at the beginning of an executable file. | ||
| 3868 | Skip the rest of the line. */ | ||
| 3869 | { | ||
| 3870 | int c; | ||
| 3871 | do | ||
| 3872 | c = READCHAR; | ||
| 3873 | while (c >= 0 && c != '\n'); | ||
| 3874 | goto read_obj; | ||
| 3875 | } | ||
| 3668 | 3876 | ||
| 3669 | if (ch == '\\') | 3877 | case 'x': |
| 3878 | case 'X': | ||
| 3879 | obj = read_integer (readcharfun, 16, stackbuf); | ||
| 3880 | break; | ||
| 3881 | |||
| 3882 | case 'o': | ||
| 3883 | case 'O': | ||
| 3884 | obj = read_integer (readcharfun, 8, stackbuf); | ||
| 3885 | break; | ||
| 3886 | |||
| 3887 | case 'b': | ||
| 3888 | case 'B': | ||
| 3889 | obj = read_integer (readcharfun, 2, stackbuf); | ||
| 3890 | break; | ||
| 3891 | |||
| 3892 | case '@': | ||
| 3893 | /* #@NUMBER is used to skip NUMBER following bytes. | ||
| 3894 | That's used in .elc files to skip over doc strings | ||
| 3895 | and function definitions that can be loaded lazily. */ | ||
| 3896 | skip_lazy_string (readcharfun); | ||
| 3897 | goto read_obj; | ||
| 3898 | |||
| 3899 | case '$': | ||
| 3900 | /* #$ -- reference to lazy-loaded string */ | ||
| 3901 | obj = Vload_file_name; | ||
| 3902 | break; | ||
| 3903 | |||
| 3904 | case ':': | ||
| 3905 | /* #:X -- uninterned symbol */ | ||
| 3906 | c = READCHAR; | ||
| 3907 | if (c <= 32 || c == NO_BREAK_SPACE | ||
| 3908 | || c == '"' || c == '\'' || c == ';' || c == '#' | ||
| 3909 | || c == '(' || c == ')' || c == '[' || c == ']' | ||
| 3910 | || c == '`' || c == ',') | ||
| 3670 | { | 3911 | { |
| 3671 | int modifiers; | 3912 | /* No symbol character follows: this is the empty symbol. */ |
| 3913 | UNREAD (c); | ||
| 3914 | obj = Fmake_symbol (empty_unibyte_string); | ||
| 3915 | break; | ||
| 3916 | } | ||
| 3917 | uninterned_symbol = true; | ||
| 3918 | skip_shorthand = false; | ||
| 3919 | goto read_symbol; | ||
| 3672 | 3920 | ||
| 3673 | ch = read_escape (readcharfun, 1); | 3921 | case '_': |
| 3922 | /* #_X -- symbol without shorthand */ | ||
| 3923 | c = READCHAR; | ||
| 3924 | if (c <= 32 || c == NO_BREAK_SPACE | ||
| 3925 | || c == '"' || c == '\'' || c == ';' || c == '#' | ||
| 3926 | || c == '(' || c == ')' || c == '[' || c == ']' | ||
| 3927 | || c == '`' || c == ',') | ||
| 3928 | { | ||
| 3929 | /* No symbol character follows: this is the empty symbol. */ | ||
| 3930 | UNREAD (c); | ||
| 3931 | obj = Fintern (empty_unibyte_string, Qnil); | ||
| 3932 | break; | ||
| 3933 | } | ||
| 3934 | uninterned_symbol = false; | ||
| 3935 | skip_shorthand = true; | ||
| 3936 | goto read_symbol; | ||
| 3674 | 3937 | ||
| 3675 | /* CH is -1 if \ newline or \ space has just been seen. */ | 3938 | default: |
| 3676 | if (ch == -1) | 3939 | if (ch >= '0' && ch <= '9') |
| 3940 | { | ||
| 3941 | /* #N=OBJ or #N# -- first read the number N */ | ||
| 3942 | EMACS_INT n = ch - '0'; | ||
| 3943 | int c; | ||
| 3944 | for (;;) | ||
| 3677 | { | 3945 | { |
| 3678 | if (p == read_buffer) | 3946 | c = READCHAR; |
| 3679 | cancel = true; | 3947 | if (c < '0' || c > '9') |
| 3680 | continue; | 3948 | break; |
| 3949 | if (INT_MULTIPLY_WRAPV (n, 10, &n) | ||
| 3950 | || INT_ADD_WRAPV (n, c - '0', &n)) | ||
| 3951 | invalid_syntax ("#", readcharfun); | ||
| 3681 | } | 3952 | } |
| 3682 | 3953 | if (c == 'r' || c == 'R') | |
| 3683 | modifiers = ch & CHAR_MODIFIER_MASK; | ||
| 3684 | ch = ch & ~CHAR_MODIFIER_MASK; | ||
| 3685 | |||
| 3686 | if (CHAR_BYTE8_P (ch)) | ||
| 3687 | force_singlebyte = true; | ||
| 3688 | else if (! ASCII_CHAR_P (ch)) | ||
| 3689 | force_multibyte = true; | ||
| 3690 | else /* I.e. ASCII_CHAR_P (ch). */ | ||
| 3691 | { | 3954 | { |
| 3692 | /* Allow `\C- ' and `\C-?'. */ | 3955 | /* #NrDIGITS -- radix-N number */ |
| 3693 | if (modifiers == CHAR_CTL) | 3956 | if (n < 0 || n > 36) |
| 3694 | { | 3957 | invalid_radix_integer (n, stackbuf, readcharfun); |
| 3695 | if (ch == ' ') | 3958 | obj = read_integer (readcharfun, n, stackbuf); |
| 3696 | ch = 0, modifiers = 0; | 3959 | break; |
| 3697 | else if (ch == '?') | 3960 | } |
| 3698 | ch = 127, modifiers = 0; | 3961 | else if (n <= MOST_POSITIVE_FIXNUM && !NILP (Vread_circle)) |
| 3699 | } | 3962 | { |
| 3700 | if (modifiers & CHAR_SHIFT) | 3963 | if (c == '=') |
| 3701 | { | 3964 | { |
| 3702 | /* Shift modifier is valid only with [A-Za-z]. */ | 3965 | /* #N=OBJ -- assign number N to OBJ */ |
| 3703 | if (ch >= 'A' && ch <= 'Z') | 3966 | Lisp_Object placeholder = Fcons (Qnil, Qnil); |
| 3704 | modifiers &= ~CHAR_SHIFT; | 3967 | |
| 3705 | else if (ch >= 'a' && ch <= 'z') | 3968 | struct Lisp_Hash_Table *h |
| 3706 | ch -= ('a' - 'A'), modifiers &= ~CHAR_SHIFT; | 3969 | = XHASH_TABLE (read_objects_map); |
| 3970 | Lisp_Object number = make_fixnum (n); | ||
| 3971 | Lisp_Object hash; | ||
| 3972 | ptrdiff_t i = hash_lookup (h, number, &hash); | ||
| 3973 | if (i >= 0) | ||
| 3974 | /* Not normal, but input could be malformed. */ | ||
| 3975 | set_hash_value_slot (h, i, placeholder); | ||
| 3976 | else | ||
| 3977 | hash_put (h, number, placeholder, hash); | ||
| 3978 | read_stack_push ((struct read_stack_entry) { | ||
| 3979 | .type = RE_numbered, | ||
| 3980 | .u.numbered.number = number, | ||
| 3981 | .u.numbered.placeholder = placeholder, | ||
| 3982 | }); | ||
| 3983 | goto read_obj; | ||
| 3707 | } | 3984 | } |
| 3708 | 3985 | else if (c == '#') | |
| 3709 | if (modifiers & CHAR_META) | ||
| 3710 | { | 3986 | { |
| 3711 | /* Move the meta bit to the right place for a | 3987 | /* #N# -- reference to numbered object */ |
| 3712 | string. */ | 3988 | struct Lisp_Hash_Table *h |
| 3713 | modifiers &= ~CHAR_META; | 3989 | = XHASH_TABLE (read_objects_map); |
| 3714 | ch = BYTE8_TO_CHAR (ch | 0x80); | 3990 | ptrdiff_t i = hash_lookup (h, make_fixnum (n), NULL); |
| 3715 | force_singlebyte = true; | 3991 | if (i < 0) |
| 3992 | invalid_syntax ("#", readcharfun); | ||
| 3993 | obj = HASH_VALUE (h, i); | ||
| 3994 | break; | ||
| 3716 | } | 3995 | } |
| 3996 | else | ||
| 3997 | invalid_syntax ("#", readcharfun); | ||
| 3717 | } | 3998 | } |
| 3718 | 3999 | else | |
| 3719 | /* Any modifiers remaining are invalid. */ | 4000 | invalid_syntax ("#", readcharfun); |
| 3720 | if (modifiers) | ||
| 3721 | invalid_syntax ("Invalid modifier in string", readcharfun); | ||
| 3722 | p += CHAR_STRING (ch, (unsigned char *) p); | ||
| 3723 | } | 4001 | } |
| 3724 | else | 4002 | else |
| 3725 | { | 4003 | invalid_syntax ("#", readcharfun); |
| 3726 | p += CHAR_STRING (ch, (unsigned char *) p); | ||
| 3727 | if (CHAR_BYTE8_P (ch)) | ||
| 3728 | force_singlebyte = true; | ||
| 3729 | else if (! ASCII_CHAR_P (ch)) | ||
| 3730 | force_multibyte = true; | ||
| 3731 | } | ||
| 3732 | nchars++; | ||
| 3733 | } | 4004 | } |
| 4005 | break; | ||
| 4006 | } | ||
| 3734 | 4007 | ||
| 3735 | if (ch < 0) | 4008 | case '?': |
| 3736 | end_of_file_error (); | 4009 | obj = read_char_literal (readcharfun); |
| 4010 | break; | ||
| 3737 | 4011 | ||
| 3738 | /* If purifying, and string starts with \ newline, | 4012 | case '"': |
| 3739 | return zero instead. This is for doc strings | 4013 | obj = read_string_literal (stackbuf, readcharfun); |
| 3740 | that we are really going to find in etc/DOC.nn.nn. */ | 4014 | break; |
| 3741 | if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel) | 4015 | |
| 3742 | return unbind_to (count, make_fixnum (0)); | 4016 | case '\'': |
| 4017 | read_stack_push ((struct read_stack_entry) { | ||
| 4018 | .type = RE_special, | ||
| 4019 | .u.special.symbol = Qquote, | ||
| 4020 | }); | ||
| 4021 | goto read_obj; | ||
| 3743 | 4022 | ||
| 3744 | if (! force_multibyte && force_singlebyte) | 4023 | case '`': |
| 4024 | read_stack_push ((struct read_stack_entry) { | ||
| 4025 | .type = RE_special, | ||
| 4026 | .u.special.symbol = Qbackquote, | ||
| 4027 | }); | ||
| 4028 | goto read_obj; | ||
| 4029 | |||
| 4030 | case ',': | ||
| 4031 | { | ||
| 4032 | int ch = READCHAR; | ||
| 4033 | Lisp_Object sym; | ||
| 4034 | if (ch == '@') | ||
| 4035 | sym = Qcomma_at; | ||
| 4036 | else | ||
| 3745 | { | 4037 | { |
| 3746 | /* READ_BUFFER contains raw 8-bit bytes and no multibyte | 4038 | if (ch >= 0) |
| 3747 | forms. Convert it to unibyte. */ | 4039 | UNREAD (ch); |
| 3748 | nchars = str_as_unibyte ((unsigned char *) read_buffer, | 4040 | sym = Qcomma; |
| 3749 | p - read_buffer); | ||
| 3750 | p = read_buffer + nchars; | ||
| 3751 | } | 4041 | } |
| 4042 | read_stack_push ((struct read_stack_entry) { | ||
| 4043 | .type = RE_special, | ||
| 4044 | .u.special.symbol = sym, | ||
| 4045 | }); | ||
| 4046 | goto read_obj; | ||
| 4047 | } | ||
| 3752 | 4048 | ||
| 3753 | Lisp_Object result | 4049 | case ';': |
| 3754 | = make_specified_string (read_buffer, nchars, p - read_buffer, | 4050 | { |
| 3755 | (force_multibyte | 4051 | int c; |
| 3756 | || (p - read_buffer != nchars))); | 4052 | do |
| 3757 | return unbind_to (count, result); | 4053 | c = READCHAR; |
| 4054 | while (c >= 0 && c != '\n'); | ||
| 4055 | goto read_obj; | ||
| 3758 | } | 4056 | } |
| 3759 | 4057 | ||
| 3760 | case '.': | 4058 | case '.': |
| 3761 | { | 4059 | { |
| 3762 | int next_char = READCHAR; | 4060 | int nch = READCHAR; |
| 3763 | UNREAD (next_char); | 4061 | UNREAD (nch); |
| 3764 | 4062 | if (nch <= 32 || nch == NO_BREAK_SPACE | |
| 3765 | if (next_char <= 040 | 4063 | || nch == '"' || nch == '\'' || nch == ';' |
| 3766 | || (next_char < 0200 | 4064 | || nch == '(' || nch == '[' || nch == '#' |
| 3767 | && strchr ("\"';([#?`,", next_char) != NULL)) | 4065 | || nch == '?' || nch == '`' || nch == ',') |
| 3768 | { | 4066 | { |
| 3769 | *pch = c; | 4067 | if (!read_stack_empty_p (base_sp) |
| 3770 | return Qnil; | 4068 | && read_stack_top ()->type == RE_list) |
| 4069 | { | ||
| 4070 | read_stack_top ()->type = RE_list_dot; | ||
| 4071 | goto read_obj; | ||
| 4072 | } | ||
| 4073 | invalid_syntax (".", readcharfun); | ||
| 3771 | } | 4074 | } |
| 3772 | } | 4075 | } |
| 3773 | /* The atom-reading loop below will now loop at least once, | 4076 | /* may be a number or symbol starting with a dot */ |
| 3774 | assuring that we will not try to UNREAD two characters in a | ||
| 3775 | row. */ | ||
| 3776 | FALLTHROUGH; | 4077 | FALLTHROUGH; |
| 4078 | |||
| 3777 | default: | 4079 | default: |
| 3778 | if (c <= 040) goto retry; | 4080 | if (c <= 32 || c == NO_BREAK_SPACE) |
| 3779 | if (c == NO_BREAK_SPACE) | 4081 | goto read_obj; |
| 3780 | goto retry; | ||
| 3781 | 4082 | ||
| 4083 | uninterned_symbol = false; | ||
| 4084 | skip_shorthand = false; | ||
| 4085 | /* symbol or number */ | ||
| 3782 | read_symbol: | 4086 | read_symbol: |
| 3783 | { | 4087 | { |
| 3784 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 3785 | char *read_buffer = stackbuf; | ||
| 3786 | ptrdiff_t read_buffer_size = sizeof stackbuf; | ||
| 3787 | char *heapbuf = NULL; | ||
| 3788 | char *p = read_buffer; | 4088 | char *p = read_buffer; |
| 3789 | char *end = read_buffer + read_buffer_size; | 4089 | char *end = read_buffer + read_buffer_size; |
| 3790 | bool quoted = false; | 4090 | bool quoted = false; |
| @@ -3805,7 +4105,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list, bool locate_syms) | |||
| 3805 | if (c == '\\') | 4105 | if (c == '\\') |
| 3806 | { | 4106 | { |
| 3807 | c = READCHAR; | 4107 | c = READCHAR; |
| 3808 | if (c == -1) | 4108 | if (c < 0) |
| 3809 | end_of_file_error (); | 4109 | end_of_file_error (); |
| 3810 | quoted = true; | 4110 | quoted = true; |
| 3811 | } | 4111 | } |
| @@ -3816,94 +4116,205 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list, bool locate_syms) | |||
| 3816 | *p++ = c; | 4116 | *p++ = c; |
| 3817 | c = READCHAR; | 4117 | c = READCHAR; |
| 3818 | } | 4118 | } |
| 3819 | while (c > 040 | 4119 | while (c > 32 |
| 3820 | && c != NO_BREAK_SPACE | 4120 | && c != NO_BREAK_SPACE |
| 3821 | && (c >= 0200 | 4121 | && (c >= 128 |
| 3822 | || strchr ("\"';()[]#`,", c) == NULL)); | 4122 | || !( c == '"' || c == '\'' || c == ';' || c == '#' |
| 4123 | || c == '(' || c == ')' || c == '[' || c == ']' | ||
| 4124 | || c == '`' || c == ','))); | ||
| 3823 | 4125 | ||
| 3824 | *p = 0; | 4126 | *p = 0; |
| 3825 | ptrdiff_t nbytes = p - read_buffer; | 4127 | ptrdiff_t nbytes = p - read_buffer; |
| 3826 | UNREAD (c); | 4128 | UNREAD (c); |
| 3827 | 4129 | ||
| 3828 | if (!quoted && !uninterned_symbol && !skip_shorthand) | 4130 | /* Only attempt to parse the token as a number if it starts as one. */ |
| 4131 | char c0 = read_buffer[0]; | ||
| 4132 | if (((c0 >= '0' && c0 <= '9') || c0 == '.' || c0 == '-' || c0 == '+') | ||
| 4133 | && !quoted && !uninterned_symbol && !skip_shorthand) | ||
| 3829 | { | 4134 | { |
| 3830 | ptrdiff_t len; | 4135 | ptrdiff_t len; |
| 3831 | Lisp_Object result = string_to_number (read_buffer, 10, &len); | 4136 | Lisp_Object result = string_to_number (read_buffer, 10, &len); |
| 3832 | if (! NILP (result) && len == nbytes) | 4137 | if (!NILP (result) && len == nbytes) |
| 3833 | return unbind_to (count, result); | 4138 | { |
| 4139 | obj = result; | ||
| 4140 | break; | ||
| 4141 | } | ||
| 3834 | } | 4142 | } |
| 3835 | { | 4143 | |
| 3836 | Lisp_Object result; | 4144 | /* symbol, possibly uninterned */ |
| 3837 | ptrdiff_t nchars | 4145 | ptrdiff_t nchars |
| 3838 | = (multibyte | 4146 | = (multibyte |
| 3839 | ? multibyte_chars_in_text ((unsigned char *) read_buffer, | 4147 | ? multibyte_chars_in_text ((unsigned char *)read_buffer, nbytes) |
| 3840 | nbytes) | 4148 | : nbytes); |
| 3841 | : nbytes); | 4149 | Lisp_Object result; |
| 3842 | 4150 | if (uninterned_symbol) | |
| 3843 | if (uninterned_symbol) | 4151 | { |
| 3844 | { | 4152 | Lisp_Object name |
| 3845 | Lisp_Object name | 4153 | = (!NILP (Vpurify_flag) |
| 3846 | = ((! NILP (Vpurify_flag) | 4154 | ? make_pure_string (read_buffer, nchars, nbytes, multibyte) |
| 3847 | ? make_pure_string : make_specified_string) | 4155 | : make_specified_string (read_buffer, nchars, nbytes, |
| 3848 | (read_buffer, nchars, nbytes, multibyte)); | 4156 | multibyte)); |
| 3849 | result = Fmake_symbol (name); | 4157 | result = Fmake_symbol (name); |
| 3850 | } | 4158 | } |
| 3851 | else | 4159 | else |
| 3852 | { | 4160 | { |
| 3853 | /* Don't create the string object for the name unless | 4161 | /* Don't create the string object for the name unless |
| 3854 | we're going to retain it in a new symbol. | 4162 | we're going to retain it in a new symbol. |
| 3855 | 4163 | ||
| 3856 | Like intern_1 but supports multibyte names. */ | 4164 | Like intern_1 but supports multibyte names. */ |
| 3857 | Lisp_Object obarray = check_obarray (Vobarray); | 4165 | Lisp_Object obarray = check_obarray (Vobarray); |
| 3858 | 4166 | ||
| 3859 | char* longhand = NULL; | 4167 | char *longhand = NULL; |
| 3860 | ptrdiff_t longhand_chars = 0; | 4168 | ptrdiff_t longhand_chars = 0; |
| 3861 | ptrdiff_t longhand_bytes = 0; | 4169 | ptrdiff_t longhand_bytes = 0; |
| 3862 | 4170 | ||
| 3863 | Lisp_Object tem; | 4171 | Lisp_Object found; |
| 3864 | if (skip_shorthand | 4172 | if (skip_shorthand |
| 3865 | /* The following ASCII characters are used in the | 4173 | /* We exempt characters used in the "core" Emacs Lisp |
| 3866 | only "core" Emacs Lisp symbols that are comprised | 4174 | symbols that are comprised entirely of characters |
| 3867 | entirely of characters that have the 'symbol | 4175 | that have the 'symbol constituent' syntax from |
| 3868 | constituent' syntax. We exempt them from | 4176 | transforming according to shorthands. */ |
| 3869 | transforming according to shorthands. */ | 4177 | || symbol_char_span (read_buffer) >= nbytes) |
| 3870 | || strspn (read_buffer, "^*+-/<=>_|") >= nbytes) | 4178 | found = oblookup (obarray, read_buffer, nchars, nbytes); |
| 3871 | tem = oblookup (obarray, read_buffer, nchars, nbytes); | 4179 | else |
| 3872 | else | 4180 | found = oblookup_considering_shorthand (obarray, read_buffer, |
| 3873 | tem = oblookup_considering_shorthand (obarray, read_buffer, | ||
| 3874 | nchars, nbytes, &longhand, | 4181 | nchars, nbytes, &longhand, |
| 3875 | &longhand_chars, | 4182 | &longhand_chars, |
| 3876 | &longhand_bytes); | 4183 | &longhand_bytes); |
| 3877 | 4184 | ||
| 3878 | if (SYMBOLP (tem)) | 4185 | if (SYMBOLP (found)) |
| 3879 | result = tem; | 4186 | result = found; |
| 3880 | else if (longhand) | 4187 | else if (longhand) |
| 3881 | { | 4188 | { |
| 3882 | Lisp_Object name | 4189 | Lisp_Object name = make_specified_string (longhand, |
| 3883 | = make_specified_string (longhand, longhand_chars, | 4190 | longhand_chars, |
| 3884 | longhand_bytes, multibyte); | 4191 | longhand_bytes, |
| 3885 | xfree (longhand); | 4192 | multibyte); |
| 3886 | result = intern_driver (name, obarray, tem); | 4193 | xfree (longhand); |
| 3887 | } | 4194 | result = intern_driver (name, obarray, found); |
| 3888 | else | 4195 | } |
| 3889 | { | 4196 | else |
| 3890 | Lisp_Object name | 4197 | { |
| 3891 | = make_specified_string (read_buffer, nchars, nbytes, | 4198 | Lisp_Object name = make_specified_string (read_buffer, nchars, |
| 3892 | multibyte); | 4199 | nbytes, multibyte); |
| 3893 | result = intern_driver (name, obarray, tem); | 4200 | result = intern_driver (name, obarray, found); |
| 3894 | } | 4201 | } |
| 3895 | } | 4202 | } |
| 3896 | if (locate_syms | 4203 | if (locate_syms && !NILP (result)) |
| 3897 | && !NILP (result) | 4204 | result = build_symbol_with_pos (result, |
| 3898 | ) | 4205 | make_fixnum (start_position)); |
| 3899 | result = build_symbol_with_pos (result, | ||
| 3900 | make_fixnum (start_position)); | ||
| 3901 | 4206 | ||
| 3902 | return unbind_to (count, result); | 4207 | obj = result; |
| 3903 | } | 4208 | break; |
| 3904 | } | 4209 | } |
| 3905 | } | 4210 | } |
| 4211 | |||
| 4212 | /* We have read an object in `obj'. Use the stack to decide what to | ||
| 4213 | do with it. */ | ||
| 4214 | while (rdstack.sp > base_sp) | ||
| 4215 | { | ||
| 4216 | struct read_stack_entry *e = read_stack_top (); | ||
| 4217 | switch (e->type) | ||
| 4218 | { | ||
| 4219 | case RE_list_start: | ||
| 4220 | e->type = RE_list; | ||
| 4221 | e->u.list.head = e->u.list.tail = Fcons (obj, Qnil); | ||
| 4222 | goto read_obj; | ||
| 4223 | |||
| 4224 | case RE_list: | ||
| 4225 | { | ||
| 4226 | Lisp_Object tl = Fcons (obj, Qnil); | ||
| 4227 | XSETCDR (e->u.list.tail, tl); | ||
| 4228 | e->u.list.tail = tl; | ||
| 4229 | goto read_obj; | ||
| 4230 | } | ||
| 4231 | |||
| 4232 | case RE_list_dot: | ||
| 4233 | { | ||
| 4234 | skip_space_and_comments (readcharfun); | ||
| 4235 | int ch = READCHAR; | ||
| 4236 | if (ch != ')') | ||
| 4237 | invalid_syntax ("expected )", readcharfun); | ||
| 4238 | XSETCDR (e->u.list.tail, obj); | ||
| 4239 | read_stack_pop (); | ||
| 4240 | obj = e->u.list.head; | ||
| 4241 | break; | ||
| 4242 | } | ||
| 4243 | |||
| 4244 | case RE_vector: | ||
| 4245 | case RE_record: | ||
| 4246 | case RE_char_table: | ||
| 4247 | case RE_sub_char_table: | ||
| 4248 | case RE_byte_code: | ||
| 4249 | case RE_string_props: | ||
| 4250 | e->u.vector.elems = Fcons (obj, e->u.vector.elems); | ||
| 4251 | goto read_obj; | ||
| 4252 | |||
| 4253 | case RE_special: | ||
| 4254 | read_stack_pop (); | ||
| 4255 | obj = list2 (e->u.special.symbol, obj); | ||
| 4256 | break; | ||
| 4257 | |||
| 4258 | case RE_numbered: | ||
| 4259 | { | ||
| 4260 | read_stack_pop (); | ||
| 4261 | Lisp_Object placeholder = e->u.numbered.placeholder; | ||
| 4262 | if (CONSP (obj)) | ||
| 4263 | { | ||
| 4264 | if (BASE_EQ (obj, placeholder)) | ||
| 4265 | /* Catch silly games like #1=#1# */ | ||
| 4266 | invalid_syntax ("nonsensical self-reference", readcharfun); | ||
| 4267 | |||
| 4268 | /* Optimisation: since the placeholder is already | ||
| 4269 | a cons, repurpose it as the actual value. | ||
| 4270 | This allows us to skip the substitution below, | ||
| 4271 | since the placeholder is already referenced | ||
| 4272 | inside OBJ at the appropriate places. */ | ||
| 4273 | Fsetcar (placeholder, XCAR (obj)); | ||
| 4274 | Fsetcdr (placeholder, XCDR (obj)); | ||
| 4275 | |||
| 4276 | struct Lisp_Hash_Table *h2 | ||
| 4277 | = XHASH_TABLE (read_objects_completed); | ||
| 4278 | Lisp_Object hash; | ||
| 4279 | ptrdiff_t i = hash_lookup (h2, placeholder, &hash); | ||
| 4280 | eassert (i < 0); | ||
| 4281 | hash_put (h2, placeholder, Qnil, hash); | ||
| 4282 | obj = placeholder; | ||
| 4283 | } | ||
| 4284 | else | ||
| 4285 | { | ||
| 4286 | /* If it can be recursive, remember it for future | ||
| 4287 | substitutions. */ | ||
| 4288 | if (!SYMBOLP (obj) && !NUMBERP (obj) | ||
| 4289 | && !(STRINGP (obj) && !string_intervals (obj))) | ||
| 4290 | { | ||
| 4291 | struct Lisp_Hash_Table *h2 | ||
| 4292 | = XHASH_TABLE (read_objects_completed); | ||
| 4293 | Lisp_Object hash; | ||
| 4294 | ptrdiff_t i = hash_lookup (h2, obj, &hash); | ||
| 4295 | eassert (i < 0); | ||
| 4296 | hash_put (h2, obj, Qnil, hash); | ||
| 4297 | } | ||
| 4298 | |||
| 4299 | /* Now put it everywhere the placeholder was... */ | ||
| 4300 | Flread__substitute_object_in_subtree (obj, placeholder, | ||
| 4301 | read_objects_completed); | ||
| 4302 | |||
| 4303 | /* ...and #n# will use the real value from now on. */ | ||
| 4304 | struct Lisp_Hash_Table *h = XHASH_TABLE (read_objects_map); | ||
| 4305 | Lisp_Object hash; | ||
| 4306 | ptrdiff_t i = hash_lookup (h, e->u.numbered.number, &hash); | ||
| 4307 | eassert (i >= 0); | ||
| 4308 | set_hash_value_slot (h, i, obj); | ||
| 4309 | } | ||
| 4310 | break; | ||
| 4311 | } | ||
| 4312 | } | ||
| 4313 | } | ||
| 4314 | |||
| 4315 | return unbind_to (count, obj); | ||
| 3906 | } | 4316 | } |
| 4317 | |||
| 3907 | 4318 | ||
| 3908 | DEFUN ("lread--substitute-object-in-subtree", | 4319 | DEFUN ("lread--substitute-object-in-subtree", |
| 3909 | Flread__substitute_object_in_subtree, | 4320 | Flread__substitute_object_in_subtree, |
| @@ -4150,214 +4561,6 @@ string_to_number (char const *string, int base, ptrdiff_t *plen) | |||
| 4150 | } | 4561 | } |
| 4151 | 4562 | ||
| 4152 | 4563 | ||
| 4153 | static Lisp_Object | ||
| 4154 | read_vector (Lisp_Object readcharfun, bool bytecodeflag, bool locate_syms) | ||
| 4155 | { | ||
| 4156 | Lisp_Object tem = read_list (1, readcharfun, locate_syms); | ||
| 4157 | ptrdiff_t size = list_length (tem); | ||
| 4158 | Lisp_Object vector = make_nil_vector (size); | ||
| 4159 | |||
| 4160 | /* Avoid accessing past the end of a vector if the vector is too | ||
| 4161 | small to be valid for bytecode. */ | ||
| 4162 | bytecodeflag &= COMPILED_STACK_DEPTH < size; | ||
| 4163 | |||
| 4164 | Lisp_Object *ptr = XVECTOR (vector)->contents; | ||
| 4165 | for (ptrdiff_t i = 0; i < size; i++) | ||
| 4166 | { | ||
| 4167 | Lisp_Object item = Fcar (tem); | ||
| 4168 | /* If `load-force-doc-strings' is t when reading a lazily-loaded | ||
| 4169 | bytecode object, the docstring containing the bytecode and | ||
| 4170 | constants values must be treated as unibyte and passed to | ||
| 4171 | Fread, to get the actual bytecode string and constants vector. */ | ||
| 4172 | if (bytecodeflag && load_force_doc_strings) | ||
| 4173 | { | ||
| 4174 | if (i == COMPILED_BYTECODE) | ||
| 4175 | { | ||
| 4176 | if (!STRINGP (item)) | ||
| 4177 | error ("Invalid byte code"); | ||
| 4178 | |||
| 4179 | /* Delay handling the bytecode slot until we know whether | ||
| 4180 | it is lazily-loaded (we can tell by whether the | ||
| 4181 | constants slot is nil). */ | ||
| 4182 | ASET (vector, COMPILED_CONSTANTS, item); | ||
| 4183 | item = Qnil; | ||
| 4184 | } | ||
| 4185 | else if (i == COMPILED_CONSTANTS) | ||
| 4186 | { | ||
| 4187 | Lisp_Object bytestr = ptr[COMPILED_CONSTANTS]; | ||
| 4188 | |||
| 4189 | if (NILP (item)) | ||
| 4190 | { | ||
| 4191 | /* Coerce string to unibyte (like string-as-unibyte, | ||
| 4192 | but without generating extra garbage and | ||
| 4193 | guaranteeing no change in the contents). */ | ||
| 4194 | STRING_SET_CHARS (bytestr, SBYTES (bytestr)); | ||
| 4195 | STRING_SET_UNIBYTE (bytestr); | ||
| 4196 | |||
| 4197 | item = Fread (Fcons (bytestr, readcharfun)); | ||
| 4198 | if (!CONSP (item)) | ||
| 4199 | error ("Invalid byte code"); | ||
| 4200 | |||
| 4201 | struct Lisp_Cons *otem = XCONS (item); | ||
| 4202 | bytestr = XCAR (item); | ||
| 4203 | item = XCDR (item); | ||
| 4204 | free_cons (otem); | ||
| 4205 | } | ||
| 4206 | |||
| 4207 | /* Now handle the bytecode slot. */ | ||
| 4208 | ASET (vector, COMPILED_BYTECODE, bytestr); | ||
| 4209 | } | ||
| 4210 | else if (i == COMPILED_DOC_STRING | ||
| 4211 | && STRINGP (item) | ||
| 4212 | && ! STRING_MULTIBYTE (item)) | ||
| 4213 | { | ||
| 4214 | if (EQ (readcharfun, Qget_emacs_mule_file_char)) | ||
| 4215 | item = Fdecode_coding_string (item, Qemacs_mule, Qnil, Qnil); | ||
| 4216 | else | ||
| 4217 | item = Fstring_as_multibyte (item); | ||
| 4218 | } | ||
| 4219 | } | ||
| 4220 | ASET (vector, i, item); | ||
| 4221 | struct Lisp_Cons *otem = XCONS (tem); | ||
| 4222 | tem = Fcdr (tem); | ||
| 4223 | free_cons (otem); | ||
| 4224 | } | ||
| 4225 | return vector; | ||
| 4226 | } | ||
| 4227 | |||
| 4228 | /* FLAG means check for ']' to terminate rather than ')' and '.'. | ||
| 4229 | LOCATE_SYMS true means read symbol occurrencess as symbols with | ||
| 4230 | position. */ | ||
| 4231 | |||
| 4232 | static Lisp_Object | ||
| 4233 | read_list (bool flag, Lisp_Object readcharfun, bool locate_syms) | ||
| 4234 | { | ||
| 4235 | Lisp_Object val, tail; | ||
| 4236 | Lisp_Object elt, tem; | ||
| 4237 | /* 0 is the normal case. | ||
| 4238 | 1 means this list is a doc reference; replace it with the number 0. | ||
| 4239 | 2 means this list is a doc reference; replace it with the doc string. */ | ||
| 4240 | int doc_reference = 0; | ||
| 4241 | |||
| 4242 | /* Initialize this to 1 if we are reading a list. */ | ||
| 4243 | bool first_in_list = flag <= 0; | ||
| 4244 | |||
| 4245 | val = Qnil; | ||
| 4246 | tail = Qnil; | ||
| 4247 | |||
| 4248 | while (1) | ||
| 4249 | { | ||
| 4250 | int ch; | ||
| 4251 | elt = read1 (readcharfun, &ch, first_in_list, locate_syms); | ||
| 4252 | |||
| 4253 | first_in_list = 0; | ||
| 4254 | |||
| 4255 | /* While building, if the list starts with #$, treat it specially. */ | ||
| 4256 | if (EQ (elt, Vload_file_name) | ||
| 4257 | && ! NILP (elt)) | ||
| 4258 | { | ||
| 4259 | if (!NILP (Vpurify_flag)) | ||
| 4260 | doc_reference = 0; | ||
| 4261 | else if (load_force_doc_strings) | ||
| 4262 | doc_reference = 2; | ||
| 4263 | } | ||
| 4264 | if (ch) | ||
| 4265 | { | ||
| 4266 | if (flag > 0) | ||
| 4267 | { | ||
| 4268 | if (ch == ']') | ||
| 4269 | return val; | ||
| 4270 | invalid_syntax (") or . in a vector", readcharfun); | ||
| 4271 | } | ||
| 4272 | if (ch == ')') | ||
| 4273 | return val; | ||
| 4274 | if (ch == '.') | ||
| 4275 | { | ||
| 4276 | if (!NILP (tail)) | ||
| 4277 | XSETCDR (tail, read0 (readcharfun, locate_syms)); | ||
| 4278 | else | ||
| 4279 | val = read0 (readcharfun, locate_syms); | ||
| 4280 | read1 (readcharfun, &ch, 0, locate_syms); | ||
| 4281 | |||
| 4282 | if (ch == ')') | ||
| 4283 | { | ||
| 4284 | if (doc_reference == 2 && FIXNUMP (XCDR (val))) | ||
| 4285 | { | ||
| 4286 | char *saved = NULL; | ||
| 4287 | file_offset saved_position; | ||
| 4288 | /* Get a doc string from the file we are loading. | ||
| 4289 | If it's in saved_doc_string, get it from there. | ||
| 4290 | |||
| 4291 | Here, we don't know if the string is a | ||
| 4292 | bytecode string or a doc string. As a | ||
| 4293 | bytecode string must be unibyte, we always | ||
| 4294 | return a unibyte string. If it is actually a | ||
| 4295 | doc string, caller must make it | ||
| 4296 | multibyte. */ | ||
| 4297 | |||
| 4298 | /* Position is negative for user variables. */ | ||
| 4299 | EMACS_INT pos = eabs (XFIXNUM (XCDR (val))); | ||
| 4300 | if (pos >= saved_doc_string_position | ||
| 4301 | && pos < (saved_doc_string_position | ||
| 4302 | + saved_doc_string_length)) | ||
| 4303 | { | ||
| 4304 | saved = saved_doc_string; | ||
| 4305 | saved_position = saved_doc_string_position; | ||
| 4306 | } | ||
| 4307 | /* Look in prev_saved_doc_string the same way. */ | ||
| 4308 | else if (pos >= prev_saved_doc_string_position | ||
| 4309 | && pos < (prev_saved_doc_string_position | ||
| 4310 | + prev_saved_doc_string_length)) | ||
| 4311 | { | ||
| 4312 | saved = prev_saved_doc_string; | ||
| 4313 | saved_position = prev_saved_doc_string_position; | ||
| 4314 | } | ||
| 4315 | if (saved) | ||
| 4316 | { | ||
| 4317 | ptrdiff_t start = pos - saved_position; | ||
| 4318 | ptrdiff_t from, to; | ||
| 4319 | |||
| 4320 | /* Process quoting with ^A, | ||
| 4321 | and find the end of the string, | ||
| 4322 | which is marked with ^_ (037). */ | ||
| 4323 | for (from = start, to = start; | ||
| 4324 | saved[from] != 037;) | ||
| 4325 | { | ||
| 4326 | int c = saved[from++]; | ||
| 4327 | if (c == 1) | ||
| 4328 | { | ||
| 4329 | c = saved[from++]; | ||
| 4330 | saved[to++] = (c == 1 ? c | ||
| 4331 | : c == '0' ? 0 | ||
| 4332 | : c == '_' ? 037 | ||
| 4333 | : c); | ||
| 4334 | } | ||
| 4335 | else | ||
| 4336 | saved[to++] = c; | ||
| 4337 | } | ||
| 4338 | |||
| 4339 | return make_unibyte_string (saved + start, | ||
| 4340 | to - start); | ||
| 4341 | } | ||
| 4342 | else | ||
| 4343 | return get_doc_string (val, 1, 0); | ||
| 4344 | } | ||
| 4345 | |||
| 4346 | return val; | ||
| 4347 | } | ||
| 4348 | invalid_syntax (". in wrong context", readcharfun); | ||
| 4349 | } | ||
| 4350 | invalid_syntax ("] in a list", readcharfun); | ||
| 4351 | } | ||
| 4352 | tem = list1 (elt); | ||
| 4353 | if (!NILP (tail)) | ||
| 4354 | XSETCDR (tail, tem); | ||
| 4355 | else | ||
| 4356 | val = tem; | ||
| 4357 | tail = tem; | ||
| 4358 | } | ||
| 4359 | } | ||
| 4360 | |||
| 4361 | static Lisp_Object initial_obarray; | 4564 | static Lisp_Object initial_obarray; |
| 4362 | 4565 | ||
| 4363 | /* `oblookup' stores the bucket number here, for the sake of Funintern. */ | 4566 | /* `oblookup' stores the bucket number here, for the sake of Funintern. */ |
| @@ -4464,7 +4667,7 @@ define_symbol (Lisp_Object sym, char const *str) | |||
| 4464 | 4667 | ||
| 4465 | /* Qunbound is uninterned, so that it's not confused with any symbol | 4668 | /* Qunbound is uninterned, so that it's not confused with any symbol |
| 4466 | 'unbound' created by a Lisp program. */ | 4669 | 'unbound' created by a Lisp program. */ |
| 4467 | if (! EQ (sym, Qunbound)) | 4670 | if (! BASE_EQ (sym, Qunbound)) |
| 4468 | { | 4671 | { |
| 4469 | Lisp_Object bucket = oblookup (initial_obarray, str, len, len); | 4672 | Lisp_Object bucket = oblookup (initial_obarray, str, len, len); |
| 4470 | eassert (FIXNUMP (bucket)); | 4673 | eassert (FIXNUMP (bucket)); |
diff --git a/src/menu.c b/src/menu.c index 398bf9329ff..eeb0c9a7e5b 100644 --- a/src/menu.c +++ b/src/menu.c | |||
| @@ -1118,7 +1118,7 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) | |||
| 1118 | Lisp_Object title; | 1118 | Lisp_Object title; |
| 1119 | const char *error_name = NULL; | 1119 | const char *error_name = NULL; |
| 1120 | Lisp_Object selection = Qnil; | 1120 | Lisp_Object selection = Qnil; |
| 1121 | struct frame *f = NULL; | 1121 | struct frame *f; |
| 1122 | Lisp_Object x, y, window; | 1122 | Lisp_Object x, y, window; |
| 1123 | int menuflags = 0; | 1123 | int menuflags = 0; |
| 1124 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 1124 | specpdl_ref specpdl_count = SPECPDL_INDEX (); |
| @@ -1269,9 +1269,9 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) | |||
| 1269 | } | 1269 | } |
| 1270 | } | 1270 | } |
| 1271 | else | 1271 | else |
| 1272 | /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, | 1272 | /* ??? Not really clean; should be Qwindow_or_framep |
| 1273 | but I don't want to make one now. */ | 1273 | but I don't want to make one now. */ |
| 1274 | CHECK_WINDOW (window); | 1274 | wrong_type_argument (Qwindowp, window); |
| 1275 | 1275 | ||
| 1276 | xpos += check_integer_range (x, | 1276 | xpos += check_integer_range (x, |
| 1277 | (xpos < INT_MIN - MOST_NEGATIVE_FIXNUM | 1277 | (xpos < INT_MIN - MOST_NEGATIVE_FIXNUM |
diff --git a/src/minibuf.c b/src/minibuf.c index df82bcb121a..1f77a6cdc18 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -201,20 +201,12 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion) | |||
| 201 | return; | 201 | return; |
| 202 | if (FRAME_LIVE_P (f) | 202 | if (FRAME_LIVE_P (f) |
| 203 | && !EQ (f->minibuffer_window, of->minibuffer_window) | 203 | && !EQ (f->minibuffer_window, of->minibuffer_window) |
| 204 | && WINDOW_LIVE_P (f->minibuffer_window) /* F not a tootip frame */ | 204 | && WINDOW_LIVE_P (f->minibuffer_window) /* F not a tooltip frame */ |
| 205 | && WINDOW_LIVE_P (of->minibuffer_window)) | 205 | && WINDOW_LIVE_P (of->minibuffer_window)) |
| 206 | { | 206 | { |
| 207 | zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); | 207 | zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); |
| 208 | if (for_deletion && XFRAME (MB_frame) != of) | 208 | if (for_deletion && XFRAME (MB_frame) != of) |
| 209 | MB_frame = selected_frame; | 209 | MB_frame = selected_frame; |
| 210 | if (!for_deletion | ||
| 211 | && MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of)))) | ||
| 212 | { | ||
| 213 | Lisp_Object old_frame; | ||
| 214 | XSETFRAME (old_frame, of); | ||
| 215 | Fset_frame_selected_window (old_frame, | ||
| 216 | Fframe_first_window (old_frame), Qnil); | ||
| 217 | } | ||
| 218 | } | 210 | } |
| 219 | } | 211 | } |
| 220 | 212 | ||
| @@ -265,7 +257,7 @@ without invoking the usual minibuffer commands. */) | |||
| 265 | 257 | ||
| 266 | static void read_minibuf_unwind (void); | 258 | static void read_minibuf_unwind (void); |
| 267 | static void minibuffer_unwind (void); | 259 | static void minibuffer_unwind (void); |
| 268 | static void run_exit_minibuf_hook (void); | 260 | static void run_exit_minibuf_hook (Lisp_Object minibuf); |
| 269 | 261 | ||
| 270 | 262 | ||
| 271 | /* Read a Lisp object from VAL and return it. If VAL is an empty | 263 | /* Read a Lisp object from VAL and return it. If VAL is an empty |
| @@ -749,7 +741,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 749 | separately from read_minibuf_unwind because we need to make sure that | 741 | separately from read_minibuf_unwind because we need to make sure that |
| 750 | read_minibuf_unwind is fully executed even if exit-minibuffer-hook | 742 | read_minibuf_unwind is fully executed even if exit-minibuffer-hook |
| 751 | signals an error. --Stef */ | 743 | signals an error. --Stef */ |
| 752 | record_unwind_protect_void (run_exit_minibuf_hook); | 744 | record_unwind_protect (run_exit_minibuf_hook, minibuffer); |
| 753 | 745 | ||
| 754 | /* Now that we can restore all those variables, start changing them. */ | 746 | /* Now that we can restore all those variables, start changing them. */ |
| 755 | 747 | ||
| @@ -768,7 +760,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 768 | 760 | ||
| 769 | /* If variable is unbound, make it nil. */ | 761 | /* If variable is unbound, make it nil. */ |
| 770 | histval = find_symbol_value (histvar); | 762 | histval = find_symbol_value (histvar); |
| 771 | if (EQ (histval, Qunbound)) | 763 | if (BASE_EQ (histval, Qunbound)) |
| 772 | { | 764 | { |
| 773 | Fset (histvar, Qnil); | 765 | Fset (histvar, Qnil); |
| 774 | histval = Qnil; | 766 | histval = Qnil; |
| @@ -1076,9 +1068,14 @@ static EMACS_INT minibuf_c_loop_level (EMACS_INT depth) | |||
| 1076 | } | 1068 | } |
| 1077 | 1069 | ||
| 1078 | static void | 1070 | static void |
| 1079 | run_exit_minibuf_hook (void) | 1071 | run_exit_minibuf_hook (Lisp_Object minibuf) |
| 1080 | { | 1072 | { |
| 1073 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 1074 | record_unwind_current_buffer (); | ||
| 1075 | if (BUFFER_LIVE_P (XBUFFER (minibuf))) | ||
| 1076 | Fset_buffer (minibuf); | ||
| 1081 | safe_run_hooks (Qminibuffer_exit_hook); | 1077 | safe_run_hooks (Qminibuffer_exit_hook); |
| 1078 | unbind_to (count, Qnil); | ||
| 1082 | } | 1079 | } |
| 1083 | 1080 | ||
| 1084 | /* This variable records the expired minibuffer's frame between the | 1081 | /* This variable records the expired minibuffer's frame between the |
| @@ -1696,7 +1693,8 @@ or from one of the possible completions. */) | |||
| 1696 | else /* if (type == hash_table) */ | 1693 | else /* if (type == hash_table) */ |
| 1697 | { | 1694 | { |
| 1698 | while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) | 1695 | while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) |
| 1699 | && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound)) | 1696 | && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx), |
| 1697 | Qunbound)) | ||
| 1700 | idx++; | 1698 | idx++; |
| 1701 | if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) | 1699 | if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) |
| 1702 | break; | 1700 | break; |
| @@ -1933,7 +1931,8 @@ with a space are ignored unless STRING itself starts with a space. */) | |||
| 1933 | else /* if (type == 3) */ | 1931 | else /* if (type == 3) */ |
| 1934 | { | 1932 | { |
| 1935 | while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) | 1933 | while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) |
| 1936 | && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound)) | 1934 | && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx), |
| 1935 | Qunbound)) | ||
| 1937 | idx++; | 1936 | idx++; |
| 1938 | if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) | 1937 | if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) |
| 1939 | break; | 1938 | break; |
| @@ -2012,6 +2011,8 @@ REQUIRE-MATCH can take the following values: | |||
| 2012 | input, but she needs to confirm her choice if she called | 2011 | input, but she needs to confirm her choice if she called |
| 2013 | `minibuffer-complete' right before `minibuffer-complete-and-exit' | 2012 | `minibuffer-complete' right before `minibuffer-complete-and-exit' |
| 2014 | and the input is not an element of COLLECTION. | 2013 | and the input is not an element of COLLECTION. |
| 2014 | - a function, which will be called with the input as the parameter. | ||
| 2015 | If it returns a non-nil value, the minibuffer is exited with that value. | ||
| 2015 | - anything else behaves like t except that typing RET does not exit if it | 2016 | - anything else behaves like t except that typing RET does not exit if it |
| 2016 | does non-null completion. | 2017 | does non-null completion. |
| 2017 | 2018 | ||
| @@ -2140,7 +2141,7 @@ the values STRING, PREDICATE and `lambda'. */) | |||
| 2140 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) | 2141 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 2141 | { | 2142 | { |
| 2142 | tem = HASH_KEY (h, i); | 2143 | tem = HASH_KEY (h, i); |
| 2143 | if (EQ (tem, Qunbound)) continue; | 2144 | if (BASE_EQ (tem, Qunbound)) continue; |
| 2144 | Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); | 2145 | Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); |
| 2145 | if (!STRINGP (strkey)) continue; | 2146 | if (!STRINGP (strkey)) continue; |
| 2146 | if (EQ (Fcompare_strings (string, Qnil, Qnil, | 2147 | if (EQ (Fcompare_strings (string, Qnil, Qnil, |
diff --git a/src/nsfns.m b/src/nsfns.m index a67dafe0950..5ab2b2ee35a 100644 --- a/src/nsfns.m +++ b/src/nsfns.m | |||
| @@ -47,12 +47,42 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) | |||
| 47 | #ifdef NS_IMPL_COCOA | 47 | #ifdef NS_IMPL_COCOA |
| 48 | #include <IOKit/graphics/IOGraphicsLib.h> | 48 | #include <IOKit/graphics/IOGraphicsLib.h> |
| 49 | #include "macfont.h" | 49 | #include "macfont.h" |
| 50 | |||
| 51 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 | ||
| 52 | #include <UniformTypeIdentifiers/UniformTypeIdentifiers.h> | ||
| 53 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 120000 | ||
| 54 | #define IOMasterPort IOMainPort | ||
| 55 | #endif | ||
| 56 | #endif | ||
| 50 | #endif | 57 | #endif |
| 51 | 58 | ||
| 52 | #ifdef HAVE_NS | 59 | #ifdef HAVE_NS |
| 53 | 60 | ||
| 54 | static EmacsTooltip *ns_tooltip = nil; | 61 | static EmacsTooltip *ns_tooltip = nil; |
| 55 | 62 | ||
| 63 | /* The frame of the currently visible tooltip, or nil if none. */ | ||
| 64 | static Lisp_Object tip_frame; | ||
| 65 | |||
| 66 | /* The X and Y deltas of the last call to `x-show-tip'. */ | ||
| 67 | static Lisp_Object tip_dx, tip_dy; | ||
| 68 | |||
| 69 | /* The window-system window corresponding to the frame of the | ||
| 70 | currently visible tooltip. */ | ||
| 71 | static NSWindow *tip_window; | ||
| 72 | |||
| 73 | /* A timer that hides or deletes the currently visible tooltip when it | ||
| 74 | fires. */ | ||
| 75 | static Lisp_Object tip_timer; | ||
| 76 | |||
| 77 | /* STRING argument of last `x-show-tip' call. */ | ||
| 78 | static Lisp_Object tip_last_string; | ||
| 79 | |||
| 80 | /* Normalized FRAME argument of last `x-show-tip' call. */ | ||
| 81 | static Lisp_Object tip_last_frame; | ||
| 82 | |||
| 83 | /* PARMS argument of last `x-show-tip' call. */ | ||
| 84 | static Lisp_Object tip_last_parms; | ||
| 85 | |||
| 56 | /* Static variables to handle AppleScript execution. */ | 86 | /* Static variables to handle AppleScript execution. */ |
| 57 | static Lisp_Object as_script, *as_result; | 87 | static Lisp_Object as_script, *as_result; |
| 58 | static int as_status; | 88 | static int as_status; |
| @@ -769,11 +799,13 @@ ns_implicitly_set_icon_type (struct frame *f) | |||
| 769 | Lisp_Object chain, elt; | 799 | Lisp_Object chain, elt; |
| 770 | NSAutoreleasePool *pool; | 800 | NSAutoreleasePool *pool; |
| 771 | BOOL setMini = YES; | 801 | BOOL setMini = YES; |
| 802 | NSWorkspace *workspace; | ||
| 772 | 803 | ||
| 773 | NSTRACE ("ns_implicitly_set_icon_type"); | 804 | NSTRACE ("ns_implicitly_set_icon_type"); |
| 774 | 805 | ||
| 775 | block_input (); | 806 | block_input (); |
| 776 | pool = [[NSAutoreleasePool alloc] init]; | 807 | pool = [[NSAutoreleasePool alloc] init]; |
| 808 | workspace = [NSWorkspace sharedWorkspace]; | ||
| 777 | if (f->output_data.ns->miniimage | 809 | if (f->output_data.ns->miniimage |
| 778 | && [[NSString stringWithLispString:f->name] | 810 | && [[NSString stringWithLispString:f->name] |
| 779 | isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]]) | 811 | isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]]) |
| @@ -818,7 +850,21 @@ ns_implicitly_set_icon_type (struct frame *f) | |||
| 818 | 850 | ||
| 819 | if (image == nil) | 851 | if (image == nil) |
| 820 | { | 852 | { |
| 821 | image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain]; | 853 | #ifndef NS_IMPL_GNUSTEP |
| 854 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 | ||
| 855 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 856 | if ([workspace respondsToSelector: @selector (iconForContentType:)]) | ||
| 857 | #endif | ||
| 858 | image = [[workspace iconForContentType: | ||
| 859 | [UTType typeWithIdentifier: @"text"]] retain]; | ||
| 860 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 861 | else | ||
| 862 | #endif | ||
| 863 | #endif | ||
| 864 | #endif | ||
| 865 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 866 | image = [[workspace iconForFileType: @"text"] retain]; | ||
| 867 | #endif | ||
| 822 | setMini = NO; | 868 | setMini = NO; |
| 823 | } | 869 | } |
| 824 | 870 | ||
| @@ -1021,7 +1067,7 @@ frame_parm_handler ns_frame_parm_handlers[] = | |||
| 1021 | /* Handler for signals raised during x_create_frame. | 1067 | /* Handler for signals raised during x_create_frame. |
| 1022 | FRAME is the frame which is partially constructed. */ | 1068 | FRAME is the frame which is partially constructed. */ |
| 1023 | 1069 | ||
| 1024 | static void | 1070 | static Lisp_Object |
| 1025 | unwind_create_frame (Lisp_Object frame) | 1071 | unwind_create_frame (Lisp_Object frame) |
| 1026 | { | 1072 | { |
| 1027 | struct frame *f = XFRAME (frame); | 1073 | struct frame *f = XFRAME (frame); |
| @@ -1030,7 +1076,7 @@ unwind_create_frame (Lisp_Object frame) | |||
| 1030 | display is disconnected after the frame has become official, but | 1076 | display is disconnected after the frame has become official, but |
| 1031 | before x_create_frame removes the unwind protect. */ | 1077 | before x_create_frame removes the unwind protect. */ |
| 1032 | if (!FRAME_LIVE_P (f)) | 1078 | if (!FRAME_LIVE_P (f)) |
| 1033 | return; | 1079 | return Qnil; |
| 1034 | 1080 | ||
| 1035 | /* If frame is ``official'', nothing to do. */ | 1081 | /* If frame is ``official'', nothing to do. */ |
| 1036 | if (NILP (Fmemq (frame, Vframe_list))) | 1082 | if (NILP (Fmemq (frame, Vframe_list))) |
| @@ -1057,7 +1103,18 @@ unwind_create_frame (Lisp_Object frame) | |||
| 1057 | /* Check that reference counts are indeed correct. */ | 1103 | /* Check that reference counts are indeed correct. */ |
| 1058 | eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount); | 1104 | eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount); |
| 1059 | #endif | 1105 | #endif |
| 1106 | |||
| 1107 | return Qt; | ||
| 1060 | } | 1108 | } |
| 1109 | |||
| 1110 | return Qnil; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | |||
| 1114 | static void | ||
| 1115 | do_unwind_create_frame (Lisp_Object frame) | ||
| 1116 | { | ||
| 1117 | unwind_create_frame (frame); | ||
| 1061 | } | 1118 | } |
| 1062 | 1119 | ||
| 1063 | /* | 1120 | /* |
| @@ -1191,7 +1248,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 1191 | FRAME_DISPLAY_INFO (f) = dpyinfo; | 1248 | FRAME_DISPLAY_INFO (f) = dpyinfo; |
| 1192 | 1249 | ||
| 1193 | /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ | 1250 | /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ |
| 1194 | record_unwind_protect (unwind_create_frame, frame); | 1251 | record_unwind_protect (do_unwind_create_frame, frame); |
| 1195 | 1252 | ||
| 1196 | f->output_data.ns->window_desc = desc_ctr++; | 1253 | f->output_data.ns->window_desc = desc_ctr++; |
| 1197 | if (TYPE_RANGED_FIXNUMP (Window, parent)) | 1254 | if (TYPE_RANGED_FIXNUMP (Window, parent)) |
| @@ -1726,7 +1783,20 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) | |||
| 1726 | ns_fd_data.ret = NO; | 1783 | ns_fd_data.ret = NO; |
| 1727 | #ifdef NS_IMPL_COCOA | 1784 | #ifdef NS_IMPL_COCOA |
| 1728 | if (! NILP (mustmatch) || ! NILP (dir_only_p)) | 1785 | if (! NILP (mustmatch) || ! NILP (dir_only_p)) |
| 1729 | [panel setAllowedFileTypes: nil]; | 1786 | { |
| 1787 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 | ||
| 1788 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 1789 | if ([panel respondsToSelector: @selector (setAllowedContentTypes:)]) | ||
| 1790 | #endif | ||
| 1791 | [panel setAllowedContentTypes: [NSArray array]]; | ||
| 1792 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 1793 | else | ||
| 1794 | #endif | ||
| 1795 | #endif | ||
| 1796 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 | ||
| 1797 | [panel setAllowedFileTypes: nil]; | ||
| 1798 | #endif | ||
| 1799 | } | ||
| 1730 | if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]]; | 1800 | if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]]; |
| 1731 | if (initS && NILP (Ffile_directory_p (init))) | 1801 | if (initS && NILP (Ffile_directory_p (init))) |
| 1732 | [panel setNameFieldStringValue: [initS lastPathComponent]]; | 1802 | [panel setNameFieldStringValue: [initS lastPathComponent]]; |
| @@ -1792,7 +1862,7 @@ ns_get_defaults_value (const char *key) | |||
| 1792 | DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0, | 1862 | DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0, |
| 1793 | doc: /* Return the value of the property NAME of OWNER from the defaults database. | 1863 | doc: /* Return the value of the property NAME of OWNER from the defaults database. |
| 1794 | If OWNER is nil, Emacs is assumed. */) | 1864 | If OWNER is nil, Emacs is assumed. */) |
| 1795 | (Lisp_Object owner, Lisp_Object name) | 1865 | (Lisp_Object owner, Lisp_Object name) |
| 1796 | { | 1866 | { |
| 1797 | const char *value; | 1867 | const char *value; |
| 1798 | 1868 | ||
| @@ -1813,7 +1883,7 @@ DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0, | |||
| 1813 | doc: /* Set property NAME of OWNER to VALUE, from the defaults database. | 1883 | doc: /* Set property NAME of OWNER to VALUE, from the defaults database. |
| 1814 | If OWNER is nil, Emacs is assumed. | 1884 | If OWNER is nil, Emacs is assumed. |
| 1815 | If VALUE is nil, the default is removed. */) | 1885 | If VALUE is nil, the default is removed. */) |
| 1816 | (Lisp_Object owner, Lisp_Object name, Lisp_Object value) | 1886 | (Lisp_Object owner, Lisp_Object name, Lisp_Object value) |
| 1817 | { | 1887 | { |
| 1818 | check_window_system (NULL); | 1888 | check_window_system (NULL); |
| 1819 | if (NILP (owner)) | 1889 | if (NILP (owner)) |
| @@ -1840,7 +1910,7 @@ DEFUN ("x-server-max-request-size", Fx_server_max_request_size, | |||
| 1840 | Sx_server_max_request_size, | 1910 | Sx_server_max_request_size, |
| 1841 | 0, 1, 0, | 1911 | 0, 1, 0, |
| 1842 | doc: /* SKIP: real doc in xfns.c. */) | 1912 | doc: /* SKIP: real doc in xfns.c. */) |
| 1843 | (Lisp_Object terminal) | 1913 | (Lisp_Object terminal) |
| 1844 | { | 1914 | { |
| 1845 | check_ns_display_info (terminal); | 1915 | check_ns_display_info (terminal); |
| 1846 | /* This function has no real equivalent under Nextstep. Return nil to | 1916 | /* This function has no real equivalent under Nextstep. Return nil to |
| @@ -2702,7 +2772,8 @@ Internal use only, use `display-monitor-attributes-list' instead. */) | |||
| 2702 | } | 2772 | } |
| 2703 | else | 2773 | else |
| 2704 | { | 2774 | { |
| 2705 | // Flip y coordinate as NS has y starting from the bottom. | 2775 | /* Flip y coordinate as NS screen coordinates originate from |
| 2776 | the bottom. */ | ||
| 2706 | y = (short) (primary_display_height - fr.size.height - fr.origin.y); | 2777 | y = (short) (primary_display_height - fr.size.height - fr.origin.y); |
| 2707 | vy = (short) (primary_display_height - | 2778 | vy = (short) (primary_display_height - |
| 2708 | vfr.size.height - vfr.origin.y); | 2779 | vfr.size.height - vfr.origin.y); |
| @@ -2714,11 +2785,12 @@ Internal use only, use `display-monitor-attributes-list' instead. */) | |||
| 2714 | m->geom.height = (unsigned short) fr.size.height; | 2785 | m->geom.height = (unsigned short) fr.size.height; |
| 2715 | 2786 | ||
| 2716 | m->work.x = (short) vfr.origin.x; | 2787 | m->work.x = (short) vfr.origin.x; |
| 2717 | // y is flipped on NS, so vy - y are pixels missing at the bottom, | 2788 | /* y is flipped on NS, so vy - y are pixels missing at the |
| 2718 | // and fr.size.height - vfr.size.height are pixels missing in total. | 2789 | bottom, and fr.size.height - vfr.size.height are pixels |
| 2719 | // Pixels missing at top are | 2790 | missing in total. |
| 2720 | // fr.size.height - vfr.size.height - vy + y. | 2791 | |
| 2721 | // work.y is then pixels missing at top + y. | 2792 | Pixels missing at top are fr.size.height - vfr.size.height - |
| 2793 | vy + y. work.y is then pixels missing at top + y. */ | ||
| 2722 | m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y; | 2794 | m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y; |
| 2723 | m->work.width = (unsigned short) vfr.size.width; | 2795 | m->work.width = (unsigned short) vfr.size.width; |
| 2724 | m->work.height = (unsigned short) vfr.size.height; | 2796 | m->work.height = (unsigned short) vfr.size.height; |
| @@ -2733,13 +2805,14 @@ Internal use only, use `display-monitor-attributes-list' instead. */) | |||
| 2733 | } | 2805 | } |
| 2734 | 2806 | ||
| 2735 | #else | 2807 | #else |
| 2736 | // Assume 92 dpi as x-display-mm-height/x-display-mm-width does. | 2808 | /* Assume 92 dpi as x-display-mm-height and x-display-mm-width |
| 2809 | do. */ | ||
| 2737 | m->mm_width = (int) (25.4 * fr.size.width / 92.0); | 2810 | m->mm_width = (int) (25.4 * fr.size.width / 92.0); |
| 2738 | m->mm_height = (int) (25.4 * fr.size.height / 92.0); | 2811 | m->mm_height = (int) (25.4 * fr.size.height / 92.0); |
| 2739 | #endif | 2812 | #endif |
| 2740 | } | 2813 | } |
| 2741 | 2814 | ||
| 2742 | // Primary monitor is always first for NS. | 2815 | /* Primary monitor is always ordered first for NS. */ |
| 2743 | attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors, | 2816 | attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors, |
| 2744 | 0, "NS"); | 2817 | 0, "NS"); |
| 2745 | 2818 | ||
| @@ -2769,16 +2842,10 @@ DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, | |||
| 2769 | return make_fixnum (1 << min (dpyinfo->n_planes, 24)); | 2842 | return make_fixnum (1 << min (dpyinfo->n_planes, 24)); |
| 2770 | } | 2843 | } |
| 2771 | 2844 | ||
| 2772 | /* TODO: move to xdisp or similar */ | ||
| 2773 | static void | 2845 | static void |
| 2774 | compute_tip_xy (struct frame *f, | 2846 | compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, |
| 2775 | Lisp_Object parms, | 2847 | Lisp_Object dy, int width, int height, int *root_x, |
| 2776 | Lisp_Object dx, | 2848 | int *root_y) |
| 2777 | Lisp_Object dy, | ||
| 2778 | int width, | ||
| 2779 | int height, | ||
| 2780 | int *root_x, | ||
| 2781 | int *root_y) | ||
| 2782 | { | 2849 | { |
| 2783 | Lisp_Object left, top, right, bottom; | 2850 | Lisp_Object left, top, right, bottom; |
| 2784 | NSPoint pt; | 2851 | NSPoint pt; |
| @@ -2847,6 +2914,299 @@ compute_tip_xy (struct frame *f, | |||
| 2847 | *root_y = screen.frame.origin.y + screen.frame.size.height - height; | 2914 | *root_y = screen.frame.origin.y + screen.frame.size.height - height; |
| 2848 | } | 2915 | } |
| 2849 | 2916 | ||
| 2917 | static void | ||
| 2918 | unwind_create_tip_frame (Lisp_Object frame) | ||
| 2919 | { | ||
| 2920 | Lisp_Object deleted; | ||
| 2921 | |||
| 2922 | deleted = unwind_create_frame (frame); | ||
| 2923 | if (EQ (deleted, Qt)) | ||
| 2924 | { | ||
| 2925 | tip_window = NULL; | ||
| 2926 | tip_frame = Qnil; | ||
| 2927 | } | ||
| 2928 | } | ||
| 2929 | |||
| 2930 | /* Create a frame for a tooltip on the display described by DPYINFO. | ||
| 2931 | PARMS is a list of frame parameters. TEXT is the string to | ||
| 2932 | display in the tip frame. Value is the frame. | ||
| 2933 | |||
| 2934 | Note that functions called here, esp. gui_default_parameter can | ||
| 2935 | signal errors, for instance when a specified color name is | ||
| 2936 | undefined. We have to make sure that we're in a consistent state | ||
| 2937 | when this happens. */ | ||
| 2938 | |||
| 2939 | static Lisp_Object | ||
| 2940 | ns_create_tip_frame (struct ns_display_info *dpyinfo, Lisp_Object parms) | ||
| 2941 | { | ||
| 2942 | struct frame *f; | ||
| 2943 | Lisp_Object frame; | ||
| 2944 | Lisp_Object name; | ||
| 2945 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 2946 | bool face_change_before = face_change; | ||
| 2947 | |||
| 2948 | if (!dpyinfo->terminal->name) | ||
| 2949 | error ("Terminal is not live, can't create new frames on it"); | ||
| 2950 | |||
| 2951 | parms = Fcopy_alist (parms); | ||
| 2952 | |||
| 2953 | /* Get the name of the frame to use for resource lookup. */ | ||
| 2954 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | ||
| 2955 | RES_TYPE_STRING); | ||
| 2956 | if (!STRINGP (name) | ||
| 2957 | && !EQ (name, Qunbound) | ||
| 2958 | && !NILP (name)) | ||
| 2959 | error ("Invalid frame name--not a string or nil"); | ||
| 2960 | |||
| 2961 | frame = Qnil; | ||
| 2962 | f = make_frame (false); | ||
| 2963 | f->wants_modeline = false; | ||
| 2964 | XSETFRAME (frame, f); | ||
| 2965 | record_unwind_protect (unwind_create_tip_frame, frame); | ||
| 2966 | |||
| 2967 | f->terminal = dpyinfo->terminal; | ||
| 2968 | |||
| 2969 | f->output_method = output_ns; | ||
| 2970 | f->output_data.ns = xzalloc (sizeof *f->output_data.ns); | ||
| 2971 | f->tooltip = true; | ||
| 2972 | |||
| 2973 | FRAME_FONTSET (f) = -1; | ||
| 2974 | FRAME_DISPLAY_INFO (f) = dpyinfo; | ||
| 2975 | |||
| 2976 | block_input (); | ||
| 2977 | #ifdef NS_IMPL_COCOA | ||
| 2978 | mac_register_font_driver (f); | ||
| 2979 | #else | ||
| 2980 | register_font_driver (&nsfont_driver, f); | ||
| 2981 | #endif | ||
| 2982 | unblock_input (); | ||
| 2983 | |||
| 2984 | image_cache_refcount = | ||
| 2985 | FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; | ||
| 2986 | |||
| 2987 | gui_default_parameter (f, parms, Qfont_backend, Qnil, | ||
| 2988 | "fontBackend", "FontBackend", RES_TYPE_STRING); | ||
| 2989 | |||
| 2990 | { | ||
| 2991 | #ifdef NS_IMPL_COCOA | ||
| 2992 | /* use for default font name */ | ||
| 2993 | id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */ | ||
| 2994 | gui_default_parameter (f, parms, Qfontsize, | ||
| 2995 | make_fixnum (0 /* (int)[font pointSize] */), | ||
| 2996 | "fontSize", "FontSize", RES_TYPE_NUMBER); | ||
| 2997 | // Remove ' Regular', not handled by backends. | ||
| 2998 | char *fontname = xstrdup ([[font displayName] UTF8String]); | ||
| 2999 | int len = strlen (fontname); | ||
| 3000 | if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0) | ||
| 3001 | fontname[len-8] = '\0'; | ||
| 3002 | gui_default_parameter (f, parms, Qfont, | ||
| 3003 | build_string (fontname), | ||
| 3004 | "font", "Font", RES_TYPE_STRING); | ||
| 3005 | xfree (fontname); | ||
| 3006 | #else | ||
| 3007 | gui_default_parameter (f, parms, Qfont, | ||
| 3008 | build_string ("fixed"), | ||
| 3009 | "font", "Font", RES_TYPE_STRING); | ||
| 3010 | #endif | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), | ||
| 3014 | "borderWidth", "BorderWidth", RES_TYPE_NUMBER); | ||
| 3015 | |||
| 3016 | /* This defaults to 1 in order to match xterm. We recognize either | ||
| 3017 | internalBorderWidth or internalBorder (which is what xterm calls | ||
| 3018 | it). */ | ||
| 3019 | if (NILP (Fassq (Qinternal_border_width, parms))) | ||
| 3020 | { | ||
| 3021 | Lisp_Object value; | ||
| 3022 | |||
| 3023 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | ||
| 3024 | "internalBorder", "internalBorder", | ||
| 3025 | RES_TYPE_NUMBER); | ||
| 3026 | if (! EQ (value, Qunbound)) | ||
| 3027 | parms = Fcons (Fcons (Qinternal_border_width, value), | ||
| 3028 | parms); | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1), | ||
| 3032 | "internalBorderWidth", "internalBorderWidth", | ||
| 3033 | RES_TYPE_NUMBER); | ||
| 3034 | gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), | ||
| 3035 | NULL, NULL, RES_TYPE_NUMBER); | ||
| 3036 | gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), | ||
| 3037 | NULL, NULL, RES_TYPE_NUMBER); | ||
| 3038 | |||
| 3039 | /* Also do the stuff which must be set before the window exists. */ | ||
| 3040 | gui_default_parameter (f, parms, Qforeground_color, build_string ("black"), | ||
| 3041 | "foreground", "Foreground", RES_TYPE_STRING); | ||
| 3042 | gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), | ||
| 3043 | "background", "Background", RES_TYPE_STRING); | ||
| 3044 | gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), | ||
| 3045 | "pointerColor", "Foreground", RES_TYPE_STRING); | ||
| 3046 | gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), | ||
| 3047 | "cursorColor", "Foreground", RES_TYPE_STRING); | ||
| 3048 | gui_default_parameter (f, parms, Qborder_color, build_string ("black"), | ||
| 3049 | "borderColor", "BorderColor", RES_TYPE_STRING); | ||
| 3050 | gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, | ||
| 3051 | NULL, NULL, RES_TYPE_BOOLEAN); | ||
| 3052 | |||
| 3053 | /* Init faces before gui_default_parameter is called for the | ||
| 3054 | scroll-bar-width parameter because otherwise we end up in | ||
| 3055 | init_iterator with a null face cache, which should not happen. */ | ||
| 3056 | init_frame_faces (f); | ||
| 3057 | |||
| 3058 | f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; | ||
| 3059 | |||
| 3060 | gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, | ||
| 3061 | "inhibitDoubleBuffering", "InhibitDoubleBuffering", | ||
| 3062 | RES_TYPE_BOOLEAN); | ||
| 3063 | |||
| 3064 | gui_figure_window_size (f, parms, false, false); | ||
| 3065 | |||
| 3066 | block_input (); | ||
| 3067 | [[EmacsView alloc] initFrameFromEmacs: f]; | ||
| 3068 | ns_icon (f, parms); | ||
| 3069 | unblock_input (); | ||
| 3070 | |||
| 3071 | gui_default_parameter (f, parms, Qauto_raise, Qnil, | ||
| 3072 | "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); | ||
| 3073 | gui_default_parameter (f, parms, Qauto_lower, Qnil, | ||
| 3074 | "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); | ||
| 3075 | gui_default_parameter (f, parms, Qcursor_type, Qbox, | ||
| 3076 | "cursorType", "CursorType", RES_TYPE_SYMBOL); | ||
| 3077 | gui_default_parameter (f, parms, Qalpha, Qnil, | ||
| 3078 | "alpha", "Alpha", RES_TYPE_NUMBER); | ||
| 3079 | |||
| 3080 | /* Add `tooltip' frame parameter's default value. */ | ||
| 3081 | if (NILP (Fframe_parameter (frame, Qtooltip))) | ||
| 3082 | { | ||
| 3083 | AUTO_FRAME_ARG (arg, Qtooltip, Qt); | ||
| 3084 | Fmodify_frame_parameters (frame, arg); | ||
| 3085 | } | ||
| 3086 | |||
| 3087 | /* FIXME - can this be done in a similar way to normal frames? | ||
| 3088 | https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */ | ||
| 3089 | |||
| 3090 | /* Set the `display-type' frame parameter before setting up faces. */ | ||
| 3091 | { | ||
| 3092 | Lisp_Object disptype = intern ("color"); | ||
| 3093 | |||
| 3094 | if (NILP (Fframe_parameter (frame, Qdisplay_type))) | ||
| 3095 | { | ||
| 3096 | AUTO_FRAME_ARG (arg, Qdisplay_type, disptype); | ||
| 3097 | Fmodify_frame_parameters (frame, arg); | ||
| 3098 | } | ||
| 3099 | } | ||
| 3100 | |||
| 3101 | /* Set up faces after all frame parameters are known. This call | ||
| 3102 | also merges in face attributes specified for new frames. | ||
| 3103 | |||
| 3104 | Frame parameters may be changed if .Xdefaults contains | ||
| 3105 | specifications for the default font. For example, if there is an | ||
| 3106 | `Emacs.default.attributeBackground: pink', the `background-color' | ||
| 3107 | attribute of the frame gets set, which let's the internal border | ||
| 3108 | of the tooltip frame appear in pink. Prevent this. */ | ||
| 3109 | { | ||
| 3110 | Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); | ||
| 3111 | |||
| 3112 | call2 (Qface_set_after_frame_default, frame, Qnil); | ||
| 3113 | |||
| 3114 | if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) | ||
| 3115 | { | ||
| 3116 | AUTO_FRAME_ARG (arg, Qbackground_color, bg); | ||
| 3117 | Fmodify_frame_parameters (frame, arg); | ||
| 3118 | } | ||
| 3119 | } | ||
| 3120 | |||
| 3121 | f->no_split = true; | ||
| 3122 | |||
| 3123 | /* Now that the frame will be official, it counts as a reference to | ||
| 3124 | its display and terminal. */ | ||
| 3125 | f->terminal->reference_count++; | ||
| 3126 | |||
| 3127 | /* It is now ok to make the frame official even if we get an error | ||
| 3128 | below. And the frame needs to be on Vframe_list or making it | ||
| 3129 | visible won't work. */ | ||
| 3130 | Vframe_list = Fcons (frame, Vframe_list); | ||
| 3131 | f->can_set_window_size = true; | ||
| 3132 | adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), | ||
| 3133 | 0, true, Qtip_frame); | ||
| 3134 | |||
| 3135 | /* Setting attributes of faces of the tooltip frame from resources | ||
| 3136 | and similar will set face_change, which leads to the clearing of | ||
| 3137 | all current matrices. Since this isn't necessary here, avoid it | ||
| 3138 | by resetting face_change to the value it had before we created | ||
| 3139 | the tip frame. */ | ||
| 3140 | face_change = face_change_before; | ||
| 3141 | |||
| 3142 | /* Discard the unwind_protect. */ | ||
| 3143 | return unbind_to (count, frame); | ||
| 3144 | } | ||
| 3145 | |||
| 3146 | static Lisp_Object | ||
| 3147 | x_hide_tip (bool delete) | ||
| 3148 | { | ||
| 3149 | if (!NILP (tip_timer)) | ||
| 3150 | { | ||
| 3151 | call1 (intern ("cancel-timer"), tip_timer); | ||
| 3152 | tip_timer = Qnil; | ||
| 3153 | } | ||
| 3154 | |||
| 3155 | if (!(ns_tooltip == nil || ![ns_tooltip isActive])) | ||
| 3156 | { | ||
| 3157 | [ns_tooltip hide]; | ||
| 3158 | tip_last_frame = Qnil; | ||
| 3159 | return Qt; | ||
| 3160 | } | ||
| 3161 | |||
| 3162 | if ((NILP (tip_last_frame) && NILP (tip_frame)) | ||
| 3163 | || (!use_system_tooltips | ||
| 3164 | && !delete | ||
| 3165 | && !NILP (tip_frame) | ||
| 3166 | && FRAME_LIVE_P (XFRAME (tip_frame)) | ||
| 3167 | && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) | ||
| 3168 | /* Either there's no tooltip to hide or it's an already invisible | ||
| 3169 | Emacs tooltip and we don't want to change its type. Return | ||
| 3170 | quickly. */ | ||
| 3171 | return Qnil; | ||
| 3172 | else | ||
| 3173 | { | ||
| 3174 | specpdl_ref count; | ||
| 3175 | Lisp_Object was_open = Qnil; | ||
| 3176 | |||
| 3177 | count = SPECPDL_INDEX (); | ||
| 3178 | specbind (Qinhibit_redisplay, Qt); | ||
| 3179 | specbind (Qinhibit_quit, Qt); | ||
| 3180 | |||
| 3181 | /* Now look whether there's an Emacs tip around. */ | ||
| 3182 | if (!NILP (tip_frame)) | ||
| 3183 | { | ||
| 3184 | struct frame *f = XFRAME (tip_frame); | ||
| 3185 | |||
| 3186 | if (FRAME_LIVE_P (f)) | ||
| 3187 | { | ||
| 3188 | if (delete || use_system_tooltips) | ||
| 3189 | { | ||
| 3190 | /* Delete the Emacs tooltip frame when DELETE is true | ||
| 3191 | or we change the tooltip type from an Emacs one to | ||
| 3192 | a GTK+ system one. */ | ||
| 3193 | delete_frame (tip_frame, Qnil); | ||
| 3194 | tip_frame = Qnil; | ||
| 3195 | } | ||
| 3196 | else | ||
| 3197 | ns_make_frame_invisible (f); | ||
| 3198 | |||
| 3199 | was_open = Qt; | ||
| 3200 | } | ||
| 3201 | else | ||
| 3202 | tip_frame = Qnil; | ||
| 3203 | } | ||
| 3204 | else | ||
| 3205 | tip_frame = Qnil; | ||
| 3206 | |||
| 3207 | return unbind_to (count, was_open); | ||
| 3208 | } | ||
| 3209 | } | ||
| 2850 | 3210 | ||
| 2851 | DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, | 3211 | DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, |
| 2852 | doc: /* SKIP: real doc in xfns.c. */) | 3212 | doc: /* SKIP: real doc in xfns.c. */) |
| @@ -2854,11 +3214,18 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, | |||
| 2854 | { | 3214 | { |
| 2855 | int root_x, root_y; | 3215 | int root_x, root_y; |
| 2856 | specpdl_ref count = SPECPDL_INDEX (); | 3216 | specpdl_ref count = SPECPDL_INDEX (); |
| 2857 | struct frame *f; | 3217 | struct frame *f, *tip_f; |
| 3218 | struct window *w; | ||
| 3219 | struct buffer *old_buffer; | ||
| 3220 | struct text_pos pos; | ||
| 3221 | int width, height; | ||
| 3222 | int old_windows_or_buffers_changed = windows_or_buffers_changed; | ||
| 3223 | specpdl_ref count_1; | ||
| 3224 | Lisp_Object window, size, tip_buf; | ||
| 2858 | char *str; | 3225 | char *str; |
| 2859 | NSSize size; | 3226 | NSWindow *nswindow; |
| 2860 | NSColor *color; | 3227 | |
| 2861 | Lisp_Object t; | 3228 | AUTO_STRING (tip, " *tip*"); |
| 2862 | 3229 | ||
| 2863 | specbind (Qinhibit_redisplay, Qt); | 3230 | specbind (Qinhibit_redisplay, Qt); |
| 2864 | 3231 | ||
| @@ -2879,32 +3246,253 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, | |||
| 2879 | else | 3246 | else |
| 2880 | CHECK_FIXNUM (dy); | 3247 | CHECK_FIXNUM (dy); |
| 2881 | 3248 | ||
| 2882 | block_input (); | 3249 | tip_dx = dx; |
| 2883 | if (ns_tooltip == nil) | 3250 | tip_dy = dy; |
| 2884 | ns_tooltip = [[EmacsTooltip alloc] init]; | 3251 | |
| 3252 | if (use_system_tooltips) | ||
| 3253 | { | ||
| 3254 | NSSize size; | ||
| 3255 | NSColor *color; | ||
| 3256 | Lisp_Object t; | ||
| 3257 | |||
| 3258 | block_input (); | ||
| 3259 | if (ns_tooltip == nil) | ||
| 3260 | ns_tooltip = [[EmacsTooltip alloc] init]; | ||
| 3261 | else | ||
| 3262 | Fx_hide_tip (); | ||
| 3263 | |||
| 3264 | t = gui_display_get_arg (NULL, parms, Qbackground_color, NULL, NULL, | ||
| 3265 | RES_TYPE_STRING); | ||
| 3266 | if (ns_lisp_to_color (t, &color) == 0) | ||
| 3267 | [ns_tooltip setBackgroundColor: color]; | ||
| 3268 | |||
| 3269 | t = gui_display_get_arg (NULL, parms, Qforeground_color, NULL, NULL, | ||
| 3270 | RES_TYPE_STRING); | ||
| 3271 | if (ns_lisp_to_color (t, &color) == 0) | ||
| 3272 | [ns_tooltip setForegroundColor: color]; | ||
| 3273 | |||
| 3274 | [ns_tooltip setText: str]; | ||
| 3275 | size = [ns_tooltip frame].size; | ||
| 3276 | |||
| 3277 | /* Move the tooltip window where the mouse pointer is. Resize and | ||
| 3278 | show it. */ | ||
| 3279 | compute_tip_xy (f, parms, dx, dy, (int) size.width, (int) size.height, | ||
| 3280 | &root_x, &root_y); | ||
| 3281 | |||
| 3282 | [ns_tooltip showAtX: root_x Y: root_y for: XFIXNUM (timeout)]; | ||
| 3283 | unblock_input (); | ||
| 3284 | } | ||
| 2885 | else | 3285 | else |
| 2886 | Fx_hide_tip (); | 3286 | { |
| 3287 | if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) | ||
| 3288 | { | ||
| 3289 | if (FRAME_VISIBLE_P (XFRAME (tip_frame)) | ||
| 3290 | && EQ (frame, tip_last_frame) | ||
| 3291 | && !NILP (Fequal_including_properties (tip_last_string, string)) | ||
| 3292 | && !NILP (Fequal (tip_last_parms, parms))) | ||
| 3293 | { | ||
| 3294 | /* Only DX and DY have changed. */ | ||
| 3295 | tip_f = XFRAME (tip_frame); | ||
| 3296 | if (!NILP (tip_timer)) | ||
| 3297 | { | ||
| 3298 | call1 (intern ("cancel-timer"), tip_timer); | ||
| 3299 | tip_timer = Qnil; | ||
| 3300 | } | ||
| 3301 | |||
| 3302 | nswindow = [FRAME_NS_VIEW (tip_f) window]; | ||
| 3303 | |||
| 3304 | block_input (); | ||
| 3305 | compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), | ||
| 3306 | FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y); | ||
| 3307 | [nswindow setFrame: NSMakeRect (root_x, root_y, | ||
| 3308 | FRAME_PIXEL_WIDTH (tip_f), | ||
| 3309 | FRAME_PIXEL_HEIGHT (tip_f)) | ||
| 3310 | display: YES]; | ||
| 3311 | [nswindow setLevel: NSPopUpMenuWindowLevel]; | ||
| 3312 | [nswindow orderFront: NSApp]; | ||
| 3313 | [nswindow display]; | ||
| 3314 | |||
| 3315 | SET_FRAME_VISIBLE (tip_f, 1); | ||
| 3316 | unblock_input (); | ||
| 3317 | |||
| 3318 | goto start_timer; | ||
| 3319 | } | ||
| 3320 | else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame)) | ||
| 3321 | { | ||
| 3322 | bool delete = false; | ||
| 3323 | Lisp_Object tail, elt, parm, last; | ||
| 3324 | |||
| 3325 | /* Check if every parameter in PARMS has the same value in | ||
| 3326 | tip_last_parms. This may destruct tip_last_parms which, | ||
| 3327 | however, will be recreated below. */ | ||
| 3328 | for (tail = parms; CONSP (tail); tail = XCDR (tail)) | ||
| 3329 | { | ||
| 3330 | elt = XCAR (tail); | ||
| 3331 | parm = Fcar (elt); | ||
| 3332 | /* The left, top, right and bottom parameters are handled | ||
| 3333 | by compute_tip_xy so they can be ignored here. */ | ||
| 3334 | if (!EQ (parm, Qleft) && !EQ (parm, Qtop) | ||
| 3335 | && !EQ (parm, Qright) && !EQ (parm, Qbottom)) | ||
| 3336 | { | ||
| 3337 | last = Fassq (parm, tip_last_parms); | ||
| 3338 | if (NILP (Fequal (Fcdr (elt), Fcdr (last)))) | ||
| 3339 | { | ||
| 3340 | /* We lost, delete the old tooltip. */ | ||
| 3341 | delete = true; | ||
| 3342 | break; | ||
| 3343 | } | ||
| 3344 | else | ||
| 3345 | tip_last_parms = | ||
| 3346 | call2 (intern ("assq-delete-all"), parm, tip_last_parms); | ||
| 3347 | } | ||
| 3348 | else | ||
| 3349 | tip_last_parms = | ||
| 3350 | call2 (intern ("assq-delete-all"), parm, tip_last_parms); | ||
| 3351 | } | ||
| 3352 | |||
| 3353 | /* Now check if every parameter in what is left of | ||
| 3354 | tip_last_parms with a non-nil value has an association in | ||
| 3355 | PARMS. */ | ||
| 3356 | for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail)) | ||
| 3357 | { | ||
| 3358 | elt = XCAR (tail); | ||
| 3359 | parm = Fcar (elt); | ||
| 3360 | if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright) | ||
| 3361 | && !EQ (parm, Qbottom) && !NILP (Fcdr (elt))) | ||
| 3362 | { | ||
| 3363 | /* We lost, delete the old tooltip. */ | ||
| 3364 | delete = true; | ||
| 3365 | break; | ||
| 3366 | } | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | x_hide_tip (delete); | ||
| 3370 | } | ||
| 3371 | else | ||
| 3372 | x_hide_tip (true); | ||
| 3373 | } | ||
| 3374 | else | ||
| 3375 | x_hide_tip (true); | ||
| 2887 | 3376 | ||
| 2888 | t = gui_display_get_arg (NULL, parms, Qbackground_color, NULL, NULL, | 3377 | tip_last_frame = frame; |
| 2889 | RES_TYPE_STRING); | 3378 | tip_last_string = string; |
| 2890 | if (ns_lisp_to_color (t, &color) == 0) | 3379 | tip_last_parms = parms; |
| 2891 | [ns_tooltip setBackgroundColor: color]; | ||
| 2892 | 3380 | ||
| 2893 | t = gui_display_get_arg (NULL, parms, Qforeground_color, NULL, NULL, | 3381 | if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) |
| 2894 | RES_TYPE_STRING); | 3382 | { |
| 2895 | if (ns_lisp_to_color (t, &color) == 0) | 3383 | /* Add default values to frame parameters. */ |
| 2896 | [ns_tooltip setForegroundColor: color]; | 3384 | if (NILP (Fassq (Qname, parms))) |
| 3385 | parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); | ||
| 3386 | if (NILP (Fassq (Qinternal_border_width, parms))) | ||
| 3387 | parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms); | ||
| 3388 | if (NILP (Fassq (Qborder_width, parms))) | ||
| 3389 | parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms); | ||
| 3390 | if (NILP (Fassq (Qborder_color, parms))) | ||
| 3391 | parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); | ||
| 3392 | if (NILP (Fassq (Qbackground_color, parms))) | ||
| 3393 | parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), | ||
| 3394 | parms); | ||
| 3395 | |||
| 3396 | /* Create a frame for the tooltip, and record it in the global | ||
| 3397 | variable tip_frame. */ | ||
| 3398 | if (NILP (tip_frame = ns_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) | ||
| 3399 | /* Creating the tip frame failed. */ | ||
| 3400 | return unbind_to (count, Qnil); | ||
| 3401 | } | ||
| 2897 | 3402 | ||
| 2898 | [ns_tooltip setText: str]; | 3403 | tip_f = XFRAME (tip_frame); |
| 2899 | size = [ns_tooltip frame].size; | 3404 | window = FRAME_ROOT_WINDOW (tip_f); |
| 3405 | tip_buf = Fget_buffer_create (tip, Qnil); | ||
| 3406 | /* We will mark the tip window a "pseudo-window" below, and such | ||
| 3407 | windows cannot have display margins. */ | ||
| 3408 | bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0)); | ||
| 3409 | bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0)); | ||
| 3410 | set_window_buffer (window, tip_buf, false, false); | ||
| 3411 | w = XWINDOW (window); | ||
| 3412 | w->pseudo_window_p = true; | ||
| 3413 | /* Try to avoid that `other-window' select us (Bug#47207). */ | ||
| 3414 | Fset_window_parameter (window, Qno_other_window, Qt); | ||
| 3415 | |||
| 3416 | /* Set up the frame's root window. Note: The following code does not | ||
| 3417 | try to size the window or its frame correctly. Its only purpose is | ||
| 3418 | to make the subsequent text size calculations work. The right | ||
| 3419 | sizes should get installed when the toolkit gets back to us. */ | ||
| 3420 | w->left_col = 0; | ||
| 3421 | w->top_line = 0; | ||
| 3422 | w->pixel_left = 0; | ||
| 3423 | w->pixel_top = 0; | ||
| 3424 | |||
| 3425 | if (CONSP (Vx_max_tooltip_size) | ||
| 3426 | && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX) | ||
| 3427 | && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX)) | ||
| 3428 | { | ||
| 3429 | w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size)); | ||
| 3430 | w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size)); | ||
| 3431 | } | ||
| 3432 | else | ||
| 3433 | { | ||
| 3434 | w->total_cols = 80; | ||
| 3435 | w->total_lines = 40; | ||
| 3436 | } | ||
| 2900 | 3437 | ||
| 2901 | /* Move the tooltip window where the mouse pointer is. Resize and | 3438 | w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f); |
| 2902 | show it. */ | 3439 | w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f); |
| 2903 | compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height, | 3440 | FRAME_TOTAL_COLS (tip_f) = w->total_cols; |
| 2904 | &root_x, &root_y); | 3441 | adjust_frame_glyphs (tip_f); |
| 3442 | |||
| 3443 | /* Insert STRING into root window's buffer and fit the frame to the | ||
| 3444 | buffer. */ | ||
| 3445 | count_1 = SPECPDL_INDEX (); | ||
| 3446 | old_buffer = current_buffer; | ||
| 3447 | set_buffer_internal_1 (XBUFFER (w->contents)); | ||
| 3448 | bset_truncate_lines (current_buffer, Qnil); | ||
| 3449 | specbind (Qinhibit_read_only, Qt); | ||
| 3450 | specbind (Qinhibit_modification_hooks, Qt); | ||
| 3451 | specbind (Qinhibit_point_motion_hooks, Qt); | ||
| 3452 | Ferase_buffer (); | ||
| 3453 | Finsert (1, &string); | ||
| 3454 | clear_glyph_matrix (w->desired_matrix); | ||
| 3455 | clear_glyph_matrix (w->current_matrix); | ||
| 3456 | SET_TEXT_POS (pos, BEGV, BEGV_BYTE); | ||
| 3457 | try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); | ||
| 3458 | /* Calculate size of tooltip window. */ | ||
| 3459 | size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, | ||
| 3460 | make_fixnum (w->pixel_height), Qnil, | ||
| 3461 | Qnil); | ||
| 3462 | /* Add the frame's internal border to calculated size. */ | ||
| 3463 | width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); | ||
| 3464 | height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); | ||
| 3465 | |||
| 3466 | /* Calculate position of tooltip frame. */ | ||
| 3467 | compute_tip_xy (tip_f, parms, dx, dy, width, | ||
| 3468 | height, &root_x, &root_y); | ||
| 3469 | |||
| 3470 | block_input (); | ||
| 3471 | nswindow = [FRAME_NS_VIEW (tip_f) window]; | ||
| 3472 | [nswindow setFrame: NSMakeRect (root_x, root_y, | ||
| 3473 | width, height) | ||
| 3474 | display: YES]; | ||
| 3475 | [nswindow setLevel: NSPopUpMenuWindowLevel]; | ||
| 3476 | [nswindow orderFront: NSApp]; | ||
| 3477 | [nswindow display]; | ||
| 3478 | |||
| 3479 | SET_FRAME_VISIBLE (tip_f, YES); | ||
| 3480 | FRAME_PIXEL_WIDTH (tip_f) = width; | ||
| 3481 | FRAME_PIXEL_HEIGHT (tip_f) = height; | ||
| 3482 | unblock_input (); | ||
| 2905 | 3483 | ||
| 2906 | [ns_tooltip showAtX: root_x Y: root_y for: XFIXNUM (timeout)]; | 3484 | w->must_be_updated_p = true; |
| 2907 | unblock_input (); | 3485 | update_single_window (w); |
| 3486 | flush_frame (tip_f); | ||
| 3487 | set_buffer_internal_1 (old_buffer); | ||
| 3488 | unbind_to (count_1, Qnil); | ||
| 3489 | windows_or_buffers_changed = old_windows_or_buffers_changed; | ||
| 3490 | |||
| 3491 | start_timer: | ||
| 3492 | /* Let the tip disappear after timeout seconds. */ | ||
| 3493 | tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, | ||
| 3494 | intern ("x-hide-tip")); | ||
| 3495 | } | ||
| 2908 | 3496 | ||
| 2909 | return unbind_to (count, Qnil); | 3497 | return unbind_to (count, Qnil); |
| 2910 | } | 3498 | } |
| @@ -2914,10 +3502,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, | |||
| 2914 | doc: /* SKIP: real doc in xfns.c. */) | 3502 | doc: /* SKIP: real doc in xfns.c. */) |
| 2915 | (void) | 3503 | (void) |
| 2916 | { | 3504 | { |
| 2917 | if (ns_tooltip == nil || ![ns_tooltip isActive]) | 3505 | return x_hide_tip (!tooltip_reuse_hidden_frame); |
| 2918 | return Qnil; | ||
| 2919 | [ns_tooltip hide]; | ||
| 2920 | return Qt; | ||
| 2921 | } | 3506 | } |
| 2922 | 3507 | ||
| 2923 | /* Return geometric attributes of FRAME. According to the value of | 3508 | /* Return geometric attributes of FRAME. According to the value of |
| @@ -3215,6 +3800,48 @@ all_nonzero_ascii (unsigned char *str, ptrdiff_t n) | |||
| 3215 | } | 3800 | } |
| 3216 | @end | 3801 | @end |
| 3217 | 3802 | ||
| 3803 | void | ||
| 3804 | ns_move_tooltip_to_mouse_location (NSPoint screen_point) | ||
| 3805 | { | ||
| 3806 | int root_x, root_y; | ||
| 3807 | NSSize size; | ||
| 3808 | NSWindow *window; | ||
| 3809 | struct frame *tip_f; | ||
| 3810 | |||
| 3811 | window = nil; | ||
| 3812 | |||
| 3813 | if (!FIXNUMP (tip_dx) || !FIXNUMP (tip_dy)) | ||
| 3814 | return; | ||
| 3815 | |||
| 3816 | if (ns_tooltip) | ||
| 3817 | size = [ns_tooltip frame].size; | ||
| 3818 | else if (!FRAMEP (tip_frame) | ||
| 3819 | || !FRAME_LIVE_P (XFRAME (tip_frame)) | ||
| 3820 | || !FRAME_VISIBLE_P (XFRAME (tip_frame))) | ||
| 3821 | return; | ||
| 3822 | else | ||
| 3823 | { | ||
| 3824 | tip_f = XFRAME (tip_frame); | ||
| 3825 | window = [FRAME_NS_VIEW (tip_f) window]; | ||
| 3826 | size = [window frame].size; | ||
| 3827 | } | ||
| 3828 | |||
| 3829 | root_x = screen_point.x; | ||
| 3830 | root_y = screen_point.y; | ||
| 3831 | |||
| 3832 | /* We can directly use `compute_tip_xy' here, since it doesn't cons | ||
| 3833 | nearly as much as it does on X. */ | ||
| 3834 | compute_tip_xy (NULL, Qnil, tip_dx, tip_dy, (int) size.width, | ||
| 3835 | (int) size.height, &root_x, &root_y); | ||
| 3836 | |||
| 3837 | if (ns_tooltip) | ||
| 3838 | [ns_tooltip moveTo: NSMakePoint (root_x, root_y)]; | ||
| 3839 | else | ||
| 3840 | [window setFrame: NSMakeRect (root_x, root_y, | ||
| 3841 | size.width, size.height) | ||
| 3842 | display: YES]; | ||
| 3843 | } | ||
| 3844 | |||
| 3218 | /* ========================================================================== | 3845 | /* ========================================================================== |
| 3219 | 3846 | ||
| 3220 | Lisp interface declaration | 3847 | Lisp interface declaration |
| @@ -3260,6 +3887,10 @@ be used as the image of the icon representing the frame. */); | |||
| 3260 | Default is t. */); | 3887 | Default is t. */); |
| 3261 | ns_use_proxy_icon = true; | 3888 | ns_use_proxy_icon = true; |
| 3262 | 3889 | ||
| 3890 | DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, | ||
| 3891 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 3892 | Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40)); | ||
| 3893 | |||
| 3263 | defsubr (&Sns_read_file_name); | 3894 | defsubr (&Sns_read_file_name); |
| 3264 | defsubr (&Sns_get_resource); | 3895 | defsubr (&Sns_get_resource); |
| 3265 | defsubr (&Sns_set_resource); | 3896 | defsubr (&Sns_set_resource); |
| @@ -3309,6 +3940,21 @@ Default is t. */); | |||
| 3309 | defsubr (&Sx_show_tip); | 3940 | defsubr (&Sx_show_tip); |
| 3310 | defsubr (&Sx_hide_tip); | 3941 | defsubr (&Sx_hide_tip); |
| 3311 | 3942 | ||
| 3943 | tip_timer = Qnil; | ||
| 3944 | staticpro (&tip_timer); | ||
| 3945 | tip_frame = Qnil; | ||
| 3946 | staticpro (&tip_frame); | ||
| 3947 | tip_last_frame = Qnil; | ||
| 3948 | staticpro (&tip_last_frame); | ||
| 3949 | tip_last_string = Qnil; | ||
| 3950 | staticpro (&tip_last_string); | ||
| 3951 | tip_last_parms = Qnil; | ||
| 3952 | staticpro (&tip_last_parms); | ||
| 3953 | tip_dx = Qnil; | ||
| 3954 | staticpro (&tip_dx); | ||
| 3955 | tip_dy = Qnil; | ||
| 3956 | staticpro (&tip_dy); | ||
| 3957 | |||
| 3312 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 | 3958 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 |
| 3313 | defsubr (&Ssystem_move_file_to_trash); | 3959 | defsubr (&Ssystem_move_file_to_trash); |
| 3314 | #endif | 3960 | #endif |
diff --git a/src/nsfont.m b/src/nsfont.m index e913a50cb69..ae5e134e15b 100644 --- a/src/nsfont.m +++ b/src/nsfont.m | |||
| @@ -1177,9 +1177,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 1177 | face = s->face; | 1177 | face = s->face; |
| 1178 | 1178 | ||
| 1179 | r.origin.x = x; | 1179 | r.origin.x = x; |
| 1180 | if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) | ||
| 1181 | r.origin.x += max (s->face->box_vertical_line_width, 0); | ||
| 1182 | |||
| 1183 | r.origin.y = y; | 1180 | r.origin.y = y; |
| 1184 | r.size.height = FONT_HEIGHT (font); | 1181 | r.size.height = FONT_HEIGHT (font); |
| 1185 | 1182 | ||
diff --git a/src/nsmenu.m b/src/nsmenu.m index b0ab12bb87d..d02d7bae4b5 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m | |||
| @@ -52,6 +52,10 @@ EmacsMenu *svcsMenu; | |||
| 52 | /* Nonzero means a menu is currently active. */ | 52 | /* Nonzero means a menu is currently active. */ |
| 53 | static int popup_activated_flag; | 53 | static int popup_activated_flag; |
| 54 | 54 | ||
| 55 | /* The last frame whose menubar was updated. (This is the frame whose | ||
| 56 | menu bar is currently being displayed.) */ | ||
| 57 | static struct frame *last_menubar_frame; | ||
| 58 | |||
| 55 | /* NOTE: toolbar implementation is at end, | 59 | /* NOTE: toolbar implementation is at end, |
| 56 | following complete menu implementation. */ | 60 | following complete menu implementation. */ |
| 57 | 61 | ||
| @@ -71,6 +75,12 @@ void | |||
| 71 | free_frame_menubar (struct frame *f) | 75 | free_frame_menubar (struct frame *f) |
| 72 | { | 76 | { |
| 73 | id menu = [NSApp mainMenu]; | 77 | id menu = [NSApp mainMenu]; |
| 78 | |||
| 79 | if (f != last_menubar_frame) | ||
| 80 | return; | ||
| 81 | |||
| 82 | last_menubar_frame = NULL; | ||
| 83 | |||
| 74 | for (int i = [menu numberOfItems] - 1 ; i >= 0; i--) | 84 | for (int i = [menu numberOfItems] - 1 ; i >= 0; i--) |
| 75 | { | 85 | { |
| 76 | NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i]; | 86 | NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i]; |
| @@ -135,9 +145,9 @@ ns_update_menubar (struct frame *f, bool deep_p) | |||
| 135 | #endif | 145 | #endif |
| 136 | return; | 146 | return; |
| 137 | } | 147 | } |
| 138 | XSETFRAME (Vmenu_updating_frame, f); | ||
| 139 | /*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */ | ||
| 140 | 148 | ||
| 149 | XSETFRAME (Vmenu_updating_frame, f); | ||
| 150 | last_menubar_frame = f; | ||
| 141 | block_input (); | 151 | block_input (); |
| 142 | 152 | ||
| 143 | /* Menu may have been created automatically; if so, discard it. */ | 153 | /* Menu may have been created automatically; if so, discard it. */ |
| @@ -155,7 +165,7 @@ ns_update_menubar (struct frame *f, bool deep_p) | |||
| 155 | 165 | ||
| 156 | #if NSMENUPROFILE | 166 | #if NSMENUPROFILE |
| 157 | ftime (&tb); | 167 | ftime (&tb); |
| 158 | t = -(1000*tb.time+tb.millitm); | 168 | t = -(1000 * tb.time + tb.millitm); |
| 159 | #endif | 169 | #endif |
| 160 | 170 | ||
| 161 | if (deep_p) | 171 | if (deep_p) |
| @@ -413,7 +423,7 @@ ns_update_menubar (struct frame *f, bool deep_p) | |||
| 413 | 423 | ||
| 414 | #if NSMENUPROFILE | 424 | #if NSMENUPROFILE |
| 415 | ftime (&tb); | 425 | ftime (&tb); |
| 416 | t += 1000*tb.time+tb.millitm; | 426 | t += 1000 * tb.time + tb.millitm; |
| 417 | fprintf (stderr, "Menu update took %ld msec.\n", t); | 427 | fprintf (stderr, "Menu update took %ld msec.\n", t); |
| 418 | #endif | 428 | #endif |
| 419 | 429 | ||
| @@ -741,15 +751,15 @@ prettify_key (const char *key) | |||
| 741 | /* p = [view convertPoint:p fromView: nil]; */ | 751 | /* p = [view convertPoint:p fromView: nil]; */ |
| 742 | p.y = NSHeight ([view frame]) - p.y; | 752 | p.y = NSHeight ([view frame]) - p.y; |
| 743 | e = [[view window] currentEvent]; | 753 | e = [[view window] currentEvent]; |
| 744 | event = [NSEvent mouseEventWithType: NSEventTypeRightMouseDown | 754 | event = [NSEvent mouseEventWithType: NSEventTypeRightMouseDown |
| 745 | location: p | 755 | location: p |
| 746 | modifierFlags: 0 | 756 | modifierFlags: 0 |
| 747 | timestamp: [e timestamp] | 757 | timestamp: [e timestamp] |
| 748 | windowNumber: [[view window] windowNumber] | 758 | windowNumber: [[view window] windowNumber] |
| 749 | context: nil | 759 | context: nil |
| 750 | eventNumber: 0 /* [e eventNumber] */ | 760 | eventNumber: 0 /* [e eventNumber] */ |
| 751 | clickCount: 1 | 761 | clickCount: 1 |
| 752 | pressure: 0]; | 762 | pressure: 0]; |
| 753 | 763 | ||
| 754 | context_menu_value = -1; | 764 | context_menu_value = -1; |
| 755 | [NSMenu popUpContextMenu: self withEvent: event forView: view]; | 765 | [NSMenu popUpContextMenu: self withEvent: event forView: view]; |
| @@ -765,13 +775,33 @@ prettify_key (const char *key) | |||
| 765 | NSInteger idx = [item tag]; | 775 | NSInteger idx = [item tag]; |
| 766 | struct frame *f = SELECTED_FRAME (); | 776 | struct frame *f = SELECTED_FRAME (); |
| 767 | Lisp_Object vec = f->menu_bar_vector; | 777 | Lisp_Object vec = f->menu_bar_vector; |
| 768 | Lisp_Object help, frame; | 778 | Lisp_Object help, frame, *client_data; |
| 769 | |||
| 770 | if (idx >= ASIZE (vec)) | ||
| 771 | return; | ||
| 772 | 779 | ||
| 773 | XSETFRAME (frame, f); | 780 | XSETFRAME (frame, f); |
| 774 | help = AREF (vec, idx + MENU_ITEMS_ITEM_HELP); | 781 | |
| 782 | /* This menu isn't a menubar, so use the pointer to the popup menu | ||
| 783 | data. */ | ||
| 784 | if (context_menu_value != 0) | ||
| 785 | { | ||
| 786 | client_data = (Lisp_Object *) idx; | ||
| 787 | |||
| 788 | if (client_data) | ||
| 789 | help = client_data[MENU_ITEMS_ITEM_HELP]; | ||
| 790 | else | ||
| 791 | help = Qnil; | ||
| 792 | } | ||
| 793 | /* Just dismiss any help-echo that might already be in progress if | ||
| 794 | no menu item will be highlighted. */ | ||
| 795 | else if (item == nil || idx <= 0) | ||
| 796 | help = Qnil; | ||
| 797 | else | ||
| 798 | { | ||
| 799 | if (idx >= ASIZE (vec)) | ||
| 800 | return; | ||
| 801 | |||
| 802 | /* Otherwise, get the help data from the menu bar vector. */ | ||
| 803 | help = AREF (vec, idx + MENU_ITEMS_ITEM_HELP); | ||
| 804 | } | ||
| 775 | 805 | ||
| 776 | popup_activated_flag++; | 806 | popup_activated_flag++; |
| 777 | if (STRINGP (help) || NILP (help)) | 807 | if (STRINGP (help) || NILP (help)) |
| @@ -849,37 +879,35 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 849 | EmacsMenu *pmenu; | 879 | EmacsMenu *pmenu; |
| 850 | NSPoint p; | 880 | NSPoint p; |
| 851 | Lisp_Object tem; | 881 | Lisp_Object tem; |
| 852 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 882 | specpdl_ref specpdl_count; |
| 853 | widget_value *wv, *first_wv = 0; | 883 | widget_value *wv, *first_wv = 0; |
| 884 | widget_value *save_wv = 0, *prev_wv = 0; | ||
| 885 | widget_value **submenu_stack; | ||
| 886 | int submenu_depth = 0; | ||
| 887 | int first_pane = 1; | ||
| 888 | int i; | ||
| 854 | bool keymaps = (menuflags & MENU_KEYMAPS); | 889 | bool keymaps = (menuflags & MENU_KEYMAPS); |
| 855 | 890 | ||
| 891 | USE_SAFE_ALLOCA; | ||
| 892 | |||
| 856 | NSTRACE ("ns_menu_show"); | 893 | NSTRACE ("ns_menu_show"); |
| 857 | 894 | ||
| 858 | block_input (); | 895 | block_input (); |
| 859 | 896 | ||
| 860 | p.x = x; p.y = y; | 897 | p.x = x; p.y = y; |
| 861 | 898 | ||
| 862 | /* Don't GC due to a mysterious bug. */ | ||
| 863 | inhibit_garbage_collection (); | ||
| 864 | |||
| 865 | /* now parse stage 2 as in ns_update_menubar */ | 899 | /* now parse stage 2 as in ns_update_menubar */ |
| 866 | wv = make_widget_value ("contextmenu", NULL, true, Qnil); | 900 | wv = make_widget_value ("contextmenu", NULL, true, Qnil); |
| 867 | wv->button_type = BUTTON_TYPE_NONE; | 901 | wv->button_type = BUTTON_TYPE_NONE; |
| 868 | first_wv = wv; | 902 | first_wv = wv; |
| 869 | 903 | ||
| 870 | #if 0 | 904 | submenu_stack |
| 871 | /* FIXME: a couple of one-line differences prevent reuse. */ | 905 | = SAFE_ALLOCA (menu_items_used * sizeof *submenu_stack); |
| 872 | wv = digest_single_submenu (0, menu_items_used, 0); | 906 | |
| 873 | #else | 907 | specpdl_count = SPECPDL_INDEX (); |
| 874 | { | 908 | |
| 875 | widget_value *save_wv = 0, *prev_wv = 0; | 909 | /* Don't GC due to a mysterious bug. */ |
| 876 | widget_value **submenu_stack | 910 | inhibit_garbage_collection (); |
| 877 | = alloca (menu_items_used * sizeof *submenu_stack); | ||
| 878 | /* Lisp_Object *subprefix_stack | ||
| 879 | = alloca (menu_items_used * sizeof *subprefix_stack); */ | ||
| 880 | int submenu_depth = 0; | ||
| 881 | int first_pane = 1; | ||
| 882 | int i; | ||
| 883 | 911 | ||
| 884 | /* Loop over all panes and items, filling in the tree. */ | 912 | /* Loop over all panes and items, filling in the tree. */ |
| 885 | i = 0; | 913 | i = 0; |
| @@ -1009,8 +1037,6 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 1009 | i += MENU_ITEMS_ITEM_LENGTH; | 1037 | i += MENU_ITEMS_ITEM_LENGTH; |
| 1010 | } | 1038 | } |
| 1011 | } | 1039 | } |
| 1012 | } | ||
| 1013 | #endif | ||
| 1014 | 1040 | ||
| 1015 | if (!NILP (title)) | 1041 | if (!NILP (title)) |
| 1016 | { | 1042 | { |
| @@ -1045,6 +1071,8 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 1045 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; | 1071 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; |
| 1046 | unbind_to (specpdl_count, Qnil); | 1072 | unbind_to (specpdl_count, Qnil); |
| 1047 | unblock_input (); | 1073 | unblock_input (); |
| 1074 | |||
| 1075 | SAFE_FREE (); | ||
| 1048 | return tem; | 1076 | return tem; |
| 1049 | } | 1077 | } |
| 1050 | 1078 | ||
| @@ -1469,6 +1497,15 @@ update_frame_tool_bar (struct frame *f) | |||
| 1469 | [timer retain]; | 1497 | [timer retain]; |
| 1470 | } | 1498 | } |
| 1471 | 1499 | ||
| 1500 | - (void) moveTo: (NSPoint) screen_point | ||
| 1501 | { | ||
| 1502 | [win setFrame: NSMakeRect (screen_point.x, | ||
| 1503 | screen_point.y, | ||
| 1504 | [self frame].size.width, | ||
| 1505 | [self frame].size.height) | ||
| 1506 | display: YES]; | ||
| 1507 | } | ||
| 1508 | |||
| 1472 | - (void) hide | 1509 | - (void) hide |
| 1473 | { | 1510 | { |
| 1474 | [win close]; | 1511 | [win close]; |
| @@ -1508,31 +1545,38 @@ pop_down_menu (void *arg) | |||
| 1508 | 1545 | ||
| 1509 | if (popup_activated_flag) | 1546 | if (popup_activated_flag) |
| 1510 | { | 1547 | { |
| 1511 | block_input (); | ||
| 1512 | popup_activated_flag = 0; | 1548 | popup_activated_flag = 0; |
| 1513 | [panel close]; | 1549 | [panel close]; |
| 1550 | /* For some reason this is required on macOS, or the selected | ||
| 1551 | frame gets the keyboard focus but doesn't become | ||
| 1552 | highlighted. */ | ||
| 1553 | #ifdef NS_IMPL_COCOA | ||
| 1514 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; | 1554 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; |
| 1515 | unblock_input (); | 1555 | #endif |
| 1556 | discard_menu_items (); | ||
| 1516 | } | 1557 | } |
| 1517 | } | 1558 | } |
| 1518 | 1559 | ||
| 1519 | |||
| 1520 | Lisp_Object | 1560 | Lisp_Object |
| 1521 | ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | 1561 | ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) |
| 1522 | { | 1562 | { |
| 1523 | id dialog; | 1563 | EmacsDialogPanel *dialog; |
| 1524 | Lisp_Object tem, title; | 1564 | Lisp_Object tem, title; |
| 1525 | NSPoint p; | 1565 | NSPoint p; |
| 1526 | BOOL isQ; | 1566 | BOOL is_question; |
| 1567 | const char *error_name; | ||
| 1568 | specpdl_ref specpdl_count; | ||
| 1527 | 1569 | ||
| 1528 | NSTRACE ("ns_popup_dialog"); | 1570 | NSTRACE ("ns_popup_dialog"); |
| 1571 | specpdl_count = SPECPDL_INDEX (); | ||
| 1529 | 1572 | ||
| 1530 | isQ = NILP (header); | 1573 | is_question = NILP (header); |
| 1531 | |||
| 1532 | check_window_system (f); | 1574 | check_window_system (f); |
| 1533 | 1575 | ||
| 1534 | p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; | 1576 | p.x = ((int) f->left_pos |
| 1535 | p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2; | 1577 | + ((int) FRAME_COLUMN_WIDTH (f) * f->text_cols) / 2); |
| 1578 | p.y = ((int) f->top_pos | ||
| 1579 | + (FRAME_LINE_HEIGHT (f) * f->text_lines) / 2); | ||
| 1536 | 1580 | ||
| 1537 | title = Fcar (contents); | 1581 | title = Fcar (contents); |
| 1538 | CHECK_STRING (title); | 1582 | CHECK_STRING (title); |
| @@ -1542,21 +1586,30 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1542 | the dialog. */ | 1586 | the dialog. */ |
| 1543 | contents = list2 (title, Fcons (build_string ("Ok"), Qt)); | 1587 | contents = list2 (title, Fcons (build_string ("Ok"), Qt)); |
| 1544 | 1588 | ||
| 1545 | block_input (); | 1589 | record_unwind_protect_void (unuse_menu_items); |
| 1546 | dialog = [[EmacsDialogPanel alloc] initFromContents: contents | 1590 | list_of_panes (list1 (contents)); |
| 1547 | isQuestion: isQ]; | ||
| 1548 | 1591 | ||
| 1549 | { | 1592 | block_input (); |
| 1550 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 1593 | dialog = [[EmacsDialogPanel alloc] initWithTitle: SSDATA (title) |
| 1551 | 1594 | isQuestion: is_question]; | |
| 1552 | record_unwind_protect_ptr (pop_down_menu, dialog); | ||
| 1553 | popup_activated_flag = 1; | ||
| 1554 | tem = [dialog runDialogAt: p]; | ||
| 1555 | unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */ | ||
| 1556 | } | ||
| 1557 | 1595 | ||
| 1596 | [dialog processMenuItems: menu_items | ||
| 1597 | used: menu_items_used | ||
| 1598 | withErrorOutput: &error_name]; | ||
| 1599 | [dialog resizeBoundsPriorToDisplay]; | ||
| 1558 | unblock_input (); | 1600 | unblock_input (); |
| 1559 | 1601 | ||
| 1602 | if (error_name) | ||
| 1603 | { | ||
| 1604 | discard_menu_items (); | ||
| 1605 | [dialog close]; | ||
| 1606 | error ("%s", error_name); | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | record_unwind_protect_ptr (pop_down_menu, dialog); | ||
| 1610 | popup_activated_flag = 1; | ||
| 1611 | tem = [dialog runDialogAt: p]; | ||
| 1612 | unbind_to (specpdl_count, Qnil); | ||
| 1560 | return tem; | 1613 | return tem; |
| 1561 | } | 1614 | } |
| 1562 | 1615 | ||
| @@ -1597,7 +1650,6 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1597 | NSImage *img; | 1650 | NSImage *img; |
| 1598 | 1651 | ||
| 1599 | dialog_return = Qundefined; | 1652 | dialog_return = Qundefined; |
| 1600 | button_values = NULL; | ||
| 1601 | area.origin.x = 3*SPACER; | 1653 | area.origin.x = 3*SPACER; |
| 1602 | area.origin.y = 2*SPACER; | 1654 | area.origin.y = 2*SPACER; |
| 1603 | area.size.width = ICONSIZE; | 1655 | area.size.width = ICONSIZE; |
| @@ -1681,58 +1733,65 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1681 | } | 1733 | } |
| 1682 | 1734 | ||
| 1683 | 1735 | ||
| 1684 | - (BOOL)windowShouldClose: (id)sender | 1736 | - (BOOL)windowShouldClose: (id) sender |
| 1685 | { | 1737 | { |
| 1686 | window_closed = YES; | 1738 | window_closed = YES; |
| 1687 | [NSApp stop:self]; | 1739 | [NSApp stop: self]; |
| 1688 | return NO; | 1740 | return NO; |
| 1689 | } | 1741 | } |
| 1690 | 1742 | ||
| 1691 | - (void)dealloc | 1743 | - (void) dealloc |
| 1692 | { | 1744 | { |
| 1693 | xfree (button_values); | ||
| 1694 | [super dealloc]; | 1745 | [super dealloc]; |
| 1695 | } | 1746 | } |
| 1696 | 1747 | ||
| 1697 | - (void)process_dialog: (Lisp_Object) list | 1748 | - (void) processMenuItems: (Lisp_Object) menu_items |
| 1749 | used: (ptrdiff_t) menu_items_used | ||
| 1750 | withErrorOutput: (const char **) error_name | ||
| 1698 | { | 1751 | { |
| 1699 | Lisp_Object item, lst = list; | 1752 | int i, nb_buttons = 0, row = 0; |
| 1700 | int row = 0; | 1753 | Lisp_Object item_name, enable; |
| 1701 | int buttons = 0, btnnr = 0; | ||
| 1702 | 1754 | ||
| 1703 | for (; CONSP (lst); lst = XCDR (lst)) | 1755 | i = MENU_ITEMS_PANE_LENGTH; |
| 1756 | *error_name = NULL; | ||
| 1757 | |||
| 1758 | /* Loop over all panes and items, filling in the tree. */ | ||
| 1759 | while (i < menu_items_used) | ||
| 1704 | { | 1760 | { |
| 1705 | item = XCAR (list); | 1761 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); |
| 1706 | if (CONSP (item)) | 1762 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); |
| 1707 | ++buttons; | ||
| 1708 | } | ||
| 1709 | 1763 | ||
| 1710 | if (buttons > 0) | 1764 | if (NILP (item_name)) |
| 1711 | button_values = xmalloc (buttons * sizeof *button_values); | 1765 | { |
| 1766 | *error_name = "Submenu in dialog items"; | ||
| 1767 | return; | ||
| 1768 | } | ||
| 1712 | 1769 | ||
| 1713 | for (; CONSP (list); list = XCDR (list)) | 1770 | if (EQ (item_name, Qquote)) |
| 1714 | { | 1771 | /* This is the boundary between elements on the left and those |
| 1715 | item = XCAR (list); | 1772 | on the right, but that boundary is currently not handled on |
| 1716 | if (STRINGP (item)) | 1773 | NS. */ |
| 1717 | { | 1774 | continue; |
| 1718 | [self addString: SSDATA (item) row: row++]; | 1775 | |
| 1719 | } | 1776 | if (nb_buttons > 9) |
| 1720 | else if (CONSP (item)) | 1777 | { |
| 1721 | { | 1778 | *error_name = "Too many dialog items"; |
| 1722 | button_values[btnnr] = XCDR (item); | 1779 | return; |
| 1723 | [self addButton: SSDATA (XCAR (item)) value: btnnr row: row++]; | 1780 | } |
| 1724 | ++btnnr; | 1781 | |
| 1725 | } | 1782 | [self addButton: SSDATA (item_name) |
| 1726 | else if (NILP (item)) | 1783 | value: (NSInteger) aref_addr (menu_items, i) |
| 1727 | { | 1784 | row: row++ |
| 1728 | [self addSplit]; | 1785 | enable: !NILP (enable)]; |
| 1729 | row = 0; | 1786 | |
| 1730 | } | 1787 | i += MENU_ITEMS_ITEM_LENGTH; |
| 1788 | nb_buttons++; | ||
| 1731 | } | 1789 | } |
| 1732 | } | 1790 | } |
| 1733 | 1791 | ||
| 1734 | 1792 | ||
| 1735 | - (void)addButton: (char *)str value: (int)tag row: (int)row | 1793 | - (void) addButton: (char *) str value: (NSInteger) tag |
| 1794 | row: (int) row enable: (BOOL) enable | ||
| 1736 | { | 1795 | { |
| 1737 | id cell; | 1796 | id cell; |
| 1738 | 1797 | ||
| @@ -1741,7 +1800,8 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1741 | [matrix addRow]; | 1800 | [matrix addRow]; |
| 1742 | rows++; | 1801 | rows++; |
| 1743 | } | 1802 | } |
| 1744 | cell = [matrix cellAtRow: row column: cols-1]; | 1803 | |
| 1804 | cell = [matrix cellAtRow: row column: cols - 1]; | ||
| 1745 | [cell setTarget: self]; | 1805 | [cell setTarget: self]; |
| 1746 | [cell setAction: @selector (clicked: )]; | 1806 | [cell setAction: @selector (clicked: )]; |
| 1747 | [cell setTitle: [NSString stringWithUTF8String: str]]; | 1807 | [cell setTitle: [NSString stringWithUTF8String: str]]; |
| @@ -1751,7 +1811,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1751 | } | 1811 | } |
| 1752 | 1812 | ||
| 1753 | 1813 | ||
| 1754 | - (void)addString: (char *)str row: (int)row | 1814 | - (void)addString: (char *) str row: (int) row |
| 1755 | { | 1815 | { |
| 1756 | id cell; | 1816 | id cell; |
| 1757 | 1817 | ||
| @@ -1774,96 +1834,95 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1774 | } | 1834 | } |
| 1775 | 1835 | ||
| 1776 | 1836 | ||
| 1777 | - (void)clicked: sender | 1837 | - (void) clicked: sender |
| 1778 | { | 1838 | { |
| 1779 | NSArray *sellist = nil; | 1839 | NSArray *sellist = nil; |
| 1780 | EMACS_INT seltag; | 1840 | NSUInteger seltag; |
| 1841 | Lisp_Object *selarray; | ||
| 1781 | 1842 | ||
| 1782 | sellist = [sender selectedCells]; | 1843 | sellist = [sender selectedCells]; |
| 1844 | |||
| 1783 | if ([sellist count] < 1) | 1845 | if ([sellist count] < 1) |
| 1784 | return; | 1846 | return; |
| 1785 | 1847 | ||
| 1786 | seltag = [[sellist objectAtIndex: 0] tag]; | 1848 | seltag = [[sellist objectAtIndex: 0] tag]; |
| 1787 | dialog_return = button_values[seltag]; | 1849 | selarray = (void *) seltag; |
| 1788 | [NSApp stop:self]; | 1850 | dialog_return = selarray[MENU_ITEMS_ITEM_VALUE]; |
| 1851 | [NSApp stop: self]; | ||
| 1789 | } | 1852 | } |
| 1790 | 1853 | ||
| 1791 | 1854 | ||
| 1792 | - (instancetype)initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ | 1855 | - (instancetype) initWithTitle: (char *) title_string |
| 1856 | isQuestion: (BOOL) is_question | ||
| 1793 | { | 1857 | { |
| 1794 | Lisp_Object head; | ||
| 1795 | [super init]; | 1858 | [super init]; |
| 1796 | 1859 | ||
| 1797 | if (CONSP (contents)) | 1860 | if (title_string) |
| 1798 | { | 1861 | [title setStringValue: |
| 1799 | head = Fcar (contents); | 1862 | [NSString stringWithUTF8String: title_string]]; |
| 1800 | [self process_dialog: Fcdr (contents)]; | ||
| 1801 | } | ||
| 1802 | else | ||
| 1803 | head = contents; | ||
| 1804 | 1863 | ||
| 1805 | if (STRINGP (head)) | 1864 | if (is_question) |
| 1806 | [title setStringValue: | 1865 | [command setStringValue: @"Question"]; |
| 1807 | [NSString stringWithUTF8String: SSDATA (head)]]; | ||
| 1808 | else if (isQ == YES) | ||
| 1809 | [title setStringValue: @"Question"]; | ||
| 1810 | else | 1866 | else |
| 1811 | [title setStringValue: @"Information"]; | 1867 | [command setStringValue: @"Information"]; |
| 1812 | 1868 | ||
| 1813 | { | 1869 | return self; |
| 1814 | int i; | 1870 | } |
| 1815 | NSRect r, s, t; | ||
| 1816 | 1871 | ||
| 1817 | if (cols == 1 && rows > 1) /* Never told where to split. */ | 1872 | - (void) resizeBoundsPriorToDisplay |
| 1818 | { | 1873 | { |
| 1819 | [matrix addColumn]; | 1874 | int i; |
| 1820 | for (i = 0; i < rows/2; i++) | 1875 | NSRect r, s, t; |
| 1821 | { | 1876 | NSSize csize; |
| 1822 | [matrix putCell: [matrix cellAtRow: (rows+1)/2 column: 0] | ||
| 1823 | atRow: i column: 1]; | ||
| 1824 | [matrix removeRow: (rows+1)/2]; | ||
| 1825 | } | ||
| 1826 | } | ||
| 1827 | 1877 | ||
| 1828 | [matrix sizeToFit]; | 1878 | if (cols == 1 && rows > 1) |
| 1829 | { | 1879 | { |
| 1830 | NSSize csize = [matrix cellSize]; | 1880 | [matrix addColumn]; |
| 1831 | if (csize.width < MINCELLWIDTH) | 1881 | for (i = 0; i < rows / 2; i++) |
| 1832 | { | 1882 | { |
| 1833 | csize.width = MINCELLWIDTH; | 1883 | [matrix putCell: [matrix cellAtRow: (rows + 1) /2 |
| 1834 | [matrix setCellSize: csize]; | 1884 | column: 0] |
| 1835 | [matrix sizeToCells]; | 1885 | atRow: i column: 1]; |
| 1836 | } | 1886 | [matrix removeRow: (rows + 1) / 2]; |
| 1887 | } | ||
| 1837 | } | 1888 | } |
| 1838 | 1889 | ||
| 1839 | [title sizeToFit]; | 1890 | [matrix sizeToFit]; |
| 1840 | [command sizeToFit]; | ||
| 1841 | 1891 | ||
| 1842 | t = [matrix frame]; | 1892 | csize = [matrix cellSize]; |
| 1843 | r = [title frame]; | 1893 | if (csize.width < MINCELLWIDTH) |
| 1844 | if (r.size.width+r.origin.x > t.size.width+t.origin.x) | 1894 | { |
| 1845 | { | 1895 | csize.width = MINCELLWIDTH; |
| 1846 | t.origin.x = r.origin.x; | 1896 | [matrix setCellSize: csize]; |
| 1847 | t.size.width = r.size.width; | 1897 | [matrix sizeToCells]; |
| 1848 | } | 1898 | } |
| 1849 | r = [command frame]; | ||
| 1850 | if (r.size.width+r.origin.x > t.size.width+t.origin.x) | ||
| 1851 | { | ||
| 1852 | t.origin.x = r.origin.x; | ||
| 1853 | t.size.width = r.size.width; | ||
| 1854 | } | ||
| 1855 | 1899 | ||
| 1856 | r = [self frame]; | 1900 | [title sizeToFit]; |
| 1857 | s = [(NSView *)[self contentView] frame]; | 1901 | [command sizeToFit]; |
| 1858 | r.size.width += t.origin.x+t.size.width +2*SPACER-s.size.width; | ||
| 1859 | r.size.height += t.origin.y+t.size.height+SPACER-s.size.height; | ||
| 1860 | [self setFrame: r display: NO]; | ||
| 1861 | } | ||
| 1862 | 1902 | ||
| 1863 | return self; | 1903 | t = [matrix frame]; |
| 1864 | } | 1904 | r = [title frame]; |
| 1905 | if (r.size.width + r.origin.x > t.size.width + t.origin.x) | ||
| 1906 | { | ||
| 1907 | t.origin.x = r.origin.x; | ||
| 1908 | t.size.width = r.size.width; | ||
| 1909 | } | ||
| 1865 | 1910 | ||
| 1911 | r = [command frame]; | ||
| 1912 | if (r.size.width + r.origin.x > t.size.width + t.origin.x) | ||
| 1913 | { | ||
| 1914 | t.origin.x = r.origin.x; | ||
| 1915 | t.size.width = r.size.width; | ||
| 1916 | } | ||
| 1866 | 1917 | ||
| 1918 | r = [self frame]; | ||
| 1919 | s = [(NSView *) [self contentView] frame]; | ||
| 1920 | r.size.width += (t.origin.x + t.size.width | ||
| 1921 | + 2 * SPACER - s.size.width); | ||
| 1922 | r.size.height += (t.origin.y + t.size.height | ||
| 1923 | + SPACER - s.size.height); | ||
| 1924 | [self setFrame: r display: NO]; | ||
| 1925 | } | ||
| 1867 | 1926 | ||
| 1868 | - (void)timeout_handler: (NSTimer *)timedEntry | 1927 | - (void)timeout_handler: (NSTimer *)timedEntry |
| 1869 | { | 1928 | { |
| @@ -1881,11 +1940,11 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1881 | /* We use stop because stopModal/abortModal out of the main loop | 1940 | /* We use stop because stopModal/abortModal out of the main loop |
| 1882 | does not seem to work in 10.6. But as we use stop we must send a | 1941 | does not seem to work in 10.6. But as we use stop we must send a |
| 1883 | real event so the stop is seen and acted upon. */ | 1942 | real event so the stop is seen and acted upon. */ |
| 1884 | [NSApp stop:self]; | 1943 | [NSApp stop: self]; |
| 1885 | [NSApp postEvent: nxev atStart: NO]; | 1944 | [NSApp postEvent: nxev atStart: NO]; |
| 1886 | } | 1945 | } |
| 1887 | 1946 | ||
| 1888 | - (Lisp_Object)runDialogAt: (NSPoint)p | 1947 | - (Lisp_Object) runDialogAt: (NSPoint) p |
| 1889 | { | 1948 | { |
| 1890 | Lisp_Object ret = Qundefined; | 1949 | Lisp_Object ret = Qundefined; |
| 1891 | 1950 | ||
| @@ -1905,13 +1964,17 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) | |||
| 1905 | [[NSRunLoop currentRunLoop] addTimer: tmo | 1964 | [[NSRunLoop currentRunLoop] addTimer: tmo |
| 1906 | forMode: NSModalPanelRunLoopMode]; | 1965 | forMode: NSModalPanelRunLoopMode]; |
| 1907 | } | 1966 | } |
| 1967 | |||
| 1908 | timer_fired = NO; | 1968 | timer_fired = NO; |
| 1909 | dialog_return = Qundefined; | 1969 | dialog_return = Qundefined; |
| 1910 | [NSApp runModalForWindow: self]; | 1970 | [NSApp runModalForWindow: self]; |
| 1911 | ret = dialog_return; | 1971 | ret = dialog_return; |
| 1912 | if (! timer_fired) | 1972 | |
| 1973 | if (!timer_fired) | ||
| 1913 | { | 1974 | { |
| 1914 | if (tmo != nil) [tmo invalidate]; /* Cancels timer. */ | 1975 | if (tmo != nil) |
| 1976 | [tmo invalidate]; /* Cancels timer. */ | ||
| 1977 | |||
| 1915 | break; | 1978 | break; |
| 1916 | } | 1979 | } |
| 1917 | } | 1980 | } |
diff --git a/src/nsselect.m b/src/nsselect.m index a7ef9df0e0e..c46bfeaf42a 100644 --- a/src/nsselect.m +++ b/src/nsselect.m | |||
| @@ -17,13 +17,11 @@ GNU General Public License for more details. | |||
| 17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ |
| 19 | 19 | ||
| 20 | /* | 20 | /* Originally by Carl Edman |
| 21 | Originally by Carl Edman | 21 | Updated by Christian Limpach (chris@nice.ch) |
| 22 | Updated by Christian Limpach (chris@nice.ch) | 22 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) |
| 23 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) | 23 | macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net) |
| 24 | macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net) | 24 | GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) */ |
| 25 | GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) | ||
| 26 | */ | ||
| 27 | 25 | ||
| 28 | /* This should be the first include, as it may set up #defines affecting | 26 | /* This should be the first include, as it may set up #defines affecting |
| 29 | interpretation of even the system includes. */ | 27 | interpretation of even the system includes. */ |
| @@ -559,6 +557,225 @@ nxatoms_of_nsselect (void) | |||
| 559 | nil] retain]; | 557 | nil] retain]; |
| 560 | } | 558 | } |
| 561 | 559 | ||
| 560 | static void | ||
| 561 | ns_decode_data_to_pasteboard (Lisp_Object type, Lisp_Object data, | ||
| 562 | NSPasteboard *pasteboard) | ||
| 563 | { | ||
| 564 | NSArray *types, *new; | ||
| 565 | NSMutableArray *temp; | ||
| 566 | Lisp_Object tem; | ||
| 567 | specpdl_ref count; | ||
| 568 | #if !NS_USE_NSPasteboardTypeFileURL | ||
| 569 | NSURL *url; | ||
| 570 | #endif | ||
| 571 | |||
| 572 | types = [pasteboard types]; | ||
| 573 | count = SPECPDL_INDEX (); | ||
| 574 | |||
| 575 | CHECK_SYMBOL (type); | ||
| 576 | |||
| 577 | if (EQ (type, Qstring)) | ||
| 578 | { | ||
| 579 | CHECK_STRING (data); | ||
| 580 | |||
| 581 | new = [types arrayByAddingObject: NSPasteboardTypeString]; | ||
| 582 | |||
| 583 | [pasteboard declareTypes: new | ||
| 584 | owner: nil]; | ||
| 585 | [pasteboard setString: [NSString stringWithLispString: data] | ||
| 586 | forType: NSPasteboardTypeString]; | ||
| 587 | } | ||
| 588 | else if (EQ (type, Qfile)) | ||
| 589 | { | ||
| 590 | #if NS_USE_NSPasteboardTypeFileURL | ||
| 591 | if (CONSP (data)) | ||
| 592 | new = [types arrayByAddingObject: NSPasteboardTypeURL]; | ||
| 593 | else | ||
| 594 | new = [types arrayByAddingObject: NSPasteboardTypeFileURL]; | ||
| 595 | #else | ||
| 596 | new = [types arrayByAddingObject: NSFilenamesPboardType]; | ||
| 597 | #endif | ||
| 598 | |||
| 599 | [pasteboard declareTypes: new | ||
| 600 | owner: nil]; | ||
| 601 | |||
| 602 | if (STRINGP (data)) | ||
| 603 | { | ||
| 604 | #if NS_USE_NSPasteboardTypeFileURL | ||
| 605 | [pasteboard setString: [NSString stringWithLispString: data] | ||
| 606 | forType: NSPasteboardTypeFileURL]; | ||
| 607 | #else | ||
| 608 | url = [NSURL URLWithString: [NSString stringWithLispString: data]]; | ||
| 609 | |||
| 610 | if (!url) | ||
| 611 | signal_error ("Invalid file URL", data); | ||
| 612 | |||
| 613 | [pasteboard setString: [url path] | ||
| 614 | forType: NSFilenamesPboardType]; | ||
| 615 | #endif | ||
| 616 | } | ||
| 617 | else | ||
| 618 | { | ||
| 619 | CHECK_LIST (data); | ||
| 620 | temp = [[NSMutableArray alloc] init]; | ||
| 621 | record_unwind_protect_ptr (ns_release_object, temp); | ||
| 622 | |||
| 623 | for (tem = data; CONSP (tem); tem = XCDR (tem)) | ||
| 624 | { | ||
| 625 | CHECK_STRING (XCAR (tem)); | ||
| 626 | |||
| 627 | [temp addObject: [NSString stringWithLispString: XCAR (tem)]]; | ||
| 628 | } | ||
| 629 | CHECK_LIST_END (tem, data); | ||
| 630 | #if NS_USE_NSPasteboardTypeFileURL | ||
| 631 | [pasteboard setPropertyList: temp | ||
| 632 | /* We have to use this deprecated pasteboard | ||
| 633 | type, since Apple doesn't let us use | ||
| 634 | dragImage:at: to drag multiple file URLs. */ | ||
| 635 | forType: @"NSFilenamesPboardType"]; | ||
| 636 | #else | ||
| 637 | [pasteboard setPropertyList: temp | ||
| 638 | forType: NSFilenamesPboardType]; | ||
| 639 | #endif | ||
| 640 | unbind_to (count, Qnil); | ||
| 641 | } | ||
| 642 | } | ||
| 643 | else | ||
| 644 | signal_error ("Unknown pasteboard type", type); | ||
| 645 | } | ||
| 646 | |||
| 647 | static void | ||
| 648 | ns_lisp_to_pasteboard (Lisp_Object object, | ||
| 649 | NSPasteboard *pasteboard) | ||
| 650 | { | ||
| 651 | Lisp_Object tem, type, data; | ||
| 652 | |||
| 653 | [pasteboard declareTypes: [NSArray array] | ||
| 654 | owner: nil]; | ||
| 655 | |||
| 656 | CHECK_LIST (object); | ||
| 657 | for (tem = object; CONSP (tem); tem = XCDR (tem)) | ||
| 658 | { | ||
| 659 | maybe_quit (); | ||
| 660 | |||
| 661 | type = Fcar (Fcar (tem)); | ||
| 662 | data = Fcdr (Fcar (tem)); | ||
| 663 | |||
| 664 | ns_decode_data_to_pasteboard (type, data, pasteboard); | ||
| 665 | } | ||
| 666 | CHECK_LIST_END (tem, object); | ||
| 667 | } | ||
| 668 | |||
| 669 | static NSDragOperation | ||
| 670 | ns_dnd_action_to_operation (Lisp_Object action) | ||
| 671 | { | ||
| 672 | if (EQ (action, QXdndActionCopy)) | ||
| 673 | return NSDragOperationCopy; | ||
| 674 | |||
| 675 | if (EQ (action, QXdndActionMove)) | ||
| 676 | return NSDragOperationMove; | ||
| 677 | |||
| 678 | if (EQ (action, QXdndActionLink)) | ||
| 679 | return NSDragOperationLink; | ||
| 680 | |||
| 681 | signal_error ("Unsupported drag-and-drop action", action); | ||
| 682 | } | ||
| 683 | |||
| 684 | static Lisp_Object | ||
| 685 | ns_dnd_action_from_operation (NSDragOperation operation) | ||
| 686 | { | ||
| 687 | switch (operation) | ||
| 688 | { | ||
| 689 | case NSDragOperationCopy: | ||
| 690 | return QXdndActionCopy; | ||
| 691 | |||
| 692 | case NSDragOperationMove: | ||
| 693 | return QXdndActionMove; | ||
| 694 | |||
| 695 | case NSDragOperationLink: | ||
| 696 | return QXdndActionLink; | ||
| 697 | |||
| 698 | case NSDragOperationNone: | ||
| 699 | return Qnil; | ||
| 700 | |||
| 701 | default: | ||
| 702 | return QXdndActionPrivate; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 6, 0, | ||
| 707 | doc: /* Begin a drag-and-drop operation on FRAME. | ||
| 708 | |||
| 709 | FRAME must be a window system frame. PBOARD is an alist of (TYPE | ||
| 710 | . DATA), where TYPE is one of the following data types that determine | ||
| 711 | the meaning of DATA: | ||
| 712 | |||
| 713 | - `string' means DATA should be a string describing text that will | ||
| 714 | be dragged to another program. | ||
| 715 | |||
| 716 | - `file' means DATA should be a file URL that will be dragged to | ||
| 717 | another program. DATA may also be a list of file names; that | ||
| 718 | means each file in the list will be dragged to another program. | ||
| 719 | |||
| 720 | ACTION is the action that will be taken by the drop target towards the | ||
| 721 | data inside PBOARD. | ||
| 722 | |||
| 723 | Return the action that the drop target actually chose to perform, or | ||
| 724 | nil if no action was performed (either because there was no drop | ||
| 725 | target, or the drop was rejected). If RETURN-FRAME is the symbol | ||
| 726 | `now', also return any frame that mouse moves into during the | ||
| 727 | drag-and-drop operation, whilst simultaneously cancelling it. Any | ||
| 728 | other non-nil value means to do the same, but to wait for the mouse to | ||
| 729 | leave FRAME first. | ||
| 730 | |||
| 731 | If ALLOW-SAME-FRAME is nil, dropping on FRAME will result in the drop | ||
| 732 | being ignored. | ||
| 733 | |||
| 734 | FOLLOW-TOOLTIP means the same thing it does in `x-begin-drag'. */) | ||
| 735 | (Lisp_Object frame, Lisp_Object pboard, Lisp_Object action, | ||
| 736 | Lisp_Object return_frame, Lisp_Object allow_same_frame, | ||
| 737 | Lisp_Object follow_tooltip) | ||
| 738 | { | ||
| 739 | struct frame *f, *return_to; | ||
| 740 | NSPasteboard *pasteboard; | ||
| 741 | EmacsWindow *window; | ||
| 742 | NSDragOperation operation; | ||
| 743 | enum ns_return_frame_mode mode; | ||
| 744 | Lisp_Object val; | ||
| 745 | |||
| 746 | if (EQ (return_frame, Qnow)) | ||
| 747 | mode = RETURN_FRAME_NOW; | ||
| 748 | else if (!NILP (return_frame)) | ||
| 749 | mode = RETURN_FRAME_EVENTUALLY; | ||
| 750 | else | ||
| 751 | mode = RETURN_FRAME_NEVER; | ||
| 752 | |||
| 753 | if (NILP (pboard)) | ||
| 754 | signal_error ("Empty pasteboard", pboard); | ||
| 755 | |||
| 756 | f = decode_window_system_frame (frame); | ||
| 757 | pasteboard = [NSPasteboard pasteboardWithName: NSPasteboardNameDrag]; | ||
| 758 | window = (EmacsWindow *) [FRAME_NS_VIEW (f) window]; | ||
| 759 | |||
| 760 | operation = ns_dnd_action_to_operation (action); | ||
| 761 | ns_lisp_to_pasteboard (pboard, pasteboard); | ||
| 762 | |||
| 763 | operation = [window beginDrag: operation | ||
| 764 | forPasteboard: pasteboard | ||
| 765 | withMode: mode | ||
| 766 | returnFrameTo: &return_to | ||
| 767 | prohibitSame: (BOOL) NILP (allow_same_frame) | ||
| 768 | followTooltip: (BOOL) !NILP (follow_tooltip)]; | ||
| 769 | |||
| 770 | if (return_to) | ||
| 771 | { | ||
| 772 | XSETFRAME (val, return_to); | ||
| 773 | return val; | ||
| 774 | } | ||
| 775 | |||
| 776 | return ns_dnd_action_from_operation (operation); | ||
| 777 | } | ||
| 778 | |||
| 562 | void | 779 | void |
| 563 | syms_of_nsselect (void) | 780 | syms_of_nsselect (void) |
| 564 | { | 781 | { |
| @@ -568,12 +785,18 @@ syms_of_nsselect (void) | |||
| 568 | DEFSYM (QFILE_NAME, "FILE_NAME"); | 785 | DEFSYM (QFILE_NAME, "FILE_NAME"); |
| 569 | 786 | ||
| 570 | DEFSYM (QTARGETS, "TARGETS"); | 787 | DEFSYM (QTARGETS, "TARGETS"); |
| 788 | DEFSYM (QXdndActionCopy, "XdndActionCopy"); | ||
| 789 | DEFSYM (QXdndActionMove, "XdndActionMove"); | ||
| 790 | DEFSYM (QXdndActionLink, "XdndActionLink"); | ||
| 791 | DEFSYM (QXdndActionPrivate, "XdndActionPrivate"); | ||
| 792 | DEFSYM (Qnow, "now"); | ||
| 571 | 793 | ||
| 572 | defsubr (&Sns_disown_selection_internal); | 794 | defsubr (&Sns_disown_selection_internal); |
| 573 | defsubr (&Sns_get_selection); | 795 | defsubr (&Sns_get_selection); |
| 574 | defsubr (&Sns_own_selection_internal); | 796 | defsubr (&Sns_own_selection_internal); |
| 575 | defsubr (&Sns_selection_exists_p); | 797 | defsubr (&Sns_selection_exists_p); |
| 576 | defsubr (&Sns_selection_owner_p); | 798 | defsubr (&Sns_selection_owner_p); |
| 799 | defsubr (&Sns_begin_drag); | ||
| 577 | 800 | ||
| 578 | Vselection_alist = Qnil; | 801 | Vselection_alist = Qnil; |
| 579 | staticpro (&Vselection_alist); | 802 | staticpro (&Vselection_alist); |
diff --git a/src/nsterm.h b/src/nsterm.h index 9d8a6f486fc..c4fdc7054f7 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -408,23 +408,48 @@ typedef id instancetype; | |||
| 408 | @end | 408 | @end |
| 409 | #endif | 409 | #endif |
| 410 | 410 | ||
| 411 | enum ns_return_frame_mode | ||
| 412 | { | ||
| 413 | RETURN_FRAME_NEVER, | ||
| 414 | RETURN_FRAME_EVENTUALLY, | ||
| 415 | RETURN_FRAME_NOW, | ||
| 416 | }; | ||
| 417 | |||
| 411 | /* EmacsWindow */ | 418 | /* EmacsWindow */ |
| 412 | @interface EmacsWindow : NSWindow | 419 | @interface EmacsWindow : NSWindow |
| 413 | { | 420 | { |
| 414 | NSPoint grabOffset; | 421 | NSPoint grabOffset; |
| 422 | NSEvent *last_drag_event; | ||
| 423 | NSDragOperation drag_op; | ||
| 424 | NSDragOperation selected_op; | ||
| 425 | |||
| 426 | struct frame *dnd_return_frame; | ||
| 427 | enum ns_return_frame_mode dnd_mode; | ||
| 428 | BOOL dnd_allow_same_frame; | ||
| 429 | BOOL dnd_move_tooltip_with_frame; | ||
| 415 | } | 430 | } |
| 416 | 431 | ||
| 417 | #ifdef NS_IMPL_GNUSTEP | 432 | #ifdef NS_IMPL_GNUSTEP |
| 418 | - (NSInteger) orderedIndex; | 433 | - (NSInteger) orderedIndex; |
| 419 | #endif | 434 | #endif |
| 420 | 435 | ||
| 421 | - (instancetype)initWithEmacsFrame:(struct frame *)f; | 436 | - (instancetype) initWithEmacsFrame: (struct frame *) f; |
| 422 | - (instancetype)initWithEmacsFrame:(struct frame *)f fullscreen:(BOOL)fullscreen screen:(NSScreen *)screen; | 437 | - (instancetype) initWithEmacsFrame: (struct frame *) f |
| 423 | - (void)createToolbar:(struct frame *)f; | 438 | fullscreen: (BOOL) fullscreen |
| 424 | - (void)setParentChildRelationships; | 439 | screen: (NSScreen *) screen; |
| 425 | - (NSInteger)borderWidth; | 440 | - (void) createToolbar: (struct frame *) f; |
| 426 | - (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above; | 441 | - (void) setParentChildRelationships; |
| 427 | - (void)setAppearance; | 442 | - (NSInteger) borderWidth; |
| 443 | - (BOOL) restackWindow: (NSWindow *) win above: (BOOL) above; | ||
| 444 | - (void) setAppearance; | ||
| 445 | - (void) setLastDragEvent: (NSEvent *) event; | ||
| 446 | - (NSDragOperation) beginDrag: (NSDragOperation) op | ||
| 447 | forPasteboard: (NSPasteboard *) pasteboard | ||
| 448 | withMode: (enum ns_return_frame_mode) mode | ||
| 449 | returnFrameTo: (struct frame **) frame_return | ||
| 450 | prohibitSame: (BOOL) prohibit_same_frame | ||
| 451 | followTooltip: (BOOL) follow_tooltip; | ||
| 452 | - (BOOL) mustNotDropOn: (NSView *) receiver; | ||
| 428 | @end | 453 | @end |
| 429 | 454 | ||
| 430 | 455 | ||
| @@ -574,22 +599,32 @@ typedef id instancetype; | |||
| 574 | ========================================================================== */ | 599 | ========================================================================== */ |
| 575 | 600 | ||
| 576 | @interface EmacsDialogPanel : NSPanel | 601 | @interface EmacsDialogPanel : NSPanel |
| 577 | { | 602 | { |
| 578 | NSTextField *command; | 603 | NSTextField *command; |
| 579 | NSTextField *title; | 604 | NSTextField *title; |
| 580 | NSMatrix *matrix; | 605 | NSMatrix *matrix; |
| 581 | int rows, cols; | 606 | int rows, cols; |
| 582 | BOOL timer_fired, window_closed; | 607 | BOOL timer_fired, window_closed; |
| 583 | Lisp_Object dialog_return; | 608 | Lisp_Object dialog_return; |
| 584 | Lisp_Object *button_values; | 609 | } |
| 585 | } | 610 | |
| 586 | - (instancetype)initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; | 611 | - (instancetype) initWithTitle: (char *) title_str |
| 587 | - (void)process_dialog: (Lisp_Object)list; | 612 | isQuestion: (BOOL) is_question; |
| 588 | - (void)addButton: (char *)str value: (int)tag row: (int)row; | 613 | - (void) processMenuItems: (Lisp_Object) menu_items |
| 589 | - (void)addString: (char *)str row: (int)row; | 614 | used: (ptrdiff_t) menu_items_used |
| 590 | - (void)addSplit; | 615 | withErrorOutput: (const char **) error_name; |
| 591 | - (Lisp_Object)runDialogAt: (NSPoint)p; | 616 | |
| 592 | - (void)timeout_handler: (NSTimer *)timedEntry; | 617 | - (void) addButton: (char *) str |
| 618 | value: (NSInteger) tag | ||
| 619 | row: (int) row | ||
| 620 | enable: (BOOL) enable; | ||
| 621 | - (void) addString: (char *) str | ||
| 622 | row: (int) row; | ||
| 623 | - (void) addSplit; | ||
| 624 | - (void) resizeBoundsPriorToDisplay; | ||
| 625 | |||
| 626 | - (Lisp_Object) runDialogAt: (NSPoint) p; | ||
| 627 | - (void) timeout_handler: (NSTimer *) timedEntry; | ||
| 593 | @end | 628 | @end |
| 594 | 629 | ||
| 595 | #ifdef NS_IMPL_COCOA | 630 | #ifdef NS_IMPL_COCOA |
| @@ -597,19 +632,21 @@ typedef id instancetype; | |||
| 597 | #else | 632 | #else |
| 598 | @interface EmacsTooltip : NSObject | 633 | @interface EmacsTooltip : NSObject |
| 599 | #endif | 634 | #endif |
| 600 | { | 635 | { |
| 601 | NSWindow *win; | 636 | NSWindow *win; |
| 602 | NSTextField *textField; | 637 | NSTextField *textField; |
| 603 | NSTimer *timer; | 638 | NSTimer *timer; |
| 604 | } | 639 | } |
| 640 | |||
| 605 | - (instancetype) init; | 641 | - (instancetype) init; |
| 606 | - (void) setText: (char *)text; | 642 | - (void) setText: (char *) text; |
| 607 | - (void) setBackgroundColor: (NSColor *)col; | 643 | - (void) setBackgroundColor: (NSColor *) col; |
| 608 | - (void) setForegroundColor: (NSColor *)col; | 644 | - (void) setForegroundColor: (NSColor *) col; |
| 609 | - (void) showAtX: (int)x Y: (int)y for: (int)seconds; | 645 | - (void) showAtX: (int) x Y: (int) y for: (int) seconds; |
| 610 | - (void) hide; | 646 | - (void) hide; |
| 611 | - (BOOL) isActive; | 647 | - (BOOL) isActive; |
| 612 | - (NSRect) frame; | 648 | - (NSRect) frame; |
| 649 | - (void) moveTo: (NSPoint) screen_point; | ||
| 613 | @end | 650 | @end |
| 614 | 651 | ||
| 615 | 652 | ||
| @@ -1107,6 +1144,9 @@ extern const char *ns_get_pending_menu_title (void); | |||
| 1107 | #endif | 1144 | #endif |
| 1108 | 1145 | ||
| 1109 | /* Implemented in nsfns, published in nsterm. */ | 1146 | /* Implemented in nsfns, published in nsterm. */ |
| 1147 | #ifdef __OBJC__ | ||
| 1148 | extern void ns_move_tooltip_to_mouse_location (NSPoint); | ||
| 1149 | #endif | ||
| 1110 | extern void ns_implicitly_set_name (struct frame *f, Lisp_Object arg, | 1150 | extern void ns_implicitly_set_name (struct frame *f, Lisp_Object arg, |
| 1111 | Lisp_Object oldval); | 1151 | Lisp_Object oldval); |
| 1112 | extern void ns_set_scroll_bar_default_width (struct frame *f); | 1152 | extern void ns_set_scroll_bar_default_width (struct frame *f); |
| @@ -1176,6 +1216,7 @@ extern size_t ns_image_size_in_bytes (void *img); | |||
| 1176 | /* This in nsterm.m */ | 1216 | /* This in nsterm.m */ |
| 1177 | extern float ns_antialias_threshold; | 1217 | extern float ns_antialias_threshold; |
| 1178 | extern void ns_make_frame_visible (struct frame *f); | 1218 | extern void ns_make_frame_visible (struct frame *f); |
| 1219 | extern void ns_make_frame_invisible (struct frame *f); | ||
| 1179 | extern void ns_iconify_frame (struct frame *f); | 1220 | extern void ns_iconify_frame (struct frame *f); |
| 1180 | extern void ns_set_undecorated (struct frame *f, Lisp_Object new_value, | 1221 | extern void ns_set_undecorated (struct frame *f, Lisp_Object new_value, |
| 1181 | Lisp_Object old_value); | 1222 | Lisp_Object old_value); |
| @@ -1312,6 +1353,7 @@ enum NSWindowTabbingMode | |||
| 1312 | #if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_13) | 1353 | #if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_13) |
| 1313 | /* Deprecated in macOS 10.13. */ | 1354 | /* Deprecated in macOS 10.13. */ |
| 1314 | #define NSPasteboardNameGeneral NSGeneralPboard | 1355 | #define NSPasteboardNameGeneral NSGeneralPboard |
| 1356 | #define NSPasteboardNameDrag NSDragPboard | ||
| 1315 | #endif | 1357 | #endif |
| 1316 | 1358 | ||
| 1317 | #if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_14) | 1359 | #if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_14) |
| @@ -1329,5 +1371,6 @@ enum NSWindowTabbingMode | |||
| 1329 | #define NSControlStateValueOn NSOnState | 1371 | #define NSControlStateValueOn NSOnState |
| 1330 | #define NSControlStateValueOff NSOffState | 1372 | #define NSControlStateValueOff NSOffState |
| 1331 | #define NSBezelStyleRounded NSRoundedBezelStyle | 1373 | #define NSBezelStyleRounded NSRoundedBezelStyle |
| 1374 | #define NSButtonTypeMomentaryPushIn NSMomentaryPushInButton | ||
| 1332 | #endif | 1375 | #endif |
| 1333 | #endif /* HAVE_NS */ | 1376 | #endif /* HAVE_NS */ |
diff --git a/src/nsterm.m b/src/nsterm.m index fef7f0dc6c8..891d52ea3f0 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -79,6 +79,9 @@ static EmacsMenu *dockMenu; | |||
| 79 | static EmacsMenu *mainMenu; | 79 | static EmacsMenu *mainMenu; |
| 80 | #endif | 80 | #endif |
| 81 | 81 | ||
| 82 | /* The last known monitor attributes list. */ | ||
| 83 | static Lisp_Object last_known_monitors; | ||
| 84 | |||
| 82 | /* ========================================================================== | 85 | /* ========================================================================== |
| 83 | 86 | ||
| 84 | NSTRACE, Trace support. | 87 | NSTRACE, Trace support. |
| @@ -89,8 +92,8 @@ static EmacsMenu *mainMenu; | |||
| 89 | 92 | ||
| 90 | /* The following use "volatile" since they can be accessed from | 93 | /* The following use "volatile" since they can be accessed from |
| 91 | parallel threads. */ | 94 | parallel threads. */ |
| 92 | volatile int nstrace_num = 0; | 95 | volatile int nstrace_num; |
| 93 | volatile int nstrace_depth = 0; | 96 | volatile int nstrace_depth; |
| 94 | 97 | ||
| 95 | /* When 0, no trace is emitted. This is used by NSTRACE_WHEN and | 98 | /* When 0, no trace is emitted. This is used by NSTRACE_WHEN and |
| 96 | NSTRACE_UNLESS to silence functions called. | 99 | NSTRACE_UNLESS to silence functions called. |
| @@ -101,33 +104,41 @@ volatile int nstrace_depth = 0; | |||
| 101 | volatile int nstrace_enabled_global = 1; | 104 | volatile int nstrace_enabled_global = 1; |
| 102 | 105 | ||
| 103 | /* Called when nstrace_enabled goes out of scope. */ | 106 | /* Called when nstrace_enabled goes out of scope. */ |
| 104 | void nstrace_leave(int * pointer_to_nstrace_enabled) | 107 | void |
| 108 | nstrace_leave (int *pointer_to_nstrace_enabled) | ||
| 105 | { | 109 | { |
| 106 | if (*pointer_to_nstrace_enabled) | 110 | if (*pointer_to_nstrace_enabled) |
| 107 | { | 111 | --nstrace_depth; |
| 108 | --nstrace_depth; | ||
| 109 | } | ||
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | 114 | ||
| 113 | /* Called when nstrace_saved_enabled_global goes out of scope. */ | 115 | /* Called when nstrace_saved_enabled_global goes out of scope. */ |
| 114 | void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global) | 116 | void |
| 117 | nstrace_restore_global_trace_state (int *pointer_to_saved_enabled_global) | ||
| 115 | { | 118 | { |
| 116 | nstrace_enabled_global = *pointer_to_saved_enabled_global; | 119 | nstrace_enabled_global = *pointer_to_saved_enabled_global; |
| 117 | } | 120 | } |
| 118 | 121 | ||
| 119 | 122 | ||
| 120 | char const * nstrace_fullscreen_type_name (int fs_type) | 123 | const char * |
| 124 | nstrace_fullscreen_type_name (int fs_type) | ||
| 121 | { | 125 | { |
| 122 | switch (fs_type) | 126 | switch (fs_type) |
| 123 | { | 127 | { |
| 124 | case -1: return "-1"; | 128 | case -1: |
| 125 | case FULLSCREEN_NONE: return "FULLSCREEN_NONE"; | 129 | return "-1"; |
| 126 | case FULLSCREEN_WIDTH: return "FULLSCREEN_WIDTH"; | 130 | case FULLSCREEN_NONE: |
| 127 | case FULLSCREEN_HEIGHT: return "FULLSCREEN_HEIGHT"; | 131 | return "FULLSCREEN_NONE"; |
| 128 | case FULLSCREEN_BOTH: return "FULLSCREEN_BOTH"; | 132 | case FULLSCREEN_WIDTH: |
| 129 | case FULLSCREEN_MAXIMIZED: return "FULLSCREEN_MAXIMIZED"; | 133 | return "FULLSCREEN_WIDTH"; |
| 130 | default: return "FULLSCREEN_?????"; | 134 | case FULLSCREEN_HEIGHT: |
| 135 | return "FULLSCREEN_HEIGHT"; | ||
| 136 | case FULLSCREEN_BOTH: | ||
| 137 | return "FULLSCREEN_BOTH"; | ||
| 138 | case FULLSCREEN_MAXIMIZED: | ||
| 139 | return "FULLSCREEN_MAXIMIZED"; | ||
| 140 | default: | ||
| 141 | return "FULLSCREEN_?????"; | ||
| 131 | } | 142 | } |
| 132 | } | 143 | } |
| 133 | #endif | 144 | #endif |
| @@ -429,28 +440,28 @@ ev_modifiers_helper (unsigned int flags, unsigned int left_mask, | |||
| 429 | 440 | ||
| 430 | /* This is a piece of code which is common to all the event handling | 441 | /* This is a piece of code which is common to all the event handling |
| 431 | methods. Maybe it should even be a function. */ | 442 | methods. Maybe it should even be a function. */ |
| 432 | #define EV_TRAILER(e) \ | 443 | #define EV_TRAILER(e) \ |
| 433 | { \ | 444 | { \ |
| 434 | XSETFRAME (emacs_event->frame_or_window, emacsframe); \ | 445 | XSETFRAME (emacs_event->frame_or_window, emacsframe); \ |
| 435 | EV_TRAILER2 (e); \ | 446 | EV_TRAILER2 (e); \ |
| 436 | } | 447 | } |
| 437 | 448 | ||
| 438 | #define EV_TRAILER2(e) \ | 449 | #define EV_TRAILER2(e) \ |
| 439 | { \ | 450 | { \ |
| 440 | if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ | 451 | if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ |
| 441 | if (q_event_ptr) \ | 452 | if (q_event_ptr) \ |
| 442 | { \ | 453 | { \ |
| 443 | Lisp_Object tem = Vinhibit_quit; \ | 454 | Lisp_Object tem = Vinhibit_quit; \ |
| 444 | Vinhibit_quit = Qt; \ | 455 | Vinhibit_quit = Qt; \ |
| 445 | n_emacs_events_pending++; \ | 456 | n_emacs_events_pending++; \ |
| 446 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ | 457 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ |
| 447 | Vinhibit_quit = tem; \ | 458 | Vinhibit_quit = tem; \ |
| 448 | } \ | 459 | } \ |
| 449 | else \ | 460 | else \ |
| 450 | hold_event (emacs_event); \ | 461 | hold_event (emacs_event); \ |
| 451 | EVENT_INIT (*emacs_event); \ | 462 | EVENT_INIT (*emacs_event); \ |
| 452 | ns_send_appdefined (-1); \ | 463 | ns_send_appdefined (-1); \ |
| 453 | } | 464 | } |
| 454 | 465 | ||
| 455 | 466 | ||
| 456 | /* TODO: Get rid of need for these forward declarations. */ | 467 | /* TODO: Get rid of need for these forward declarations. */ |
| @@ -1517,7 +1528,7 @@ ns_make_frame_visible (struct frame *f) | |||
| 1517 | } | 1528 | } |
| 1518 | 1529 | ||
| 1519 | 1530 | ||
| 1520 | static void | 1531 | void |
| 1521 | ns_make_frame_invisible (struct frame *f) | 1532 | ns_make_frame_invisible (struct frame *f) |
| 1522 | /* -------------------------------------------------------------------------- | 1533 | /* -------------------------------------------------------------------------- |
| 1523 | Hide the window (X11 semantics) | 1534 | Hide the window (X11 semantics) |
| @@ -1708,10 +1719,8 @@ ns_set_offset (struct frame *f, int xoff, int yoff, int change_grav) | |||
| 1708 | 1719 | ||
| 1709 | 1720 | ||
| 1710 | static void | 1721 | static void |
| 1711 | ns_set_window_size (struct frame *f, | 1722 | ns_set_window_size (struct frame *f, bool change_gravity, |
| 1712 | bool change_gravity, | 1723 | int width, int height) |
| 1713 | int width, | ||
| 1714 | int height) | ||
| 1715 | /* -------------------------------------------------------------------------- | 1724 | /* -------------------------------------------------------------------------- |
| 1716 | Adjust window pixel size based on native sizes WIDTH and HEIGHT. | 1725 | Adjust window pixel size based on native sizes WIDTH and HEIGHT. |
| 1717 | Impl is a bit more complex than other terms, need to do some | 1726 | Impl is a bit more complex than other terms, need to do some |
| @@ -2288,6 +2297,11 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 2288 | struct frame *f = NULL; | 2297 | struct frame *f = NULL; |
| 2289 | struct ns_display_info *dpyinfo; | 2298 | struct ns_display_info *dpyinfo; |
| 2290 | bool return_no_frame_flag = false; | 2299 | bool return_no_frame_flag = false; |
| 2300 | #ifdef NS_IMPL_COCOA | ||
| 2301 | NSPoint screen_position; | ||
| 2302 | NSInteger window_number; | ||
| 2303 | NSWindow *w; | ||
| 2304 | #endif | ||
| 2291 | 2305 | ||
| 2292 | NSTRACE ("ns_mouse_position"); | 2306 | NSTRACE ("ns_mouse_position"); |
| 2293 | 2307 | ||
| @@ -2314,18 +2328,29 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 2314 | This doesn't work on GNUstep, although in recent versions there | 2328 | This doesn't work on GNUstep, although in recent versions there |
| 2315 | is compatibility code that makes it a noop. */ | 2329 | is compatibility code that makes it a noop. */ |
| 2316 | 2330 | ||
| 2317 | NSPoint screen_position = [NSEvent mouseLocation]; | 2331 | screen_position = [NSEvent mouseLocation]; |
| 2318 | NSInteger window_number = 0; | 2332 | window_number = 0; |
| 2333 | |||
| 2319 | do | 2334 | do |
| 2320 | { | 2335 | { |
| 2321 | NSWindow *w; | 2336 | window_number = [NSWindow windowNumberAtPoint: screen_position |
| 2337 | belowWindowWithWindowNumber: window_number]; | ||
| 2338 | w = [NSApp windowWithWindowNumber: window_number]; | ||
| 2322 | 2339 | ||
| 2323 | window_number = [NSWindow windowNumberAtPoint:screen_position | 2340 | if ((EQ (track_mouse, Qdrag_source) |
| 2324 | belowWindowWithWindowNumber:window_number]; | 2341 | || EQ (track_mouse, Qdropping)) |
| 2325 | w = [NSApp windowWithWindowNumber:window_number]; | 2342 | && w && [[w delegate] isKindOfClass: [EmacsTooltip class]]) |
| 2343 | continue; | ||
| 2326 | 2344 | ||
| 2327 | if (w && [[w delegate] isKindOfClass:[EmacsView class]]) | 2345 | if (w && [[w delegate] isKindOfClass: [EmacsView class]]) |
| 2328 | f = ((EmacsView *)[w delegate])->emacsframe; | 2346 | f = ((EmacsView *) [w delegate])->emacsframe; |
| 2347 | else if (EQ (track_mouse, Qdrag_source)) | ||
| 2348 | break; | ||
| 2349 | |||
| 2350 | if (f && (EQ (track_mouse, Qdrag_source) | ||
| 2351 | || EQ (track_mouse, Qdropping)) | ||
| 2352 | && FRAME_TOOLTIP_P (f)) | ||
| 2353 | continue; | ||
| 2329 | } | 2354 | } |
| 2330 | while (window_number > 0 && !f); | 2355 | while (window_number > 0 && !f); |
| 2331 | #endif | 2356 | #endif |
| @@ -2340,6 +2365,9 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 2340 | if (!FRAME_NS_P (f)) | 2365 | if (!FRAME_NS_P (f)) |
| 2341 | f = NULL; | 2366 | f = NULL; |
| 2342 | 2367 | ||
| 2368 | if (f && FRAME_TOOLTIP_P (f)) | ||
| 2369 | f = dpyinfo->last_mouse_frame; | ||
| 2370 | |||
| 2343 | /* While dropping, use the last mouse frame only if there is no | 2371 | /* While dropping, use the last mouse frame only if there is no |
| 2344 | currently focused frame. */ | 2372 | currently focused frame. */ |
| 2345 | if (!f && (EQ (track_mouse, Qdropping) | 2373 | if (!f && (EQ (track_mouse, Qdropping) |
| @@ -3079,7 +3107,9 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3079 | break; | 3107 | break; |
| 3080 | case HOLLOW_BOX_CURSOR: | 3108 | case HOLLOW_BOX_CURSOR: |
| 3081 | draw_phys_cursor_glyph (w, glyph_row, DRAW_NORMAL_TEXT); | 3109 | draw_phys_cursor_glyph (w, glyph_row, DRAW_NORMAL_TEXT); |
| 3082 | [NSBezierPath strokeRect: r]; | 3110 | |
| 3111 | /* This works like it does in PostScript, not X Windows. */ | ||
| 3112 | [NSBezierPath strokeRect: NSInsetRect (r, 0.5, 0.5)]; | ||
| 3083 | break; | 3113 | break; |
| 3084 | case HBAR_CURSOR: | 3114 | case HBAR_CURSOR: |
| 3085 | NSRectFill (r); | 3115 | NSRectFill (r); |
| @@ -3448,36 +3478,35 @@ ns_draw_box (NSRect r, CGFloat hthickness, CGFloat vthickness, | |||
| 3448 | 3478 | ||
| 3449 | static void | 3479 | static void |
| 3450 | ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p, | 3480 | ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p, |
| 3451 | char top_p, char bottom_p, char left_p, char right_p, | 3481 | char top_p, char bottom_p, char left_p, char right_p, |
| 3452 | struct glyph_string *s) | 3482 | struct glyph_string *s) |
| 3453 | /* -------------------------------------------------------------------------- | 3483 | /* -------------------------------------------------------------------------- |
| 3454 | Draw a relief rect inside r, optionally leaving some sides open. | 3484 | Draw a relief rect inside r, optionally leaving some sides open. |
| 3455 | Note we can't just use an NSDrawBezel command, because of the possibility | 3485 | Note we can't just use an NSDrawBezel command, because of the possibility |
| 3456 | of some sides not being drawn, and because the rect will be filled. | 3486 | of some sides not being drawn, and because the rect will be filled. |
| 3457 | -------------------------------------------------------------------------- */ | 3487 | -------------------------------------------------------------------------- */ |
| 3458 | { | 3488 | { |
| 3459 | static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil; | 3489 | static NSColor *baseCol, *lightCol, *darkCol; |
| 3460 | NSColor *newBaseCol = nil; | 3490 | NSColor *newBaseCol; |
| 3461 | NSRect inner; | 3491 | NSRect inner; |
| 3492 | NSBezierPath *p; | ||
| 3493 | |||
| 3494 | baseCol = nil; | ||
| 3495 | lightCol = nil; | ||
| 3496 | newBaseCol = nil; | ||
| 3497 | p = nil; | ||
| 3462 | 3498 | ||
| 3463 | NSTRACE ("ns_draw_relief"); | 3499 | NSTRACE ("ns_draw_relief"); |
| 3464 | 3500 | ||
| 3465 | /* set up colors */ | 3501 | /* set up colors */ |
| 3466 | 3502 | ||
| 3467 | if (s->face->use_box_color_for_shadows_p) | 3503 | if (s->face->use_box_color_for_shadows_p) |
| 3468 | { | 3504 | newBaseCol = [NSColor colorWithUnsignedLong: s->face->box_color]; |
| 3469 | newBaseCol = [NSColor colorWithUnsignedLong:s->face->box_color]; | ||
| 3470 | } | ||
| 3471 | /* else if (s->first_glyph->type == IMAGE_GLYPH | ||
| 3472 | && s->img->pixmap | ||
| 3473 | && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) | ||
| 3474 | { | ||
| 3475 | newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0); | ||
| 3476 | } */ | ||
| 3477 | else | 3505 | else |
| 3478 | { | 3506 | newBaseCol = [NSColor colorWithUnsignedLong: s->face->background]; |
| 3479 | newBaseCol = [NSColor colorWithUnsignedLong:s->face->background]; | 3507 | |
| 3480 | } | 3508 | if (s->hl == DRAW_CURSOR) |
| 3509 | newBaseCol = FRAME_CURSOR_COLOR (s->f); | ||
| 3481 | 3510 | ||
| 3482 | if (newBaseCol == nil) | 3511 | if (newBaseCol == nil) |
| 3483 | newBaseCol = [NSColor grayColor]; | 3512 | newBaseCol = [NSColor grayColor]; |
| @@ -3487,35 +3516,49 @@ ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p, | |||
| 3487 | [baseCol release]; | 3516 | [baseCol release]; |
| 3488 | baseCol = [newBaseCol retain]; | 3517 | baseCol = [newBaseCol retain]; |
| 3489 | [lightCol release]; | 3518 | [lightCol release]; |
| 3490 | lightCol = [[baseCol highlightWithLevel: 0.2] retain]; | 3519 | lightCol = [[baseCol highlightWithLevel: 0.4] retain]; |
| 3491 | [darkCol release]; | 3520 | [darkCol release]; |
| 3492 | darkCol = [[baseCol shadowWithLevel: 0.3] retain]; | 3521 | darkCol = [[baseCol shadowWithLevel: 0.4] retain]; |
| 3493 | } | 3522 | } |
| 3494 | 3523 | ||
| 3495 | /* Calculate the inner rectangle. */ | 3524 | /* Calculate the inner rectangle. */ |
| 3496 | inner = NSMakeRect (NSMinX (outer) + (left_p ? hthickness : 0), | 3525 | inner = outer; |
| 3497 | NSMinY (outer) + (top_p ? vthickness : 0), | 3526 | |
| 3498 | NSWidth (outer) - (left_p ? hthickness : 0) | 3527 | if (left_p) |
| 3499 | - (right_p ? hthickness : 0), | 3528 | { |
| 3500 | NSHeight (outer) - (top_p ? vthickness : 0) | 3529 | inner.origin.x += vthickness; |
| 3501 | - (bottom_p ? vthickness : 0)); | 3530 | inner.size.width -= vthickness; |
| 3531 | } | ||
| 3532 | |||
| 3533 | if (right_p) | ||
| 3534 | inner.size.width -= vthickness; | ||
| 3535 | |||
| 3536 | if (top_p) | ||
| 3537 | { | ||
| 3538 | inner.origin.y += hthickness; | ||
| 3539 | inner.size.height -= hthickness; | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | if (bottom_p) | ||
| 3543 | inner.size.height -= hthickness; | ||
| 3502 | 3544 | ||
| 3503 | [(raised_p ? lightCol : darkCol) set]; | 3545 | [(raised_p ? lightCol : darkCol) set]; |
| 3504 | 3546 | ||
| 3505 | if (top_p || left_p) | 3547 | if (top_p || left_p) |
| 3506 | { | 3548 | { |
| 3507 | NSBezierPath *p = [NSBezierPath bezierPath]; | 3549 | p = [NSBezierPath bezierPath]; |
| 3508 | [p moveToPoint:NSMakePoint (NSMinX (outer), NSMinY (outer))]; | 3550 | |
| 3551 | [p moveToPoint: NSMakePoint (NSMinX (outer), NSMinY (outer))]; | ||
| 3509 | if (top_p) | 3552 | if (top_p) |
| 3510 | { | 3553 | { |
| 3511 | [p lineToPoint:NSMakePoint (NSMaxX (outer), NSMinY (outer))]; | 3554 | [p lineToPoint: NSMakePoint (NSMaxX (outer), NSMinY (outer))]; |
| 3512 | [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMinY (inner))]; | 3555 | [p lineToPoint: NSMakePoint (NSMaxX (inner), NSMinY (inner))]; |
| 3513 | } | 3556 | } |
| 3514 | [p lineToPoint:NSMakePoint (NSMinX (inner), NSMinY (inner))]; | 3557 | [p lineToPoint: NSMakePoint (NSMinX (inner), NSMinY (inner))]; |
| 3515 | if (left_p) | 3558 | if (left_p) |
| 3516 | { | 3559 | { |
| 3517 | [p lineToPoint:NSMakePoint (NSMinX (inner), NSMaxY (inner))]; | 3560 | [p lineToPoint: NSMakePoint (NSMinX (inner), NSMaxY (inner))]; |
| 3518 | [p lineToPoint:NSMakePoint (NSMinX (outer), NSMaxY (outer))]; | 3561 | [p lineToPoint: NSMakePoint (NSMinX (outer), NSMaxY (outer))]; |
| 3519 | } | 3562 | } |
| 3520 | [p closePath]; | 3563 | [p closePath]; |
| 3521 | [p fill]; | 3564 | [p fill]; |
| @@ -3523,24 +3566,93 @@ ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p, | |||
| 3523 | 3566 | ||
| 3524 | [(raised_p ? darkCol : lightCol) set]; | 3567 | [(raised_p ? darkCol : lightCol) set]; |
| 3525 | 3568 | ||
| 3526 | if (bottom_p || right_p) | 3569 | if (bottom_p || right_p) |
| 3527 | { | 3570 | { |
| 3528 | NSBezierPath *p = [NSBezierPath bezierPath]; | 3571 | p = [NSBezierPath bezierPath]; |
| 3529 | [p moveToPoint:NSMakePoint (NSMaxX (outer), NSMaxY (outer))]; | 3572 | |
| 3573 | [p moveToPoint: NSMakePoint (NSMaxX (outer), NSMaxY (outer))]; | ||
| 3530 | if (right_p) | 3574 | if (right_p) |
| 3531 | { | 3575 | { |
| 3532 | [p lineToPoint:NSMakePoint (NSMaxX (outer), NSMinY (outer))]; | 3576 | [p lineToPoint: NSMakePoint (NSMaxX (outer), NSMinY (outer))]; |
| 3533 | [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMinY (inner))]; | 3577 | [p lineToPoint: NSMakePoint (NSMaxX (inner), NSMinY (inner))]; |
| 3534 | } | 3578 | } |
| 3535 | [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMaxY (inner))]; | 3579 | [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMaxY (inner))]; |
| 3536 | if (bottom_p) | 3580 | if (bottom_p) |
| 3537 | { | 3581 | { |
| 3538 | [p lineToPoint:NSMakePoint (NSMinX (inner), NSMaxY (inner))]; | 3582 | [p lineToPoint: NSMakePoint (NSMinX (inner), NSMaxY (inner))]; |
| 3539 | [p lineToPoint:NSMakePoint (NSMinX (outer), NSMaxY (outer))]; | 3583 | [p lineToPoint: NSMakePoint (NSMinX (outer), NSMaxY (outer))]; |
| 3540 | } | 3584 | } |
| 3541 | [p closePath]; | 3585 | [p closePath]; |
| 3542 | [p fill]; | 3586 | [p fill]; |
| 3543 | } | 3587 | } |
| 3588 | |||
| 3589 | /* If one of h/vthickness are more than 1, draw the outermost line | ||
| 3590 | on the respective sides in the black relief color. */ | ||
| 3591 | |||
| 3592 | if (p) | ||
| 3593 | [p removeAllPoints]; | ||
| 3594 | else | ||
| 3595 | p = [NSBezierPath bezierPath]; | ||
| 3596 | |||
| 3597 | if (hthickness > 1 && top_p) | ||
| 3598 | { | ||
| 3599 | [p moveToPoint: NSMakePoint (NSMinX (outer), | ||
| 3600 | NSMinY (outer) + 0.5)]; | ||
| 3601 | [p lineToPoint: NSMakePoint (NSMaxX (outer), | ||
| 3602 | NSMinY (outer) + 0.5)]; | ||
| 3603 | } | ||
| 3604 | |||
| 3605 | if (hthickness > 1 && bottom_p) | ||
| 3606 | { | ||
| 3607 | [p moveToPoint: NSMakePoint (NSMinX (outer), | ||
| 3608 | NSMaxY (outer) - 0.5)]; | ||
| 3609 | [p lineToPoint: NSMakePoint (NSMaxX (outer), | ||
| 3610 | NSMaxY (outer) - 0.5)]; | ||
| 3611 | } | ||
| 3612 | |||
| 3613 | if (vthickness > 1 && left_p) | ||
| 3614 | { | ||
| 3615 | [p moveToPoint: NSMakePoint (NSMinX (outer) + 0.5, | ||
| 3616 | NSMinY (outer) + 0.5)]; | ||
| 3617 | [p lineToPoint: NSMakePoint (NSMinX (outer) + 0.5, | ||
| 3618 | NSMaxY (outer) - 0.5)]; | ||
| 3619 | } | ||
| 3620 | |||
| 3621 | if (vthickness > 1 && left_p) | ||
| 3622 | { | ||
| 3623 | [p moveToPoint: NSMakePoint (NSMinX (outer) + 0.5, | ||
| 3624 | NSMinY (outer) + 0.5)]; | ||
| 3625 | [p lineToPoint: NSMakePoint (NSMinX (outer) + 0.5, | ||
| 3626 | NSMaxY (outer) - 0.5)]; | ||
| 3627 | } | ||
| 3628 | |||
| 3629 | [darkCol set]; | ||
| 3630 | [p stroke]; | ||
| 3631 | |||
| 3632 | if (vthickness > 1 && hthickness > 1) | ||
| 3633 | { | ||
| 3634 | [FRAME_BACKGROUND_COLOR (s->f) set]; | ||
| 3635 | |||
| 3636 | if (left_p && top_p) | ||
| 3637 | [NSBezierPath fillRect: NSMakeRect (NSMinX (outer), | ||
| 3638 | NSMinY (outer), | ||
| 3639 | 1, 1)]; | ||
| 3640 | |||
| 3641 | if (right_p && top_p) | ||
| 3642 | [NSBezierPath fillRect: NSMakeRect (NSMaxX (outer) - 1, | ||
| 3643 | NSMinY (outer), | ||
| 3644 | 1, 1)]; | ||
| 3645 | |||
| 3646 | if (right_p && bottom_p) | ||
| 3647 | [NSBezierPath fillRect: NSMakeRect (NSMaxX (outer) - 1, | ||
| 3648 | NSMaxY (outer) - 1, | ||
| 3649 | 1, 1)]; | ||
| 3650 | |||
| 3651 | if (left_p && bottom_p) | ||
| 3652 | [NSBezierPath fillRect: NSMakeRect (NSMinX (outer), | ||
| 3653 | NSMaxY (outer) - 1, | ||
| 3654 | 1, 1)]; | ||
| 3655 | } | ||
| 3544 | } | 3656 | } |
| 3545 | 3657 | ||
| 3546 | 3658 | ||
| @@ -3622,6 +3734,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) | |||
| 3622 | if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/) | 3734 | if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/) |
| 3623 | { | 3735 | { |
| 3624 | int box_line_width = max (s->face->box_horizontal_line_width, 0); | 3736 | int box_line_width = max (s->face->box_horizontal_line_width, 0); |
| 3737 | |||
| 3625 | if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width | 3738 | if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width |
| 3626 | /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font | 3739 | /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font |
| 3627 | dimensions, since the actual glyphs might be much | 3740 | dimensions, since the actual glyphs might be much |
| @@ -3648,7 +3761,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) | |||
| 3648 | 3761 | ||
| 3649 | NSRect r = NSMakeRect (s->x, s->y + box_line_width, | 3762 | NSRect r = NSMakeRect (s->x, s->y + box_line_width, |
| 3650 | s->background_width, | 3763 | s->background_width, |
| 3651 | s->height-2*box_line_width); | 3764 | s->height - 2 * box_line_width); |
| 3652 | NSRectFill (r); | 3765 | NSRectFill (r); |
| 3653 | 3766 | ||
| 3654 | s->background_filled_p = 1; | 3767 | s->background_filled_p = 1; |
| @@ -3656,6 +3769,92 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) | |||
| 3656 | } | 3769 | } |
| 3657 | } | 3770 | } |
| 3658 | 3771 | ||
| 3772 | static void | ||
| 3773 | ns_draw_image_relief (struct glyph_string *s) | ||
| 3774 | { | ||
| 3775 | int x1, y1, thick; | ||
| 3776 | bool raised_p, top_p, bot_p, left_p, right_p; | ||
| 3777 | int extra_x, extra_y; | ||
| 3778 | int x = s->x; | ||
| 3779 | int y = s->ybase - image_ascent (s->img, s->face, &s->slice); | ||
| 3780 | |||
| 3781 | /* If first glyph of S has a left box line, start drawing it to the | ||
| 3782 | right of that line. */ | ||
| 3783 | if (s->face->box != FACE_NO_BOX | ||
| 3784 | && s->first_glyph->left_box_line_p | ||
| 3785 | && s->slice.x == 0) | ||
| 3786 | x += max (s->face->box_vertical_line_width, 0); | ||
| 3787 | |||
| 3788 | /* If there is a margin around the image, adjust x- and y-position | ||
| 3789 | by that margin. */ | ||
| 3790 | if (s->slice.x == 0) | ||
| 3791 | x += s->img->hmargin; | ||
| 3792 | if (s->slice.y == 0) | ||
| 3793 | y += s->img->vmargin; | ||
| 3794 | |||
| 3795 | if (s->hl == DRAW_IMAGE_SUNKEN | ||
| 3796 | || s->hl == DRAW_IMAGE_RAISED) | ||
| 3797 | { | ||
| 3798 | if (s->face->id == TAB_BAR_FACE_ID) | ||
| 3799 | thick = (tab_bar_button_relief < 0 | ||
| 3800 | ? DEFAULT_TAB_BAR_BUTTON_RELIEF | ||
| 3801 | : min (tab_bar_button_relief, 1000000)); | ||
| 3802 | else | ||
| 3803 | thick = (tool_bar_button_relief < 0 | ||
| 3804 | ? DEFAULT_TOOL_BAR_BUTTON_RELIEF | ||
| 3805 | : min (tool_bar_button_relief, 1000000)); | ||
| 3806 | raised_p = s->hl == DRAW_IMAGE_RAISED; | ||
| 3807 | } | ||
| 3808 | else | ||
| 3809 | { | ||
| 3810 | thick = eabs (s->img->relief); | ||
| 3811 | raised_p = s->img->relief > 0; | ||
| 3812 | } | ||
| 3813 | |||
| 3814 | x1 = x + s->slice.width - 1; | ||
| 3815 | y1 = y + s->slice.height - 1; | ||
| 3816 | |||
| 3817 | extra_x = extra_y = 0; | ||
| 3818 | if (s->face->id == TAB_BAR_FACE_ID) | ||
| 3819 | { | ||
| 3820 | if (CONSP (Vtab_bar_button_margin) | ||
| 3821 | && FIXNUMP (XCAR (Vtab_bar_button_margin)) | ||
| 3822 | && FIXNUMP (XCDR (Vtab_bar_button_margin))) | ||
| 3823 | { | ||
| 3824 | extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick; | ||
| 3825 | extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick; | ||
| 3826 | } | ||
| 3827 | else if (FIXNUMP (Vtab_bar_button_margin)) | ||
| 3828 | extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick; | ||
| 3829 | } | ||
| 3830 | |||
| 3831 | if (s->face->id == TOOL_BAR_FACE_ID) | ||
| 3832 | { | ||
| 3833 | if (CONSP (Vtool_bar_button_margin) | ||
| 3834 | && FIXNUMP (XCAR (Vtool_bar_button_margin)) | ||
| 3835 | && FIXNUMP (XCDR (Vtool_bar_button_margin))) | ||
| 3836 | { | ||
| 3837 | extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin)); | ||
| 3838 | extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin)); | ||
| 3839 | } | ||
| 3840 | else if (FIXNUMP (Vtool_bar_button_margin)) | ||
| 3841 | extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin); | ||
| 3842 | } | ||
| 3843 | |||
| 3844 | top_p = bot_p = left_p = right_p = false; | ||
| 3845 | |||
| 3846 | if (s->slice.x == 0) | ||
| 3847 | x -= thick + extra_x, left_p = true; | ||
| 3848 | if (s->slice.y == 0) | ||
| 3849 | y -= thick + extra_y, top_p = true; | ||
| 3850 | if (s->slice.x + s->slice.width == s->img->width) | ||
| 3851 | x1 += thick + extra_x, right_p = true; | ||
| 3852 | if (s->slice.y + s->slice.height == s->img->height) | ||
| 3853 | y1 += thick + extra_y, bot_p = true; | ||
| 3854 | |||
| 3855 | ns_draw_relief (NSMakeRect (x, y, x1 - x + 1, y1 - y + 1), thick, | ||
| 3856 | thick, raised_p, top_p, bot_p, left_p, right_p, s); | ||
| 3857 | } | ||
| 3659 | 3858 | ||
| 3660 | static void | 3859 | static void |
| 3661 | ns_dumpglyphs_image (struct glyph_string *s, NSRect r) | 3860 | ns_dumpglyphs_image (struct glyph_string *s, NSRect r) |
| @@ -3667,8 +3866,6 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) | |||
| 3667 | int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); | 3866 | int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); |
| 3668 | int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice); | 3867 | int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice); |
| 3669 | int bg_x, bg_y, bg_height; | 3868 | int bg_x, bg_y, bg_height; |
| 3670 | int th; | ||
| 3671 | char raised_p; | ||
| 3672 | NSRect br; | 3869 | NSRect br; |
| 3673 | struct face *face = s->face; | 3870 | struct face *face = s->face; |
| 3674 | NSColor *tdCol; | 3871 | NSColor *tdCol; |
| @@ -3762,51 +3959,29 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) | |||
| 3762 | if (s->hl == DRAW_CURSOR) | 3959 | if (s->hl == DRAW_CURSOR) |
| 3763 | { | 3960 | { |
| 3764 | [FRAME_CURSOR_COLOR (s->f) set]; | 3961 | [FRAME_CURSOR_COLOR (s->f) set]; |
| 3765 | tdCol = [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)]; | 3962 | tdCol = [NSColor colorWithUnsignedLong: NS_FACE_BACKGROUND (face)]; |
| 3766 | } | 3963 | } |
| 3767 | else | 3964 | else |
| 3768 | { | 3965 | tdCol = [NSColor colorWithUnsignedLong: NS_FACE_FOREGROUND (face)]; |
| 3769 | tdCol = [NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (face)]; | ||
| 3770 | } | ||
| 3771 | 3966 | ||
| 3772 | /* Draw underline, overline, strike-through. */ | 3967 | /* Draw underline, overline, strike-through. */ |
| 3773 | ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x); | 3968 | ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x); |
| 3774 | 3969 | ||
| 3775 | /* Draw relief, if requested */ | 3970 | /* If we must draw a relief around the image, do it. */ |
| 3776 | if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN) | 3971 | if (s->img->relief |
| 3777 | { | 3972 | || s->hl == DRAW_IMAGE_RAISED |
| 3778 | if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) | 3973 | || s->hl == DRAW_IMAGE_SUNKEN) |
| 3779 | { | 3974 | ns_draw_image_relief (s); |
| 3780 | th = (tool_bar_button_relief < 0 | ||
| 3781 | ? DEFAULT_TOOL_BAR_BUTTON_RELIEF | ||
| 3782 | : min (tool_bar_button_relief, 1000000)); | ||
| 3783 | raised_p = (s->hl == DRAW_IMAGE_RAISED); | ||
| 3784 | } | ||
| 3785 | else | ||
| 3786 | { | ||
| 3787 | th = abs (s->img->relief); | ||
| 3788 | raised_p = (s->img->relief > 0); | ||
| 3789 | } | ||
| 3790 | |||
| 3791 | r.origin.x = x - th; | ||
| 3792 | r.origin.y = y - th; | ||
| 3793 | r.size.width = s->slice.width + 2*th-1; | ||
| 3794 | r.size.height = s->slice.height + 2*th-1; | ||
| 3795 | ns_draw_relief (r, th, th, raised_p, | ||
| 3796 | s->slice.y == 0, | ||
| 3797 | s->slice.y + s->slice.height == s->img->height, | ||
| 3798 | s->slice.x == 0, | ||
| 3799 | s->slice.x + s->slice.width == s->img->width, s); | ||
| 3800 | } | ||
| 3801 | 3975 | ||
| 3802 | /* If there is no mask, the background won't be seen, | 3976 | /* If there is no mask, the background won't be seen, so draw a |
| 3803 | so draw a rectangle on the image for the cursor. | 3977 | rectangle on the image for the cursor. Do this for all images, |
| 3804 | Do this for all images, getting transparency right is not reliable. */ | 3978 | getting transparency right is not reliable. */ |
| 3805 | if (s->hl == DRAW_CURSOR) | 3979 | if (s->hl == DRAW_CURSOR) |
| 3806 | { | 3980 | { |
| 3807 | int thickness = abs (s->img->relief); | 3981 | int thickness = abs (s->img->relief); |
| 3808 | if (thickness == 0) thickness = 1; | 3982 | if (thickness == 0) thickness = 1; |
| 3809 | ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1); | 3983 | ns_draw_box (br, thickness, thickness, |
| 3984 | FRAME_CURSOR_COLOR (s->f), 1, 1); | ||
| 3810 | } | 3985 | } |
| 3811 | } | 3986 | } |
| 3812 | 3987 | ||
| @@ -4035,6 +4210,10 @@ ns_draw_glyphless_glyph_string_foreground (struct glyph_string *s) | |||
| 4035 | YES, YES); | 4210 | YES, YES); |
| 4036 | x += glyph->pixel_width; | 4211 | x += glyph->pixel_width; |
| 4037 | } | 4212 | } |
| 4213 | |||
| 4214 | /* GCC 12 complains even though nothing ever uses s->char2b after | ||
| 4215 | this function returns. */ | ||
| 4216 | s->char2b = NULL; | ||
| 4038 | } | 4217 | } |
| 4039 | 4218 | ||
| 4040 | static void | 4219 | static void |
| @@ -4363,11 +4542,14 @@ check_native_fs () | |||
| 4363 | 4542 | ||
| 4364 | 4543 | ||
| 4365 | static int | 4544 | static int |
| 4366 | ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | 4545 | ns_read_socket_1 (struct terminal *terminal, struct input_event *hold_quit, |
| 4546 | BOOL no_release) | ||
| 4367 | /* -------------------------------------------------------------------------- | 4547 | /* -------------------------------------------------------------------------- |
| 4368 | External (hook): Post an event to ourself and keep reading events until | 4548 | External (hook): Post an event to ourself and keep reading events until |
| 4369 | we read it back again. In effect process all events which were waiting. | 4549 | we read it back again. In effect process all events which were waiting. |
| 4370 | From 21+ we have to manage the event buffer ourselves. | 4550 | From 21+ we have to manage the event buffer ourselves. |
| 4551 | |||
| 4552 | NO_RELEASE means not to touch the global autorelease pool. | ||
| 4371 | -------------------------------------------------------------------------- */ | 4553 | -------------------------------------------------------------------------- */ |
| 4372 | { | 4554 | { |
| 4373 | struct input_event ev; | 4555 | struct input_event ev; |
| @@ -4398,11 +4580,14 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 4398 | ns_init_events (&ev); | 4580 | ns_init_events (&ev); |
| 4399 | q_event_ptr = hold_quit; | 4581 | q_event_ptr = hold_quit; |
| 4400 | 4582 | ||
| 4401 | /* We manage autorelease pools by allocate/reallocate each time around | 4583 | if (!no_release) |
| 4402 | the loop; strict nesting is occasionally violated but seems not to | 4584 | { |
| 4403 | matter... earlier methods using full nesting caused major memory leaks. */ | 4585 | /* We manage autorelease pools by allocate/reallocate each time around |
| 4404 | [outerpool release]; | 4586 | the loop; strict nesting is occasionally violated but seems not to |
| 4405 | outerpool = [[NSAutoreleasePool alloc] init]; | 4587 | matter... earlier methods using full nesting caused major memory leaks. */ |
| 4588 | [outerpool release]; | ||
| 4589 | outerpool = [[NSAutoreleasePool alloc] init]; | ||
| 4590 | } | ||
| 4406 | 4591 | ||
| 4407 | /* If have pending open-file requests, attend to the next one of those. */ | 4592 | /* If have pending open-file requests, attend to the next one of those. */ |
| 4408 | if (ns_pending_files && [ns_pending_files count] != 0 | 4593 | if (ns_pending_files && [ns_pending_files count] != 0 |
| @@ -4441,6 +4626,12 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 4441 | return nevents; | 4626 | return nevents; |
| 4442 | } | 4627 | } |
| 4443 | 4628 | ||
| 4629 | static int | ||
| 4630 | ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | ||
| 4631 | { | ||
| 4632 | return ns_read_socket_1 (terminal, hold_quit, NO); | ||
| 4633 | } | ||
| 4634 | |||
| 4444 | 4635 | ||
| 4445 | static int | 4636 | static int |
| 4446 | ns_select_1 (int nfds, fd_set *readfds, fd_set *writefds, | 4637 | ns_select_1 (int nfds, fd_set *readfds, fd_set *writefds, |
| @@ -5022,11 +5213,22 @@ ns_update_window_end (struct window *w, bool cursor_on_p, | |||
| 5022 | } | 5213 | } |
| 5023 | #endif | 5214 | #endif |
| 5024 | 5215 | ||
| 5025 | /* This and next define (many of the) public functions in this file. */ | 5216 | static void |
| 5026 | /* gui_* are generic versions in xdisp.c that we, and other terms, get away | 5217 | ns_flush_display (struct frame *f) |
| 5027 | with using despite presence in the "system dependent" redisplay | 5218 | { |
| 5028 | interface. In addition, many of the ns_ methods have code that is | 5219 | struct input_event ie; |
| 5029 | shared with all terms, indicating need for further refactoring. */ | 5220 | |
| 5221 | EVENT_INIT (ie); | ||
| 5222 | ns_read_socket_1 (FRAME_TERMINAL (f), &ie, YES); | ||
| 5223 | } | ||
| 5224 | |||
| 5225 | /* This and next define (many of the) public functions in this | ||
| 5226 | file. */ | ||
| 5227 | /* gui_* are generic versions in xdisp.c that we, and other terms, get | ||
| 5228 | away with using despite presence in the "system dependent" | ||
| 5229 | redisplay interface. In addition, many of the ns_ methods have | ||
| 5230 | code that is shared with all terms, indicating need for further | ||
| 5231 | refactoring. */ | ||
| 5030 | extern frame_parm_handler ns_frame_parm_handlers[]; | 5232 | extern frame_parm_handler ns_frame_parm_handlers[]; |
| 5031 | static struct redisplay_interface ns_redisplay_interface = | 5233 | static struct redisplay_interface ns_redisplay_interface = |
| 5032 | { | 5234 | { |
| @@ -5043,7 +5245,7 @@ static struct redisplay_interface ns_redisplay_interface = | |||
| 5043 | #else | 5245 | #else |
| 5044 | ns_update_window_end, | 5246 | ns_update_window_end, |
| 5045 | #endif | 5247 | #endif |
| 5046 | 0, /* flush_display */ | 5248 | ns_flush_display, |
| 5047 | gui_clear_window_mouse_face, | 5249 | gui_clear_window_mouse_face, |
| 5048 | gui_get_glyph_overhangs, | 5250 | gui_get_glyph_overhangs, |
| 5049 | gui_fix_overlapping_area, | 5251 | gui_fix_overlapping_area, |
| @@ -5064,6 +5266,39 @@ static struct redisplay_interface ns_redisplay_interface = | |||
| 5064 | ns_default_font_parameter | 5266 | ns_default_font_parameter |
| 5065 | }; | 5267 | }; |
| 5066 | 5268 | ||
| 5269 | #ifdef NS_IMPL_COCOA | ||
| 5270 | static void | ||
| 5271 | ns_displays_reconfigured (CGDirectDisplayID display, | ||
| 5272 | CGDisplayChangeSummaryFlags flags, | ||
| 5273 | void *user_info) | ||
| 5274 | { | ||
| 5275 | struct input_event ie; | ||
| 5276 | union buffered_input_event *ev; | ||
| 5277 | Lisp_Object new_monitors; | ||
| 5278 | |||
| 5279 | EVENT_INIT (ie); | ||
| 5280 | |||
| 5281 | new_monitors = Fns_display_monitor_attributes_list (Qnil); | ||
| 5282 | |||
| 5283 | if (!NILP (Fequal (new_monitors, last_known_monitors))) | ||
| 5284 | return; | ||
| 5285 | |||
| 5286 | last_known_monitors = new_monitors; | ||
| 5287 | |||
| 5288 | ev = (kbd_store_ptr == kbd_buffer | ||
| 5289 | ? kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 5290 | : kbd_store_ptr - 1); | ||
| 5291 | |||
| 5292 | if (kbd_store_ptr != kbd_fetch_ptr | ||
| 5293 | && ev->ie.kind == MONITORS_CHANGED_EVENT) | ||
| 5294 | return; | ||
| 5295 | |||
| 5296 | ie.kind = MONITORS_CHANGED_EVENT; | ||
| 5297 | XSETTERMINAL (ie.arg, x_display_list->terminal); | ||
| 5298 | |||
| 5299 | kbd_buffer_store_event (&ie); | ||
| 5300 | } | ||
| 5301 | #endif | ||
| 5067 | 5302 | ||
| 5068 | static void | 5303 | static void |
| 5069 | ns_delete_display (struct ns_display_info *dpyinfo) | 5304 | ns_delete_display (struct ns_display_info *dpyinfo) |
| @@ -5419,6 +5654,16 @@ ns_term_init (Lisp_Object display_name) | |||
| 5419 | catch_child_signal (); | 5654 | catch_child_signal (); |
| 5420 | #endif | 5655 | #endif |
| 5421 | 5656 | ||
| 5657 | #ifdef NS_IMPL_COCOA | ||
| 5658 | /* Begin listening for display reconfiguration, so we can run the | ||
| 5659 | appropriate hooks. FIXME: is this called when the resolution of | ||
| 5660 | a monitor changes? */ | ||
| 5661 | |||
| 5662 | CGDisplayRegisterReconfigurationCallback (ns_displays_reconfigured, | ||
| 5663 | NULL); | ||
| 5664 | #endif | ||
| 5665 | last_known_monitors = Fns_display_monitor_attributes_list (Qnil); | ||
| 5666 | |||
| 5422 | NSTRACE_MSG ("ns_term_init done"); | 5667 | NSTRACE_MSG ("ns_term_init done"); |
| 5423 | 5668 | ||
| 5424 | unblock_input (); | 5669 | unblock_input (); |
| @@ -5459,6 +5704,10 @@ ns_term_shutdown (int sig) | |||
| 5459 | 5704 | ||
| 5460 | - (id)init | 5705 | - (id)init |
| 5461 | { | 5706 | { |
| 5707 | #ifdef NS_IMPL_GNUSTEP | ||
| 5708 | NSNotificationCenter *notification_center; | ||
| 5709 | #endif | ||
| 5710 | |||
| 5462 | NSTRACE ("[EmacsApp init]"); | 5711 | NSTRACE ("[EmacsApp init]"); |
| 5463 | 5712 | ||
| 5464 | if ((self = [super init])) | 5713 | if ((self = [super init])) |
| @@ -5471,6 +5720,14 @@ ns_term_shutdown (int sig) | |||
| 5471 | #endif | 5720 | #endif |
| 5472 | } | 5721 | } |
| 5473 | 5722 | ||
| 5723 | #ifdef NS_IMPL_GNUSTEP | ||
| 5724 | notification_center = [NSNotificationCenter defaultCenter]; | ||
| 5725 | [notification_center addObserver: self | ||
| 5726 | selector: @selector(updateMonitors:) | ||
| 5727 | name: NSApplicationDidChangeScreenParametersNotification | ||
| 5728 | object: nil]; | ||
| 5729 | #endif | ||
| 5730 | |||
| 5474 | return self; | 5731 | return self; |
| 5475 | } | 5732 | } |
| 5476 | 5733 | ||
| @@ -5483,11 +5740,11 @@ ns_term_shutdown (int sig) | |||
| 5483 | #define NSAppKitVersionNumber10_9 1265 | 5740 | #define NSAppKitVersionNumber10_9 1265 |
| 5484 | #endif | 5741 | #endif |
| 5485 | 5742 | ||
| 5486 | if ((int)NSAppKitVersionNumber != NSAppKitVersionNumber10_9) | 5743 | if ((int) NSAppKitVersionNumber != NSAppKitVersionNumber10_9) |
| 5487 | { | 5744 | { |
| 5488 | [super run]; | 5745 | [super run]; |
| 5489 | return; | 5746 | return; |
| 5490 | } | 5747 | } |
| 5491 | 5748 | ||
| 5492 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | 5749 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
| 5493 | 5750 | ||
| @@ -5671,6 +5928,36 @@ ns_term_shutdown (int sig) | |||
| 5671 | return YES; | 5928 | return YES; |
| 5672 | } | 5929 | } |
| 5673 | 5930 | ||
| 5931 | #ifdef NS_IMPL_GNUSTEP | ||
| 5932 | - (void) updateMonitors: (NSNotification *) notification | ||
| 5933 | { | ||
| 5934 | struct input_event ie; | ||
| 5935 | union buffered_input_event *ev; | ||
| 5936 | Lisp_Object new_monitors; | ||
| 5937 | |||
| 5938 | EVENT_INIT (ie); | ||
| 5939 | |||
| 5940 | new_monitors = Fns_display_monitor_attributes_list (Qnil); | ||
| 5941 | |||
| 5942 | if (!NILP (Fequal (new_monitors, last_known_monitors))) | ||
| 5943 | return; | ||
| 5944 | |||
| 5945 | last_known_monitors = new_monitors; | ||
| 5946 | |||
| 5947 | ev = (kbd_store_ptr == kbd_buffer | ||
| 5948 | ? kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 5949 | : kbd_store_ptr - 1); | ||
| 5950 | |||
| 5951 | if (kbd_store_ptr != kbd_fetch_ptr | ||
| 5952 | && ev->ie.kind == MONITORS_CHANGED_EVENT) | ||
| 5953 | return; | ||
| 5954 | |||
| 5955 | ie.kind = MONITORS_CHANGED_EVENT; | ||
| 5956 | XSETTERMINAL (ie.arg, x_display_list->terminal); | ||
| 5957 | |||
| 5958 | kbd_buffer_store_event (&ie); | ||
| 5959 | } | ||
| 5960 | #endif | ||
| 5674 | 5961 | ||
| 5675 | /* ************************************************************************** | 5962 | /* ************************************************************************** |
| 5676 | 5963 | ||
| @@ -6814,17 +7101,24 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 6814 | { | 7101 | { |
| 6815 | struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); | 7102 | struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); |
| 6816 | NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; | 7103 | NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; |
| 7104 | EmacsWindow *window; | ||
| 6817 | 7105 | ||
| 6818 | NSTRACE ("[EmacsView mouseDown:]"); | 7106 | NSTRACE ("[EmacsView mouseDown:]"); |
| 6819 | 7107 | ||
| 6820 | if (!emacs_event) | 7108 | if (!emacs_event) |
| 6821 | return; | 7109 | return; |
| 6822 | 7110 | ||
| 7111 | if (FRAME_TOOLTIP_P (emacsframe)) | ||
| 7112 | return; | ||
| 7113 | |||
| 6823 | dpyinfo->last_mouse_frame = emacsframe; | 7114 | dpyinfo->last_mouse_frame = emacsframe; |
| 6824 | /* Appears to be needed to prevent spurious movement events generated on | 7115 | /* Appears to be needed to prevent spurious movement events generated on |
| 6825 | button clicks. */ | 7116 | button clicks. */ |
| 6826 | emacsframe->mouse_moved = 0; | 7117 | emacsframe->mouse_moved = 0; |
| 6827 | 7118 | ||
| 7119 | window = (EmacsWindow *) [self window]; | ||
| 7120 | [window setLastDragEvent: theEvent]; | ||
| 7121 | |||
| 6828 | if ([theEvent type] == NSEventTypeScrollWheel) | 7122 | if ([theEvent type] == NSEventTypeScrollWheel) |
| 6829 | { | 7123 | { |
| 6830 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 | 7124 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 |
| @@ -7017,7 +7311,8 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 7017 | tab_bar_p = EQ (window, emacsframe->tab_bar_window); | 7311 | tab_bar_p = EQ (window, emacsframe->tab_bar_window); |
| 7018 | 7312 | ||
| 7019 | if (tab_bar_p) | 7313 | if (tab_bar_p) |
| 7020 | tab_bar_arg = handle_tab_bar_click (emacsframe, x, y, EV_UDMODIFIERS (theEvent) & down_modifier, | 7314 | tab_bar_arg = handle_tab_bar_click (emacsframe, x, y, |
| 7315 | EV_UDMODIFIERS (theEvent) & down_modifier, | ||
| 7021 | EV_MODIFIERS (theEvent) | EV_UDMODIFIERS (theEvent)); | 7316 | EV_MODIFIERS (theEvent) | EV_UDMODIFIERS (theEvent)); |
| 7022 | } | 7317 | } |
| 7023 | 7318 | ||
| @@ -7092,6 +7387,9 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 7092 | NSPoint pt; | 7387 | NSPoint pt; |
| 7093 | BOOL dragging; | 7388 | BOOL dragging; |
| 7094 | 7389 | ||
| 7390 | if (FRAME_TOOLTIP_P (emacsframe)) | ||
| 7391 | return; | ||
| 7392 | |||
| 7095 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]"); | 7393 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]"); |
| 7096 | 7394 | ||
| 7097 | dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e); | 7395 | dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e); |
| @@ -8330,13 +8628,30 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8330 | 8628 | ||
| 8331 | -(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender | 8629 | -(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender |
| 8332 | { | 8630 | { |
| 8631 | id source; | ||
| 8632 | |||
| 8333 | NSTRACE ("[EmacsView draggingEntered:]"); | 8633 | NSTRACE ("[EmacsView draggingEntered:]"); |
| 8634 | |||
| 8635 | source = [sender draggingSource]; | ||
| 8636 | |||
| 8637 | if (source && [source respondsToSelector: @selector(mustNotDropOn:)] | ||
| 8638 | && [source mustNotDropOn: self]) | ||
| 8639 | return NSDragOperationNone; | ||
| 8640 | |||
| 8334 | return NSDragOperationGeneric; | 8641 | return NSDragOperationGeneric; |
| 8335 | } | 8642 | } |
| 8336 | 8643 | ||
| 8337 | 8644 | ||
| 8338 | -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender | 8645 | -(BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender |
| 8339 | { | 8646 | { |
| 8647 | id source; | ||
| 8648 | |||
| 8649 | source = [sender draggingSource]; | ||
| 8650 | |||
| 8651 | if (source && [source respondsToSelector: @selector(mustNotDropOn:)] | ||
| 8652 | && [source mustNotDropOn: self]) | ||
| 8653 | return NO; | ||
| 8654 | |||
| 8340 | return YES; | 8655 | return YES; |
| 8341 | } | 8656 | } |
| 8342 | 8657 | ||
| @@ -8347,12 +8662,24 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8347 | 8662 | ||
| 8348 | - (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender | 8663 | - (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender |
| 8349 | { | 8664 | { |
| 8665 | #ifdef NS_IMPL_GNUSTEP | ||
| 8350 | struct input_event ie; | 8666 | struct input_event ie; |
| 8667 | #else | ||
| 8668 | Lisp_Object frame; | ||
| 8669 | #endif | ||
| 8351 | NSPoint position; | 8670 | NSPoint position; |
| 8352 | int x, y; | 8671 | int x, y; |
| 8672 | NSAutoreleasePool *ap; | ||
| 8673 | specpdl_ref count; | ||
| 8353 | 8674 | ||
| 8675 | ap = [[NSAutoreleasePool alloc] init]; | ||
| 8676 | count = SPECPDL_INDEX (); | ||
| 8677 | record_unwind_protect_ptr (ns_release_autorelease_pool, ap); | ||
| 8678 | |||
| 8679 | #ifdef NS_IMPL_GNUSTEP | ||
| 8354 | EVENT_INIT (ie); | 8680 | EVENT_INIT (ie); |
| 8355 | ie.kind = DRAG_N_DROP_EVENT; | 8681 | ie.kind = DRAG_N_DROP_EVENT; |
| 8682 | #endif | ||
| 8356 | 8683 | ||
| 8357 | /* Get rid of mouse face. */ | 8684 | /* Get rid of mouse face. */ |
| 8358 | [self mouseExited: [[self window] currentEvent]]; | 8685 | [self mouseExited: [[self window] currentEvent]]; |
| @@ -8362,6 +8689,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8362 | x = lrint (position.x); | 8689 | x = lrint (position.x); |
| 8363 | y = lrint (position.y); | 8690 | y = lrint (position.y); |
| 8364 | 8691 | ||
| 8692 | #ifdef NS_IMPL_GNUSTEP | ||
| 8365 | XSETINT (ie.x, x); | 8693 | XSETINT (ie.x, x); |
| 8366 | XSETINT (ie.y, y); | 8694 | XSETINT (ie.y, y); |
| 8367 | XSETFRAME (ie.frame_or_window, emacsframe); | 8695 | XSETFRAME (ie.frame_or_window, emacsframe); |
| @@ -8369,28 +8697,44 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8369 | ie.modifiers = 0; | 8697 | ie.modifiers = 0; |
| 8370 | 8698 | ||
| 8371 | kbd_buffer_store_event (&ie); | 8699 | kbd_buffer_store_event (&ie); |
| 8700 | #else | ||
| 8701 | /* Input events won't be processed until the drop happens on macOS, | ||
| 8702 | so call this function instead. */ | ||
| 8703 | XSETFRAME (frame, emacsframe); | ||
| 8704 | |||
| 8705 | safe_call (4, Vns_drag_motion_function, frame, | ||
| 8706 | make_fixnum (x), make_fixnum (y)); | ||
| 8707 | |||
| 8708 | redisplay (); | ||
| 8709 | #endif | ||
| 8710 | |||
| 8711 | unbind_to (count, Qnil); | ||
| 8372 | return NSDragOperationGeneric; | 8712 | return NSDragOperationGeneric; |
| 8373 | } | 8713 | } |
| 8374 | 8714 | ||
| 8375 | -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender | 8715 | - (BOOL) performDragOperation: (id <NSDraggingInfo>) sender |
| 8376 | { | 8716 | { |
| 8377 | id pb; | 8717 | id pb, source; |
| 8378 | int x, y; | 8718 | int x, y; |
| 8379 | NSString *type; | 8719 | NSString *type; |
| 8380 | NSEvent *theEvent = [[self window] currentEvent]; | ||
| 8381 | NSPoint position; | 8720 | NSPoint position; |
| 8382 | NSDragOperation op = [sender draggingSourceOperationMask]; | 8721 | NSDragOperation op = [sender draggingSourceOperationMask]; |
| 8383 | Lisp_Object operations = Qnil; | 8722 | Lisp_Object operations = Qnil; |
| 8384 | Lisp_Object strings = Qnil; | 8723 | Lisp_Object strings = Qnil; |
| 8385 | Lisp_Object type_sym; | 8724 | Lisp_Object type_sym; |
| 8725 | struct input_event ie; | ||
| 8386 | 8726 | ||
| 8387 | NSTRACE ("[EmacsView performDragOperation:]"); | 8727 | NSTRACE (@"[EmacsView performDragOperation:]"); |
| 8388 | 8728 | ||
| 8389 | if (!emacs_event) | 8729 | source = [sender draggingSource]; |
| 8730 | |||
| 8731 | if (source && [source respondsToSelector: @selector(mustNotDropOn:)] | ||
| 8732 | && [source mustNotDropOn: self]) | ||
| 8390 | return NO; | 8733 | return NO; |
| 8391 | 8734 | ||
| 8392 | position = [self convertPoint: [sender draggingLocation] fromView: nil]; | 8735 | position = [self convertPoint: [sender draggingLocation] fromView: nil]; |
| 8393 | x = lrint (position.x); y = lrint (position.y); | 8736 | x = lrint (position.x); |
| 8737 | y = lrint (position.y); | ||
| 8394 | 8738 | ||
| 8395 | pb = [sender draggingPasteboard]; | 8739 | pb = [sender draggingPasteboard]; |
| 8396 | type = [pb availableTypeFromArray: ns_drag_types]; | 8740 | type = [pb availableTypeFromArray: ns_drag_types]; |
| @@ -8406,11 +8750,9 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8406 | if (op & NSDragOperationGeneric || NILP (operations)) | 8750 | if (op & NSDragOperationGeneric || NILP (operations)) |
| 8407 | operations = Fcons (Qns_drag_operation_generic, operations); | 8751 | operations = Fcons (Qns_drag_operation_generic, operations); |
| 8408 | 8752 | ||
| 8409 | if (type == 0) | 8753 | if (!type) |
| 8410 | { | 8754 | return NO; |
| 8411 | return NO; | 8755 | #if NS_USE_NSPasteboardTypeFileURL |
| 8412 | } | ||
| 8413 | #if NS_USE_NSPasteboardTypeFileURL != 0 | ||
| 8414 | else if ([type isEqualToString: NSPasteboardTypeFileURL]) | 8756 | else if ([type isEqualToString: NSPasteboardTypeFileURL]) |
| 8415 | { | 8757 | { |
| 8416 | type_sym = Qfile; | 8758 | type_sym = Qfile; |
| @@ -8425,18 +8767,29 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8425 | #else // !NS_USE_NSPasteboardTypeFileURL | 8767 | #else // !NS_USE_NSPasteboardTypeFileURL |
| 8426 | else if ([type isEqualToString: NSFilenamesPboardType]) | 8768 | else if ([type isEqualToString: NSFilenamesPboardType]) |
| 8427 | { | 8769 | { |
| 8428 | NSArray *files; | 8770 | id files; |
| 8429 | NSEnumerator *fenum; | 8771 | NSEnumerator *fenum; |
| 8430 | NSString *file; | 8772 | NSString *file; |
| 8431 | 8773 | ||
| 8432 | if (!(files = [pb propertyListForType: type])) | 8774 | files = [pb propertyListForType: type]; |
| 8775 | |||
| 8776 | if (!files) | ||
| 8433 | return NO; | 8777 | return NO; |
| 8434 | 8778 | ||
| 8435 | type_sym = Qfile; | 8779 | type_sym = Qfile; |
| 8436 | 8780 | ||
| 8437 | fenum = [files objectEnumerator]; | 8781 | /* On GNUstep, files might be a string. */ |
| 8438 | while ( (file = [fenum nextObject]) ) | 8782 | |
| 8439 | strings = Fcons ([file lispString], strings); | 8783 | if ([files respondsToSelector: @selector (objectEnumerator:)]) |
| 8784 | { | ||
| 8785 | fenum = [files objectEnumerator]; | ||
| 8786 | |||
| 8787 | while ((file = [fenum nextObject])) | ||
| 8788 | strings = Fcons ([file lispString], strings); | ||
| 8789 | } | ||
| 8790 | else | ||
| 8791 | /* Then `files' is an NSString. */ | ||
| 8792 | strings = list1 ([files lispString]); | ||
| 8440 | } | 8793 | } |
| 8441 | #endif // !NS_USE_NSPasteboardTypeFileURL | 8794 | #endif // !NS_USE_NSPasteboardTypeFileURL |
| 8442 | else if ([type isEqualToString: NSPasteboardTypeURL]) | 8795 | else if ([type isEqualToString: NSPasteboardTypeURL]) |
| @@ -8453,29 +8806,26 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8453 | { | 8806 | { |
| 8454 | NSString *data; | 8807 | NSString *data; |
| 8455 | 8808 | ||
| 8456 | if (! (data = [pb stringForType: type])) | 8809 | data = [pb stringForType: type]; |
| 8810 | |||
| 8811 | if (!data) | ||
| 8457 | return NO; | 8812 | return NO; |
| 8458 | 8813 | ||
| 8459 | type_sym = Qnil; | 8814 | type_sym = Qnil; |
| 8460 | |||
| 8461 | strings = list1 ([data lispString]); | 8815 | strings = list1 ([data lispString]); |
| 8462 | } | 8816 | } |
| 8463 | else | 8817 | else |
| 8464 | { | 8818 | return NO; |
| 8465 | fputs ("Invalid data type in dragging pasteboard\n", stderr); | ||
| 8466 | return NO; | ||
| 8467 | } | ||
| 8468 | |||
| 8469 | emacs_event->kind = DRAG_N_DROP_EVENT; | ||
| 8470 | XSETINT (emacs_event->x, x); | ||
| 8471 | XSETINT (emacs_event->y, y); | ||
| 8472 | emacs_event->modifiers = 0; | ||
| 8473 | 8819 | ||
| 8474 | emacs_event->arg = Fcons (type_sym, | 8820 | EVENT_INIT (ie); |
| 8475 | Fcons (operations, | 8821 | ie.kind = DRAG_N_DROP_EVENT; |
| 8476 | strings)); | 8822 | ie.arg = Fcons (type_sym, Fcons (operations, |
| 8477 | EV_TRAILER (theEvent); | 8823 | strings)); |
| 8824 | XSETINT (ie.x, x); | ||
| 8825 | XSETINT (ie.y, y); | ||
| 8826 | XSETFRAME (ie.frame_or_window, emacsframe); | ||
| 8478 | 8827 | ||
| 8828 | kbd_buffer_store_event (&ie); | ||
| 8479 | return YES; | 8829 | return YES; |
| 8480 | } | 8830 | } |
| 8481 | 8831 | ||
| @@ -8582,17 +8932,18 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8582 | @implementation EmacsWindow | 8932 | @implementation EmacsWindow |
| 8583 | 8933 | ||
| 8584 | 8934 | ||
| 8585 | - (instancetype) initWithEmacsFrame:(struct frame *)f | 8935 | - (instancetype) initWithEmacsFrame: (struct frame *) f |
| 8586 | { | 8936 | { |
| 8587 | return [self initWithEmacsFrame:f fullscreen:NO screen:nil]; | 8937 | return [self initWithEmacsFrame:f fullscreen:NO screen:nil]; |
| 8588 | } | 8938 | } |
| 8589 | 8939 | ||
| 8590 | 8940 | ||
| 8591 | - (instancetype) initWithEmacsFrame:(struct frame *)f | 8941 | - (instancetype) initWithEmacsFrame: (struct frame *) f |
| 8592 | fullscreen:(BOOL)fullscreen | 8942 | fullscreen: (BOOL) fullscreen |
| 8593 | screen:(NSScreen *)screen | 8943 | screen: (NSScreen *) screen |
| 8594 | { | 8944 | { |
| 8595 | NSWindowStyleMask styleMask; | 8945 | NSWindowStyleMask styleMask; |
| 8946 | int width, height; | ||
| 8596 | 8947 | ||
| 8597 | NSTRACE ("[EmacsWindow initWithEmacsFrame:fullscreen:screen:]"); | 8948 | NSTRACE ("[EmacsWindow initWithEmacsFrame:fullscreen:screen:]"); |
| 8598 | 8949 | ||
| @@ -8605,20 +8956,24 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8605 | styleMask |= NSWindowStyleMaskResizable; | 8956 | styleMask |= NSWindowStyleMaskResizable; |
| 8606 | #endif | 8957 | #endif |
| 8607 | } | 8958 | } |
| 8959 | else if (f->tooltip) | ||
| 8960 | styleMask = 0; | ||
| 8608 | else | 8961 | else |
| 8609 | styleMask = NSWindowStyleMaskTitled | 8962 | styleMask = (NSWindowStyleMaskTitled |
| 8610 | | NSWindowStyleMaskResizable | 8963 | | NSWindowStyleMaskResizable |
| 8611 | | NSWindowStyleMaskMiniaturizable | 8964 | | NSWindowStyleMaskMiniaturizable |
| 8612 | | NSWindowStyleMaskClosable; | 8965 | | NSWindowStyleMaskClosable); |
| 8613 | 8966 | ||
| 8614 | self = [super initWithContentRect: | 8967 | last_drag_event = nil; |
| 8615 | NSMakeRect (0, 0, | 8968 | |
| 8616 | FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols), | 8969 | width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols); |
| 8617 | FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines)) | 8970 | height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines); |
| 8618 | styleMask:styleMask | 8971 | |
| 8619 | backing:NSBackingStoreBuffered | 8972 | self = [super initWithContentRect: NSMakeRect (0, 0, width, height) |
| 8620 | defer:YES | 8973 | styleMask: styleMask |
| 8621 | screen:screen]; | 8974 | backing: NSBackingStoreBuffered |
| 8975 | defer: YES | ||
| 8976 | screen: screen]; | ||
| 8622 | if (self) | 8977 | if (self) |
| 8623 | { | 8978 | { |
| 8624 | NSString *name; | 8979 | NSString *name; |
| @@ -8726,6 +9081,11 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) | |||
| 8726 | 9081 | ||
| 8727 | /* We need to release the toolbar ourselves. */ | 9082 | /* We need to release the toolbar ourselves. */ |
| 8728 | [[self toolbar] release]; | 9083 | [[self toolbar] release]; |
| 9084 | |||
| 9085 | /* Also the last button press event . */ | ||
| 9086 | if (last_drag_event) | ||
| 9087 | [last_drag_event release]; | ||
| 9088 | |||
| 8729 | [super dealloc]; | 9089 | [super dealloc]; |
| 8730 | } | 9090 | } |
| 8731 | 9091 | ||
| @@ -9250,6 +9610,153 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) | |||
| 9250 | return YES; | 9610 | return YES; |
| 9251 | } | 9611 | } |
| 9252 | 9612 | ||
| 9613 | - (void) setLastDragEvent: (NSEvent *) event | ||
| 9614 | { | ||
| 9615 | if (last_drag_event) | ||
| 9616 | [last_drag_event release]; | ||
| 9617 | last_drag_event = [event copy]; | ||
| 9618 | } | ||
| 9619 | |||
| 9620 | - (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) is_local | ||
| 9621 | { | ||
| 9622 | return drag_op; | ||
| 9623 | } | ||
| 9624 | |||
| 9625 | - (void) draggedImage: (NSImage *) image | ||
| 9626 | endedAt: (NSPoint) screen_point | ||
| 9627 | operation: (NSDragOperation) operation | ||
| 9628 | { | ||
| 9629 | selected_op = operation; | ||
| 9630 | } | ||
| 9631 | |||
| 9632 | - (void) draggedImage: (NSImage *) dragged_image | ||
| 9633 | movedTo: (NSPoint) screen_point | ||
| 9634 | { | ||
| 9635 | NSPoint mouse_loc; | ||
| 9636 | #ifdef NS_IMPL_COCOA | ||
| 9637 | NSInteger window_number; | ||
| 9638 | NSWindow *w; | ||
| 9639 | #endif | ||
| 9640 | |||
| 9641 | mouse_loc = [NSEvent mouseLocation]; | ||
| 9642 | |||
| 9643 | #ifdef NS_IMPL_COCOA | ||
| 9644 | if (dnd_mode != RETURN_FRAME_NEVER) | ||
| 9645 | { | ||
| 9646 | window_number = [NSWindow windowNumberAtPoint: mouse_loc | ||
| 9647 | belowWindowWithWindowNumber: 0]; | ||
| 9648 | w = [NSApp windowWithWindowNumber: window_number]; | ||
| 9649 | |||
| 9650 | if (!w || w != self) | ||
| 9651 | dnd_mode = RETURN_FRAME_NOW; | ||
| 9652 | |||
| 9653 | if (dnd_mode != RETURN_FRAME_NOW | ||
| 9654 | || ![[w delegate] isKindOfClass: [EmacsView class]] | ||
| 9655 | || ((EmacsView *) [w delegate])->emacsframe->tooltip) | ||
| 9656 | goto out; | ||
| 9657 | |||
| 9658 | dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; | ||
| 9659 | |||
| 9660 | /* FIXME: there must be a better way to leave the event loop. */ | ||
| 9661 | [NSException raise: @"" | ||
| 9662 | format: @"Must return DND frame"]; | ||
| 9663 | } | ||
| 9664 | |||
| 9665 | out: | ||
| 9666 | #endif | ||
| 9667 | |||
| 9668 | if (dnd_move_tooltip_with_frame) | ||
| 9669 | ns_move_tooltip_to_mouse_location (mouse_loc); | ||
| 9670 | } | ||
| 9671 | |||
| 9672 | - (BOOL) mustNotDropOn: (NSView *) receiver | ||
| 9673 | { | ||
| 9674 | return ([receiver window] == self | ||
| 9675 | ? !dnd_allow_same_frame : NO); | ||
| 9676 | } | ||
| 9677 | |||
| 9678 | - (NSDragOperation) beginDrag: (NSDragOperation) op | ||
| 9679 | forPasteboard: (NSPasteboard *) pasteboard | ||
| 9680 | withMode: (enum ns_return_frame_mode) mode | ||
| 9681 | returnFrameTo: (struct frame **) frame_return | ||
| 9682 | prohibitSame: (BOOL) prohibit_same_frame | ||
| 9683 | followTooltip: (BOOL) follow_tooltip | ||
| 9684 | { | ||
| 9685 | NSImage *image; | ||
| 9686 | #ifdef NS_IMPL_COCOA | ||
| 9687 | NSInteger window_number; | ||
| 9688 | NSWindow *w; | ||
| 9689 | #endif | ||
| 9690 | drag_op = op; | ||
| 9691 | selected_op = NSDragOperationNone; | ||
| 9692 | image = [[NSImage alloc] initWithSize: NSMakeSize (1.0, 1.0)]; | ||
| 9693 | dnd_mode = mode; | ||
| 9694 | dnd_return_frame = NULL; | ||
| 9695 | dnd_allow_same_frame = !prohibit_same_frame; | ||
| 9696 | dnd_move_tooltip_with_frame = follow_tooltip; | ||
| 9697 | |||
| 9698 | /* Now draw transparency onto the image. */ | ||
| 9699 | [image lockFocus]; | ||
| 9700 | [[NSColor colorWithUnsignedLong: 0] set]; | ||
| 9701 | NSRectFillUsingOperation (NSMakeRect (0, 0, 1, 1), | ||
| 9702 | NSCompositingOperationCopy); | ||
| 9703 | [image unlockFocus]; | ||
| 9704 | |||
| 9705 | block_input (); | ||
| 9706 | #ifdef NS_IMPL_COCOA | ||
| 9707 | if (mode == RETURN_FRAME_NOW) | ||
| 9708 | { | ||
| 9709 | window_number = [NSWindow windowNumberAtPoint: [NSEvent mouseLocation] | ||
| 9710 | belowWindowWithWindowNumber: 0]; | ||
| 9711 | w = [NSApp windowWithWindowNumber: window_number]; | ||
| 9712 | |||
| 9713 | if (w && [[w delegate] isKindOfClass: [EmacsView class]] | ||
| 9714 | && !((EmacsView *) [w delegate])->emacsframe->tooltip) | ||
| 9715 | { | ||
| 9716 | *frame_return = ((EmacsView *) [w delegate])->emacsframe; | ||
| 9717 | [image release]; | ||
| 9718 | unblock_input (); | ||
| 9719 | |||
| 9720 | return NSDragOperationNone; | ||
| 9721 | } | ||
| 9722 | } | ||
| 9723 | |||
| 9724 | @try | ||
| 9725 | { | ||
| 9726 | #endif | ||
| 9727 | if (last_drag_event) | ||
| 9728 | [self dragImage: image | ||
| 9729 | at: NSMakePoint (0, 0) | ||
| 9730 | offset: NSMakeSize (0, 0) | ||
| 9731 | event: last_drag_event | ||
| 9732 | pasteboard: pasteboard | ||
| 9733 | source: self | ||
| 9734 | slideBack: NO]; | ||
| 9735 | #ifdef NS_IMPL_COCOA | ||
| 9736 | } | ||
| 9737 | @catch (NSException *e) | ||
| 9738 | { | ||
| 9739 | /* Ignore. This is probably the wrong way to leave the | ||
| 9740 | drag-and-drop run loop. */ | ||
| 9741 | } | ||
| 9742 | #endif | ||
| 9743 | unblock_input (); | ||
| 9744 | |||
| 9745 | /* The drop happened, so delete the tooltip. */ | ||
| 9746 | if (follow_tooltip) | ||
| 9747 | Fx_hide_tip (); | ||
| 9748 | |||
| 9749 | /* Assume all buttons have been released since the drag-and-drop | ||
| 9750 | operation is now over. */ | ||
| 9751 | if (!dnd_return_frame) | ||
| 9752 | x_display_list->grabbed = 0; | ||
| 9753 | |||
| 9754 | [image release]; | ||
| 9755 | |||
| 9756 | *frame_return = dnd_return_frame; | ||
| 9757 | return selected_op; | ||
| 9758 | } | ||
| 9759 | |||
| 9253 | @end /* EmacsWindow */ | 9760 | @end /* EmacsWindow */ |
| 9254 | 9761 | ||
| 9255 | 9762 | ||
| @@ -10182,6 +10689,7 @@ syms_of_nsterm (void) | |||
| 10182 | DEFSYM (Qns_drag_operation_copy, "ns-drag-operation-copy"); | 10689 | DEFSYM (Qns_drag_operation_copy, "ns-drag-operation-copy"); |
| 10183 | DEFSYM (Qns_drag_operation_link, "ns-drag-operation-link"); | 10690 | DEFSYM (Qns_drag_operation_link, "ns-drag-operation-link"); |
| 10184 | DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic"); | 10691 | DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic"); |
| 10692 | DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion"); | ||
| 10185 | 10693 | ||
| 10186 | Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); | 10694 | Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); |
| 10187 | Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); | 10695 | Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); |
| @@ -10189,117 +10697,117 @@ syms_of_nsterm (void) | |||
| 10189 | Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier)); | 10697 | Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier)); |
| 10190 | Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier)); | 10698 | Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier)); |
| 10191 | 10699 | ||
| 10192 | DEFVAR_LISP ("ns-input-file", ns_input_file, | 10700 | DEFVAR_LISP ("ns-input-font", ns_input_font, |
| 10193 | "The file specified in the last NS event."); | 10701 | doc: /* The font specified in the last NS event. */); |
| 10194 | ns_input_file =Qnil; | 10702 | ns_input_font = Qnil; |
| 10195 | 10703 | ||
| 10196 | DEFVAR_LISP ("ns-working-text", ns_working_text, | 10704 | DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize, |
| 10197 | "String for visualizing working composition sequence."); | 10705 | doc: /* The fontsize specified in the last NS event. */); |
| 10198 | ns_working_text =Qnil; | 10706 | ns_input_fontsize = Qnil; |
| 10199 | 10707 | ||
| 10200 | DEFVAR_LISP ("ns-input-font", ns_input_font, | 10708 | DEFVAR_LISP ("ns-input-line", ns_input_line, |
| 10201 | "The font specified in the last NS event."); | 10709 | doc: /* The line specified in the last NS event. */); |
| 10202 | ns_input_font =Qnil; | 10710 | ns_input_line = Qnil; |
| 10203 | 10711 | ||
| 10204 | DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize, | 10712 | DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name, |
| 10205 | "The fontsize specified in the last NS event."); | 10713 | doc: /* The service name specified in the last NS event. */); |
| 10206 | ns_input_fontsize =Qnil; | 10714 | ns_input_spi_name = Qnil; |
| 10207 | 10715 | ||
| 10208 | DEFVAR_LISP ("ns-input-line", ns_input_line, | 10716 | DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg, |
| 10209 | "The line specified in the last NS event."); | 10717 | doc: /* The service argument specified in the last NS event. */); |
| 10210 | ns_input_line =Qnil; | 10718 | ns_input_spi_arg = Qnil; |
| 10211 | 10719 | ||
| 10212 | DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name, | 10720 | DEFVAR_LISP ("ns-input-file", ns_input_file, |
| 10213 | "The service name specified in the last NS event."); | 10721 | doc: /* The file specified in the last NS event. */); |
| 10214 | ns_input_spi_name =Qnil; | 10722 | ns_input_file = Qnil; |
| 10215 | 10723 | ||
| 10216 | DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg, | 10724 | DEFVAR_LISP ("ns-working-text", ns_working_text, |
| 10217 | "The service argument specified in the last NS event."); | 10725 | doc: /* String for visualizing working composition sequence. */); |
| 10218 | ns_input_spi_arg =Qnil; | 10726 | ns_working_text = Qnil; |
| 10219 | 10727 | ||
| 10220 | DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier, | 10728 | DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier, |
| 10221 | "This variable describes the behavior of the alternate or option key.\n\ | 10729 | doc: /* This variable describes the behavior of the alternate or option key. |
| 10222 | Either SYMBOL, describing the behavior for any event,\n\ | 10730 | Either SYMBOL, describing the behavior for any event, |
| 10223 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10731 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10224 | separately for ordinary keys, function keys, and mouse events.\n\ | 10732 | separately for ordinary keys, function keys, and mouse events. |
| 10225 | \n\ | 10733 | |
| 10226 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10734 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10227 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10735 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10228 | ns_alternate_modifier = Qmeta; | 10736 | ns_alternate_modifier = Qmeta; |
| 10229 | 10737 | ||
| 10230 | DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier, | 10738 | DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier, |
| 10231 | "This variable describes the behavior of the right alternate or option key.\n\ | 10739 | doc: /* This variable describes the behavior of the right alternate or option key. |
| 10232 | Either SYMBOL, describing the behavior for any event,\n\ | 10740 | Either SYMBOL, describing the behavior for any event, |
| 10233 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10741 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10234 | separately for ordinary keys, function keys, and mouse events.\n\ | 10742 | separately for ordinary keys, function keys, and mouse events. |
| 10235 | It can also be `left' to use the value of `ns-alternate-modifier' instead.\n\ | 10743 | It can also be `left' to use the value of `ns-alternate-modifier' instead. |
| 10236 | \n\ | 10744 | |
| 10237 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10745 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10238 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10746 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10239 | ns_right_alternate_modifier = Qleft; | 10747 | ns_right_alternate_modifier = Qleft; |
| 10240 | 10748 | ||
| 10241 | DEFVAR_LISP ("ns-command-modifier", ns_command_modifier, | 10749 | DEFVAR_LISP ("ns-command-modifier", ns_command_modifier, |
| 10242 | "This variable describes the behavior of the command key.\n\ | 10750 | doc: /* This variable describes the behavior of the command key. |
| 10243 | Either SYMBOL, describing the behavior for any event,\n\ | 10751 | Either SYMBOL, describing the behavior for any event, |
| 10244 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10752 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10245 | separately for ordinary keys, function keys, and mouse events.\n\ | 10753 | separately for ordinary keys, function keys, and mouse events. |
| 10246 | \n\ | 10754 | |
| 10247 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10755 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10248 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10756 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10249 | ns_command_modifier = Qsuper; | 10757 | ns_command_modifier = Qsuper; |
| 10250 | 10758 | ||
| 10251 | DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier, | 10759 | DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier, |
| 10252 | "This variable describes the behavior of the right command key.\n\ | 10760 | doc: /* This variable describes the behavior of the right command key. |
| 10253 | Either SYMBOL, describing the behavior for any event,\n\ | 10761 | Either SYMBOL, describing the behavior for any event, |
| 10254 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10762 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10255 | separately for ordinary keys, function keys, and mouse events.\n\ | 10763 | separately for ordinary keys, function keys, and mouse events. |
| 10256 | It can also be `left' to use the value of `ns-command-modifier' instead.\n\ | 10764 | It can also be `left' to use the value of `ns-command-modifier' instead. |
| 10257 | \n\ | 10765 | |
| 10258 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10766 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10259 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10767 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10260 | ns_right_command_modifier = Qleft; | 10768 | ns_right_command_modifier = Qleft; |
| 10261 | 10769 | ||
| 10262 | DEFVAR_LISP ("ns-control-modifier", ns_control_modifier, | 10770 | DEFVAR_LISP ("ns-control-modifier", ns_control_modifier, |
| 10263 | "This variable describes the behavior of the control key.\n\ | 10771 | doc: /* This variable describes the behavior of the control key. |
| 10264 | Either SYMBOL, describing the behavior for any event,\n\ | 10772 | Either SYMBOL, describing the behavior for any event, |
| 10265 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10773 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10266 | separately for ordinary keys, function keys, and mouse events.\n\ | 10774 | separately for ordinary keys, function keys, and mouse events. |
| 10267 | \n\ | 10775 | |
| 10268 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10776 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10269 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10777 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10270 | ns_control_modifier = Qcontrol; | 10778 | ns_control_modifier = Qcontrol; |
| 10271 | 10779 | ||
| 10272 | DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier, | 10780 | DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier, |
| 10273 | "This variable describes the behavior of the right control key.\n\ | 10781 | doc: /* This variable describes the behavior of the right control key. |
| 10274 | Either SYMBOL, describing the behavior for any event,\n\ | 10782 | Either SYMBOL, describing the behavior for any event, |
| 10275 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10783 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10276 | separately for ordinary keys, function keys, and mouse events.\n\ | 10784 | separately for ordinary keys, function keys, and mouse events. |
| 10277 | It can also be `left' to use the value of `ns-control-modifier' instead.\n\ | 10785 | It can also be `left' to use the value of `ns-control-modifier' instead. |
| 10278 | \n\ | 10786 | |
| 10279 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10787 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10280 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10788 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10281 | ns_right_control_modifier = Qleft; | 10789 | ns_right_control_modifier = Qleft; |
| 10282 | 10790 | ||
| 10283 | DEFVAR_LISP ("ns-function-modifier", ns_function_modifier, | 10791 | DEFVAR_LISP ("ns-function-modifier", ns_function_modifier, |
| 10284 | "This variable describes the behavior of the function (fn) key.\n\ | 10792 | doc: /* This variable describes the behavior of the function (fn) key. |
| 10285 | Either SYMBOL, describing the behavior for any event,\n\ | 10793 | Either SYMBOL, describing the behavior for any event, |
| 10286 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\ | 10794 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior |
| 10287 | separately for ordinary keys, function keys, and mouse events.\n\ | 10795 | separately for ordinary keys, function keys, and mouse events. |
| 10288 | \n\ | 10796 | |
| 10289 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | 10797 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'. |
| 10290 | If `none', the key is ignored by Emacs and retains its standard meaning."); | 10798 | If `none', the key is ignored by Emacs and retains its standard meaning. */); |
| 10291 | ns_function_modifier = Qnone; | 10799 | ns_function_modifier = Qnone; |
| 10292 | 10800 | ||
| 10293 | DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, | 10801 | DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, |
| 10294 | "Non-nil (the default) means to render text antialiased."); | 10802 | doc: /* Non-nil (the default) means to render text antialiased. */); |
| 10295 | ns_antialias_text = Qt; | 10803 | ns_antialias_text = Qt; |
| 10296 | 10804 | ||
| 10297 | DEFVAR_LISP ("ns-use-thin-smoothing", ns_use_thin_smoothing, | 10805 | DEFVAR_LISP ("ns-use-thin-smoothing", ns_use_thin_smoothing, |
| 10298 | "Non-nil turns on a font smoothing method that produces thinner strokes."); | 10806 | doc: /* Non-nil turns on a font smoothing method that produces thinner strokes. */); |
| 10299 | ns_use_thin_smoothing = Qnil; | 10807 | ns_use_thin_smoothing = Qnil; |
| 10300 | 10808 | ||
| 10301 | DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit, | 10809 | DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit, |
| 10302 | "Whether to confirm application quit using dialog."); | 10810 | doc: /* Whether to confirm application quit using dialog. */); |
| 10303 | ns_confirm_quit = Qnil; | 10811 | ns_confirm_quit = Qnil; |
| 10304 | 10812 | ||
| 10305 | DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar, | 10813 | DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar, |
| @@ -10369,6 +10877,16 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); | |||
| 10369 | mice with smooth scrolling capability. */); | 10877 | mice with smooth scrolling capability. */); |
| 10370 | Vns_scroll_event_delta_factor = make_float (1.0); | 10878 | Vns_scroll_event_delta_factor = make_float (1.0); |
| 10371 | 10879 | ||
| 10880 | DEFVAR_LISP ("ns-drag-motion-function", Vns_drag_motion_function, | ||
| 10881 | doc: /* Function called when another program drags items over Emacs. | ||
| 10882 | |||
| 10883 | It is called with three arguments FRAME, X, and Y, whenever the user | ||
| 10884 | moves the mouse over an Emacs frame as part of a drag-and-drop | ||
| 10885 | operation. FRAME is the frame the mouse is on top of, and X and Y are | ||
| 10886 | the frame-relative positions of the mouse in the X and Y axises | ||
| 10887 | respectively. */); | ||
| 10888 | Vns_drag_motion_function = Qns_handle_drag_motion; | ||
| 10889 | |||
| 10372 | /* Tell Emacs about this window system. */ | 10890 | /* Tell Emacs about this window system. */ |
| 10373 | Fprovide (Qns, Qnil); | 10891 | Fprovide (Qns, Qnil); |
| 10374 | 10892 | ||
| @@ -10389,4 +10907,6 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); | |||
| 10389 | syms_of_nsfont (); | 10907 | syms_of_nsfont (); |
| 10390 | #endif | 10908 | #endif |
| 10391 | 10909 | ||
| 10910 | last_known_monitors = Qnil; | ||
| 10911 | staticpro (&last_known_monitors); | ||
| 10392 | } | 10912 | } |
diff --git a/src/nsxwidget.m b/src/nsxwidget.m index f79873235cb..be0eba0bcb1 100644 --- a/src/nsxwidget.m +++ b/src/nsxwidget.m | |||
| @@ -69,10 +69,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 69 | [configuration.preferences setValue:@YES | 69 | [configuration.preferences setValue:@YES |
| 70 | forKey:@"developerExtrasEnabled"]; | 70 | forKey:@"developerExtrasEnabled"]; |
| 71 | 71 | ||
| 72 | #if 0 /* Plugins are not supported by Mac OS X anymore. */ | ||
| 72 | Lisp_Object enablePlugins = | 73 | Lisp_Object enablePlugins = |
| 73 | Fintern (build_string ("xwidget-webkit-enable-plugins"), Qnil); | 74 | Fintern (build_string ("xwidget-webkit-enable-plugins"), Qnil); |
| 75 | |||
| 74 | if (!EQ (Fsymbol_value (enablePlugins), Qnil)) | 76 | if (!EQ (Fsymbol_value (enablePlugins), Qnil)) |
| 75 | configuration.preferences.plugInsEnabled = YES; | 77 | configuration.preferences.plugInsEnabled = YES; |
| 78 | #endif | ||
| 76 | 79 | ||
| 77 | self = [super initWithFrame:frame configuration:configuration]; | 80 | self = [super initWithFrame:frame configuration:configuration]; |
| 78 | if (self) | 81 | if (self) |
diff --git a/src/pdumper.c b/src/pdumper.c index 5923d9b1d82..50ae4f85e7e 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -1069,7 +1069,7 @@ dump_queue_enqueue (struct dump_queue *dump_queue, | |||
| 1069 | } | 1069 | } |
| 1070 | } | 1070 | } |
| 1071 | 1071 | ||
| 1072 | if (!EQ (weights, orig_weights)) | 1072 | if (!BASE_EQ (weights, orig_weights)) |
| 1073 | Fputhash (object, weights, dump_queue->link_weights); | 1073 | Fputhash (object, weights, dump_queue->link_weights); |
| 1074 | } | 1074 | } |
| 1075 | 1075 | ||
| @@ -1383,7 +1383,7 @@ print_paths_to_root_1 (struct dump_context *ctx, | |||
| 1383 | { | 1383 | { |
| 1384 | Lisp_Object referrer = XCAR (referrers); | 1384 | Lisp_Object referrer = XCAR (referrers); |
| 1385 | referrers = XCDR (referrers); | 1385 | referrers = XCDR (referrers); |
| 1386 | Lisp_Object repr = Fprin1_to_string (referrer, Qnil); | 1386 | Lisp_Object repr = Fprin1_to_string (referrer, Qnil, Qnil); |
| 1387 | for (int i = 0; i < level; ++i) | 1387 | for (int i = 0; i < level; ++i) |
| 1388 | putc (' ', stderr); | 1388 | putc (' ', stderr); |
| 1389 | fwrite (SDATA (repr), 1, SBYTES (repr), stderr); | 1389 | fwrite (SDATA (repr), 1, SBYTES (repr), stderr); |
| @@ -3758,7 +3758,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object lreloc) | |||
| 3758 | reloc.u.dump_offset = dump_recall_object (ctx, target_value); | 3758 | reloc.u.dump_offset = dump_recall_object (ctx, target_value); |
| 3759 | if (reloc.u.dump_offset <= 0) | 3759 | if (reloc.u.dump_offset <= 0) |
| 3760 | { | 3760 | { |
| 3761 | Lisp_Object repr = Fprin1_to_string (target_value, Qnil); | 3761 | Lisp_Object repr = Fprin1_to_string (target_value, Qnil, Qnil); |
| 3762 | error ("relocation target was not dumped: %s", SDATA (repr)); | 3762 | error ("relocation target was not dumped: %s", SDATA (repr)); |
| 3763 | } | 3763 | } |
| 3764 | dump_check_dump_off (ctx, reloc.u.dump_offset); | 3764 | dump_check_dump_off (ctx, reloc.u.dump_offset); |
| @@ -5543,7 +5543,10 @@ pdumper_load (const char *dump_filename, char *argv0) | |||
| 5543 | 5543 | ||
| 5544 | struct dump_header header_buf = { 0 }; | 5544 | struct dump_header header_buf = { 0 }; |
| 5545 | struct dump_header *header = &header_buf; | 5545 | struct dump_header *header = &header_buf; |
| 5546 | struct dump_memory_map sections[NUMBER_DUMP_SECTIONS] = { 0 }; | 5546 | struct dump_memory_map sections[NUMBER_DUMP_SECTIONS]; |
| 5547 | |||
| 5548 | /* Use memset instead of "= { 0 }" to work around GCC bug 105961. */ | ||
| 5549 | memset (sections, 0, sizeof sections); | ||
| 5547 | 5550 | ||
| 5548 | const struct timespec start_time = current_timespec (); | 5551 | const struct timespec start_time = current_timespec (); |
| 5549 | char *dump_filename_copy; | 5552 | char *dump_filename_copy; |
diff --git a/src/pgtkfns.c b/src/pgtkfns.c index a0fcf70f31b..294bdb37917 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c | |||
| @@ -566,15 +566,23 @@ pgtk_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) | |||
| 566 | static void | 566 | static void |
| 567 | pgtk_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 567 | pgtk_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) |
| 568 | { | 568 | { |
| 569 | int border = check_int_nonnegative (arg); | 569 | int border; |
| 570 | |||
| 571 | if (NILP (arg)) | ||
| 572 | border = -1; | ||
| 573 | else if (RANGED_FIXNUMP (0, arg, INT_MAX)) | ||
| 574 | border = XFIXNAT (arg); | ||
| 575 | else | ||
| 576 | signal_error ("Invalid child frame border width", arg); | ||
| 570 | 577 | ||
| 571 | if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f)) | 578 | if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f)) |
| 572 | { | 579 | { |
| 573 | f->child_frame_border_width = border; | 580 | f->child_frame_border_width = border; |
| 574 | 581 | ||
| 575 | if (FRAME_X_WINDOW (f)) | 582 | if (FRAME_GTK_WIDGET (f)) |
| 576 | { | 583 | { |
| 577 | adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width); | 584 | adjust_frame_size (f, -1, -1, 3, |
| 585 | false, Qchild_frame_border_width); | ||
| 578 | pgtk_clear_under_internal_border (f); | 586 | pgtk_clear_under_internal_border (f); |
| 579 | } | 587 | } |
| 580 | } | 588 | } |
| @@ -848,7 +856,7 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, | |||
| 848 | error ("Unknown color."); | 856 | error ("Unknown color."); |
| 849 | 857 | ||
| 850 | /* On pgtk, this frame parameter should be ignored, and honor | 858 | /* On pgtk, this frame parameter should be ignored, and honor |
| 851 | gtk theme. (It honors the GTK theme if not explictly set, so | 859 | gtk theme. (It honors the GTK theme if not explicitly set, so |
| 852 | I see no harm in letting users tinker a bit more.) */ | 860 | I see no harm in letting users tinker a bit more.) */ |
| 853 | char css[64]; | 861 | char css[64]; |
| 854 | sprintf (css, "scrollbar trough { background-color: #%06x; }", | 862 | sprintf (css, "scrollbar trough { background-color: #%06x; }", |
| @@ -1060,7 +1068,7 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) | |||
| 1060 | gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, | 1068 | gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, |
| 1061 | RES_TYPE_STRING); | 1069 | RES_TYPE_STRING); |
| 1062 | Lisp_Object font = Qnil; | 1070 | Lisp_Object font = Qnil; |
| 1063 | if (EQ (font_param, Qunbound)) | 1071 | if (BASE_EQ (font_param, Qunbound)) |
| 1064 | font_param = Qnil; | 1072 | font_param = Qnil; |
| 1065 | 1073 | ||
| 1066 | if (NILP (font_param)) | 1074 | if (NILP (font_param)) |
| @@ -1213,10 +1221,10 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1213 | 1221 | ||
| 1214 | display = | 1222 | display = |
| 1215 | gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); | 1223 | gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); |
| 1216 | if (EQ (display, Qunbound)) | 1224 | if (BASE_EQ (display, Qunbound)) |
| 1217 | display = | 1225 | display = |
| 1218 | gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); | 1226 | gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); |
| 1219 | if (EQ (display, Qunbound)) | 1227 | if (BASE_EQ (display, Qunbound)) |
| 1220 | display = Qnil; | 1228 | display = Qnil; |
| 1221 | dpyinfo = check_pgtk_display_info (display); | 1229 | dpyinfo = check_pgtk_display_info (display); |
| 1222 | kb = dpyinfo->terminal->kboard; | 1230 | kb = dpyinfo->terminal->kboard; |
| @@ -1227,7 +1235,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1227 | name = | 1235 | name = |
| 1228 | gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 1236 | gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 1229 | RES_TYPE_STRING); | 1237 | RES_TYPE_STRING); |
| 1230 | if (!STRINGP (name) && !EQ (name, Qunbound) && !NILP (name)) | 1238 | if (!STRINGP (name) && !BASE_EQ (name, Qunbound) && !NILP (name)) |
| 1231 | error ("Invalid frame name--not a string or nil"); | 1239 | error ("Invalid frame name--not a string or nil"); |
| 1232 | 1240 | ||
| 1233 | if (STRINGP (name)) | 1241 | if (STRINGP (name)) |
| @@ -1237,7 +1245,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1237 | parent = | 1245 | parent = |
| 1238 | gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, | 1246 | gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, |
| 1239 | RES_TYPE_NUMBER); | 1247 | RES_TYPE_NUMBER); |
| 1240 | if (EQ (parent, Qunbound)) | 1248 | if (BASE_EQ (parent, Qunbound)) |
| 1241 | parent = Qnil; | 1249 | parent = Qnil; |
| 1242 | if (!NILP (parent)) | 1250 | if (!NILP (parent)) |
| 1243 | CHECK_NUMBER (parent); | 1251 | CHECK_NUMBER (parent); |
| @@ -1263,7 +1271,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1263 | RES_TYPE_SYMBOL); | 1271 | RES_TYPE_SYMBOL); |
| 1264 | /* Accept parent-frame iff parent-id was not specified. */ | 1272 | /* Accept parent-frame iff parent-id was not specified. */ |
| 1265 | if (!NILP (parent) | 1273 | if (!NILP (parent) |
| 1266 | || EQ (parent_frame, Qunbound) | 1274 | || BASE_EQ (parent_frame, Qunbound) |
| 1267 | || NILP (parent_frame) | 1275 | || NILP (parent_frame) |
| 1268 | || !FRAMEP (parent_frame) | 1276 | || !FRAMEP (parent_frame) |
| 1269 | || !FRAME_LIVE_P (XFRAME (parent_frame)) | 1277 | || !FRAME_LIVE_P (XFRAME (parent_frame)) |
| @@ -1277,7 +1285,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1277 | (tem = | 1285 | (tem = |
| 1278 | (gui_display_get_arg | 1286 | (gui_display_get_arg |
| 1279 | (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN))) | 1287 | (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN))) |
| 1280 | && !(EQ (tem, Qunbound))) | 1288 | && !(BASE_EQ (tem, Qunbound))) |
| 1281 | undecorated = true; | 1289 | undecorated = true; |
| 1282 | 1290 | ||
| 1283 | FRAME_UNDECORATED (f) = undecorated; | 1291 | FRAME_UNDECORATED (f) = undecorated; |
| @@ -1287,7 +1295,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1287 | (tem = | 1295 | (tem = |
| 1288 | (gui_display_get_arg | 1296 | (gui_display_get_arg |
| 1289 | (dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN))) | 1297 | (dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN))) |
| 1290 | && !(EQ (tem, Qunbound))) | 1298 | && !(BASE_EQ (tem, Qunbound))) |
| 1291 | override_redirect = true; | 1299 | override_redirect = true; |
| 1292 | 1300 | ||
| 1293 | FRAME_OVERRIDE_REDIRECT (f) = override_redirect; | 1301 | FRAME_OVERRIDE_REDIRECT (f) = override_redirect; |
| @@ -1363,7 +1371,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1363 | 1371 | ||
| 1364 | /* Set the name; the functions to which we pass f expect the name to | 1372 | /* Set the name; the functions to which we pass f expect the name to |
| 1365 | be set. */ | 1373 | be set. */ |
| 1366 | if (EQ (name, Qunbound) || NILP (name)) | 1374 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 1367 | { | 1375 | { |
| 1368 | fset_name (f, build_string (dpyinfo->x_id_name)); | 1376 | fset_name (f, build_string (dpyinfo->x_id_name)); |
| 1369 | f->explicit_name = false; | 1377 | f->explicit_name = false; |
| @@ -1406,7 +1414,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1406 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 1414 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 1407 | "internalBorder", "internalBorder", | 1415 | "internalBorder", "internalBorder", |
| 1408 | RES_TYPE_NUMBER); | 1416 | RES_TYPE_NUMBER); |
| 1409 | if (!EQ (value, Qunbound)) | 1417 | if (!BASE_EQ (value, Qunbound)) |
| 1410 | parms = Fcons (Fcons (Qinternal_border_width, value), parms); | 1418 | parms = Fcons (Fcons (Qinternal_border_width, value), parms); |
| 1411 | } | 1419 | } |
| 1412 | 1420 | ||
| @@ -1423,14 +1431,13 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1423 | value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, | 1431 | value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, |
| 1424 | "childFrameBorder", "childFrameBorder", | 1432 | "childFrameBorder", "childFrameBorder", |
| 1425 | RES_TYPE_NUMBER); | 1433 | RES_TYPE_NUMBER); |
| 1426 | if (! EQ (value, Qunbound)) | 1434 | if (! BASE_EQ (value, Qunbound)) |
| 1427 | parms = Fcons (Fcons (Qchild_frame_border_width, value), | 1435 | parms = Fcons (Fcons (Qchild_frame_border_width, value), |
| 1428 | parms); | 1436 | parms); |
| 1429 | 1437 | ||
| 1430 | } | 1438 | } |
| 1431 | 1439 | ||
| 1432 | gui_default_parameter (f, parms, Qchild_frame_border_width, | 1440 | gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil, |
| 1433 | make_fixnum (0), | ||
| 1434 | "childFrameBorderWidth", "childFrameBorderWidth", | 1441 | "childFrameBorderWidth", "childFrameBorderWidth", |
| 1435 | RES_TYPE_NUMBER); | 1442 | RES_TYPE_NUMBER); |
| 1436 | gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), | 1443 | gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), |
| @@ -1688,7 +1695,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1688 | } | 1695 | } |
| 1689 | else | 1696 | else |
| 1690 | { | 1697 | { |
| 1691 | if (EQ (visibility, Qunbound)) | 1698 | if (BASE_EQ (visibility, Qunbound)) |
| 1692 | visibility = Qt; | 1699 | visibility = Qt; |
| 1693 | 1700 | ||
| 1694 | if (!NILP (visibility)) | 1701 | if (!NILP (visibility)) |
| @@ -1702,7 +1709,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) | |||
| 1702 | from `x-create-frame-with-faces' (see above comment). */ | 1709 | from `x-create-frame-with-faces' (see above comment). */ |
| 1703 | f->was_invisible | 1710 | f->was_invisible |
| 1704 | = (f->was_invisible | 1711 | = (f->was_invisible |
| 1705 | && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); | 1712 | && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound))); |
| 1706 | 1713 | ||
| 1707 | store_frame_param (f, Qvisibility, visibility); | 1714 | store_frame_param (f, Qvisibility, visibility); |
| 1708 | } | 1715 | } |
| @@ -2670,7 +2677,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct | |||
| 2670 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 2677 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 2671 | RES_TYPE_STRING); | 2678 | RES_TYPE_STRING); |
| 2672 | if (!STRINGP (name) | 2679 | if (!STRINGP (name) |
| 2673 | && !EQ (name, Qunbound) | 2680 | && !BASE_EQ (name, Qunbound) |
| 2674 | && !NILP (name)) | 2681 | && !NILP (name)) |
| 2675 | error ("Invalid frame name--not a string or nil"); | 2682 | error ("Invalid frame name--not a string or nil"); |
| 2676 | 2683 | ||
| @@ -2721,7 +2728,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct | |||
| 2721 | 2728 | ||
| 2722 | /* Set the name; the functions to which we pass f expect the name to | 2729 | /* Set the name; the functions to which we pass f expect the name to |
| 2723 | be set. */ | 2730 | be set. */ |
| 2724 | if (EQ (name, Qunbound) || NILP (name)) | 2731 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 2725 | { | 2732 | { |
| 2726 | fset_name (f, build_string (dpyinfo->x_id_name)); | 2733 | fset_name (f, build_string (dpyinfo->x_id_name)); |
| 2727 | f->explicit_name = false; | 2734 | f->explicit_name = false; |
| @@ -2762,7 +2769,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct | |||
| 2762 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 2769 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 2763 | "internalBorder", "internalBorder", | 2770 | "internalBorder", "internalBorder", |
| 2764 | RES_TYPE_NUMBER); | 2771 | RES_TYPE_NUMBER); |
| 2765 | if (! EQ (value, Qunbound)) | 2772 | if (! BASE_EQ (value, Qunbound)) |
| 2766 | parms = Fcons (Fcons (Qinternal_border_width, value), | 2773 | parms = Fcons (Fcons (Qinternal_border_width, value), |
| 2767 | parms); | 2774 | parms); |
| 2768 | } | 2775 | } |
| @@ -2853,7 +2860,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct | |||
| 2853 | Frame parameters may be changed if .Xdefaults contains | 2860 | Frame parameters may be changed if .Xdefaults contains |
| 2854 | specifications for the default font. For example, if there is an | 2861 | specifications for the default font. For example, if there is an |
| 2855 | `Emacs.default.attributeBackground: pink', the `background-color' | 2862 | `Emacs.default.attributeBackground: pink', the `background-color' |
| 2856 | attribute of the frame get's set, which let's the internal border | 2863 | attribute of the frame gets set, which lets the internal border |
| 2857 | of the tooltip frame appear in pink. Prevent this. */ | 2864 | of the tooltip frame appear in pink. Prevent this. */ |
| 2858 | { | 2865 | { |
| 2859 | Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); | 2866 | Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); |
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index eec9f419d07..2eabf6ac1bc 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c | |||
| @@ -610,11 +610,6 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 610 | 610 | ||
| 611 | *error_name = NULL; | 611 | *error_name = NULL; |
| 612 | 612 | ||
| 613 | if (!FRAME_GTK_OUTER_WIDGET (f)) { | ||
| 614 | *error_name = "Can't popup from child frames."; | ||
| 615 | return Qnil; | ||
| 616 | } | ||
| 617 | |||
| 618 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) | 613 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) |
| 619 | { | 614 | { |
| 620 | *error_name = "Empty menu"; | 615 | *error_name = "Empty menu"; |
| @@ -919,11 +914,6 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, | |||
| 919 | 914 | ||
| 920 | *error_name = NULL; | 915 | *error_name = NULL; |
| 921 | 916 | ||
| 922 | if (!FRAME_GTK_OUTER_WIDGET (f)) { | ||
| 923 | *error_name = "Can't popup from child frames."; | ||
| 924 | return Qnil; | ||
| 925 | } | ||
| 926 | |||
| 927 | if (menu_items_n_panes > 1) | 917 | if (menu_items_n_panes > 1) |
| 928 | { | 918 | { |
| 929 | *error_name = "Multiple panes in dialog box"; | 919 | *error_name = "Multiple panes in dialog box"; |
diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 4c87aaa7ea6..76901b9eb1d 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c | |||
| @@ -323,7 +323,7 @@ nil, it defaults to the selected frame. */) | |||
| 323 | gtk_target_list_unref (list); | 323 | gtk_target_list_unref (list); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | if (!EQ (Vpgtk_sent_selection_hooks, Qunbound)) | 326 | if (!BASE_EQ (Vpgtk_sent_selection_hooks, Qunbound)) |
| 327 | { | 327 | { |
| 328 | /* FIXME: Use run-hook-with-args! */ | 328 | /* FIXME: Use run-hook-with-args! */ |
| 329 | for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); | 329 | for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); |
diff --git a/src/pgtkterm.c b/src/pgtkterm.c index c8c8bd0d85e..da958a6664a 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c | |||
| @@ -1333,9 +1333,7 @@ pgtk_draw_glyph_string_background (struct glyph_string *s, bool force_p) | |||
| 1333 | if (s->stippled_p) | 1333 | if (s->stippled_p) |
| 1334 | { | 1334 | { |
| 1335 | /* Fill background with a stipple pattern. */ | 1335 | /* Fill background with a stipple pattern. */ |
| 1336 | 1336 | fill_background (s, s->x, s->y + box_line_width, | |
| 1337 | fill_background (s, | ||
| 1338 | s->x, s->y + box_line_width, | ||
| 1339 | s->background_width, | 1337 | s->background_width, |
| 1340 | s->height - 2 * box_line_width); | 1338 | s->height - 2 * box_line_width); |
| 1341 | s->background_filled_p = true; | 1339 | s->background_filled_p = true; |
| @@ -1589,6 +1587,10 @@ pgtk_draw_glyphless_glyph_string_foreground (struct glyph_string *s) | |||
| 1589 | false); | 1587 | false); |
| 1590 | x += glyph->pixel_width; | 1588 | x += glyph->pixel_width; |
| 1591 | } | 1589 | } |
| 1590 | |||
| 1591 | /* Pacify GCC 12 even though s->char2b is not used after this | ||
| 1592 | function returns. */ | ||
| 1593 | s->char2b = NULL; | ||
| 1592 | } | 1594 | } |
| 1593 | 1595 | ||
| 1594 | /* Brightness beyond which a color won't have its highlight brightness | 1596 | /* Brightness beyond which a color won't have its highlight brightness |
| @@ -2501,9 +2503,7 @@ pgtk_draw_glyph_string (struct glyph_string *s) | |||
| 2501 | if (s->face->underline_defaulted_p) | 2503 | if (s->face->underline_defaulted_p) |
| 2502 | pgtk_draw_underwave (s, s->xgcv.foreground); | 2504 | pgtk_draw_underwave (s, s->xgcv.foreground); |
| 2503 | else | 2505 | else |
| 2504 | { | 2506 | pgtk_draw_underwave (s, s->face->underline_color); |
| 2505 | pgtk_draw_underwave (s, s->face->underline_color); | ||
| 2506 | } | ||
| 2507 | } | 2507 | } |
| 2508 | else if (s->face->underline == FACE_UNDER_LINE) | 2508 | else if (s->face->underline == FACE_UNDER_LINE) |
| 2509 | { | 2509 | { |
| @@ -2555,7 +2555,7 @@ pgtk_draw_glyph_string (struct glyph_string *s) | |||
| 2555 | } | 2555 | } |
| 2556 | 2556 | ||
| 2557 | /* Ignore minimum_offset if the amount of pixels was | 2557 | /* Ignore minimum_offset if the amount of pixels was |
| 2558 | explictly specified. */ | 2558 | explicitly specified. */ |
| 2559 | if (!s->face->underline_pixels_above_descent_line) | 2559 | if (!s->face->underline_pixels_above_descent_line) |
| 2560 | position = max (position, underline_minimum_offset); | 2560 | position = max (position, underline_minimum_offset); |
| 2561 | } | 2561 | } |
| @@ -2670,6 +2670,11 @@ pgtk_draw_glyph_string (struct glyph_string *s) | |||
| 2670 | } | 2670 | } |
| 2671 | } | 2671 | } |
| 2672 | 2672 | ||
| 2673 | /* TODO: figure out in which cases the stipple is actually drawn on | ||
| 2674 | PGTK. */ | ||
| 2675 | if (!s->row->stipple_p) | ||
| 2676 | s->row->stipple_p = s->face->stipple; | ||
| 2677 | |||
| 2673 | /* Reset clipping. */ | 2678 | /* Reset clipping. */ |
| 2674 | pgtk_end_cr_clip (s->f); | 2679 | pgtk_end_cr_clip (s->f); |
| 2675 | s->num_clips = 0; | 2680 | s->num_clips = 0; |
| @@ -3346,15 +3351,10 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, | |||
| 3346 | if (gui_mouse_grabbed (dpyinfo) | 3351 | if (gui_mouse_grabbed (dpyinfo) |
| 3347 | && (!EQ (track_mouse, Qdropping) | 3352 | && (!EQ (track_mouse, Qdropping) |
| 3348 | && !EQ (track_mouse, Qdrag_source))) | 3353 | && !EQ (track_mouse, Qdrag_source))) |
| 3349 | { | 3354 | f1 = dpyinfo->last_mouse_frame; |
| 3350 | /* 1.1. use last_mouse_frame as frame where the pointer is | ||
| 3351 | on. */ | ||
| 3352 | f1 = dpyinfo->last_mouse_frame; | ||
| 3353 | } | ||
| 3354 | else | 3355 | else |
| 3355 | { | 3356 | { |
| 3356 | f1 = *fp; | 3357 | f1 = *fp; |
| 3357 | /* 1.2. get frame where the pointer is on. */ | ||
| 3358 | win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp)); | 3358 | win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp)); |
| 3359 | seat = gdk_display_get_default_seat (dpyinfo->gdpy); | 3359 | seat = gdk_display_get_default_seat (dpyinfo->gdpy); |
| 3360 | device = gdk_seat_get_pointer (seat); | 3360 | device = gdk_seat_get_pointer (seat); |
| @@ -3380,19 +3380,17 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, | |||
| 3380 | return; | 3380 | return; |
| 3381 | } | 3381 | } |
| 3382 | 3382 | ||
| 3383 | /* 2. get the display and the device. */ | ||
| 3384 | win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1)); | 3383 | win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1)); |
| 3385 | GdkDisplay *gdpy = gdk_window_get_display (win); | 3384 | seat = gdk_display_get_default_seat (dpyinfo->gdpy); |
| 3386 | seat = gdk_display_get_default_seat (gdpy); | ||
| 3387 | device = gdk_seat_get_pointer (seat); | 3385 | device = gdk_seat_get_pointer (seat); |
| 3388 | 3386 | ||
| 3389 | /* 3. get x, y relative to edit window of the frame. */ | 3387 | win = gdk_window_get_device_position (win, device, |
| 3390 | win = gdk_window_get_device_position (win, device, &win_x, &win_y, &mask); | 3388 | &win_x, &win_y, &mask); |
| 3391 | 3389 | ||
| 3392 | if (f1 != NULL) | 3390 | if (f1 != NULL) |
| 3393 | { | 3391 | { |
| 3394 | dpyinfo = FRAME_DISPLAY_INFO (f1); | 3392 | remember_mouse_glyph (f1, win_x, win_y, |
| 3395 | remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); | 3393 | &dpyinfo->last_mouse_glyph); |
| 3396 | dpyinfo->last_mouse_glyph_frame = f1; | 3394 | dpyinfo->last_mouse_glyph_frame = f1; |
| 3397 | 3395 | ||
| 3398 | *bar_window = Qnil; | 3396 | *bar_window = Qnil; |
| @@ -3505,9 +3503,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3505 | mono-displays, the fill style may have been changed to | 3503 | mono-displays, the fill style may have been changed to |
| 3506 | FillSolid in pgtk_draw_glyph_string_background. */ | 3504 | FillSolid in pgtk_draw_glyph_string_background. */ |
| 3507 | if (face->stipple) | 3505 | if (face->stipple) |
| 3508 | { | 3506 | fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny); |
| 3509 | fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny); | ||
| 3510 | } | ||
| 3511 | else | 3507 | else |
| 3512 | { | 3508 | { |
| 3513 | pgtk_set_cr_source_with_color (f, face->background, true); | 3509 | pgtk_set_cr_source_with_color (f, face->background, true); |
| @@ -6164,6 +6160,20 @@ drag_data_received (GtkWidget *widget, GdkDragContext *context, | |||
| 6164 | gtk_drag_finish (context, TRUE, FALSE, time); | 6160 | gtk_drag_finish (context, TRUE, FALSE, time); |
| 6165 | } | 6161 | } |
| 6166 | 6162 | ||
| 6163 | static void | ||
| 6164 | pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data) | ||
| 6165 | { | ||
| 6166 | struct terminal *terminal; | ||
| 6167 | union buffered_input_event inev; | ||
| 6168 | |||
| 6169 | EVENT_INIT (inev.ie); | ||
| 6170 | terminal = user_data; | ||
| 6171 | inev.ie.kind = MONITORS_CHANGED_EVENT; | ||
| 6172 | XSETTERMINAL (inev.ie.arg, terminal); | ||
| 6173 | |||
| 6174 | evq_enqueue (&inev); | ||
| 6175 | } | ||
| 6176 | |||
| 6167 | void | 6177 | void |
| 6168 | pgtk_set_event_handler (struct frame *f) | 6178 | pgtk_set_event_handler (struct frame *f) |
| 6169 | { | 6179 | { |
| @@ -6282,26 +6292,6 @@ same_x_server (const char *name1, const char *name2) | |||
| 6282 | && (*name2 == '.' || *name2 == '\0')); | 6292 | && (*name2 == '.' || *name2 == '\0')); |
| 6283 | } | 6293 | } |
| 6284 | 6294 | ||
| 6285 | #define GNOME_INTERFACE_SCHEMA "org.gnome.desktop.interface" | ||
| 6286 | |||
| 6287 | static gdouble pgtk_text_scaling_factor (void) | ||
| 6288 | { | ||
| 6289 | GSettingsSchemaSource *schema_source = g_settings_schema_source_get_default (); | ||
| 6290 | if (schema_source != NULL) | ||
| 6291 | { | ||
| 6292 | GSettingsSchema *schema = g_settings_schema_source_lookup (schema_source, | ||
| 6293 | GNOME_INTERFACE_SCHEMA, true); | ||
| 6294 | if (schema != NULL) | ||
| 6295 | { | ||
| 6296 | g_settings_schema_unref (schema); | ||
| 6297 | GSettings *set = g_settings_new (GNOME_INTERFACE_SCHEMA); | ||
| 6298 | return g_settings_get_double (set, "text-scaling-factor"); | ||
| 6299 | } | ||
| 6300 | } | ||
| 6301 | return 1; | ||
| 6302 | } | ||
| 6303 | |||
| 6304 | |||
| 6305 | /* Open a connection to X display DISPLAY_NAME, and return | 6295 | /* Open a connection to X display DISPLAY_NAME, and return |
| 6306 | the structure that describes the open display. | 6296 | the structure that describes the open display. |
| 6307 | If we cannot contact the display, return null. */ | 6297 | If we cannot contact the display, return null. */ |
| @@ -6318,6 +6308,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) | |||
| 6318 | char *dpy_name; | 6308 | char *dpy_name; |
| 6319 | static void *handle = NULL; | 6309 | static void *handle = NULL; |
| 6320 | Lisp_Object lisp_dpy_name = Qnil; | 6310 | Lisp_Object lisp_dpy_name = Qnil; |
| 6311 | GdkScreen *gscr; | ||
| 6312 | gdouble dpi; | ||
| 6321 | 6313 | ||
| 6322 | block_input (); | 6314 | block_input (); |
| 6323 | 6315 | ||
| @@ -6468,21 +6460,22 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) | |||
| 6468 | 6460 | ||
| 6469 | reset_mouse_highlight (&dpyinfo->mouse_highlight); | 6461 | reset_mouse_highlight (&dpyinfo->mouse_highlight); |
| 6470 | 6462 | ||
| 6471 | { | 6463 | gscr = gdk_display_get_default_screen (dpyinfo->gdpy); |
| 6472 | GdkScreen *gscr = gdk_display_get_default_screen (dpyinfo->gdpy); | 6464 | dpi = gdk_screen_get_resolution (gscr); |
| 6473 | 6465 | ||
| 6474 | gdouble dpi = gdk_screen_get_resolution (gscr); | 6466 | if (dpi < 0) |
| 6475 | if (dpi < 0) | 6467 | dpi = 96.0; |
| 6476 | dpi = 96.0; | ||
| 6477 | 6468 | ||
| 6478 | dpi *= pgtk_text_scaling_factor (); | 6469 | dpyinfo->resx = dpi; |
| 6479 | dpyinfo->resx = dpi; | 6470 | dpyinfo->resy = dpi; |
| 6480 | dpyinfo->resy = dpi; | 6471 | |
| 6481 | } | 6472 | g_signal_connect (G_OBJECT (gscr), "monitors-changed", |
| 6473 | G_CALLBACK (pgtk_monitors_changed_cb), | ||
| 6474 | terminal); | ||
| 6482 | 6475 | ||
| 6483 | /* smooth scroll setting */ | 6476 | /* Set up scrolling increments. */ |
| 6484 | dpyinfo->scroll.x_per_char = 2; | 6477 | dpyinfo->scroll.x_per_char = 1; |
| 6485 | dpyinfo->scroll.y_per_line = 2; | 6478 | dpyinfo->scroll.y_per_line = 1; |
| 6486 | 6479 | ||
| 6487 | dpyinfo->connection = -1; | 6480 | dpyinfo->connection = -1; |
| 6488 | 6481 | ||
| @@ -6608,9 +6601,9 @@ pgtk_xlfd_to_fontname (const char *xlfd) | |||
| 6608 | } | 6601 | } |
| 6609 | 6602 | ||
| 6610 | bool | 6603 | bool |
| 6611 | pgtk_defined_color (struct frame *f, | 6604 | pgtk_defined_color (struct frame *f, const char *name, |
| 6612 | const char *name, | 6605 | Emacs_Color *color_def, bool alloc, |
| 6613 | Emacs_Color * color_def, bool alloc, bool makeIndex) | 6606 | bool makeIndex) |
| 6614 | /* -------------------------------------------------------------------------- | 6607 | /* -------------------------------------------------------------------------- |
| 6615 | Return true if named color found, and set color_def rgb accordingly. | 6608 | Return true if named color found, and set color_def rgb accordingly. |
| 6616 | If makeIndex and alloc are nonzero put the color in the color_table, | 6609 | If makeIndex and alloc are nonzero put the color in the color_table, |
diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 20c161e63b9..e31e62ae193 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h | |||
| @@ -96,7 +96,7 @@ struct scroll_bar | |||
| 96 | editing large files, we establish a minimum height by always | 96 | editing large files, we establish a minimum height by always |
| 97 | drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below | 97 | drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below |
| 98 | where they would be normally; the bottom and top are in a | 98 | where they would be normally; the bottom and top are in a |
| 99 | different co-ordinate system. */ | 99 | different coordinate system. */ |
| 100 | int start, end; | 100 | int start, end; |
| 101 | 101 | ||
| 102 | /* If the scroll bar handle is currently being dragged by the user, | 102 | /* If the scroll bar handle is currently being dragged by the user, |
diff --git a/src/print.c b/src/print.c index 81b524d79fe..5aee5731e40 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -624,7 +624,86 @@ If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used. */) | |||
| 624 | return val; | 624 | return val; |
| 625 | } | 625 | } |
| 626 | 626 | ||
| 627 | DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0, | 627 | static Lisp_Object Vprint_variable_mapping; |
| 628 | |||
| 629 | static void | ||
| 630 | print_bind_all_defaults (void) | ||
| 631 | { | ||
| 632 | for (Lisp_Object vars = Vprint_variable_mapping; !NILP (vars); | ||
| 633 | vars = XCDR (vars)) | ||
| 634 | { | ||
| 635 | Lisp_Object elem = XCDR (XCAR (vars)); | ||
| 636 | specbind (XCAR (elem), XCAR (XCDR (elem))); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | |||
| 640 | static void | ||
| 641 | print_create_variable_mapping (void) | ||
| 642 | { | ||
| 643 | Lisp_Object total[] = { | ||
| 644 | list3 (intern ("length"), intern ("print-length"), Qnil), | ||
| 645 | list3 (intern ("level"), intern ("print-level"), Qnil), | ||
| 646 | list3 (intern ("circle"), intern ("print-circle"), Qnil), | ||
| 647 | list3 (intern ("quoted"), intern ("print-quoted"), Qt), | ||
| 648 | list3 (intern ("escape-newlines"), intern ("print-escape-newlines"), Qnil), | ||
| 649 | list3 (intern ("escape-control-characters"), | ||
| 650 | intern ("print-escape-control-characters"), Qnil), | ||
| 651 | list3 (intern ("escape-nonascii"), intern ("print-escape-nonascii"), Qnil), | ||
| 652 | list3 (intern ("escape-multibyte"), | ||
| 653 | intern ("print-escape-multibyte"), Qnil), | ||
| 654 | list3 (intern ("charset-text-property"), | ||
| 655 | intern ("print-charset-text-property"), Qnil), | ||
| 656 | list3 (intern ("unreadeable-function"), | ||
| 657 | intern ("print-unreadable-function"), Qnil), | ||
| 658 | list3 (intern ("gensym"), intern ("print-gensym"), Qnil), | ||
| 659 | list3 (intern ("continuous-numbering"), | ||
| 660 | intern ("print-continuous-numbering"), Qnil), | ||
| 661 | list3 (intern ("number-table"), intern ("print-number-table"), Qnil), | ||
| 662 | list3 (intern ("float-format"), intern ("float-output-format"), Qnil), | ||
| 663 | list3 (intern ("integers-as-characters"), | ||
| 664 | intern ("print-integers-as-characters"), Qnil), | ||
| 665 | }; | ||
| 666 | |||
| 667 | Vprint_variable_mapping = CALLMANY (Flist, total); | ||
| 668 | } | ||
| 669 | |||
| 670 | static void | ||
| 671 | print_bind_overrides (Lisp_Object overrides) | ||
| 672 | { | ||
| 673 | if (NILP (Vprint_variable_mapping)) | ||
| 674 | print_create_variable_mapping (); | ||
| 675 | |||
| 676 | if (EQ (overrides, Qt)) | ||
| 677 | print_bind_all_defaults (); | ||
| 678 | else if (!CONSP (overrides)) | ||
| 679 | xsignal (Qwrong_type_argument, Qconsp); | ||
| 680 | else | ||
| 681 | { | ||
| 682 | while (!NILP (overrides)) | ||
| 683 | { | ||
| 684 | Lisp_Object setting = XCAR (overrides); | ||
| 685 | if (EQ (setting, Qt)) | ||
| 686 | print_bind_all_defaults (); | ||
| 687 | else if (!CONSP (setting)) | ||
| 688 | xsignal (Qwrong_type_argument, Qconsp); | ||
| 689 | else | ||
| 690 | { | ||
| 691 | Lisp_Object key = XCAR (setting), | ||
| 692 | value = XCDR (setting); | ||
| 693 | Lisp_Object map = Fassq (key, Vprint_variable_mapping); | ||
| 694 | if (NILP (map)) | ||
| 695 | xsignal2 (Qwrong_type_argument, Qsymbolp, map); | ||
| 696 | specbind (XCAR (XCDR (map)), value); | ||
| 697 | } | ||
| 698 | |||
| 699 | if (!NILP (XCDR (overrides)) && !CONSP (XCDR (overrides))) | ||
| 700 | xsignal (Qwrong_type_argument, Qconsp); | ||
| 701 | overrides = XCDR (overrides); | ||
| 702 | } | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | DEFUN ("prin1", Fprin1, Sprin1, 1, 3, 0, | ||
| 628 | doc: /* Output the printed representation of OBJECT, any Lisp object. | 707 | doc: /* Output the printed representation of OBJECT, any Lisp object. |
| 629 | Quoting characters are printed when needed to make output that `read' | 708 | Quoting characters are printed when needed to make output that `read' |
| 630 | can handle, whenever this is possible. For complex objects, the behavior | 709 | can handle, whenever this is possible. For complex objects, the behavior |
| @@ -646,21 +725,43 @@ of these: | |||
| 646 | - t, in which case the output is displayed in the echo area. | 725 | - t, in which case the output is displayed in the echo area. |
| 647 | 726 | ||
| 648 | If PRINTCHARFUN is omitted, the value of `standard-output' (which see) | 727 | If PRINTCHARFUN is omitted, the value of `standard-output' (which see) |
| 649 | is used instead. */) | 728 | is used instead. |
| 650 | (Lisp_Object object, Lisp_Object printcharfun) | 729 | |
| 730 | Optional argument OVERRIDES should be a list of settings for print-related | ||
| 731 | variables. An element in this list can be the symbol t, which means "reset | ||
| 732 | all the values to their defaults". Otherwise, an element should be a pair, | ||
| 733 | where the `car' or the pair is the setting symbol, and the `cdr' is the | ||
| 734 | value of of the setting to use for this `prin1' call. | ||
| 735 | |||
| 736 | For instance: | ||
| 737 | |||
| 738 | (prin1 object nil \\='((length . 100) (circle . t))). | ||
| 739 | |||
| 740 | See the manual entry `(elisp)Output Overrides' for a list of possible | ||
| 741 | values. | ||
| 742 | |||
| 743 | As a special case, OVERRIDES can also simply be the symbol t, which | ||
| 744 | means "use default values for all the print-related settings". */) | ||
| 745 | (Lisp_Object object, Lisp_Object printcharfun, Lisp_Object overrides) | ||
| 651 | { | 746 | { |
| 747 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 748 | |||
| 652 | if (NILP (printcharfun)) | 749 | if (NILP (printcharfun)) |
| 653 | printcharfun = Vstandard_output; | 750 | printcharfun = Vstandard_output; |
| 751 | if (!NILP (overrides)) | ||
| 752 | print_bind_overrides (overrides); | ||
| 753 | |||
| 654 | PRINTPREPARE; | 754 | PRINTPREPARE; |
| 655 | print (object, printcharfun, 1); | 755 | print (object, printcharfun, 1); |
| 656 | PRINTFINISH; | 756 | PRINTFINISH; |
| 657 | return object; | 757 | |
| 758 | return unbind_to (count, object); | ||
| 658 | } | 759 | } |
| 659 | 760 | ||
| 660 | /* A buffer which is used to hold output being built by prin1-to-string. */ | 761 | /* A buffer which is used to hold output being built by prin1-to-string. */ |
| 661 | Lisp_Object Vprin1_to_string_buffer; | 762 | Lisp_Object Vprin1_to_string_buffer; |
| 662 | 763 | ||
| 663 | DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 2, 0, | 764 | DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 3, 0, |
| 664 | doc: /* Return a string containing the printed representation of OBJECT. | 765 | doc: /* Return a string containing the printed representation of OBJECT. |
| 665 | OBJECT can be any Lisp object. This function outputs quoting characters | 766 | OBJECT can be any Lisp object. This function outputs quoting characters |
| 666 | when necessary to make output that `read' can handle, whenever possible, | 767 | when necessary to make output that `read' can handle, whenever possible, |
| @@ -670,13 +771,18 @@ the behavior is controlled by `print-level' and `print-length', which see. | |||
| 670 | OBJECT is any of the Lisp data types: a number, a string, a symbol, | 771 | OBJECT is any of the Lisp data types: a number, a string, a symbol, |
| 671 | a list, a buffer, a window, a frame, etc. | 772 | a list, a buffer, a window, a frame, etc. |
| 672 | 773 | ||
| 774 | See `prin1' for the meaning of OVERRIDES. | ||
| 775 | |||
| 673 | A printed representation of an object is text which describes that object. */) | 776 | A printed representation of an object is text which describes that object. */) |
| 674 | (Lisp_Object object, Lisp_Object noescape) | 777 | (Lisp_Object object, Lisp_Object noescape, Lisp_Object overrides) |
| 675 | { | 778 | { |
| 676 | specpdl_ref count = SPECPDL_INDEX (); | 779 | specpdl_ref count = SPECPDL_INDEX (); |
| 677 | 780 | ||
| 678 | specbind (Qinhibit_modification_hooks, Qt); | 781 | specbind (Qinhibit_modification_hooks, Qt); |
| 679 | 782 | ||
| 783 | if (!NILP (overrides)) | ||
| 784 | print_bind_overrides (overrides); | ||
| 785 | |||
| 680 | /* Save and restore this: we are altering a buffer | 786 | /* Save and restore this: we are altering a buffer |
| 681 | but we don't want to deactivate the mark just for that. | 787 | but we don't want to deactivate the mark just for that. |
| 682 | No need for specbind, since errors deactivate the mark. */ | 788 | No need for specbind, since errors deactivate the mark. */ |
| @@ -732,7 +838,13 @@ is used instead. */) | |||
| 732 | if (NILP (printcharfun)) | 838 | if (NILP (printcharfun)) |
| 733 | printcharfun = Vstandard_output; | 839 | printcharfun = Vstandard_output; |
| 734 | PRINTPREPARE; | 840 | PRINTPREPARE; |
| 735 | print (object, printcharfun, 0); | 841 | if (STRINGP (object) |
| 842 | && !string_intervals (object) | ||
| 843 | && NILP (Vprint_continuous_numbering)) | ||
| 844 | /* fast path for plain strings */ | ||
| 845 | print_string (object, printcharfun); | ||
| 846 | else | ||
| 847 | print (object, printcharfun, 0); | ||
| 736 | PRINTFINISH; | 848 | PRINTFINISH; |
| 737 | return object; | 849 | return object; |
| 738 | } | 850 | } |
| @@ -851,7 +963,7 @@ append to existing target file. */) | |||
| 851 | void | 963 | void |
| 852 | debug_print (Lisp_Object arg) | 964 | debug_print (Lisp_Object arg) |
| 853 | { | 965 | { |
| 854 | Fprin1 (arg, Qexternal_debugging_output); | 966 | Fprin1 (arg, Qexternal_debugging_output, Qnil); |
| 855 | fputs ("\r\n", stderr); | 967 | fputs ("\r\n", stderr); |
| 856 | } | 968 | } |
| 857 | 969 | ||
| @@ -999,7 +1111,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, | |||
| 999 | || EQ (errname, Qend_of_file) || EQ (errname, Quser_error)) | 1111 | || EQ (errname, Qend_of_file) || EQ (errname, Quser_error)) |
| 1000 | Fprinc (obj, stream); | 1112 | Fprinc (obj, stream); |
| 1001 | else | 1113 | else |
| 1002 | Fprin1 (obj, stream); | 1114 | Fprin1 (obj, stream, Qnil); |
| 1003 | } | 1115 | } |
| 1004 | } | 1116 | } |
| 1005 | } | 1117 | } |
| @@ -1147,7 +1259,6 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1147 | { | 1259 | { |
| 1148 | /* Construct Vprint_number_table. | 1260 | /* Construct Vprint_number_table. |
| 1149 | This increments print_number_index for the objects added. */ | 1261 | This increments print_number_index for the objects added. */ |
| 1150 | print_depth = 0; | ||
| 1151 | print_preprocess (obj); | 1262 | print_preprocess (obj); |
| 1152 | 1263 | ||
| 1153 | if (HASH_TABLE_P (Vprint_number_table)) | 1264 | if (HASH_TABLE_P (Vprint_number_table)) |
| @@ -1159,7 +1270,7 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1159 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) | 1270 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 1160 | { | 1271 | { |
| 1161 | Lisp_Object key = HASH_KEY (h, i); | 1272 | Lisp_Object key = HASH_KEY (h, i); |
| 1162 | if (!EQ (key, Qunbound) | 1273 | if (!BASE_EQ (key, Qunbound) |
| 1163 | && EQ (HASH_VALUE (h, i), Qt)) | 1274 | && EQ (HASH_VALUE (h, i), Qt)) |
| 1164 | Fremhash (key, Vprint_number_table); | 1275 | Fremhash (key, Vprint_number_table); |
| 1165 | } | 1276 | } |
| @@ -1171,10 +1282,7 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1171 | } | 1282 | } |
| 1172 | 1283 | ||
| 1173 | #define PRINT_CIRCLE_CANDIDATE_P(obj) \ | 1284 | #define PRINT_CIRCLE_CANDIDATE_P(obj) \ |
| 1174 | ((STRINGP (obj) \ | 1285 | (STRINGP (obj) \ |
| 1175 | && (string_intervals (obj) \ | ||
| 1176 | || print_depth > 1 \ | ||
| 1177 | || !NILP (Vprint_continuous_numbering))) \ | ||
| 1178 | || CONSP (obj) \ | 1286 | || CONSP (obj) \ |
| 1179 | || (VECTORLIKEP (obj) \ | 1287 | || (VECTORLIKEP (obj) \ |
| 1180 | && (VECTORP (obj) || COMPILEDP (obj) \ | 1288 | && (VECTORP (obj) || COMPILEDP (obj) \ |
| @@ -1185,6 +1293,78 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1185 | && SYMBOLP (obj) \ | 1293 | && SYMBOLP (obj) \ |
| 1186 | && !SYMBOL_INTERNED_P (obj))) | 1294 | && !SYMBOL_INTERNED_P (obj))) |
| 1187 | 1295 | ||
| 1296 | /* The print preprocess stack, used to traverse data structures. */ | ||
| 1297 | |||
| 1298 | struct print_pp_entry { | ||
| 1299 | ptrdiff_t n; /* number of values, or 0 if a single value */ | ||
| 1300 | union { | ||
| 1301 | Lisp_Object value; /* when n = 0 */ | ||
| 1302 | Lisp_Object *values; /* when n > 0 */ | ||
| 1303 | } u; | ||
| 1304 | }; | ||
| 1305 | |||
| 1306 | struct print_pp_stack { | ||
| 1307 | struct print_pp_entry *stack; /* base of stack */ | ||
| 1308 | ptrdiff_t size; /* allocated size in entries */ | ||
| 1309 | ptrdiff_t sp; /* current number of entries */ | ||
| 1310 | }; | ||
| 1311 | |||
| 1312 | static struct print_pp_stack ppstack = {NULL, 0, 0}; | ||
| 1313 | |||
| 1314 | NO_INLINE static void | ||
| 1315 | grow_pp_stack (void) | ||
| 1316 | { | ||
| 1317 | struct print_pp_stack *ps = &ppstack; | ||
| 1318 | eassert (ps->sp == ps->size); | ||
| 1319 | ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack); | ||
| 1320 | eassert (ps->sp < ps->size); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | static inline void | ||
| 1324 | pp_stack_push_value (Lisp_Object value) | ||
| 1325 | { | ||
| 1326 | if (ppstack.sp >= ppstack.size) | ||
| 1327 | grow_pp_stack (); | ||
| 1328 | ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = 0, | ||
| 1329 | .u.value = value}; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | static inline void | ||
| 1333 | pp_stack_push_values (Lisp_Object *values, ptrdiff_t n) | ||
| 1334 | { | ||
| 1335 | eassume (n >= 0); | ||
| 1336 | if (n == 0) | ||
| 1337 | return; | ||
| 1338 | if (ppstack.sp >= ppstack.size) | ||
| 1339 | grow_pp_stack (); | ||
| 1340 | ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = n, | ||
| 1341 | .u.values = values}; | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | static inline bool | ||
| 1345 | pp_stack_empty_p (void) | ||
| 1346 | { | ||
| 1347 | return ppstack.sp <= 0; | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | static inline Lisp_Object | ||
| 1351 | pp_stack_pop (void) | ||
| 1352 | { | ||
| 1353 | eassume (!pp_stack_empty_p ()); | ||
| 1354 | struct print_pp_entry *e = &ppstack.stack[ppstack.sp - 1]; | ||
| 1355 | if (e->n == 0) /* single value */ | ||
| 1356 | { | ||
| 1357 | --ppstack.sp; | ||
| 1358 | return e->u.value; | ||
| 1359 | } | ||
| 1360 | /* Array of values: pop them left to right, which seems to be slightly | ||
| 1361 | faster than right to left. */ | ||
| 1362 | e->n--; | ||
| 1363 | if (e->n == 0) | ||
| 1364 | --ppstack.sp; /* last value consumed */ | ||
| 1365 | return (++e->u.values)[-1]; | ||
| 1366 | } | ||
| 1367 | |||
| 1188 | /* Construct Vprint_number_table for the print-circle feature | 1368 | /* Construct Vprint_number_table for the print-circle feature |
| 1189 | according to the structure of OBJ. OBJ itself and all its elements | 1369 | according to the structure of OBJ. OBJ itself and all its elements |
| 1190 | will be added to Vprint_number_table recursively if it is a list, | 1370 | will be added to Vprint_number_table recursively if it is a list, |
| @@ -1196,86 +1376,81 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1196 | static void | 1376 | static void |
| 1197 | print_preprocess (Lisp_Object obj) | 1377 | print_preprocess (Lisp_Object obj) |
| 1198 | { | 1378 | { |
| 1199 | int i; | ||
| 1200 | ptrdiff_t size; | ||
| 1201 | int loop_count = 0; | ||
| 1202 | Lisp_Object halftail; | ||
| 1203 | |||
| 1204 | eassert (!NILP (Vprint_circle)); | 1379 | eassert (!NILP (Vprint_circle)); |
| 1380 | ptrdiff_t base_sp = ppstack.sp; | ||
| 1205 | 1381 | ||
| 1206 | print_depth++; | 1382 | for (;;) |
| 1207 | halftail = obj; | ||
| 1208 | |||
| 1209 | loop: | ||
| 1210 | if (PRINT_CIRCLE_CANDIDATE_P (obj)) | ||
| 1211 | { | 1383 | { |
| 1212 | if (!HASH_TABLE_P (Vprint_number_table)) | 1384 | if (PRINT_CIRCLE_CANDIDATE_P (obj)) |
| 1213 | Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq); | 1385 | { |
| 1214 | 1386 | if (!HASH_TABLE_P (Vprint_number_table)) | |
| 1215 | Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); | 1387 | Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq); |
| 1216 | if (!NILP (num) | 1388 | |
| 1217 | /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym, | 1389 | Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); |
| 1218 | always print the gensym with a number. This is a special for | 1390 | if (!NILP (num) |
| 1219 | the lisp function byte-compile-output-docform. */ | 1391 | /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym, |
| 1220 | || (!NILP (Vprint_continuous_numbering) | 1392 | always print the gensym with a number. This is a special for |
| 1221 | && SYMBOLP (obj) | 1393 | the lisp function byte-compile-output-docform. */ |
| 1222 | && !SYMBOL_INTERNED_P (obj))) | 1394 | || (!NILP (Vprint_continuous_numbering) |
| 1223 | { /* OBJ appears more than once. Let's remember that. */ | 1395 | && SYMBOLP (obj) |
| 1224 | if (!FIXNUMP (num)) | 1396 | && !SYMBOL_INTERNED_P (obj))) |
| 1225 | { | 1397 | { /* OBJ appears more than once. Let's remember that. */ |
| 1226 | print_number_index++; | 1398 | if (!FIXNUMP (num)) |
| 1227 | /* Negative number indicates it hasn't been printed yet. */ | 1399 | { |
| 1228 | Fputhash (obj, make_fixnum (- print_number_index), | 1400 | print_number_index++; |
| 1229 | Vprint_number_table); | 1401 | /* Negative number indicates it hasn't been printed yet. */ |
| 1402 | Fputhash (obj, make_fixnum (- print_number_index), | ||
| 1403 | Vprint_number_table); | ||
| 1404 | } | ||
| 1230 | } | 1405 | } |
| 1231 | print_depth--; | 1406 | else |
| 1232 | return; | 1407 | { |
| 1233 | } | 1408 | /* OBJ is not yet recorded. Let's add to the table. */ |
| 1234 | else | 1409 | Fputhash (obj, Qt, Vprint_number_table); |
| 1235 | /* OBJ is not yet recorded. Let's add to the table. */ | ||
| 1236 | Fputhash (obj, Qt, Vprint_number_table); | ||
| 1237 | 1410 | ||
| 1238 | switch (XTYPE (obj)) | 1411 | switch (XTYPE (obj)) |
| 1239 | { | 1412 | { |
| 1240 | case Lisp_String: | 1413 | case Lisp_String: |
| 1241 | /* A string may have text properties, which can be circular. */ | 1414 | /* A string may have text properties, |
| 1242 | traverse_intervals_noorder (string_intervals (obj), | 1415 | which can be circular. */ |
| 1243 | print_preprocess_string, NULL); | 1416 | traverse_intervals_noorder (string_intervals (obj), |
| 1244 | break; | 1417 | print_preprocess_string, NULL); |
| 1418 | break; | ||
| 1245 | 1419 | ||
| 1246 | case Lisp_Cons: | 1420 | case Lisp_Cons: |
| 1247 | /* Use HALFTAIL and LOOP_COUNT to detect circular lists, | 1421 | if (!NILP (XCDR (obj))) |
| 1248 | just as in print_object. */ | 1422 | pp_stack_push_value (XCDR (obj)); |
| 1249 | if (loop_count && EQ (obj, halftail)) | 1423 | obj = XCAR (obj); |
| 1250 | break; | 1424 | continue; |
| 1251 | print_preprocess (XCAR (obj)); | ||
| 1252 | obj = XCDR (obj); | ||
| 1253 | loop_count++; | ||
| 1254 | if (!(loop_count & 1)) | ||
| 1255 | halftail = XCDR (halftail); | ||
| 1256 | goto loop; | ||
| 1257 | |||
| 1258 | case Lisp_Vectorlike: | ||
| 1259 | size = ASIZE (obj); | ||
| 1260 | if (size & PSEUDOVECTOR_FLAG) | ||
| 1261 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 1262 | for (i = (SUB_CHAR_TABLE_P (obj) | ||
| 1263 | ? SUB_CHAR_TABLE_OFFSET : 0); i < size; i++) | ||
| 1264 | print_preprocess (AREF (obj, i)); | ||
| 1265 | if (HASH_TABLE_P (obj)) | ||
| 1266 | { /* For hash tables, the key_and_value slot is past | ||
| 1267 | `size' because it needs to be marked specially in case | ||
| 1268 | the table is weak. */ | ||
| 1269 | struct Lisp_Hash_Table *h = XHASH_TABLE (obj); | ||
| 1270 | print_preprocess (h->key_and_value); | ||
| 1271 | } | ||
| 1272 | break; | ||
| 1273 | 1425 | ||
| 1274 | default: | 1426 | case Lisp_Vectorlike: |
| 1275 | break; | 1427 | { |
| 1428 | struct Lisp_Vector *vec = XVECTOR (obj); | ||
| 1429 | ptrdiff_t size = ASIZE (obj); | ||
| 1430 | if (size & PSEUDOVECTOR_FLAG) | ||
| 1431 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 1432 | ptrdiff_t start = (SUB_CHAR_TABLE_P (obj) | ||
| 1433 | ? SUB_CHAR_TABLE_OFFSET : 0); | ||
| 1434 | pp_stack_push_values (vec->contents + start, size - start); | ||
| 1435 | if (HASH_TABLE_P (obj)) | ||
| 1436 | { | ||
| 1437 | struct Lisp_Hash_Table *h = XHASH_TABLE (obj); | ||
| 1438 | obj = h->key_and_value; | ||
| 1439 | continue; | ||
| 1440 | } | ||
| 1441 | break; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | default: | ||
| 1445 | break; | ||
| 1446 | } | ||
| 1447 | } | ||
| 1276 | } | 1448 | } |
| 1449 | |||
| 1450 | if (ppstack.sp <= base_sp) | ||
| 1451 | break; | ||
| 1452 | obj = pp_stack_pop (); | ||
| 1277 | } | 1453 | } |
| 1278 | print_depth--; | ||
| 1279 | } | 1454 | } |
| 1280 | 1455 | ||
| 1281 | DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0, | 1456 | DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0, |
| @@ -1467,162 +1642,6 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, | |||
| 1467 | } | 1642 | } |
| 1468 | return true; | 1643 | return true; |
| 1469 | 1644 | ||
| 1470 | case PVEC_HASH_TABLE: | ||
| 1471 | { | ||
| 1472 | struct Lisp_Hash_Table *h = XHASH_TABLE (obj); | ||
| 1473 | /* Implement a readable output, e.g.: | ||
| 1474 | #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ | ||
| 1475 | /* Always print the size. */ | ||
| 1476 | int len = sprintf (buf, "#s(hash-table size %"pD"d", | ||
| 1477 | HASH_TABLE_SIZE (h)); | ||
| 1478 | strout (buf, len, len, printcharfun); | ||
| 1479 | |||
| 1480 | if (!NILP (h->test.name)) | ||
| 1481 | { | ||
| 1482 | print_c_string (" test ", printcharfun); | ||
| 1483 | print_object (h->test.name, printcharfun, escapeflag); | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | if (!NILP (h->weak)) | ||
| 1487 | { | ||
| 1488 | print_c_string (" weakness ", printcharfun); | ||
| 1489 | print_object (h->weak, printcharfun, escapeflag); | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | print_c_string (" rehash-size ", printcharfun); | ||
| 1493 | print_object (Fhash_table_rehash_size (obj), | ||
| 1494 | printcharfun, escapeflag); | ||
| 1495 | |||
| 1496 | print_c_string (" rehash-threshold ", printcharfun); | ||
| 1497 | print_object (Fhash_table_rehash_threshold (obj), | ||
| 1498 | printcharfun, escapeflag); | ||
| 1499 | |||
| 1500 | if (h->purecopy) | ||
| 1501 | { | ||
| 1502 | print_c_string (" purecopy ", printcharfun); | ||
| 1503 | print_object (h->purecopy ? Qt : Qnil, printcharfun, escapeflag); | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | print_c_string (" data ", printcharfun); | ||
| 1507 | |||
| 1508 | /* Print the data here as a plist. */ | ||
| 1509 | ptrdiff_t real_size = HASH_TABLE_SIZE (h); | ||
| 1510 | ptrdiff_t size = h->count; | ||
| 1511 | |||
| 1512 | /* Don't print more elements than the specified maximum. */ | ||
| 1513 | if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size) | ||
| 1514 | size = XFIXNAT (Vprint_length); | ||
| 1515 | |||
| 1516 | printchar ('(', printcharfun); | ||
| 1517 | ptrdiff_t j = 0; | ||
| 1518 | for (ptrdiff_t i = 0; i < real_size; i++) | ||
| 1519 | { | ||
| 1520 | Lisp_Object key = HASH_KEY (h, i); | ||
| 1521 | if (!EQ (key, Qunbound)) | ||
| 1522 | { | ||
| 1523 | if (j++) printchar (' ', printcharfun); | ||
| 1524 | print_object (key, printcharfun, escapeflag); | ||
| 1525 | printchar (' ', printcharfun); | ||
| 1526 | print_object (HASH_VALUE (h, i), printcharfun, escapeflag); | ||
| 1527 | if (j == size) | ||
| 1528 | break; | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | if (j < h->count) | ||
| 1533 | { | ||
| 1534 | if (j) | ||
| 1535 | printchar (' ', printcharfun); | ||
| 1536 | print_c_string ("...", printcharfun); | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | print_c_string ("))", printcharfun); | ||
| 1540 | } | ||
| 1541 | return true; | ||
| 1542 | |||
| 1543 | case PVEC_RECORD: | ||
| 1544 | { | ||
| 1545 | ptrdiff_t size = PVSIZE (obj); | ||
| 1546 | |||
| 1547 | /* Don't print more elements than the specified maximum. */ | ||
| 1548 | ptrdiff_t n | ||
| 1549 | = (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size | ||
| 1550 | ? XFIXNAT (Vprint_length) : size); | ||
| 1551 | |||
| 1552 | print_c_string ("#s(", printcharfun); | ||
| 1553 | for (ptrdiff_t i = 0; i < n; i ++) | ||
| 1554 | { | ||
| 1555 | if (i) printchar (' ', printcharfun); | ||
| 1556 | print_object (AREF (obj, i), printcharfun, escapeflag); | ||
| 1557 | } | ||
| 1558 | if (n < size) | ||
| 1559 | print_c_string (" ...", printcharfun); | ||
| 1560 | printchar (')', printcharfun); | ||
| 1561 | } | ||
| 1562 | return true; | ||
| 1563 | |||
| 1564 | case PVEC_SUB_CHAR_TABLE: | ||
| 1565 | case PVEC_COMPILED: | ||
| 1566 | case PVEC_CHAR_TABLE: | ||
| 1567 | case PVEC_NORMAL_VECTOR: | ||
| 1568 | { | ||
| 1569 | ptrdiff_t size = ASIZE (obj); | ||
| 1570 | if (COMPILEDP (obj)) | ||
| 1571 | { | ||
| 1572 | printchar ('#', printcharfun); | ||
| 1573 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 1574 | } | ||
| 1575 | if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)) | ||
| 1576 | { | ||
| 1577 | /* Print a char-table as if it were a vector, | ||
| 1578 | lumping the parent and default slots in with the | ||
| 1579 | character slots. But add #^ as a prefix. */ | ||
| 1580 | |||
| 1581 | /* Make each lowest sub_char_table start a new line. | ||
| 1582 | Otherwise we'll make a line extremely long, which | ||
| 1583 | results in slow redisplay. */ | ||
| 1584 | if (SUB_CHAR_TABLE_P (obj) | ||
| 1585 | && XSUB_CHAR_TABLE (obj)->depth == 3) | ||
| 1586 | printchar ('\n', printcharfun); | ||
| 1587 | print_c_string ("#^", printcharfun); | ||
| 1588 | if (SUB_CHAR_TABLE_P (obj)) | ||
| 1589 | printchar ('^', printcharfun); | ||
| 1590 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 1591 | } | ||
| 1592 | if (size & PSEUDOVECTOR_FLAG) | ||
| 1593 | return false; | ||
| 1594 | |||
| 1595 | printchar ('[', printcharfun); | ||
| 1596 | |||
| 1597 | int idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0; | ||
| 1598 | Lisp_Object tem; | ||
| 1599 | ptrdiff_t real_size = size; | ||
| 1600 | |||
| 1601 | /* For a sub char-table, print heading non-Lisp data first. */ | ||
| 1602 | if (SUB_CHAR_TABLE_P (obj)) | ||
| 1603 | { | ||
| 1604 | int i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth, | ||
| 1605 | XSUB_CHAR_TABLE (obj)->min_char); | ||
| 1606 | strout (buf, i, i, printcharfun); | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | /* Don't print more elements than the specified maximum. */ | ||
| 1610 | if (FIXNATP (Vprint_length) | ||
| 1611 | && XFIXNAT (Vprint_length) < size) | ||
| 1612 | size = XFIXNAT (Vprint_length); | ||
| 1613 | |||
| 1614 | for (int i = idx; i < size; i++) | ||
| 1615 | { | ||
| 1616 | if (i) printchar (' ', printcharfun); | ||
| 1617 | tem = AREF (obj, i); | ||
| 1618 | print_object (tem, printcharfun, escapeflag); | ||
| 1619 | } | ||
| 1620 | if (size < real_size) | ||
| 1621 | print_c_string (" ...", printcharfun); | ||
| 1622 | printchar (']', printcharfun); | ||
| 1623 | } | ||
| 1624 | return true; | ||
| 1625 | |||
| 1626 | default: | 1645 | default: |
| 1627 | break; | 1646 | break; |
| 1628 | } | 1647 | } |
| @@ -2028,32 +2047,132 @@ named_escape (int i) | |||
| 2028 | return 0; | 2047 | return 0; |
| 2029 | } | 2048 | } |
| 2030 | 2049 | ||
| 2050 | enum print_entry_type | ||
| 2051 | { | ||
| 2052 | PE_list, /* print rest of list */ | ||
| 2053 | PE_rbrac, /* print ")" */ | ||
| 2054 | PE_vector, /* print rest of vector */ | ||
| 2055 | PE_hash, /* print rest of hash data */ | ||
| 2056 | }; | ||
| 2057 | |||
| 2058 | struct print_stack_entry | ||
| 2059 | { | ||
| 2060 | enum print_entry_type type; | ||
| 2061 | |||
| 2062 | union | ||
| 2063 | { | ||
| 2064 | struct | ||
| 2065 | { | ||
| 2066 | Lisp_Object last; /* cons whose car was just printed */ | ||
| 2067 | intmax_t maxlen; /* max number of elements left to print */ | ||
| 2068 | /* State for Brent cycle detection. See | ||
| 2069 | Brent RP. BIT. 1980;20(2):176-184. doi:10.1007/BF01933190 | ||
| 2070 | https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf */ | ||
| 2071 | Lisp_Object tortoise; /* slow pointer */ | ||
| 2072 | ptrdiff_t n; /* tortoise step countdown */ | ||
| 2073 | ptrdiff_t m; /* tortoise step period */ | ||
| 2074 | intmax_t tortoise_idx; /* index of tortoise */ | ||
| 2075 | } list; | ||
| 2076 | |||
| 2077 | struct | ||
| 2078 | { | ||
| 2079 | Lisp_Object obj; /* object to print after " . " */ | ||
| 2080 | } dotted_cdr; | ||
| 2081 | |||
| 2082 | struct | ||
| 2083 | { | ||
| 2084 | Lisp_Object obj; /* vector object */ | ||
| 2085 | ptrdiff_t size; /* length of vector */ | ||
| 2086 | ptrdiff_t idx; /* index of next element */ | ||
| 2087 | const char *end; /* string to print at end */ | ||
| 2088 | bool truncated; /* whether to print "..." before end */ | ||
| 2089 | } vector; | ||
| 2090 | |||
| 2091 | struct | ||
| 2092 | { | ||
| 2093 | Lisp_Object obj; /* hash-table object */ | ||
| 2094 | ptrdiff_t nobjs; /* number of keys and values to print */ | ||
| 2095 | ptrdiff_t idx; /* index of key-value pair */ | ||
| 2096 | ptrdiff_t printed; /* number of keys and values printed */ | ||
| 2097 | bool truncated; /* whether to print "..." before end */ | ||
| 2098 | } hash; | ||
| 2099 | } u; | ||
| 2100 | }; | ||
| 2101 | |||
| 2102 | struct print_stack | ||
| 2103 | { | ||
| 2104 | struct print_stack_entry *stack; /* base of stack */ | ||
| 2105 | ptrdiff_t size; /* allocated size in entries */ | ||
| 2106 | ptrdiff_t sp; /* current number of entries */ | ||
| 2107 | }; | ||
| 2108 | |||
| 2109 | static struct print_stack prstack = {NULL, 0, 0}; | ||
| 2110 | |||
| 2111 | NO_INLINE static void | ||
| 2112 | grow_print_stack (void) | ||
| 2113 | { | ||
| 2114 | struct print_stack *ps = &prstack; | ||
| 2115 | eassert (ps->sp == ps->size); | ||
| 2116 | ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack); | ||
| 2117 | eassert (ps->sp < ps->size); | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | static inline void | ||
| 2121 | print_stack_push (struct print_stack_entry e) | ||
| 2122 | { | ||
| 2123 | if (prstack.sp >= prstack.size) | ||
| 2124 | grow_print_stack (); | ||
| 2125 | prstack.stack[prstack.sp++] = e; | ||
| 2126 | } | ||
| 2127 | |||
| 2128 | static void | ||
| 2129 | print_stack_push_vector (const char *lbrac, const char *rbrac, | ||
| 2130 | Lisp_Object obj, ptrdiff_t start, ptrdiff_t size, | ||
| 2131 | Lisp_Object printcharfun) | ||
| 2132 | { | ||
| 2133 | print_c_string (lbrac, printcharfun); | ||
| 2134 | |||
| 2135 | ptrdiff_t print_size = ((FIXNATP (Vprint_length) | ||
| 2136 | && XFIXNAT (Vprint_length) < size) | ||
| 2137 | ? XFIXNAT (Vprint_length) : size); | ||
| 2138 | print_stack_push ((struct print_stack_entry){ | ||
| 2139 | .type = PE_vector, | ||
| 2140 | .u.vector.obj = obj, | ||
| 2141 | .u.vector.size = print_size, | ||
| 2142 | .u.vector.idx = start, | ||
| 2143 | .u.vector.end = rbrac, | ||
| 2144 | .u.vector.truncated = (print_size < size), | ||
| 2145 | }); | ||
| 2146 | } | ||
| 2147 | |||
| 2031 | static void | 2148 | static void |
| 2032 | print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | 2149 | print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) |
| 2033 | { | 2150 | { |
| 2151 | ptrdiff_t base_depth = print_depth; | ||
| 2152 | ptrdiff_t base_sp = prstack.sp; | ||
| 2034 | char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), | 2153 | char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), |
| 2035 | max (sizeof " . #" + INT_STRLEN_BOUND (intmax_t), | 2154 | max (sizeof " . #" + INT_STRLEN_BOUND (intmax_t), |
| 2036 | max ((sizeof " with data 0x" | 2155 | max ((sizeof " with data 0x" |
| 2037 | + (sizeof (uintmax_t) * CHAR_BIT + 4 - 1) / 4), | 2156 | + (sizeof (uintmax_t) * CHAR_BIT + 4 - 1) / 4), |
| 2038 | 40)))]; | 2157 | 40)))]; |
| 2039 | current_thread->stack_top = buf; | 2158 | current_thread->stack_top = buf; |
| 2159 | |||
| 2160 | print_obj: | ||
| 2040 | maybe_quit (); | 2161 | maybe_quit (); |
| 2041 | 2162 | ||
| 2042 | /* Detect circularities and truncate them. */ | 2163 | /* Detect circularities and truncate them. */ |
| 2043 | if (NILP (Vprint_circle)) | 2164 | if (NILP (Vprint_circle)) |
| 2044 | { | 2165 | { |
| 2045 | /* Simple but incomplete way. */ | 2166 | /* Simple but incomplete way. */ |
| 2046 | int i; | ||
| 2047 | |||
| 2048 | if (print_depth >= PRINT_CIRCLE) | 2167 | if (print_depth >= PRINT_CIRCLE) |
| 2049 | error ("Apparently circular structure being printed"); | 2168 | error ("Apparently circular structure being printed"); |
| 2050 | 2169 | ||
| 2051 | for (i = 0; i < print_depth; i++) | 2170 | for (int i = 0; i < print_depth; i++) |
| 2052 | if (BASE_EQ (obj, being_printed[i])) | 2171 | if (BASE_EQ (obj, being_printed[i])) |
| 2053 | { | 2172 | { |
| 2054 | int len = sprintf (buf, "#%d", i); | 2173 | int len = sprintf (buf, "#%d", i); |
| 2055 | strout (buf, len, len, printcharfun); | 2174 | strout (buf, len, len, printcharfun); |
| 2056 | return; | 2175 | goto next_obj; |
| 2057 | } | 2176 | } |
| 2058 | being_printed[print_depth] = obj; | 2177 | being_printed[print_depth] = obj; |
| 2059 | } | 2178 | } |
| @@ -2077,7 +2196,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2077 | /* Just print #n# if OBJ has already been printed. */ | 2196 | /* Just print #n# if OBJ has already been printed. */ |
| 2078 | int len = sprintf (buf, "#%"pI"d#", n); | 2197 | int len = sprintf (buf, "#%"pI"d#", n); |
| 2079 | strout (buf, len, len, printcharfun); | 2198 | strout (buf, len, len, printcharfun); |
| 2080 | return; | 2199 | goto next_obj; |
| 2081 | } | 2200 | } |
| 2082 | } | 2201 | } |
| 2083 | } | 2202 | } |
| @@ -2151,7 +2270,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2151 | for (i = 0, i_byte = 0; i_byte < size_byte;) | 2270 | for (i = 0, i_byte = 0; i_byte < size_byte;) |
| 2152 | { | 2271 | { |
| 2153 | /* Here, we must convert each multi-byte form to the | 2272 | /* Here, we must convert each multi-byte form to the |
| 2154 | corresponding character code before handing it to printchar. */ | 2273 | corresponding character code before handing it to |
| 2274 | printchar. */ | ||
| 2155 | int c = fetch_string_char_advance (obj, &i, &i_byte); | 2275 | int c = fetch_string_char_advance (obj, &i, &i_byte); |
| 2156 | 2276 | ||
| 2157 | maybe_quit (); | 2277 | maybe_quit (); |
| @@ -2171,7 +2291,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2171 | else if (multibyte | 2291 | else if (multibyte |
| 2172 | && ! ASCII_CHAR_P (c) && print_escape_multibyte) | 2292 | && ! ASCII_CHAR_P (c) && print_escape_multibyte) |
| 2173 | { | 2293 | { |
| 2174 | /* When requested, print multibyte chars using hex escapes. */ | 2294 | /* When requested, print multibyte chars using |
| 2295 | hex escapes. */ | ||
| 2175 | char outbuf[sizeof "\\x" + INT_STRLEN_BOUND (c)]; | 2296 | char outbuf[sizeof "\\x" + INT_STRLEN_BOUND (c)]; |
| 2176 | int len = sprintf (outbuf, "\\x%04x", c + 0u); | 2297 | int len = sprintf (outbuf, "\\x%04x", c + 0u); |
| 2177 | strout (outbuf, len, len, printcharfun); | 2298 | strout (outbuf, len, len, printcharfun); |
| @@ -2282,14 +2403,22 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2282 | && EQ (XCAR (obj), Qquote)) | 2403 | && EQ (XCAR (obj), Qquote)) |
| 2283 | { | 2404 | { |
| 2284 | printchar ('\'', printcharfun); | 2405 | printchar ('\'', printcharfun); |
| 2285 | print_object (XCAR (XCDR (obj)), printcharfun, escapeflag); | 2406 | obj = XCAR (XCDR (obj)); |
| 2407 | --print_depth; /* tail recursion */ | ||
| 2408 | goto print_obj; | ||
| 2286 | } | 2409 | } |
| 2287 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) | 2410 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) |
| 2288 | && EQ (XCAR (obj), Qfunction)) | 2411 | && EQ (XCAR (obj), Qfunction)) |
| 2289 | { | 2412 | { |
| 2290 | print_c_string ("#'", printcharfun); | 2413 | print_c_string ("#'", printcharfun); |
| 2291 | print_object (XCAR (XCDR (obj)), printcharfun, escapeflag); | 2414 | obj = XCAR (XCDR (obj)); |
| 2415 | --print_depth; /* tail recursion */ | ||
| 2416 | goto print_obj; | ||
| 2292 | } | 2417 | } |
| 2418 | /* FIXME: Do we really need the new_backquote_output gating of | ||
| 2419 | special syntax for comma and comma-at? There is basically no | ||
| 2420 | benefit from it at all, and it would be nice to get rid of | ||
| 2421 | the recursion here without additional complexity. */ | ||
| 2293 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) | 2422 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) |
| 2294 | && EQ (XCAR (obj), Qbackquote)) | 2423 | && EQ (XCAR (obj), Qbackquote)) |
| 2295 | { | 2424 | { |
| @@ -2299,9 +2428,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2299 | new_backquote_output--; | 2428 | new_backquote_output--; |
| 2300 | } | 2429 | } |
| 2301 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) | 2430 | else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj))) |
| 2302 | && new_backquote_output | ||
| 2303 | && (EQ (XCAR (obj), Qcomma) | 2431 | && (EQ (XCAR (obj), Qcomma) |
| 2304 | || EQ (XCAR (obj), Qcomma_at))) | 2432 | || EQ (XCAR (obj), Qcomma_at)) |
| 2433 | && new_backquote_output) | ||
| 2305 | { | 2434 | { |
| 2306 | print_object (XCAR (obj), printcharfun, false); | 2435 | print_object (XCAR (obj), printcharfun, false); |
| 2307 | new_backquote_output--; | 2436 | new_backquote_output--; |
| @@ -2311,70 +2440,135 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2311 | else | 2440 | else |
| 2312 | { | 2441 | { |
| 2313 | printchar ('(', printcharfun); | 2442 | printchar ('(', printcharfun); |
| 2314 | |||
| 2315 | /* Negative values of print-length are invalid in CL. | 2443 | /* Negative values of print-length are invalid in CL. |
| 2316 | Treat them like nil, as CMUCL does. */ | 2444 | Treat them like nil, as CMUCL does. */ |
| 2317 | intmax_t print_length = (FIXNATP (Vprint_length) | 2445 | intmax_t print_length = (FIXNATP (Vprint_length) |
| 2318 | ? XFIXNAT (Vprint_length) | 2446 | ? XFIXNAT (Vprint_length) |
| 2319 | : INTMAX_MAX); | 2447 | : INTMAX_MAX); |
| 2320 | Lisp_Object objtail = Qnil; | 2448 | if (print_length == 0) |
| 2321 | intmax_t i = 0; | 2449 | print_c_string ("...)", printcharfun); |
| 2322 | FOR_EACH_TAIL_SAFE (obj) | 2450 | else |
| 2323 | { | 2451 | { |
| 2324 | if (i != 0) | 2452 | print_stack_push ((struct print_stack_entry){ |
| 2325 | { | 2453 | .type = PE_list, |
| 2326 | printchar (' ', printcharfun); | 2454 | .u.list.last = obj, |
| 2327 | 2455 | .u.list.maxlen = print_length, | |
| 2328 | if (!NILP (Vprint_circle)) | 2456 | .u.list.tortoise = obj, |
| 2329 | { | 2457 | .u.list.n = 2, |
| 2330 | /* With the print-circle feature. */ | 2458 | .u.list.m = 2, |
| 2331 | Lisp_Object num = Fgethash (obj, Vprint_number_table, | 2459 | .u.list.tortoise_idx = 0, |
| 2332 | Qnil); | 2460 | }); |
| 2333 | if (FIXNUMP (num)) | 2461 | /* print the car */ |
| 2334 | { | 2462 | obj = XCAR (obj); |
| 2335 | print_c_string (". ", printcharfun); | 2463 | goto print_obj; |
| 2336 | print_object (obj, printcharfun, escapeflag); | ||
| 2337 | goto end_of_list; | ||
| 2338 | } | ||
| 2339 | } | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | if (print_length <= i) | ||
| 2343 | { | ||
| 2344 | print_c_string ("...", printcharfun); | ||
| 2345 | goto end_of_list; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | i++; | ||
| 2349 | print_object (XCAR (obj), printcharfun, escapeflag); | ||
| 2350 | objtail = XCDR (obj); | ||
| 2351 | } | 2464 | } |
| 2465 | } | ||
| 2466 | break; | ||
| 2352 | 2467 | ||
| 2353 | /* OBJTAIL non-nil here means it's the end of a dotted list | 2468 | case Lisp_Vectorlike: |
| 2354 | or FOR_EACH_TAIL_SAFE detected a circular list. */ | 2469 | /* First do all the vectorlike types that have a readable syntax. */ |
| 2355 | if (!NILP (objtail)) | 2470 | switch (PSEUDOVECTOR_TYPE (XVECTOR (obj))) |
| 2356 | { | 2471 | { |
| 2357 | print_c_string (" . ", printcharfun); | 2472 | case PVEC_NORMAL_VECTOR: |
| 2473 | { | ||
| 2474 | print_stack_push_vector ("[", "]", obj, 0, ASIZE (obj), | ||
| 2475 | printcharfun); | ||
| 2476 | goto next_obj; | ||
| 2477 | } | ||
| 2478 | case PVEC_RECORD: | ||
| 2479 | { | ||
| 2480 | print_stack_push_vector ("#s(", ")", obj, 0, PVSIZE (obj), | ||
| 2481 | printcharfun); | ||
| 2482 | goto next_obj; | ||
| 2483 | } | ||
| 2484 | case PVEC_COMPILED: | ||
| 2485 | { | ||
| 2486 | print_stack_push_vector ("#[", "]", obj, 0, PVSIZE (obj), | ||
| 2487 | printcharfun); | ||
| 2488 | goto next_obj; | ||
| 2489 | } | ||
| 2490 | case PVEC_CHAR_TABLE: | ||
| 2491 | { | ||
| 2492 | print_stack_push_vector ("#^[", "]", obj, 0, PVSIZE (obj), | ||
| 2493 | printcharfun); | ||
| 2494 | goto next_obj; | ||
| 2495 | } | ||
| 2496 | case PVEC_SUB_CHAR_TABLE: | ||
| 2497 | { | ||
| 2498 | /* Make each lowest sub_char_table start a new line. | ||
| 2499 | Otherwise we'll make a line extremely long, which | ||
| 2500 | results in slow redisplay. */ | ||
| 2501 | if (XSUB_CHAR_TABLE (obj)->depth == 3) | ||
| 2502 | printchar ('\n', printcharfun); | ||
| 2503 | print_c_string ("#^^[", printcharfun); | ||
| 2504 | int n = sprintf (buf, "%d %d", | ||
| 2505 | XSUB_CHAR_TABLE (obj)->depth, | ||
| 2506 | XSUB_CHAR_TABLE (obj)->min_char); | ||
| 2507 | strout (buf, n, n, printcharfun); | ||
| 2508 | print_stack_push_vector ("", "]", obj, | ||
| 2509 | SUB_CHAR_TABLE_OFFSET, PVSIZE (obj), | ||
| 2510 | printcharfun); | ||
| 2511 | goto next_obj; | ||
| 2512 | } | ||
| 2513 | case PVEC_HASH_TABLE: | ||
| 2514 | { | ||
| 2515 | struct Lisp_Hash_Table *h = XHASH_TABLE (obj); | ||
| 2516 | /* Implement a readable output, e.g.: | ||
| 2517 | #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ | ||
| 2518 | /* Always print the size. */ | ||
| 2519 | int len = sprintf (buf, "#s(hash-table size %"pD"d", | ||
| 2520 | HASH_TABLE_SIZE (h)); | ||
| 2521 | strout (buf, len, len, printcharfun); | ||
| 2358 | 2522 | ||
| 2359 | if (CONSP (objtail) && NILP (Vprint_circle)) | 2523 | if (!NILP (h->test.name)) |
| 2360 | { | 2524 | { |
| 2361 | int len = sprintf (buf, "#%"PRIdMAX, i >> 1); | 2525 | print_c_string (" test ", printcharfun); |
| 2362 | strout (buf, len, len, printcharfun); | 2526 | print_object (h->test.name, printcharfun, escapeflag); |
| 2363 | goto end_of_list; | 2527 | } |
| 2364 | } | ||
| 2365 | 2528 | ||
| 2366 | print_object (objtail, printcharfun, escapeflag); | 2529 | if (!NILP (h->weak)) |
| 2367 | } | 2530 | { |
| 2531 | print_c_string (" weakness ", printcharfun); | ||
| 2532 | print_object (h->weak, printcharfun, escapeflag); | ||
| 2533 | } | ||
| 2368 | 2534 | ||
| 2369 | end_of_list: | 2535 | print_c_string (" rehash-size ", printcharfun); |
| 2370 | printchar (')', printcharfun); | 2536 | print_object (Fhash_table_rehash_size (obj), |
| 2537 | printcharfun, escapeflag); | ||
| 2538 | |||
| 2539 | print_c_string (" rehash-threshold ", printcharfun); | ||
| 2540 | print_object (Fhash_table_rehash_threshold (obj), | ||
| 2541 | printcharfun, escapeflag); | ||
| 2542 | |||
| 2543 | if (h->purecopy) | ||
| 2544 | print_c_string (" purecopy t", printcharfun); | ||
| 2545 | |||
| 2546 | print_c_string (" data (", printcharfun); | ||
| 2547 | |||
| 2548 | ptrdiff_t size = h->count; | ||
| 2549 | /* Don't print more elements than the specified maximum. */ | ||
| 2550 | if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size) | ||
| 2551 | size = XFIXNAT (Vprint_length); | ||
| 2552 | |||
| 2553 | print_stack_push ((struct print_stack_entry){ | ||
| 2554 | .type = PE_hash, | ||
| 2555 | .u.hash.obj = obj, | ||
| 2556 | .u.hash.nobjs = size * 2, | ||
| 2557 | .u.hash.idx = 0, | ||
| 2558 | .u.hash.printed = 0, | ||
| 2559 | .u.hash.truncated = (size < h->count), | ||
| 2560 | }); | ||
| 2561 | goto next_obj; | ||
| 2562 | } | ||
| 2563 | |||
| 2564 | default: | ||
| 2565 | break; | ||
| 2371 | } | 2566 | } |
| 2372 | break; | ||
| 2373 | 2567 | ||
| 2374 | case Lisp_Vectorlike: | ||
| 2375 | if (print_vectorlike (obj, printcharfun, escapeflag, buf)) | 2568 | if (print_vectorlike (obj, printcharfun, escapeflag, buf)) |
| 2376 | break; | 2569 | break; |
| 2377 | FALLTHROUGH; | 2570 | FALLTHROUGH; |
| 2571 | |||
| 2378 | default: | 2572 | default: |
| 2379 | { | 2573 | { |
| 2380 | int len; | 2574 | int len; |
| @@ -2389,10 +2583,157 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2389 | print_c_string ((" Save your buffers immediately" | 2583 | print_c_string ((" Save your buffers immediately" |
| 2390 | " and please report this bug>"), | 2584 | " and please report this bug>"), |
| 2391 | printcharfun); | 2585 | printcharfun); |
| 2586 | break; | ||
| 2392 | } | 2587 | } |
| 2393 | } | 2588 | } |
| 2394 | |||
| 2395 | print_depth--; | 2589 | print_depth--; |
| 2590 | |||
| 2591 | next_obj: | ||
| 2592 | if (prstack.sp > base_sp) | ||
| 2593 | { | ||
| 2594 | /* Handle a continuation on the print stack. */ | ||
| 2595 | struct print_stack_entry *e = &prstack.stack[prstack.sp - 1]; | ||
| 2596 | switch (e->type) | ||
| 2597 | { | ||
| 2598 | case PE_list: | ||
| 2599 | { | ||
| 2600 | /* after "(" ELEM (* " " ELEM) */ | ||
| 2601 | Lisp_Object next = XCDR (e->u.list.last); | ||
| 2602 | if (NILP (next)) | ||
| 2603 | { | ||
| 2604 | /* end of list: print ")" */ | ||
| 2605 | printchar (')', printcharfun); | ||
| 2606 | --prstack.sp; | ||
| 2607 | --print_depth; | ||
| 2608 | goto next_obj; | ||
| 2609 | } | ||
| 2610 | else if (CONSP (next)) | ||
| 2611 | { | ||
| 2612 | if (!NILP (Vprint_circle)) | ||
| 2613 | { | ||
| 2614 | /* With the print-circle feature. */ | ||
| 2615 | Lisp_Object num = Fgethash (next, Vprint_number_table, | ||
| 2616 | Qnil); | ||
| 2617 | if (FIXNUMP (num)) | ||
| 2618 | { | ||
| 2619 | print_c_string (" . ", printcharfun); | ||
| 2620 | obj = next; | ||
| 2621 | e->type = PE_rbrac; | ||
| 2622 | goto print_obj; | ||
| 2623 | } | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | /* list continues: print " " ELEM ... */ | ||
| 2627 | |||
| 2628 | printchar (' ', printcharfun); | ||
| 2629 | |||
| 2630 | --e->u.list.maxlen; | ||
| 2631 | if (e->u.list.maxlen <= 0) | ||
| 2632 | { | ||
| 2633 | print_c_string ("...)", printcharfun); | ||
| 2634 | --prstack.sp; | ||
| 2635 | --print_depth; | ||
| 2636 | goto next_obj; | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | e->u.list.last = next; | ||
| 2640 | e->u.list.n--; | ||
| 2641 | if (e->u.list.n == 0) | ||
| 2642 | { | ||
| 2643 | /* Double tortoise update period and teleport it. */ | ||
| 2644 | e->u.list.tortoise_idx += e->u.list.m; | ||
| 2645 | e->u.list.m <<= 1; | ||
| 2646 | e->u.list.n = e->u.list.m; | ||
| 2647 | e->u.list.tortoise = next; | ||
| 2648 | } | ||
| 2649 | else if (BASE_EQ (next, e->u.list.tortoise)) | ||
| 2650 | { | ||
| 2651 | /* FIXME: This #N tail index is somewhat ambiguous; | ||
| 2652 | see bug#55395. */ | ||
| 2653 | int len = sprintf (buf, ". #%" PRIdMAX ")", | ||
| 2654 | e->u.list.tortoise_idx); | ||
| 2655 | strout (buf, len, len, printcharfun); | ||
| 2656 | --prstack.sp; | ||
| 2657 | --print_depth; | ||
| 2658 | goto next_obj; | ||
| 2659 | } | ||
| 2660 | obj = XCAR (next); | ||
| 2661 | } | ||
| 2662 | else | ||
| 2663 | { | ||
| 2664 | /* non-nil ending: print " . " ELEM ")" */ | ||
| 2665 | print_c_string (" . ", printcharfun); | ||
| 2666 | obj = next; | ||
| 2667 | e->type = PE_rbrac; | ||
| 2668 | } | ||
| 2669 | break; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | case PE_rbrac: | ||
| 2673 | printchar (')', printcharfun); | ||
| 2674 | --prstack.sp; | ||
| 2675 | --print_depth; | ||
| 2676 | goto next_obj; | ||
| 2677 | |||
| 2678 | case PE_vector: | ||
| 2679 | if (e->u.vector.idx >= e->u.vector.size) | ||
| 2680 | { | ||
| 2681 | if (e->u.vector.truncated) | ||
| 2682 | { | ||
| 2683 | if (e->u.vector.idx > 0) | ||
| 2684 | printchar (' ', printcharfun); | ||
| 2685 | print_c_string ("...", printcharfun); | ||
| 2686 | } | ||
| 2687 | print_c_string (e->u.vector.end, printcharfun); | ||
| 2688 | --prstack.sp; | ||
| 2689 | --print_depth; | ||
| 2690 | goto next_obj; | ||
| 2691 | } | ||
| 2692 | if (e->u.vector.idx > 0) | ||
| 2693 | printchar (' ', printcharfun); | ||
| 2694 | obj = AREF (e->u.vector.obj, e->u.vector.idx); | ||
| 2695 | e->u.vector.idx++; | ||
| 2696 | break; | ||
| 2697 | |||
| 2698 | case PE_hash: | ||
| 2699 | if (e->u.hash.printed >= e->u.hash.nobjs) | ||
| 2700 | { | ||
| 2701 | if (e->u.hash.truncated) | ||
| 2702 | { | ||
| 2703 | if (e->u.hash.printed) | ||
| 2704 | printchar (' ', printcharfun); | ||
| 2705 | print_c_string ("...", printcharfun); | ||
| 2706 | } | ||
| 2707 | print_c_string ("))", printcharfun); | ||
| 2708 | --prstack.sp; | ||
| 2709 | --print_depth; | ||
| 2710 | goto next_obj; | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | if (e->u.hash.printed) | ||
| 2714 | printchar (' ', printcharfun); | ||
| 2715 | |||
| 2716 | struct Lisp_Hash_Table *h = XHASH_TABLE (e->u.hash.obj); | ||
| 2717 | if ((e->u.hash.printed & 1) == 0) | ||
| 2718 | { | ||
| 2719 | Lisp_Object key; | ||
| 2720 | ptrdiff_t idx = e->u.hash.idx; | ||
| 2721 | while (BASE_EQ ((key = HASH_KEY (h, idx)), Qunbound)) | ||
| 2722 | idx++; | ||
| 2723 | e->u.hash.idx = idx; | ||
| 2724 | obj = key; | ||
| 2725 | } | ||
| 2726 | else | ||
| 2727 | { | ||
| 2728 | obj = HASH_VALUE (h, e->u.hash.idx); | ||
| 2729 | e->u.hash.idx++; | ||
| 2730 | } | ||
| 2731 | e->u.hash.printed++; | ||
| 2732 | break; | ||
| 2733 | } | ||
| 2734 | goto print_obj; | ||
| 2735 | } | ||
| 2736 | eassert (print_depth == base_depth); | ||
| 2396 | } | 2737 | } |
| 2397 | 2738 | ||
| 2398 | 2739 | ||
| @@ -2602,4 +2943,7 @@ be printed. */); | |||
| 2602 | DEFSYM (Qprint_unreadable_function, "print-unreadable-function"); | 2943 | DEFSYM (Qprint_unreadable_function, "print-unreadable-function"); |
| 2603 | 2944 | ||
| 2604 | defsubr (&Sflush_standard_output); | 2945 | defsubr (&Sflush_standard_output); |
| 2946 | |||
| 2947 | /* Initialized in print_create_variable_mapping. */ | ||
| 2948 | staticpro (&Vprint_variable_mapping); | ||
| 2605 | } | 2949 | } |
diff --git a/src/process.c b/src/process.c index 08a02ad9423..ccfc0bdf547 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1071,13 +1071,24 @@ record_deleted_pid (pid_t pid, Lisp_Object filename) | |||
| 1071 | 1071 | ||
| 1072 | } | 1072 | } |
| 1073 | 1073 | ||
| 1074 | DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0, | 1074 | DEFUN ("delete-process", Fdelete_process, Sdelete_process, 0, 1, |
| 1075 | "(list 'message)", | ||
| 1075 | doc: /* Delete PROCESS: kill it and forget about it immediately. | 1076 | doc: /* Delete PROCESS: kill it and forget about it immediately. |
| 1076 | PROCESS may be a process, a buffer, the name of a process or buffer, or | 1077 | PROCESS may be a process, a buffer, the name of a process or buffer, or |
| 1077 | nil, indicating the current buffer's process. */) | 1078 | nil, indicating the current buffer's process. |
| 1079 | |||
| 1080 | Interactively, it will kill the current buffer's process. */) | ||
| 1078 | (register Lisp_Object process) | 1081 | (register Lisp_Object process) |
| 1079 | { | 1082 | { |
| 1080 | register struct Lisp_Process *p; | 1083 | register struct Lisp_Process *p; |
| 1084 | bool mess = false; | ||
| 1085 | |||
| 1086 | /* We use this to see whether we were called interactively. */ | ||
| 1087 | if (EQ (process, Qmessage)) | ||
| 1088 | { | ||
| 1089 | mess = true; | ||
| 1090 | process = Qnil; | ||
| 1091 | } | ||
| 1081 | 1092 | ||
| 1082 | process = get_process (process); | 1093 | process = get_process (process); |
| 1083 | p = XPROCESS (process); | 1094 | p = XPROCESS (process); |
| @@ -1131,6 +1142,8 @@ nil, indicating the current buffer's process. */) | |||
| 1131 | } | 1142 | } |
| 1132 | } | 1143 | } |
| 1133 | remove_process (process); | 1144 | remove_process (process); |
| 1145 | if (mess) | ||
| 1146 | message ("Deleted process"); | ||
| 1134 | return Qnil; | 1147 | return Qnil; |
| 1135 | } | 1148 | } |
| 1136 | 1149 | ||
| @@ -2132,6 +2145,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 2132 | inchannel = p->open_fd[READ_FROM_SUBPROCESS]; | 2145 | inchannel = p->open_fd[READ_FROM_SUBPROCESS]; |
| 2133 | forkout = p->open_fd[SUBPROCESS_STDOUT]; | 2146 | forkout = p->open_fd[SUBPROCESS_STDOUT]; |
| 2134 | 2147 | ||
| 2148 | #if defined(GNU_LINUX) && defined(F_SETPIPE_SZ) | ||
| 2149 | fcntl (inchannel, F_SETPIPE_SZ, read_process_output_max); | ||
| 2150 | #endif | ||
| 2151 | |||
| 2135 | if (!NILP (p->stderrproc)) | 2152 | if (!NILP (p->stderrproc)) |
| 2136 | { | 2153 | { |
| 2137 | struct Lisp_Process *pp = XPROCESS (p->stderrproc); | 2154 | struct Lisp_Process *pp = XPROCESS (p->stderrproc); |
| @@ -4766,7 +4783,7 @@ corresponding connection was closed. */) | |||
| 4766 | SDATA (proc->name), | 4783 | SDATA (proc->name), |
| 4767 | STRINGP (proc_thread_name) | 4784 | STRINGP (proc_thread_name) |
| 4768 | ? SDATA (proc_thread_name) | 4785 | ? SDATA (proc_thread_name) |
| 4769 | : SDATA (Fprin1_to_string (proc->thread, Qt))); | 4786 | : SDATA (Fprin1_to_string (proc->thread, Qt, Qnil))); |
| 4770 | } | 4787 | } |
| 4771 | } | 4788 | } |
| 4772 | else | 4789 | else |
| @@ -8618,7 +8635,10 @@ returns non-nil. */); | |||
| 8618 | DEFVAR_INT ("read-process-output-max", read_process_output_max, | 8635 | DEFVAR_INT ("read-process-output-max", read_process_output_max, |
| 8619 | doc: /* Maximum number of bytes to read from subprocess in a single chunk. | 8636 | doc: /* Maximum number of bytes to read from subprocess in a single chunk. |
| 8620 | Enlarge the value only if the subprocess generates very large (megabytes) | 8637 | Enlarge the value only if the subprocess generates very large (megabytes) |
| 8621 | amounts of data in one go. */); | 8638 | amounts of data in one go. |
| 8639 | |||
| 8640 | On GNU/Linux systems, the value should not exceed | ||
| 8641 | /proc/sys/fs/pipe-max-size. See pipe(7) manpage for details. */); | ||
| 8622 | read_process_output_max = 4096; | 8642 | read_process_output_max = 4096; |
| 8623 | 8643 | ||
| 8624 | DEFVAR_INT ("process-error-pause-time", process_error_pause_time, | 8644 | DEFVAR_INT ("process-error-pause-time", process_error_pause_time, |
| @@ -8637,6 +8657,7 @@ sentinel or a process filter function has an error. */); | |||
| 8637 | 8657 | ||
| 8638 | DEFSYM (Qnull, "null"); | 8658 | DEFSYM (Qnull, "null"); |
| 8639 | DEFSYM (Qpipe_process_p, "pipe-process-p"); | 8659 | DEFSYM (Qpipe_process_p, "pipe-process-p"); |
| 8660 | DEFSYM (Qmessage, "message"); | ||
| 8640 | 8661 | ||
| 8641 | defsubr (&Sprocessp); | 8662 | defsubr (&Sprocessp); |
| 8642 | defsubr (&Sget_process); | 8663 | defsubr (&Sget_process); |
diff --git a/src/profiler.c b/src/profiler.c index 31a46d1b5e5..5cb42d54fa6 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -132,7 +132,7 @@ static void evict_lower_half (log_t *log) | |||
| 132 | XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ | 132 | XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ |
| 133 | Fremhash (key, tmp); | 133 | Fremhash (key, tmp); |
| 134 | } | 134 | } |
| 135 | eassert (EQ (Qunbound, HASH_KEY (log, i))); | 135 | eassert (BASE_EQ (Qunbound, HASH_KEY (log, i))); |
| 136 | eassert (log->next_free == i); | 136 | eassert (log->next_free == i); |
| 137 | 137 | ||
| 138 | eassert (VECTORP (key)); | 138 | eassert (VECTORP (key)); |
| @@ -158,7 +158,7 @@ record_backtrace (log_t *log, EMACS_INT count) | |||
| 158 | 158 | ||
| 159 | /* Get a "working memory" vector. */ | 159 | /* Get a "working memory" vector. */ |
| 160 | Lisp_Object backtrace = HASH_VALUE (log, index); | 160 | Lisp_Object backtrace = HASH_VALUE (log, index); |
| 161 | eassert (EQ (Qunbound, HASH_KEY (log, index))); | 161 | eassert (BASE_EQ (Qunbound, HASH_KEY (log, index))); |
| 162 | get_backtrace (backtrace); | 162 | get_backtrace (backtrace); |
| 163 | 163 | ||
| 164 | { /* We basically do a `gethash+puthash' here, except that we have to be | 164 | { /* We basically do a `gethash+puthash' here, except that we have to be |
diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 700a6c357de..8662fe8d6d0 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c | |||
| @@ -1244,21 +1244,22 @@ static int analyze_first (re_char *p, re_char *pend, | |||
| 1244 | return REG_ESIZE; \ | 1244 | return REG_ESIZE; \ |
| 1245 | ptrdiff_t b_off = b - old_buffer; \ | 1245 | ptrdiff_t b_off = b - old_buffer; \ |
| 1246 | ptrdiff_t begalt_off = begalt - old_buffer; \ | 1246 | ptrdiff_t begalt_off = begalt - old_buffer; \ |
| 1247 | bool fixup_alt_jump_set = !!fixup_alt_jump; \ | 1247 | ptrdiff_t fixup_alt_jump_off = \ |
| 1248 | bool laststart_set = !!laststart; \ | 1248 | fixup_alt_jump ? fixup_alt_jump - old_buffer : -1; \ |
| 1249 | bool pending_exact_set = !!pending_exact; \ | 1249 | ptrdiff_t laststart_off = laststart ? laststart - old_buffer : -1; \ |
| 1250 | ptrdiff_t fixup_alt_jump_off, laststart_off, pending_exact_off; \ | 1250 | ptrdiff_t pending_exact_off = \ |
| 1251 | if (fixup_alt_jump_set) fixup_alt_jump_off = fixup_alt_jump - old_buffer; \ | 1251 | pending_exact ? pending_exact - old_buffer : -1; \ |
| 1252 | if (laststart_set) laststart_off = laststart - old_buffer; \ | ||
| 1253 | if (pending_exact_set) pending_exact_off = pending_exact - old_buffer; \ | ||
| 1254 | bufp->buffer = xpalloc (bufp->buffer, &bufp->allocated, \ | 1252 | bufp->buffer = xpalloc (bufp->buffer, &bufp->allocated, \ |
| 1255 | requested_extension, MAX_BUF_SIZE, 1); \ | 1253 | requested_extension, MAX_BUF_SIZE, 1); \ |
| 1256 | unsigned char *new_buffer = bufp->buffer; \ | 1254 | unsigned char *new_buffer = bufp->buffer; \ |
| 1257 | b = new_buffer + b_off; \ | 1255 | b = new_buffer + b_off; \ |
| 1258 | begalt = new_buffer + begalt_off; \ | 1256 | begalt = new_buffer + begalt_off; \ |
| 1259 | if (fixup_alt_jump_set) fixup_alt_jump = new_buffer + fixup_alt_jump_off; \ | 1257 | if (0 <= fixup_alt_jump_off) \ |
| 1260 | if (laststart_set) laststart = new_buffer + laststart_off; \ | 1258 | fixup_alt_jump = new_buffer + fixup_alt_jump_off; \ |
| 1261 | if (pending_exact_set) pending_exact = new_buffer + pending_exact_off; \ | 1259 | if (0 <= laststart_off) \ |
| 1260 | laststart = new_buffer + laststart_off; \ | ||
| 1261 | if (0 <= pending_exact_off) \ | ||
| 1262 | pending_exact = new_buffer + pending_exact_off; \ | ||
| 1262 | } while (false) | 1263 | } while (false) |
| 1263 | 1264 | ||
| 1264 | 1265 | ||
diff --git a/src/sort.c b/src/sort.c index c7ccfc23055..d10ae692d33 100644 --- a/src/sort.c +++ b/src/sort.c | |||
| @@ -783,7 +783,7 @@ merge_at (merge_state *ms, const ptrdiff_t i) | |||
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | 785 | ||
| 786 | /* Compute the "power" of the first of two adjacent runs begining at | 786 | /* Compute the "power" of the first of two adjacent runs beginning at |
| 787 | index S1, with the first having length N1 and the second (starting | 787 | index S1, with the first having length N1 and the second (starting |
| 788 | at index S1+N1) having length N2. The run has total length N. */ | 788 | at index S1+N1) having length N2. The run has total length N. */ |
| 789 | 789 | ||
diff --git a/src/sysstdio.h b/src/sysstdio.h index 727a466be52..efedc3e450b 100644 --- a/src/sysstdio.h +++ b/src/sysstdio.h | |||
| @@ -28,7 +28,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | #include <attribute.h> | 28 | #include <attribute.h> |
| 29 | #include <unlocked-io.h> | 29 | #include <unlocked-io.h> |
| 30 | 30 | ||
| 31 | extern FILE *emacs_fopen (char const *, char const *) ATTRIBUTE_MALLOC; | 31 | extern FILE *emacs_fopen (char const *, char const *) |
| 32 | ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC (fclose, 1); | ||
| 32 | extern void errputc (int); | 33 | extern void errputc (int); |
| 33 | extern void errwrite (void const *, ptrdiff_t); | 34 | extern void errwrite (void const *, ptrdiff_t); |
| 34 | extern void close_output_streams (void); | 35 | extern void close_output_streams (void); |
diff --git a/src/term.c b/src/term.c index bad1127c93b..3bea621dbda 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -2287,9 +2287,9 @@ A suspended tty may be resumed by calling `resume-tty' on it. */) | |||
| 2287 | delete_keyboard_wait_descriptor (fileno (f)); | 2287 | delete_keyboard_wait_descriptor (fileno (f)); |
| 2288 | 2288 | ||
| 2289 | #ifndef MSDOS | 2289 | #ifndef MSDOS |
| 2290 | fclose (f); | ||
| 2291 | if (f != t->display_info.tty->output) | 2290 | if (f != t->display_info.tty->output) |
| 2292 | fclose (t->display_info.tty->output); | 2291 | fclose (t->display_info.tty->output); |
| 2292 | fclose (f); | ||
| 2293 | #endif | 2293 | #endif |
| 2294 | 2294 | ||
| 2295 | t->display_info.tty->input = 0; | 2295 | t->display_info.tty->input = 0; |
diff --git a/src/termhooks.h b/src/termhooks.h index 8c193914ba8..d7190e77362 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -31,7 +31,8 @@ struct glyph; | |||
| 31 | 31 | ||
| 32 | INLINE_HEADER_BEGIN | 32 | INLINE_HEADER_BEGIN |
| 33 | 33 | ||
| 34 | enum scroll_bar_part { | 34 | enum scroll_bar_part |
| 35 | { | ||
| 35 | scroll_bar_nowhere, | 36 | scroll_bar_nowhere, |
| 36 | scroll_bar_above_handle, | 37 | scroll_bar_above_handle, |
| 37 | scroll_bar_handle, | 38 | scroll_bar_handle, |
| @@ -223,6 +224,11 @@ enum event_kind | |||
| 223 | gives the timestamp where the drop | 224 | gives the timestamp where the drop |
| 224 | happened. | 225 | happened. |
| 225 | 226 | ||
| 227 | .modifiers gives a number that | ||
| 228 | determines if an event was already | ||
| 229 | handled by | ||
| 230 | `x_dnd_begin_drag_and_drop'. | ||
| 231 | |||
| 226 | .x and .y give the coordinates of | 232 | .x and .y give the coordinates of |
| 227 | the drop originating from the root | 233 | the drop originating from the root |
| 228 | window. */ | 234 | window. */ |
| @@ -296,8 +302,9 @@ enum event_kind | |||
| 296 | #endif | 302 | #endif |
| 297 | 303 | ||
| 298 | #ifdef HAVE_XWIDGETS | 304 | #ifdef HAVE_XWIDGETS |
| 299 | /* events generated by xwidgets*/ | 305 | /* An event generated by an xwidget to tell us something. */ |
| 300 | , XWIDGET_EVENT | 306 | , XWIDGET_EVENT |
| 307 | |||
| 301 | /* Event generated when WebKit asks us to display another widget. */ | 308 | /* Event generated when WebKit asks us to display another widget. */ |
| 302 | , XWIDGET_DISPLAY_EVENT | 309 | , XWIDGET_DISPLAY_EVENT |
| 303 | #endif | 310 | #endif |
| @@ -344,6 +351,11 @@ enum event_kind | |||
| 344 | positive delta represents a change clockwise, and a negative | 351 | positive delta represents a change clockwise, and a negative |
| 345 | delta represents a change counter-clockwise. */ | 352 | delta represents a change counter-clockwise. */ |
| 346 | , PINCH_EVENT | 353 | , PINCH_EVENT |
| 354 | |||
| 355 | /* In a MONITORS_CHANGED_EVENT, .arg gives the terminal on which the | ||
| 356 | monitor configuration changed. .timestamp gives the time on | ||
| 357 | which the monitors changed. */ | ||
| 358 | , MONITORS_CHANGED_EVENT | ||
| 347 | }; | 359 | }; |
| 348 | 360 | ||
| 349 | /* Bit width of an enum event_kind tag at the start of structs and unions. */ | 361 | /* Bit width of an enum event_kind tag at the start of structs and unions. */ |
diff --git a/src/terminal.c b/src/terminal.c index 80f3aed7006..dcde8e9f557 100644 --- a/src/terminal.c +++ b/src/terminal.c | |||
| @@ -290,13 +290,13 @@ create_terminal (enum output_method type, struct redisplay_interface *rif) | |||
| 290 | keyboard_coding = | 290 | keyboard_coding = |
| 291 | find_symbol_value (intern ("default-keyboard-coding-system")); | 291 | find_symbol_value (intern ("default-keyboard-coding-system")); |
| 292 | if (NILP (keyboard_coding) | 292 | if (NILP (keyboard_coding) |
| 293 | || EQ (keyboard_coding, Qunbound) | 293 | || BASE_EQ (keyboard_coding, Qunbound) |
| 294 | || NILP (Fcoding_system_p (keyboard_coding))) | 294 | || NILP (Fcoding_system_p (keyboard_coding))) |
| 295 | keyboard_coding = Qno_conversion; | 295 | keyboard_coding = Qno_conversion; |
| 296 | terminal_coding = | 296 | terminal_coding = |
| 297 | find_symbol_value (intern ("default-terminal-coding-system")); | 297 | find_symbol_value (intern ("default-terminal-coding-system")); |
| 298 | if (NILP (terminal_coding) | 298 | if (NILP (terminal_coding) |
| 299 | || EQ (terminal_coding, Qunbound) | 299 | || BASE_EQ (terminal_coding, Qunbound) |
| 300 | || NILP (Fcoding_system_p (terminal_coding))) | 300 | || NILP (Fcoding_system_p (terminal_coding))) |
| 301 | terminal_coding = Qundecided; | 301 | terminal_coding = Qundecided; |
| 302 | 302 | ||
diff --git a/src/textprop.c b/src/textprop.c index 072aac28667..c11ee98f020 100644 --- a/src/textprop.c +++ b/src/textprop.c | |||
| @@ -341,7 +341,7 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object) | |||
| 341 | for (sym = properties; | 341 | for (sym = properties; |
| 342 | PLIST_ELT_P (sym, value); | 342 | PLIST_ELT_P (sym, value); |
| 343 | sym = XCDR (value)) | 343 | sym = XCDR (value)) |
| 344 | if (EQ (property_value (interval->plist, XCAR (sym)), Qunbound)) | 344 | if (BASE_EQ (property_value (interval->plist, XCAR (sym)), Qunbound)) |
| 345 | { | 345 | { |
| 346 | record_property_change (interval->position, LENGTH (interval), | 346 | record_property_change (interval->position, LENGTH (interval), |
| 347 | XCAR (sym), Qnil, | 347 | XCAR (sym), Qnil, |
diff --git a/src/tparam.h b/src/tparam.h index 653f01bdde0..4f4bdc8820f 100644 --- a/src/tparam.h +++ b/src/tparam.h | |||
| @@ -20,6 +20,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 20 | #ifndef EMACS_TPARAM_H | 20 | #ifndef EMACS_TPARAM_H |
| 21 | #define EMACS_TPARAM_H | 21 | #define EMACS_TPARAM_H |
| 22 | 22 | ||
| 23 | #include <stdlib.h> | ||
| 24 | |||
| 23 | #include <attribute.h> | 25 | #include <attribute.h> |
| 24 | 26 | ||
| 25 | /* Don't try to include termcap.h. On some systems, configure finds a | 27 | /* Don't try to include termcap.h. On some systems, configure finds a |
| @@ -32,7 +34,8 @@ int tgetnum (const char *); | |||
| 32 | char *tgetstr (const char *, char **); | 34 | char *tgetstr (const char *, char **); |
| 33 | char *tgoto (const char *, int, int); | 35 | char *tgoto (const char *, int, int); |
| 34 | 36 | ||
| 35 | char *tparam (const char *, char *, int, int, int, int, int) ATTRIBUTE_MALLOC; | 37 | char *tparam (const char *, char *, int, int, int, int, int) |
| 38 | ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE; | ||
| 36 | 39 | ||
| 37 | extern char PC; | 40 | extern char PC; |
| 38 | extern char *BC; | 41 | extern char *BC; |
| @@ -10297,7 +10297,8 @@ check_windows_init_file (void) | |||
| 10297 | openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0); | 10297 | openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0); |
| 10298 | if (fd < 0) | 10298 | if (fd < 0) |
| 10299 | { | 10299 | { |
| 10300 | Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil); | 10300 | Lisp_Object load_path_print = Fprin1_to_string (Vload_path, |
| 10301 | Qnil, Qnil); | ||
| 10301 | char *init_file_name = SSDATA (init_file); | 10302 | char *init_file_name = SSDATA (init_file); |
| 10302 | char *load_path = SSDATA (load_path_print); | 10303 | char *load_path = SSDATA (load_path_print); |
| 10303 | char *buffer = alloca (1024 | 10304 | char *buffer = alloca (1024 |
diff --git a/src/w32fns.c b/src/w32fns.c index 0f25c1a594a..8716b762eb0 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -247,6 +247,8 @@ static HWND w32_visible_system_caret_hwnd; | |||
| 247 | 247 | ||
| 248 | static int w32_unicode_gui; | 248 | static int w32_unicode_gui; |
| 249 | 249 | ||
| 250 | static bool w32_selection_dialog_open; | ||
| 251 | |||
| 250 | /* From w32menu.c */ | 252 | /* From w32menu.c */ |
| 251 | int menubar_in_use = 0; | 253 | int menubar_in_use = 0; |
| 252 | 254 | ||
| @@ -4184,6 +4186,16 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 4184 | update_rect.left, update_rect.top, | 4186 | update_rect.left, update_rect.top, |
| 4185 | update_rect.right, update_rect.bottom)); | 4187 | update_rect.right, update_rect.bottom)); |
| 4186 | #endif | 4188 | #endif |
| 4189 | /* Under double-buffering, update the frame from the back | ||
| 4190 | buffer, to prevent a "ghost" of the selection dialog to | ||
| 4191 | be left on display while the user selects in the dialog. */ | ||
| 4192 | if (w32_selection_dialog_open | ||
| 4193 | && !w32_disable_double_buffering | ||
| 4194 | && FRAME_OUTPUT_DATA (f)->paint_dc) | ||
| 4195 | BitBlt (FRAME_OUTPUT_DATA (f)->paint_buffer_handle, | ||
| 4196 | 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), | ||
| 4197 | FRAME_OUTPUT_DATA (f)->paint_dc, 0, 0, SRCCOPY); | ||
| 4198 | |||
| 4187 | EndPaint (hwnd, &paintStruct); | 4199 | EndPaint (hwnd, &paintStruct); |
| 4188 | leave_crit (); | 4200 | leave_crit (); |
| 4189 | 4201 | ||
| @@ -5536,11 +5548,11 @@ my_create_window (struct frame * f) | |||
| 5536 | RES_TYPE_NUMBER); | 5548 | RES_TYPE_NUMBER); |
| 5537 | top = gui_display_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", | 5549 | top = gui_display_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", |
| 5538 | RES_TYPE_NUMBER); | 5550 | RES_TYPE_NUMBER); |
| 5539 | if (EQ (left, Qunbound)) | 5551 | if (BASE_EQ (left, Qunbound)) |
| 5540 | coords[0] = CW_USEDEFAULT; | 5552 | coords[0] = CW_USEDEFAULT; |
| 5541 | else | 5553 | else |
| 5542 | coords[0] = XFIXNUM (left); | 5554 | coords[0] = XFIXNUM (left); |
| 5543 | if (EQ (top, Qunbound)) | 5555 | if (BASE_EQ (top, Qunbound)) |
| 5544 | coords[1] = CW_USEDEFAULT; | 5556 | coords[1] = CW_USEDEFAULT; |
| 5545 | else | 5557 | else |
| 5546 | coords[1] = XFIXNUM (top); | 5558 | coords[1] = XFIXNUM (top); |
| @@ -5656,12 +5668,12 @@ w32_icon (struct frame *f, Lisp_Object parms) | |||
| 5656 | RES_TYPE_NUMBER); | 5668 | RES_TYPE_NUMBER); |
| 5657 | icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, | 5669 | icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, |
| 5658 | RES_TYPE_NUMBER); | 5670 | RES_TYPE_NUMBER); |
| 5659 | if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) | 5671 | if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound)) |
| 5660 | { | 5672 | { |
| 5661 | CHECK_FIXNUM (icon_x); | 5673 | CHECK_FIXNUM (icon_x); |
| 5662 | CHECK_FIXNUM (icon_y); | 5674 | CHECK_FIXNUM (icon_y); |
| 5663 | } | 5675 | } |
| 5664 | else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) | 5676 | else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound)) |
| 5665 | error ("Both left and top icon corners of icon must be specified"); | 5677 | error ("Both left and top icon corners of icon must be specified"); |
| 5666 | 5678 | ||
| 5667 | block_input (); | 5679 | block_input (); |
| @@ -5756,7 +5768,7 @@ w32_default_font_parameter (struct frame *f, Lisp_Object parms) | |||
| 5756 | parms, Qfont, NULL, NULL, | 5768 | parms, Qfont, NULL, NULL, |
| 5757 | RES_TYPE_STRING); | 5769 | RES_TYPE_STRING); |
| 5758 | Lisp_Object font; | 5770 | Lisp_Object font; |
| 5759 | if (EQ (font_param, Qunbound)) | 5771 | if (BASE_EQ (font_param, Qunbound)) |
| 5760 | font_param = Qnil; | 5772 | font_param = Qnil; |
| 5761 | font = !NILP (font_param) ? font_param | 5773 | font = !NILP (font_param) ? font_param |
| 5762 | : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", | 5774 | : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", |
| @@ -5821,10 +5833,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5821 | 5833 | ||
| 5822 | display = gui_display_get_arg (dpyinfo, parameters, Qterminal, 0, 0, | 5834 | display = gui_display_get_arg (dpyinfo, parameters, Qterminal, 0, 0, |
| 5823 | RES_TYPE_NUMBER); | 5835 | RES_TYPE_NUMBER); |
| 5824 | if (EQ (display, Qunbound)) | 5836 | if (BASE_EQ (display, Qunbound)) |
| 5825 | display = gui_display_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, | 5837 | display = gui_display_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, |
| 5826 | RES_TYPE_STRING); | 5838 | RES_TYPE_STRING); |
| 5827 | if (EQ (display, Qunbound)) | 5839 | if (BASE_EQ (display, Qunbound)) |
| 5828 | display = Qnil; | 5840 | display = Qnil; |
| 5829 | dpyinfo = check_x_display_info (display); | 5841 | dpyinfo = check_x_display_info (display); |
| 5830 | kb = dpyinfo->terminal->kboard; | 5842 | kb = dpyinfo->terminal->kboard; |
| @@ -5835,7 +5847,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5835 | name = gui_display_get_arg (dpyinfo, parameters, Qname, "name", "Name", | 5847 | name = gui_display_get_arg (dpyinfo, parameters, Qname, "name", "Name", |
| 5836 | RES_TYPE_STRING); | 5848 | RES_TYPE_STRING); |
| 5837 | if (!STRINGP (name) | 5849 | if (!STRINGP (name) |
| 5838 | && ! EQ (name, Qunbound) | 5850 | && ! BASE_EQ (name, Qunbound) |
| 5839 | && ! NILP (name)) | 5851 | && ! NILP (name)) |
| 5840 | error ("Invalid frame name--not a string or nil"); | 5852 | error ("Invalid frame name--not a string or nil"); |
| 5841 | 5853 | ||
| @@ -5845,7 +5857,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5845 | /* See if parent window is specified. */ | 5857 | /* See if parent window is specified. */ |
| 5846 | parent = gui_display_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, | 5858 | parent = gui_display_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, |
| 5847 | RES_TYPE_NUMBER); | 5859 | RES_TYPE_NUMBER); |
| 5848 | if (EQ (parent, Qunbound)) | 5860 | if (BASE_EQ (parent, Qunbound)) |
| 5849 | parent = Qnil; | 5861 | parent = Qnil; |
| 5850 | else if (!NILP (parent)) | 5862 | else if (!NILP (parent)) |
| 5851 | CHECK_FIXNUM (parent); | 5863 | CHECK_FIXNUM (parent); |
| @@ -5888,14 +5900,14 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5888 | 5900 | ||
| 5889 | tem = gui_display_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL, | 5901 | tem = gui_display_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL, |
| 5890 | RES_TYPE_BOOLEAN); | 5902 | RES_TYPE_BOOLEAN); |
| 5891 | FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound); | 5903 | FRAME_UNDECORATED (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound); |
| 5892 | store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil); | 5904 | store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil); |
| 5893 | 5905 | ||
| 5894 | tem = gui_display_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL, | 5906 | tem = gui_display_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL, |
| 5895 | RES_TYPE_BOOLEAN); | 5907 | RES_TYPE_BOOLEAN); |
| 5896 | FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound); | 5908 | FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound); |
| 5897 | store_frame_param (f, Qskip_taskbar, | 5909 | store_frame_param (f, Qskip_taskbar, |
| 5898 | (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt); | 5910 | (NILP (tem) || BASE_EQ (tem, Qunbound)) ? Qnil : Qt); |
| 5899 | 5911 | ||
| 5900 | /* By default, make scrollbars the system standard width and height. */ | 5912 | /* By default, make scrollbars the system standard width and height. */ |
| 5901 | FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); | 5913 | FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); |
| @@ -5951,7 +5963,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5951 | 5963 | ||
| 5952 | /* Set the name; the functions to which we pass f expect the name to | 5964 | /* Set the name; the functions to which we pass f expect the name to |
| 5953 | be set. */ | 5965 | be set. */ |
| 5954 | if (EQ (name, Qunbound) || NILP (name)) | 5966 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 5955 | { | 5967 | { |
| 5956 | fset_name (f, build_string (dpyinfo->w32_id_name)); | 5968 | fset_name (f, build_string (dpyinfo->w32_id_name)); |
| 5957 | f->explicit_name = false; | 5969 | f->explicit_name = false; |
| @@ -5991,7 +6003,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 5991 | value = gui_display_get_arg (dpyinfo, parameters, Qinternal_border_width, | 6003 | value = gui_display_get_arg (dpyinfo, parameters, Qinternal_border_width, |
| 5992 | "internalBorder", "internalBorder", | 6004 | "internalBorder", "internalBorder", |
| 5993 | RES_TYPE_NUMBER); | 6005 | RES_TYPE_NUMBER); |
| 5994 | if (! EQ (value, Qunbound)) | 6006 | if (! BASE_EQ (value, Qunbound)) |
| 5995 | parameters = Fcons (Fcons (Qinternal_border_width, value), | 6007 | parameters = Fcons (Fcons (Qinternal_border_width, value), |
| 5996 | parameters); | 6008 | parameters); |
| 5997 | } | 6009 | } |
| @@ -6008,7 +6020,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 6008 | value = gui_display_get_arg (dpyinfo, parameters, Qchild_frame_border_width, | 6020 | value = gui_display_get_arg (dpyinfo, parameters, Qchild_frame_border_width, |
| 6009 | "childFrameBorder", "childFrameBorder", | 6021 | "childFrameBorder", "childFrameBorder", |
| 6010 | RES_TYPE_NUMBER); | 6022 | RES_TYPE_NUMBER); |
| 6011 | if (!EQ (value, Qunbound)) | 6023 | if (!BASE_EQ (value, Qunbound)) |
| 6012 | parameters = Fcons (Fcons (Qchild_frame_border_width, value), | 6024 | parameters = Fcons (Fcons (Qchild_frame_border_width, value), |
| 6013 | parameters); | 6025 | parameters); |
| 6014 | } | 6026 | } |
| @@ -6207,7 +6219,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 6207 | w32_iconify_frame (f); | 6219 | w32_iconify_frame (f); |
| 6208 | else | 6220 | else |
| 6209 | { | 6221 | { |
| 6210 | if (EQ (visibility, Qunbound)) | 6222 | if (BASE_EQ (visibility, Qunbound)) |
| 6211 | visibility = Qt; | 6223 | visibility = Qt; |
| 6212 | 6224 | ||
| 6213 | if (!NILP (visibility)) | 6225 | if (!NILP (visibility)) |
| @@ -6999,7 +7011,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) | |||
| 6999 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 7011 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 7000 | RES_TYPE_STRING); | 7012 | RES_TYPE_STRING); |
| 7001 | if (!STRINGP (name) | 7013 | if (!STRINGP (name) |
| 7002 | && !EQ (name, Qunbound) | 7014 | && !BASE_EQ (name, Qunbound) |
| 7003 | && !NILP (name)) | 7015 | && !NILP (name)) |
| 7004 | error ("Invalid frame name--not a string or nil"); | 7016 | error ("Invalid frame name--not a string or nil"); |
| 7005 | Vx_resource_name = name; | 7017 | Vx_resource_name = name; |
| @@ -7033,7 +7045,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) | |||
| 7033 | 7045 | ||
| 7034 | /* Set the name; the functions to which we pass f expect the name to | 7046 | /* Set the name; the functions to which we pass f expect the name to |
| 7035 | be set. */ | 7047 | be set. */ |
| 7036 | if (EQ (name, Qunbound) || NILP (name)) | 7048 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 7037 | { | 7049 | { |
| 7038 | fset_name (f, build_string (dpyinfo->w32_id_name)); | 7050 | fset_name (f, build_string (dpyinfo->w32_id_name)); |
| 7039 | f->explicit_name = false; | 7051 | f->explicit_name = false; |
| @@ -7072,7 +7084,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) | |||
| 7072 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 7084 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 7073 | "internalBorder", "internalBorder", | 7085 | "internalBorder", "internalBorder", |
| 7074 | RES_TYPE_NUMBER); | 7086 | RES_TYPE_NUMBER); |
| 7075 | if (! EQ (value, Qunbound)) | 7087 | if (! BASE_EQ (value, Qunbound)) |
| 7076 | parms = Fcons (Fcons (Qinternal_border_width, value), | 7088 | parms = Fcons (Fcons (Qinternal_border_width, value), |
| 7077 | parms); | 7089 | parms); |
| 7078 | } | 7090 | } |
| @@ -7755,6 +7767,15 @@ w32_dialog_in_progress (Lisp_Object in_progress) | |||
| 7755 | { | 7767 | { |
| 7756 | Lisp_Object frames, frame; | 7768 | Lisp_Object frames, frame; |
| 7757 | 7769 | ||
| 7770 | /* Indicate to w32_wnd_proc that the selection dialog is about to be | ||
| 7771 | open (or was closed, if IN_PROGRESS is nil). */ | ||
| 7772 | if (!w32_disable_double_buffering) | ||
| 7773 | { | ||
| 7774 | enter_crit (); | ||
| 7775 | w32_selection_dialog_open = !NILP (in_progress); | ||
| 7776 | leave_crit (); | ||
| 7777 | } | ||
| 7778 | |||
| 7758 | /* Don't let frames in `above' z-group obscure dialog windows. */ | 7779 | /* Don't let frames in `above' z-group obscure dialog windows. */ |
| 7759 | FOR_EACH_FRAME (frames, frame) | 7780 | FOR_EACH_FRAME (frames, frame) |
| 7760 | { | 7781 | { |
| @@ -10769,21 +10790,6 @@ bass-down, bass-boost, bass-up, treble-down, treble-up */); | |||
| 10769 | doc: /* SKIP: real doc in xfns.c. */); | 10790 | doc: /* SKIP: real doc in xfns.c. */); |
| 10770 | Vx_pixel_size_width_font_regexp = Qnil; | 10791 | Vx_pixel_size_width_font_regexp = Qnil; |
| 10771 | 10792 | ||
| 10772 | DEFVAR_LISP ("w32-bdf-filename-alist", | ||
| 10773 | Vw32_bdf_filename_alist, | ||
| 10774 | doc: /* List of bdf fonts and their corresponding filenames. */); | ||
| 10775 | Vw32_bdf_filename_alist = Qnil; | ||
| 10776 | |||
| 10777 | DEFVAR_BOOL ("w32-strict-fontnames", | ||
| 10778 | w32_strict_fontnames, | ||
| 10779 | doc: /* Non-nil means only use fonts that are exact matches for those requested. | ||
| 10780 | Default is nil, which allows old fontnames that are not XLFD compliant, | ||
| 10781 | and allows third-party CJK display to work by specifying false charset | ||
| 10782 | fields to trick Emacs into translating to Big5, SJIS etc. | ||
| 10783 | Setting this to t will prevent wrong fonts being selected when | ||
| 10784 | fontsets are automatically created. */); | ||
| 10785 | w32_strict_fontnames = 0; | ||
| 10786 | |||
| 10787 | DEFVAR_BOOL ("w32-strict-painting", | 10793 | DEFVAR_BOOL ("w32-strict-painting", |
| 10788 | w32_strict_painting, | 10794 | w32_strict_painting, |
| 10789 | doc: /* Non-nil means use strict rules for repainting frames. | 10795 | doc: /* Non-nil means use strict rules for repainting frames. |
diff --git a/src/w32font.c b/src/w32font.c index 1f93f6d5e05..611a0c89658 100644 --- a/src/w32font.c +++ b/src/w32font.c | |||
| @@ -1540,6 +1540,19 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font, | |||
| 1540 | || physical_font->ntmFontSig.fsUsb[1] | 1540 | || physical_font->ntmFontSig.fsUsb[1] |
| 1541 | || physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff; | 1541 | || physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff; |
| 1542 | 1542 | ||
| 1543 | /* Kludgey fix for Arial Unicode MS font that claims support for | ||
| 1544 | scripts it doesn't actually cover. */ | ||
| 1545 | if (strncmp (logical_font->elfLogFont.lfFaceName, | ||
| 1546 | "Arial Unicode MS", 16) == 0) | ||
| 1547 | { | ||
| 1548 | /* Reset bits 4 (Phonetic), 12 (Vai), 14 (Nko), 27 (Balinese). */ | ||
| 1549 | physical_font->ntmFontSig.fsUsb[0] &= 0xf7ffafef; | ||
| 1550 | /* Reset bits 53 (Phags-pa) and 58 (Phoenician). */ | ||
| 1551 | physical_font->ntmFontSig.fsUsb[1] &= 0xfbdfffff; | ||
| 1552 | /* Set bit 70 (Tibetan). */ | ||
| 1553 | physical_font->ntmFontSig.fsUsb[2] |= 0x00000040; | ||
| 1554 | } | ||
| 1555 | |||
| 1543 | /* Skip non matching fonts. */ | 1556 | /* Skip non matching fonts. */ |
| 1544 | 1557 | ||
| 1545 | /* For uniscribe backend, consider only truetype or opentype fonts | 1558 | /* For uniscribe backend, consider only truetype or opentype fonts |
| @@ -2834,18 +2847,18 @@ syms_of_w32font (void) | |||
| 2834 | DEFSYM (Qhanunoo, "hanunoo"); | 2847 | DEFSYM (Qhanunoo, "hanunoo"); |
| 2835 | DEFSYM (Qkharoshthi, "kharoshthi"); | 2848 | DEFSYM (Qkharoshthi, "kharoshthi"); |
| 2836 | DEFSYM (Qlimbu, "limbu"); | 2849 | DEFSYM (Qlimbu, "limbu"); |
| 2837 | DEFSYM (Qlinear_b, "linear_b"); | 2850 | DEFSYM (Qlinear_b, "linear-b"); |
| 2838 | DEFSYM (Qaegean_number, "aegean-number"); | 2851 | DEFSYM (Qaegean_number, "aegean-number"); |
| 2839 | DEFSYM (Qold_italic, "old_italic"); | 2852 | DEFSYM (Qold_italic, "old-italic"); |
| 2840 | DEFSYM (Qold_persian, "old_persian"); | 2853 | DEFSYM (Qold_persian, "old-persian"); |
| 2841 | DEFSYM (Qosmanya, "osmanya"); | 2854 | DEFSYM (Qosmanya, "osmanya"); |
| 2842 | DEFSYM (Qphags_pa, "phags-pa"); | 2855 | DEFSYM (Qphags_pa, "phags-pa"); |
| 2843 | DEFSYM (Qphoenician, "phoenician"); | 2856 | DEFSYM (Qphoenician, "phoenician"); |
| 2844 | DEFSYM (Qshavian, "shavian"); | 2857 | DEFSYM (Qshavian, "shavian"); |
| 2845 | DEFSYM (Qsyloti_nagri, "syloti_nagri"); | 2858 | DEFSYM (Qsyloti_nagri, "syloti-nagri"); |
| 2846 | DEFSYM (Qtagalog, "tagalog"); | 2859 | DEFSYM (Qtagalog, "tagalog"); |
| 2847 | DEFSYM (Qtagbanwa, "tagbanwa"); | 2860 | DEFSYM (Qtagbanwa, "tagbanwa"); |
| 2848 | DEFSYM (Qtai_le, "tai_le"); | 2861 | DEFSYM (Qtai_le, "tai-le"); |
| 2849 | DEFSYM (Qtifinagh, "tifinagh"); | 2862 | DEFSYM (Qtifinagh, "tifinagh"); |
| 2850 | DEFSYM (Qugaritic, "ugaritic"); | 2863 | DEFSYM (Qugaritic, "ugaritic"); |
| 2851 | DEFSYM (Qlycian, "lycian"); | 2864 | DEFSYM (Qlycian, "lycian"); |
diff --git a/src/w32menu.c b/src/w32menu.c index 5cd6c3310e3..b10239d5cc6 100644 --- a/src/w32menu.c +++ b/src/w32menu.c | |||
| @@ -556,10 +556,8 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 556 | HMENU menu; | 556 | HMENU menu; |
| 557 | POINT pos; | 557 | POINT pos; |
| 558 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 558 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 559 | widget_value **submenu_stack | 559 | widget_value **submenu_stack; |
| 560 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 560 | Lisp_Object *subprefix_stack; |
| 561 | Lisp_Object *subprefix_stack | ||
| 562 | = (Lisp_Object *) alloca (menu_items_used * word_size); | ||
| 563 | int submenu_depth = 0; | 561 | int submenu_depth = 0; |
| 564 | bool first_pane; | 562 | bool first_pane; |
| 565 | 563 | ||
| @@ -574,6 +572,11 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 574 | return Qnil; | 572 | return Qnil; |
| 575 | } | 573 | } |
| 576 | 574 | ||
| 575 | USE_SAFE_ALLOCA; | ||
| 576 | |||
| 577 | submenu_stack = SAFE_ALLOCA (menu_items_used * sizeof (widget_value *)); | ||
| 578 | subprefix_stack = SAFE_ALLOCA (menu_items_used * word_size); | ||
| 579 | |||
| 577 | block_input (); | 580 | block_input (); |
| 578 | 581 | ||
| 579 | /* Create a tree of widget_value objects | 582 | /* Create a tree of widget_value objects |
| @@ -816,6 +819,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 816 | entry = Fcons (subprefix_stack[j], entry); | 819 | entry = Fcons (subprefix_stack[j], entry); |
| 817 | } | 820 | } |
| 818 | unblock_input (); | 821 | unblock_input (); |
| 822 | SAFE_FREE (); | ||
| 819 | return entry; | 823 | return entry; |
| 820 | } | 824 | } |
| 821 | i += MENU_ITEMS_ITEM_LENGTH; | 825 | i += MENU_ITEMS_ITEM_LENGTH; |
| @@ -830,6 +834,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 830 | } | 834 | } |
| 831 | 835 | ||
| 832 | unblock_input (); | 836 | unblock_input (); |
| 837 | SAFE_FREE (); | ||
| 833 | return Qnil; | 838 | return Qnil; |
| 834 | } | 839 | } |
| 835 | 840 | ||
diff --git a/src/w32notify.c b/src/w32notify.c index ccefecb6596..72e634f77c7 100644 --- a/src/w32notify.c +++ b/src/w32notify.c | |||
| @@ -519,16 +519,16 @@ watched for some reason, this function signals a `file-error' error. | |||
| 519 | FILTER is a list of conditions for reporting an event. It can include | 519 | FILTER is a list of conditions for reporting an event. It can include |
| 520 | the following symbols: | 520 | the following symbols: |
| 521 | 521 | ||
| 522 | 'file-name' -- report file creation, deletion, or renaming | 522 | `file-name' -- report file creation, deletion, or renaming |
| 523 | 'directory-name' -- report directory creation, deletion, or renaming | 523 | `directory-name' -- report directory creation, deletion, or renaming |
| 524 | 'attributes' -- report changes in attributes | 524 | `attributes' -- report changes in attributes |
| 525 | 'size' -- report changes in file-size | 525 | `size' -- report changes in file-size |
| 526 | 'last-write-time' -- report changes in last-write time | 526 | `last-write-time' -- report changes in last-write time |
| 527 | 'last-access-time' -- report changes in last-access time | 527 | `last-access-time' -- report changes in last-access time |
| 528 | 'creation-time' -- report changes in creation time | 528 | `creation-time' -- report changes in creation time |
| 529 | 'security-desc' -- report changes in security descriptor | 529 | `security-desc' -- report changes in security descriptor |
| 530 | 530 | ||
| 531 | If FILE is a directory, and FILTER includes 'subtree', then all the | 531 | If FILE is a directory, and FILTER includes `subtree', then all the |
| 532 | subdirectories will also be watched and changes in them reported. | 532 | subdirectories will also be watched and changes in them reported. |
| 533 | 533 | ||
| 534 | When any event happens that satisfies the conditions specified by | 534 | When any event happens that satisfies the conditions specified by |
| @@ -541,11 +541,11 @@ DESCRIPTOR is the same object as the one returned by this function. | |||
| 541 | ACTION is the description of the event. It could be any one of the | 541 | ACTION is the description of the event. It could be any one of the |
| 542 | following: | 542 | following: |
| 543 | 543 | ||
| 544 | 'added' -- FILE was added | 544 | `added' -- FILE was added |
| 545 | 'removed' -- FILE was deleted | 545 | `removed' -- FILE was deleted |
| 546 | 'modified' -- FILE's contents or its attributes were modified | 546 | `modified' -- FILE's contents or its attributes were modified |
| 547 | 'renamed-from' -- a file was renamed whose old name was FILE | 547 | `renamed-from' -- a file was renamed whose old name was FILE |
| 548 | 'renamed-to' -- a file was renamed and its new name is FILE | 548 | `renamed-to' -- a file was renamed and its new name is FILE |
| 549 | 549 | ||
| 550 | FILE is the name of the file whose event is being reported. | 550 | FILE is the name of the file whose event is being reported. |
| 551 | 551 | ||
diff --git a/src/w32proc.c b/src/w32proc.c index 781a19f480f..7acfba64d70 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -63,6 +63,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 63 | #include "w32term.h" | 63 | #include "w32term.h" |
| 64 | #include "coding.h" | 64 | #include "coding.h" |
| 65 | 65 | ||
| 66 | void w32_raise (int); | ||
| 67 | |||
| 66 | #define RVA_TO_PTR(var,section,filedata) \ | 68 | #define RVA_TO_PTR(var,section,filedata) \ |
| 67 | ((void *)((section)->PointerToRawData \ | 69 | ((void *)((section)->PointerToRawData \ |
| 68 | + ((DWORD_PTR)(var) - (section)->VirtualAddress) \ | 70 | + ((DWORD_PTR)(var) - (section)->VirtualAddress) \ |
| @@ -311,6 +313,21 @@ sigismember (const sigset_t *set, int signo) | |||
| 311 | return (*set & (1U << signo)) != 0; | 313 | return (*set & (1U << signo)) != 0; |
| 312 | } | 314 | } |
| 313 | 315 | ||
| 316 | /* A fuller emulation of 'raise', which supports signals that MS | ||
| 317 | runtime doesn't know about. */ | ||
| 318 | void | ||
| 319 | w32_raise (int signo) | ||
| 320 | { | ||
| 321 | if (!(signo == SIGCHLD || signo == SIGALRM || signo == SIGPROF)) | ||
| 322 | raise (signo); | ||
| 323 | |||
| 324 | /* Call the handler directly for the signals that we handle | ||
| 325 | ourselves. */ | ||
| 326 | signal_handler handler = sig_handlers[signo]; | ||
| 327 | if (!(handler == SIG_DFL || handler == SIG_IGN || handler == SIG_ERR)) | ||
| 328 | handler (signo); | ||
| 329 | } | ||
| 330 | |||
| 314 | pid_t | 331 | pid_t |
| 315 | getpgrp (void) | 332 | getpgrp (void) |
| 316 | { | 333 | { |
diff --git a/src/w32term.c b/src/w32term.c index 19786da3a6d..d0577efccc1 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -2682,13 +2682,13 @@ w32_draw_glyph_string (struct glyph_string *s) | |||
| 2682 | val = (WINDOW_BUFFER_LOCAL_VALUE | 2682 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 2683 | (Qx_underline_at_descent_line, s->w)); | 2683 | (Qx_underline_at_descent_line, s->w)); |
| 2684 | underline_at_descent_line | 2684 | underline_at_descent_line |
| 2685 | = (!(NILP (val) || EQ (val, Qunbound)) | 2685 | = (!(NILP (val) || BASE_EQ (val, Qunbound)) |
| 2686 | || s->face->underline_at_descent_line_p); | 2686 | || s->face->underline_at_descent_line_p); |
| 2687 | 2687 | ||
| 2688 | val = (WINDOW_BUFFER_LOCAL_VALUE | 2688 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 2689 | (Qx_use_underline_position_properties, s->w)); | 2689 | (Qx_use_underline_position_properties, s->w)); |
| 2690 | use_underline_position_properties | 2690 | use_underline_position_properties |
| 2691 | = !(NILP (val) || EQ (val, Qunbound)); | 2691 | = !(NILP (val) || BASE_EQ (val, Qunbound)); |
| 2692 | 2692 | ||
| 2693 | /* Get the underline thickness. Default is 1 pixel. */ | 2693 | /* Get the underline thickness. Default is 1 pixel. */ |
| 2694 | if (font && font->underline_thickness > 0) | 2694 | if (font && font->underline_thickness > 0) |
| @@ -2720,7 +2720,7 @@ w32_draw_glyph_string (struct glyph_string *s) | |||
| 2720 | 2720 | ||
| 2721 | if (!(s->face->underline_at_descent_line_p | 2721 | if (!(s->face->underline_at_descent_line_p |
| 2722 | /* Ignore minimum_offset if the amount of pixels | 2722 | /* Ignore minimum_offset if the amount of pixels |
| 2723 | was explictly specified. */ | 2723 | was explicitly specified. */ |
| 2724 | && s->face->underline_pixels_above_descent_line)) | 2724 | && s->face->underline_pixels_above_descent_line)) |
| 2725 | position = max (position, minimum_offset); | 2725 | position = max (position, minimum_offset); |
| 2726 | } | 2726 | } |
| @@ -5912,6 +5912,29 @@ w32_read_socket (struct terminal *terminal, | |||
| 5912 | (short) HIWORD (msg.msg.lParam))); | 5912 | (short) HIWORD (msg.msg.lParam))); |
| 5913 | } | 5913 | } |
| 5914 | 5914 | ||
| 5915 | /* According to the MS documentation, this message is sent | ||
| 5916 | to each window whenever a monitor is added, removed, or | ||
| 5917 | has its resolution change. Detect duplicate events when | ||
| 5918 | there are multiple frames by ensuring only one event is | ||
| 5919 | put in the keyboard buffer at any given time. */ | ||
| 5920 | { | ||
| 5921 | union buffered_input_event *ev; | ||
| 5922 | |||
| 5923 | ev = (kbd_store_ptr == kbd_buffer | ||
| 5924 | ? kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 5925 | : kbd_store_ptr - 1); | ||
| 5926 | |||
| 5927 | if (kbd_store_ptr != kbd_fetch_ptr | ||
| 5928 | && ev->ie.kind == MONITORS_CHANGED_EVENT | ||
| 5929 | && XTERMINAL (ev->ie.arg) == dpyinfo->terminal) | ||
| 5930 | /* Don't store a MONITORS_CHANGED_EVENT if there is | ||
| 5931 | already an undelivered event on the queue. */ | ||
| 5932 | break; | ||
| 5933 | |||
| 5934 | inev.kind = MONITORS_CHANGED_EVENT; | ||
| 5935 | XSETTERMINAL (inev.arg, dpyinfo->terminal); | ||
| 5936 | } | ||
| 5937 | |||
| 5915 | check_visibility = 1; | 5938 | check_visibility = 1; |
| 5916 | break; | 5939 | break; |
| 5917 | 5940 | ||
diff --git a/src/window.c b/src/window.c index 15d6cf94b0e..ac8408a9a97 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -1014,11 +1014,22 @@ WINDOW must be a valid window and defaults to the selected one. */) | |||
| 1014 | return make_fixnum (decode_valid_window (window)->top_line); | 1014 | return make_fixnum (decode_valid_window (window)->top_line); |
| 1015 | } | 1015 | } |
| 1016 | 1016 | ||
| 1017 | static enum window_body_unit | ||
| 1018 | window_body_unit_from_symbol (Lisp_Object unit) | ||
| 1019 | { | ||
| 1020 | return | ||
| 1021 | EQ (unit, Qremap) | ||
| 1022 | ? WINDOW_BODY_IN_REMAPPED_CHARS | ||
| 1023 | : (NILP (unit) | ||
| 1024 | ? WINDOW_BODY_IN_CANONICAL_CHARS | ||
| 1025 | : WINDOW_BODY_IN_PIXELS); | ||
| 1026 | } | ||
| 1027 | |||
| 1017 | /* Return the number of lines/pixels of W's body. Don't count any mode | 1028 | /* Return the number of lines/pixels of W's body. Don't count any mode |
| 1018 | or header line or horizontal divider of W. Rounds down to nearest | 1029 | or header line or horizontal divider of W. Rounds down to nearest |
| 1019 | integer when not working pixelwise. */ | 1030 | integer when not working pixelwise. */ |
| 1020 | static int | 1031 | static int |
| 1021 | window_body_height (struct window *w, bool pixelwise) | 1032 | window_body_height (struct window *w, enum window_body_unit pixelwise) |
| 1022 | { | 1033 | { |
| 1023 | int height = (w->pixel_height | 1034 | int height = (w->pixel_height |
| 1024 | - WINDOW_TAB_LINE_HEIGHT (w) | 1035 | - WINDOW_TAB_LINE_HEIGHT (w) |
| @@ -1029,11 +1040,27 @@ window_body_height (struct window *w, bool pixelwise) | |||
| 1029 | - WINDOW_MODE_LINE_HEIGHT (w) | 1040 | - WINDOW_MODE_LINE_HEIGHT (w) |
| 1030 | - WINDOW_BOTTOM_DIVIDER_WIDTH (w)); | 1041 | - WINDOW_BOTTOM_DIVIDER_WIDTH (w)); |
| 1031 | 1042 | ||
| 1043 | int denom = 1; | ||
| 1044 | if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS) | ||
| 1045 | { | ||
| 1046 | if (!NILP (Vface_remapping_alist)) | ||
| 1047 | { | ||
| 1048 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 1049 | int face_id = lookup_named_face (NULL, f, Qdefault, true); | ||
| 1050 | struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); | ||
| 1051 | if (face && face->font && face->font->height) | ||
| 1052 | denom = face->font->height; | ||
| 1053 | } | ||
| 1054 | /* For performance, use canonical chars if no face remapping. */ | ||
| 1055 | else | ||
| 1056 | pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS) | ||
| 1060 | denom = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)); | ||
| 1061 | |||
| 1032 | /* Don't return a negative value. */ | 1062 | /* Don't return a negative value. */ |
| 1033 | return max (pixelwise | 1063 | return max (height / denom, 0); |
| 1034 | ? height | ||
| 1035 | : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)), | ||
| 1036 | 0); | ||
| 1037 | } | 1064 | } |
| 1038 | 1065 | ||
| 1039 | /* Return the number of columns/pixels of W's body. Don't count columns | 1066 | /* Return the number of columns/pixels of W's body. Don't count columns |
| @@ -1042,7 +1069,7 @@ window_body_height (struct window *w, bool pixelwise) | |||
| 1042 | fringes either. Round down to nearest integer when not working | 1069 | fringes either. Round down to nearest integer when not working |
| 1043 | pixelwise. */ | 1070 | pixelwise. */ |
| 1044 | int | 1071 | int |
| 1045 | window_body_width (struct window *w, bool pixelwise) | 1072 | window_body_width (struct window *w, enum window_body_unit pixelwise) |
| 1046 | { | 1073 | { |
| 1047 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 1074 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 1048 | 1075 | ||
| @@ -1059,50 +1086,76 @@ window_body_width (struct window *w, bool pixelwise) | |||
| 1059 | ? WINDOW_FRINGES_WIDTH (w) | 1086 | ? WINDOW_FRINGES_WIDTH (w) |
| 1060 | : 0)); | 1087 | : 0)); |
| 1061 | 1088 | ||
| 1089 | int denom = 1; | ||
| 1090 | if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS) | ||
| 1091 | { | ||
| 1092 | if (!NILP (Vface_remapping_alist)) | ||
| 1093 | { | ||
| 1094 | int face_id = lookup_named_face (NULL, f, Qdefault, true); | ||
| 1095 | struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); | ||
| 1096 | if (face && face->font) | ||
| 1097 | { | ||
| 1098 | if (face->font->average_width) | ||
| 1099 | denom = face->font->average_width; | ||
| 1100 | else if (face->font->space_width) | ||
| 1101 | denom = face->font->space_width; | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | /* For performance, use canonical chars if no face remapping. */ | ||
| 1105 | else | ||
| 1106 | pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS) | ||
| 1110 | denom = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)); | ||
| 1111 | |||
| 1062 | /* Don't return a negative value. */ | 1112 | /* Don't return a negative value. */ |
| 1063 | return max (pixelwise | 1113 | return max (width / denom, 0); |
| 1064 | ? width | ||
| 1065 | : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)), | ||
| 1066 | 0); | ||
| 1067 | } | 1114 | } |
| 1068 | 1115 | ||
| 1069 | DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0, | 1116 | DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0, |
| 1070 | doc: /* Return the width of WINDOW's text area. | 1117 | doc: /* Return the width of WINDOW's text area. |
| 1071 | WINDOW must be a live window and defaults to the selected one. Optional | 1118 | WINDOW must be a live window and defaults to the selected one. The |
| 1072 | argument PIXELWISE non-nil means return the width in pixels. The return | 1119 | return value does not include any vertical dividers, fringes or |
| 1073 | value does not include any vertical dividers, fringes or marginal areas, | 1120 | marginal areas, or scroll bars. |
| 1074 | or scroll bars. | ||
| 1075 | 1121 | ||
| 1076 | If PIXELWISE is nil, return the largest integer smaller than WINDOW's | 1122 | The optional argument PIXELWISE defines the units to use for the |
| 1077 | pixel width divided by the character width of WINDOW's frame. This | 1123 | width. If nil, return the largest integer smaller than WINDOW's pixel |
| 1078 | means that if a column at the right of the text area is only partially | 1124 | width in units of the character width of WINDOW's frame. If PIXELWISE |
| 1079 | visible, that column is not counted. | 1125 | is `remap' and the default face is remapped (see |
| 1126 | `face-remapping-alist'), use the remapped face to determine the | ||
| 1127 | character width. For any other non-nil value, return the width in | ||
| 1128 | pixels. | ||
| 1080 | 1129 | ||
| 1081 | Note that the returned value includes the column reserved for the | 1130 | Note that the returned value includes the column reserved for the |
| 1082 | continuation glyph. | 1131 | continuation glyph. |
| 1083 | 1132 | ||
| 1084 | Also see `window-max-characters-per-line'. */) | 1133 | Also see `window-max-chars-per-line'. */) |
| 1085 | (Lisp_Object window, Lisp_Object pixelwise) | 1134 | (Lisp_Object window, Lisp_Object pixelwise) |
| 1086 | { | 1135 | { |
| 1087 | return make_fixnum (window_body_width (decode_live_window (window), | 1136 | return (make_fixnum |
| 1088 | !NILP (pixelwise))); | 1137 | (window_body_width (decode_live_window (window), |
| 1138 | window_body_unit_from_symbol (pixelwise)))); | ||
| 1089 | } | 1139 | } |
| 1090 | 1140 | ||
| 1091 | DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0, | 1141 | DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0, |
| 1092 | doc: /* Return the height of WINDOW's text area. | 1142 | doc: /* Return the height of WINDOW's text area. |
| 1093 | WINDOW must be a live window and defaults to the selected one. Optional | 1143 | WINDOW must be a live window and defaults to the selected one. The |
| 1094 | argument PIXELWISE non-nil means return the height of WINDOW's text area | 1144 | return value does not include the mode line or header line or any |
| 1095 | in pixels. The return value does not include the mode line or header | 1145 | horizontal divider. |
| 1096 | line or any horizontal divider. | 1146 | |
| 1097 | 1147 | The optional argument PIXELWISE defines the units to use for the | |
| 1098 | If PIXELWISE is nil, return the largest integer smaller than WINDOW's | 1148 | height. If nil, return the largest integer smaller than WINDOW's |
| 1099 | pixel height divided by the character height of WINDOW's frame. This | 1149 | pixel height in units of the character height of WINDOW's frame. If |
| 1100 | means that if a line at the bottom of the text area is only partially | 1150 | PIXELWISE is `remap' and the default face is remapped (see |
| 1101 | visible, that line is not counted. */) | 1151 | `face-remapping-alist'), use the remapped face to determine the |
| 1152 | character height. For any other non-nil value, return the height in | ||
| 1153 | pixels. */) | ||
| 1102 | (Lisp_Object window, Lisp_Object pixelwise) | 1154 | (Lisp_Object window, Lisp_Object pixelwise) |
| 1103 | { | 1155 | { |
| 1104 | return make_fixnum (window_body_height (decode_live_window (window), | 1156 | return (make_fixnum |
| 1105 | !NILP (pixelwise))); | 1157 | (window_body_height (decode_live_window (window), |
| 1158 | window_body_unit_from_symbol (pixelwise)))); | ||
| 1106 | } | 1159 | } |
| 1107 | 1160 | ||
| 1108 | DEFUN ("window-old-body-pixel-width", | 1161 | DEFUN ("window-old-body-pixel-width", |
| @@ -2124,7 +2177,8 @@ though when run from an idle timer with a delay of zero seconds. */) | |||
| 2124 | struct glyph_row *row, *end_row; | 2177 | struct glyph_row *row, *end_row; |
| 2125 | int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w); | 2178 | int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w); |
| 2126 | Lisp_Object rows = Qnil; | 2179 | Lisp_Object rows = Qnil; |
| 2127 | int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true); | 2180 | int window_width = NILP (body) |
| 2181 | ? w->pixel_width : window_body_width (w, WINDOW_BODY_IN_PIXELS); | ||
| 2128 | int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w); | 2182 | int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w); |
| 2129 | int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); | 2183 | int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); |
| 2130 | int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height); | 2184 | int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height); |
| @@ -3657,8 +3711,10 @@ window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number) | |||
| 3657 | wset_old_buffer (w, w->contents); | 3711 | wset_old_buffer (w, w->contents); |
| 3658 | w->old_pixel_width = w->pixel_width; | 3712 | w->old_pixel_width = w->pixel_width; |
| 3659 | w->old_pixel_height = w->pixel_height; | 3713 | w->old_pixel_height = w->pixel_height; |
| 3660 | w->old_body_pixel_width = window_body_width (w, true); | 3714 | w->old_body_pixel_width |
| 3661 | w->old_body_pixel_height = window_body_height (w, true); | 3715 | = window_body_width (w, WINDOW_BODY_IN_PIXELS); |
| 3716 | w->old_body_pixel_height | ||
| 3717 | = window_body_height (w, WINDOW_BODY_IN_PIXELS); | ||
| 3662 | } | 3718 | } |
| 3663 | 3719 | ||
| 3664 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | 3720 | w = NILP (w->next) ? 0 : XWINDOW (w->next); |
| @@ -3903,8 +3959,10 @@ run_window_change_functions (void) | |||
| 3903 | && (window_buffer_change | 3959 | && (window_buffer_change |
| 3904 | || w->pixel_width != w->old_pixel_width | 3960 | || w->pixel_width != w->old_pixel_width |
| 3905 | || w->pixel_height != w->old_pixel_height | 3961 | || w->pixel_height != w->old_pixel_height |
| 3906 | || window_body_width (w, true) != w->old_body_pixel_width | 3962 | || (window_body_width (w, WINDOW_BODY_IN_PIXELS) |
| 3907 | || window_body_height (w, true) != w->old_body_pixel_height)); | 3963 | != w->old_body_pixel_width) |
| 3964 | || (window_body_height (w, WINDOW_BODY_IN_PIXELS) | ||
| 3965 | != w->old_body_pixel_height))); | ||
| 3908 | 3966 | ||
| 3909 | /* The following two are needed when running the default | 3967 | /* The following two are needed when running the default |
| 3910 | values for this frame below. */ | 3968 | values for this frame below. */ |
| @@ -4768,7 +4826,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag) | |||
| 4768 | Lisp_Object mini = f->minibuffer_window; | 4826 | Lisp_Object mini = f->minibuffer_window; |
| 4769 | struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL; | 4827 | struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL; |
| 4770 | int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) | 4828 | int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) |
| 4771 | ? unit + m->pixel_height - window_body_height (m, true) | 4829 | ? (unit + m->pixel_height |
| 4830 | - window_body_height (m, WINDOW_BODY_IN_PIXELS)) | ||
| 4772 | : 0); | 4831 | : 0); |
| 4773 | 4832 | ||
| 4774 | new_pixel_size = max (horflag ? size : size - mini_height, unit); | 4833 | new_pixel_size = max (horflag ? size : size - mini_height, unit); |
| @@ -5255,7 +5314,7 @@ void | |||
| 5255 | grow_mini_window (struct window *w, int delta) | 5314 | grow_mini_window (struct window *w, int delta) |
| 5256 | { | 5315 | { |
| 5257 | struct frame *f = XFRAME (w->frame); | 5316 | struct frame *f = XFRAME (w->frame); |
| 5258 | int old_height = window_body_height (w, true); | 5317 | int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS); |
| 5259 | int min_height = FRAME_LINE_HEIGHT (f); | 5318 | int min_height = FRAME_LINE_HEIGHT (f); |
| 5260 | 5319 | ||
| 5261 | eassert (MINI_WINDOW_P (w)); | 5320 | eassert (MINI_WINDOW_P (w)); |
| @@ -5289,7 +5348,8 @@ void | |||
| 5289 | shrink_mini_window (struct window *w) | 5348 | shrink_mini_window (struct window *w) |
| 5290 | { | 5349 | { |
| 5291 | struct frame *f = XFRAME (w->frame); | 5350 | struct frame *f = XFRAME (w->frame); |
| 5292 | int delta = window_body_height (w, true) - FRAME_LINE_HEIGHT (f); | 5351 | int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS) |
| 5352 | - FRAME_LINE_HEIGHT (f)); | ||
| 5293 | 5353 | ||
| 5294 | eassert (MINI_WINDOW_P (w)); | 5354 | eassert (MINI_WINDOW_P (w)); |
| 5295 | 5355 | ||
| @@ -5636,7 +5696,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5636 | if (w->vscroll < 0 && rtop > 0) | 5696 | if (w->vscroll < 0 && rtop > 0) |
| 5637 | { | 5697 | { |
| 5638 | px = max (0, -w->vscroll - min (rtop, -dy)); | 5698 | px = max (0, -w->vscroll - min (rtop, -dy)); |
| 5639 | Fset_window_vscroll (window, make_fixnum (px), Qt); | 5699 | Fset_window_vscroll (window, make_fixnum (px), Qt, |
| 5700 | Qnil); | ||
| 5640 | return; | 5701 | return; |
| 5641 | } | 5702 | } |
| 5642 | } | 5703 | } |
| @@ -5646,7 +5707,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5646 | if (rbot > 0 && (w->vscroll < 0 || vpos == 0)) | 5707 | if (rbot > 0 && (w->vscroll < 0 || vpos == 0)) |
| 5647 | { | 5708 | { |
| 5648 | px = max (0, -w->vscroll + min (rbot, dy)); | 5709 | px = max (0, -w->vscroll + min (rbot, dy)); |
| 5649 | Fset_window_vscroll (window, make_fixnum (px), Qt); | 5710 | Fset_window_vscroll (window, make_fixnum (px), Qt, |
| 5711 | Qnil); | ||
| 5650 | return; | 5712 | return; |
| 5651 | } | 5713 | } |
| 5652 | 5714 | ||
| @@ -5655,7 +5717,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5655 | { | 5717 | { |
| 5656 | ptrdiff_t spos; | 5718 | ptrdiff_t spos; |
| 5657 | 5719 | ||
| 5658 | Fset_window_vscroll (window, make_fixnum (0), Qt); | 5720 | Fset_window_vscroll (window, make_fixnum (0), Qt, |
| 5721 | Qnil); | ||
| 5659 | /* If there are other text lines above the current row, | 5722 | /* If there are other text lines above the current row, |
| 5660 | move window start to current row. Else to next row. */ | 5723 | move window start to current row. Else to next row. */ |
| 5661 | if (rbot > 0) | 5724 | if (rbot > 0) |
| @@ -5674,7 +5737,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5674 | } | 5737 | } |
| 5675 | } | 5738 | } |
| 5676 | /* Cancel previous vscroll. */ | 5739 | /* Cancel previous vscroll. */ |
| 5677 | Fset_window_vscroll (window, make_fixnum (0), Qt); | 5740 | Fset_window_vscroll (window, make_fixnum (0), Qt, Qnil); |
| 5678 | } | 5741 | } |
| 5679 | 5742 | ||
| 5680 | itdata = bidi_shelve_cache (); | 5743 | itdata = bidi_shelve_cache (); |
| @@ -6353,9 +6416,10 @@ by this function. This happens in an interactive call. */) | |||
| 6353 | (register Lisp_Object arg, Lisp_Object set_minimum) | 6416 | (register Lisp_Object arg, Lisp_Object set_minimum) |
| 6354 | { | 6417 | { |
| 6355 | struct window *w = XWINDOW (selected_window); | 6418 | struct window *w = XWINDOW (selected_window); |
| 6356 | EMACS_INT requested_arg = (NILP (arg) | 6419 | EMACS_INT requested_arg = |
| 6357 | ? window_body_width (w, 0) - 2 | 6420 | (NILP (arg) |
| 6358 | : XFIXNUM (Fprefix_numeric_value (arg))); | 6421 | ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2 |
| 6422 | : XFIXNUM (Fprefix_numeric_value (arg))); | ||
| 6359 | Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg); | 6423 | Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg); |
| 6360 | 6424 | ||
| 6361 | if (!NILP (set_minimum)) | 6425 | if (!NILP (set_minimum)) |
| @@ -6378,9 +6442,10 @@ by this function. This happens in an interactive call. */) | |||
| 6378 | (register Lisp_Object arg, Lisp_Object set_minimum) | 6442 | (register Lisp_Object arg, Lisp_Object set_minimum) |
| 6379 | { | 6443 | { |
| 6380 | struct window *w = XWINDOW (selected_window); | 6444 | struct window *w = XWINDOW (selected_window); |
| 6381 | EMACS_INT requested_arg = (NILP (arg) | 6445 | EMACS_INT requested_arg = |
| 6382 | ? window_body_width (w, 0) - 2 | 6446 | (NILP (arg) |
| 6383 | : XFIXNUM (Fprefix_numeric_value (arg))); | 6447 | ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2 |
| 6448 | : XFIXNUM (Fprefix_numeric_value (arg))); | ||
| 6384 | Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg); | 6449 | Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg); |
| 6385 | 6450 | ||
| 6386 | if (!NILP (set_minimum)) | 6451 | if (!NILP (set_minimum)) |
| @@ -7944,7 +8009,7 @@ optional second arg PIXELS-P means value is measured in pixels. */) | |||
| 7944 | 8009 | ||
| 7945 | 8010 | ||
| 7946 | DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll, | 8011 | DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll, |
| 7947 | 2, 3, 0, | 8012 | 2, 4, 0, |
| 7948 | doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL. | 8013 | doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL. |
| 7949 | This takes effect when displaying tall lines or images. | 8014 | This takes effect when displaying tall lines or images. |
| 7950 | 8015 | ||
| @@ -7954,8 +8019,12 @@ optional third arg PIXELS-P non-nil means that VSCROLL is in pixels. | |||
| 7954 | If PIXELS-P is nil, VSCROLL may have to be rounded so that it | 8019 | If PIXELS-P is nil, VSCROLL may have to be rounded so that it |
| 7955 | corresponds to an integral number of pixels. The return value is the | 8020 | corresponds to an integral number of pixels. The return value is the |
| 7956 | result of this rounding. | 8021 | result of this rounding. |
| 7957 | If PIXELS-P is non-nil, the return value is VSCROLL. */) | 8022 | If PIXELS-P is non-nil, the return value is VSCROLL. |
| 7958 | (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p) | 8023 | |
| 8024 | PRESERVE-VSCROLL-P makes setting the start of WINDOW preserve the | ||
| 8025 | vscroll if its start is "frozen" due to a resized mini-window. */) | ||
| 8026 | (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p, | ||
| 8027 | Lisp_Object preserve_vscroll_p) | ||
| 7959 | { | 8028 | { |
| 7960 | struct window *w = decode_live_window (window); | 8029 | struct window *w = decode_live_window (window); |
| 7961 | struct frame *f = XFRAME (w->frame); | 8030 | struct frame *f = XFRAME (w->frame); |
| @@ -7980,7 +8049,12 @@ If PIXELS-P is non-nil, the return value is VSCROLL. */) | |||
| 7980 | 8049 | ||
| 7981 | /* Prevent redisplay shortcuts. */ | 8050 | /* Prevent redisplay shortcuts. */ |
| 7982 | XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true; | 8051 | XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true; |
| 8052 | |||
| 8053 | /* Mark W for redisplay. (bug#55299) */ | ||
| 8054 | wset_redisplay (w); | ||
| 7983 | } | 8055 | } |
| 8056 | |||
| 8057 | w->preserve_vscroll_p = !NILP (preserve_vscroll_p); | ||
| 7984 | } | 8058 | } |
| 7985 | 8059 | ||
| 7986 | return Fwindow_vscroll (window, pixels_p); | 8060 | return Fwindow_vscroll (window, pixels_p); |
| @@ -8109,11 +8183,11 @@ compare_window_configurations (Lisp_Object configuration1, | |||
| 8109 | return true; | 8183 | return true; |
| 8110 | } | 8184 | } |
| 8111 | 8185 | ||
| 8112 | DEFUN ("compare-window-configurations", Fcompare_window_configurations, | 8186 | DEFUN ("window-configuration-equal-p", Fwindow_configuration_equal_p, |
| 8113 | Scompare_window_configurations, 2, 2, 0, | 8187 | Swindow_configuration_equal_p, 2, 2, 0, |
| 8114 | doc: /* Compare two window configurations as regards the structure of windows. | 8188 | doc: /* Say whether two window configurations have the same window layout. |
| 8115 | This function ignores details such as the values of point | 8189 | This function ignores details such as the values of point and |
| 8116 | and scrolling positions. */) | 8190 | scrolling positions. */) |
| 8117 | (Lisp_Object x, Lisp_Object y) | 8191 | (Lisp_Object x, Lisp_Object y) |
| 8118 | { | 8192 | { |
| 8119 | if (compare_window_configurations (x, y)) | 8193 | if (compare_window_configurations (x, y)) |
| @@ -8601,7 +8675,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */); | |||
| 8601 | defsubr (&Swindow_scroll_bars); | 8675 | defsubr (&Swindow_scroll_bars); |
| 8602 | defsubr (&Swindow_vscroll); | 8676 | defsubr (&Swindow_vscroll); |
| 8603 | defsubr (&Sset_window_vscroll); | 8677 | defsubr (&Sset_window_vscroll); |
| 8604 | defsubr (&Scompare_window_configurations); | 8678 | defsubr (&Swindow_configuration_equal_p); |
| 8605 | defsubr (&Swindow_bump_use_time); | 8679 | defsubr (&Swindow_bump_use_time); |
| 8606 | defsubr (&Swindow_list); | 8680 | defsubr (&Swindow_list); |
| 8607 | defsubr (&Swindow_list_1); | 8681 | defsubr (&Swindow_list_1); |
diff --git a/src/window.h b/src/window.h index 387a3be36a9..298a80a5366 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -445,6 +445,10 @@ struct window | |||
| 445 | window. */ | 445 | window. */ |
| 446 | bool_bf suspend_auto_hscroll : 1; | 446 | bool_bf suspend_auto_hscroll : 1; |
| 447 | 447 | ||
| 448 | /* True if vscroll should be preserved while forcing the start due | ||
| 449 | to a frozen window. */ | ||
| 450 | bool_bf preserve_vscroll_p : 1; | ||
| 451 | |||
| 448 | /* Amount by which lines of this window are scrolled in | 452 | /* Amount by which lines of this window are scrolled in |
| 449 | y-direction (smooth scrolling). */ | 453 | y-direction (smooth scrolling). */ |
| 450 | int vscroll; | 454 | int vscroll; |
| @@ -1182,7 +1186,13 @@ extern bool window_wants_mode_line (struct window *); | |||
| 1182 | extern bool window_wants_header_line (struct window *); | 1186 | extern bool window_wants_header_line (struct window *); |
| 1183 | extern bool window_wants_tab_line (struct window *); | 1187 | extern bool window_wants_tab_line (struct window *); |
| 1184 | extern int window_internal_height (struct window *); | 1188 | extern int window_internal_height (struct window *); |
| 1185 | extern int window_body_width (struct window *w, bool); | 1189 | enum window_body_unit |
| 1190 | { | ||
| 1191 | WINDOW_BODY_IN_CANONICAL_CHARS, | ||
| 1192 | WINDOW_BODY_IN_PIXELS, | ||
| 1193 | WINDOW_BODY_IN_REMAPPED_CHARS | ||
| 1194 | }; | ||
| 1195 | extern int window_body_width (struct window *w, enum window_body_unit); | ||
| 1186 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; | 1196 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; |
| 1187 | extern int window_scroll_margin (struct window *, enum margin_unit); | 1197 | extern int window_scroll_margin (struct window *, enum margin_unit); |
| 1188 | extern void temp_output_buffer_show (Lisp_Object); | 1198 | extern void temp_output_buffer_show (Lisp_Object); |
diff --git a/src/xdisp.c b/src/xdisp.c index 50efa50c55b..b02375ab2d8 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -5894,7 +5894,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | |||
| 5894 | location = tem; | 5894 | location = tem; |
| 5895 | } | 5895 | } |
| 5896 | 5896 | ||
| 5897 | if (EQ (location, Qunbound)) | 5897 | if (BASE_EQ (location, Qunbound)) |
| 5898 | { | 5898 | { |
| 5899 | location = Qnil; | 5899 | location = Qnil; |
| 5900 | value = spec; | 5900 | value = spec; |
| @@ -11234,7 +11234,7 @@ argument if the size of the buffer is large or unknown. | |||
| 11234 | 11234 | ||
| 11235 | Optional argument MODE-LINES nil or omitted means do not include the | 11235 | Optional argument MODE-LINES nil or omitted means do not include the |
| 11236 | height of the mode-, tab- or header-line of WINDOW in the return value. | 11236 | height of the mode-, tab- or header-line of WINDOW in the return value. |
| 11237 | If it is the symbol `mode-line', 'tab-line' or `header-line', include | 11237 | If it is the symbol `mode-line', `tab-line' or `header-line', include |
| 11238 | only the height of that line, if present, in the return value. If t, | 11238 | only the height of that line, if present, in the return value. If t, |
| 11239 | include the height of any of these, if present, in the return value. | 11239 | include the height of any of these, if present, in the return value. |
| 11240 | 11240 | ||
| @@ -13148,7 +13148,7 @@ store_mode_line_noprop (const char *string, int field_width, int precision) | |||
| 13148 | Vicon_title_format if FRAME is iconified, otherwise it is | 13148 | Vicon_title_format if FRAME is iconified, otherwise it is |
| 13149 | frame_title_format. */ | 13149 | frame_title_format. */ |
| 13150 | 13150 | ||
| 13151 | static void | 13151 | void |
| 13152 | gui_consider_frame_title (Lisp_Object frame) | 13152 | gui_consider_frame_title (Lisp_Object frame) |
| 13153 | { | 13153 | { |
| 13154 | struct frame *f = XFRAME (frame); | 13154 | struct frame *f = XFRAME (frame); |
| @@ -13200,8 +13200,9 @@ gui_consider_frame_title (Lisp_Object frame) | |||
| 13200 | mode_line_noprop_buf; then display the title. */ | 13200 | mode_line_noprop_buf; then display the title. */ |
| 13201 | record_unwind_protect (unwind_format_mode_line, | 13201 | record_unwind_protect (unwind_format_mode_line, |
| 13202 | format_mode_line_unwind_data | 13202 | format_mode_line_unwind_data |
| 13203 | (NULL, current_buffer, Qnil, false)); | 13203 | (f, current_buffer, selected_window, false)); |
| 13204 | 13204 | ||
| 13205 | Fselect_window (f->selected_window, Qt); | ||
| 13205 | set_buffer_internal_1 | 13206 | set_buffer_internal_1 |
| 13206 | (XBUFFER (XWINDOW (f->selected_window)->contents)); | 13207 | (XBUFFER (XWINDOW (f->selected_window)->contents)); |
| 13207 | fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; | 13208 | fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; |
| @@ -17006,6 +17007,7 @@ mark_window_display_accurate_1 (struct window *w, bool accurate_p) | |||
| 17006 | 17007 | ||
| 17007 | w->window_end_valid = true; | 17008 | w->window_end_valid = true; |
| 17008 | w->update_mode_line = false; | 17009 | w->update_mode_line = false; |
| 17010 | w->preserve_vscroll_p = false; | ||
| 17009 | } | 17011 | } |
| 17010 | 17012 | ||
| 17011 | w->redisplay = !accurate_p; | 17013 | w->redisplay = !accurate_p; |
| @@ -17850,7 +17852,7 @@ cursor_row_fully_visible_p (struct window *w, bool force_p, | |||
| 17850 | buffer_local_value (Qmake_cursor_line_fully_visible, w->contents); | 17852 | buffer_local_value (Qmake_cursor_line_fully_visible, w->contents); |
| 17851 | 17853 | ||
| 17852 | /* If no local binding, use the global value. */ | 17854 | /* If no local binding, use the global value. */ |
| 17853 | if (EQ (mclfv_p, Qunbound)) | 17855 | if (BASE_EQ (mclfv_p, Qunbound)) |
| 17854 | mclfv_p = Vmake_cursor_line_fully_visible; | 17856 | mclfv_p = Vmake_cursor_line_fully_visible; |
| 17855 | /* Follow mode sets the variable to a Lisp function in buffers that | 17857 | /* Follow mode sets the variable to a Lisp function in buffers that |
| 17856 | are under Follow mode. */ | 17858 | are under Follow mode. */ |
| @@ -19168,7 +19170,14 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19168 | int new_vpos = -1; | 19170 | int new_vpos = -1; |
| 19169 | 19171 | ||
| 19170 | w->force_start = false; | 19172 | w->force_start = false; |
| 19171 | w->vscroll = 0; | 19173 | |
| 19174 | /* The vscroll should be preserved in this case, since | ||
| 19175 | `pixel-scroll-precision-mode' must continue working normally | ||
| 19176 | when a mini-window is resized. (bug#55312) */ | ||
| 19177 | if (!w->preserve_vscroll_p || !window_frozen_p (w)) | ||
| 19178 | w->vscroll = 0; | ||
| 19179 | |||
| 19180 | w->preserve_vscroll_p = false; | ||
| 19172 | w->window_end_valid = false; | 19181 | w->window_end_valid = false; |
| 19173 | 19182 | ||
| 19174 | /* Forget any recorded base line for line number display. */ | 19183 | /* Forget any recorded base line for line number display. */ |
| @@ -22463,6 +22472,13 @@ compute_line_metrics (struct it *it) | |||
| 22463 | } | 22472 | } |
| 22464 | 22473 | ||
| 22465 | 22474 | ||
| 22475 | static void | ||
| 22476 | clear_position (struct it *it) | ||
| 22477 | { | ||
| 22478 | it->position.charpos = 0; | ||
| 22479 | it->position.bytepos = 0; | ||
| 22480 | } | ||
| 22481 | |||
| 22466 | /* Append one space to the glyph row of iterator IT if doing a | 22482 | /* Append one space to the glyph row of iterator IT if doing a |
| 22467 | window-based redisplay. The space has the same face as | 22483 | window-based redisplay. The space has the same face as |
| 22468 | IT->face_id. Value is true if a space was added. | 22484 | IT->face_id. Value is true if a space was added. |
| @@ -22498,7 +22514,7 @@ append_space_for_newline (struct it *it, bool default_face_p) | |||
| 22498 | struct face *face; | 22514 | struct face *face; |
| 22499 | 22515 | ||
| 22500 | it->what = IT_CHARACTER; | 22516 | it->what = IT_CHARACTER; |
| 22501 | memset (&it->position, 0, sizeof it->position); | 22517 | clear_position (it); |
| 22502 | it->object = Qnil; | 22518 | it->object = Qnil; |
| 22503 | it->len = 1; | 22519 | it->len = 1; |
| 22504 | 22520 | ||
| @@ -22827,7 +22843,7 @@ extend_face_to_end_of_line (struct it *it) | |||
| 22827 | const int stretch_width = | 22843 | const int stretch_width = |
| 22828 | indicator_column - it->current_x - char_width; | 22844 | indicator_column - it->current_x - char_width; |
| 22829 | 22845 | ||
| 22830 | memset (&it->position, 0, sizeof it->position); | 22846 | clear_position (it); |
| 22831 | 22847 | ||
| 22832 | /* Only generate a stretch glyph if there is distance | 22848 | /* Only generate a stretch glyph if there is distance |
| 22833 | between current_x and the indicator position. */ | 22849 | between current_x and the indicator position. */ |
| @@ -22861,7 +22877,7 @@ extend_face_to_end_of_line (struct it *it) | |||
| 22861 | 22877 | ||
| 22862 | if (stretch_width > 0) | 22878 | if (stretch_width > 0) |
| 22863 | { | 22879 | { |
| 22864 | memset (&it->position, 0, sizeof it->position); | 22880 | clear_position (it); |
| 22865 | append_stretch_glyph (it, Qnil, stretch_width, | 22881 | append_stretch_glyph (it, Qnil, stretch_width, |
| 22866 | it->ascent + it->descent, | 22882 | it->ascent + it->descent, |
| 22867 | stretch_ascent); | 22883 | stretch_ascent); |
| @@ -22911,7 +22927,7 @@ extend_face_to_end_of_line (struct it *it) | |||
| 22911 | (((it->ascent + it->descent) | 22927 | (((it->ascent + it->descent) |
| 22912 | * FONT_BASE (font)) / FONT_HEIGHT (font)); | 22928 | * FONT_BASE (font)) / FONT_HEIGHT (font)); |
| 22913 | saved_pos = it->position; | 22929 | saved_pos = it->position; |
| 22914 | memset (&it->position, 0, sizeof it->position); | 22930 | clear_position (it); |
| 22915 | saved_avoid_cursor = it->avoid_cursor_p; | 22931 | saved_avoid_cursor = it->avoid_cursor_p; |
| 22916 | it->avoid_cursor_p = true; | 22932 | it->avoid_cursor_p = true; |
| 22917 | saved_face_id = it->face_id; | 22933 | saved_face_id = it->face_id; |
| @@ -22949,7 +22965,7 @@ extend_face_to_end_of_line (struct it *it) | |||
| 22949 | enum display_element_type saved_what = it->what; | 22965 | enum display_element_type saved_what = it->what; |
| 22950 | 22966 | ||
| 22951 | it->what = IT_CHARACTER; | 22967 | it->what = IT_CHARACTER; |
| 22952 | memset (&it->position, 0, sizeof it->position); | 22968 | clear_position (it); |
| 22953 | it->object = Qnil; | 22969 | it->object = Qnil; |
| 22954 | it->c = it->char_to_display = ' '; | 22970 | it->c = it->char_to_display = ' '; |
| 22955 | it->len = 1; | 22971 | it->len = 1; |
| @@ -28357,7 +28373,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 28357 | } | 28373 | } |
| 28358 | 28374 | ||
| 28359 | prop = buffer_local_value (prop, it->w->contents); | 28375 | prop = buffer_local_value (prop, it->w->contents); |
| 28360 | if (EQ (prop, Qunbound)) | 28376 | if (BASE_EQ (prop, Qunbound)) |
| 28361 | prop = Qnil; | 28377 | prop = Qnil; |
| 28362 | } | 28378 | } |
| 28363 | 28379 | ||
| @@ -28420,13 +28436,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 28420 | } | 28436 | } |
| 28421 | 28437 | ||
| 28422 | car = buffer_local_value (car, it->w->contents); | 28438 | car = buffer_local_value (car, it->w->contents); |
| 28423 | if (EQ (car, Qunbound)) | 28439 | if (BASE_EQ (car, Qunbound)) |
| 28424 | car = Qnil; | 28440 | car = Qnil; |
| 28425 | } | 28441 | } |
| 28426 | 28442 | ||
| 28427 | /* '(NUM)': absolute number of pixels. */ | 28443 | /* '(NUM)': absolute number of pixels. */ |
| 28428 | if (NUMBERP (car)) | 28444 | if (NUMBERP (car)) |
| 28429 | { | 28445 | { |
| 28430 | double fact; | 28446 | double fact; |
| 28431 | int offset = | 28447 | int offset = |
| 28432 | width_p && align_to && *align_to < 0 ? it->lnum_pixel_width : 0; | 28448 | width_p && align_to && *align_to < 0 ? it->lnum_pixel_width : 0; |
| @@ -32015,14 +32031,16 @@ gui_insert_glyphs (struct window *w, struct glyph_row *updated_row, | |||
| 32015 | 32031 | ||
| 32016 | void | 32032 | void |
| 32017 | gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row, | 32033 | gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row, |
| 32018 | enum glyph_row_area updated_area, int to_x) | 32034 | enum glyph_row_area updated_area, int to_x) |
| 32019 | { | 32035 | { |
| 32020 | struct frame *f; | 32036 | struct frame *f; |
| 32021 | int max_x, min_y, max_y; | 32037 | int max_x, min_y, max_y; |
| 32022 | int from_x, from_y, to_y; | 32038 | int from_x, from_y, to_y; |
| 32039 | struct face *face; | ||
| 32023 | 32040 | ||
| 32024 | eassert (updated_row); | 32041 | eassert (updated_row); |
| 32025 | f = XFRAME (w->frame); | 32042 | f = XFRAME (w->frame); |
| 32043 | face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID); | ||
| 32026 | 32044 | ||
| 32027 | if (updated_row->full_width_p) | 32045 | if (updated_row->full_width_p) |
| 32028 | max_x = (WINDOW_PIXEL_WIDTH (w) | 32046 | max_x = (WINDOW_PIXEL_WIDTH (w) |
| @@ -32074,6 +32092,9 @@ gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row, | |||
| 32074 | block_input (); | 32092 | block_input (); |
| 32075 | FRAME_RIF (f)->clear_frame_area (f, from_x, from_y, | 32093 | FRAME_RIF (f)->clear_frame_area (f, from_x, from_y, |
| 32076 | to_x - from_x, to_y - from_y); | 32094 | to_x - from_x, to_y - from_y); |
| 32095 | |||
| 32096 | if (face && !updated_row->stipple_p) | ||
| 32097 | updated_row->stipple_p = face->stipple; | ||
| 32077 | unblock_input (); | 32098 | unblock_input (); |
| 32078 | } | 32099 | } |
| 32079 | } | 32100 | } |
| @@ -32638,7 +32659,7 @@ display_and_set_cursor (struct window *w, bool on, | |||
| 32638 | { | 32659 | { |
| 32639 | struct frame *f = XFRAME (w->frame); | 32660 | struct frame *f = XFRAME (w->frame); |
| 32640 | int new_cursor_type; | 32661 | int new_cursor_type; |
| 32641 | int new_cursor_width; | 32662 | int new_cursor_width UNINIT; |
| 32642 | bool active_cursor; | 32663 | bool active_cursor; |
| 32643 | struct glyph_row *glyph_row; | 32664 | struct glyph_row *glyph_row; |
| 32644 | struct glyph *glyph; | 32665 | struct glyph *glyph; |
| @@ -36229,7 +36250,7 @@ they return to their normal size when the minibuffer is closed, or the | |||
| 36229 | echo area becomes empty. | 36250 | echo area becomes empty. |
| 36230 | 36251 | ||
| 36231 | This variable does not affect resizing of the minibuffer window of | 36252 | This variable does not affect resizing of the minibuffer window of |
| 36232 | minibuffer-only frames. These are handled by 'resize-mini-frames' | 36253 | minibuffer-only frames. These are handled by `resize-mini-frames' |
| 36233 | only. */); | 36254 | only. */); |
| 36234 | /* Contrary to the doc string, we initialize this to nil, so that | 36255 | /* Contrary to the doc string, we initialize this to nil, so that |
| 36235 | loading loadup.el won't try to resize windows before loading | 36256 | loading loadup.el won't try to resize windows before loading |
| @@ -36453,7 +36474,7 @@ see biditest.el in the test suite. */); | |||
| 36453 | doc: /* Non-nil means inhibit the Bidirectional Parentheses Algorithm. | 36474 | doc: /* Non-nil means inhibit the Bidirectional Parentheses Algorithm. |
| 36454 | Disabling the BPA makes redisplay faster, but might produce incorrect | 36475 | Disabling the BPA makes redisplay faster, but might produce incorrect |
| 36455 | display reordering of bidirectional text with embedded parentheses and | 36476 | display reordering of bidirectional text with embedded parentheses and |
| 36456 | other bracket characters whose 'paired-bracket' Unicode property is | 36477 | other bracket characters whose `paired-bracket' Unicode property is |
| 36457 | non-nil, see `get-char-code-property'. */); | 36478 | non-nil, see `get-char-code-property'. */); |
| 36458 | bidi_inhibit_bpa = false; | 36479 | bidi_inhibit_bpa = false; |
| 36459 | 36480 | ||
diff --git a/src/xfaces.c b/src/xfaces.c index 05e0df4b7dc..7395ce157ec 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -6871,7 +6871,6 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources, | |||
| 6871 | Initialization | 6871 | Initialization |
| 6872 | ***********************************************************************/ | 6872 | ***********************************************************************/ |
| 6873 | 6873 | ||
| 6874 | #ifdef HAVE_PDUMPER | ||
| 6875 | /* All the faces defined during loadup are recorded in | 6874 | /* All the faces defined during loadup are recorded in |
| 6876 | face-new-frame-defaults. We need to set next_lface_id to the next | 6875 | face-new-frame-defaults. We need to set next_lface_id to the next |
| 6877 | face ID number, so that any new faces defined in this session will | 6876 | face ID number, so that any new faces defined in this session will |
| @@ -6881,26 +6880,35 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources, | |||
| 6881 | void | 6880 | void |
| 6882 | init_xfaces (void) | 6881 | init_xfaces (void) |
| 6883 | { | 6882 | { |
| 6884 | int nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults)); | 6883 | #ifdef HAVE_PDUMPER |
| 6885 | if (nfaces > 0) | 6884 | int nfaces; |
| 6886 | { | ||
| 6887 | /* Allocate the lface_id_to_name[] array. */ | ||
| 6888 | lface_id_to_name_size = next_lface_id = nfaces; | ||
| 6889 | lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name); | ||
| 6890 | 6885 | ||
| 6891 | /* Store the faces. */ | 6886 | if (dumped_with_pdumper_p ()) |
| 6892 | struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults); | 6887 | { |
| 6893 | for (ptrdiff_t idx = 0; idx < nfaces; ++idx) | 6888 | nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults)); |
| 6889 | if (nfaces > 0) | ||
| 6894 | { | 6890 | { |
| 6895 | Lisp_Object lface = HASH_KEY (table, idx); | 6891 | /* Allocate the lface_id_to_name[] array. */ |
| 6896 | Lisp_Object face_id = CAR (HASH_VALUE (table, idx)); | 6892 | lface_id_to_name_size = next_lface_id = nfaces; |
| 6897 | if (FIXNATP (face_id)) { | 6893 | lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name); |
| 6898 | int id = XFIXNAT (face_id); | 6894 | |
| 6899 | eassert (id >= 0); | 6895 | /* Store the faces. */ |
| 6900 | lface_id_to_name[id] = lface; | 6896 | struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults); |
| 6901 | } | 6897 | for (ptrdiff_t idx = 0; idx < nfaces; ++idx) |
| 6898 | { | ||
| 6899 | Lisp_Object lface = HASH_KEY (table, idx); | ||
| 6900 | Lisp_Object face_id = CAR (HASH_VALUE (table, idx)); | ||
| 6901 | if (FIXNATP (face_id)) | ||
| 6902 | { | ||
| 6903 | int id = XFIXNAT (face_id); | ||
| 6904 | eassert (id >= 0); | ||
| 6905 | lface_id_to_name[id] = lface; | ||
| 6906 | } | ||
| 6907 | } | ||
| 6902 | } | 6908 | } |
| 6903 | } | 6909 | } |
| 6910 | #endif | ||
| 6911 | |||
| 6904 | face_attr_sym[0] = Qface; | 6912 | face_attr_sym[0] = Qface; |
| 6905 | face_attr_sym[LFACE_FOUNDRY_INDEX] = QCfoundry; | 6913 | face_attr_sym[LFACE_FOUNDRY_INDEX] = QCfoundry; |
| 6906 | face_attr_sym[LFACE_SWIDTH_INDEX] = QCwidth; | 6914 | face_attr_sym[LFACE_SWIDTH_INDEX] = QCwidth; |
| @@ -6921,7 +6929,6 @@ init_xfaces (void) | |||
| 6921 | face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground; | 6929 | face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground; |
| 6922 | face_attr_sym[LFACE_EXTEND_INDEX] = QCextend; | 6930 | face_attr_sym[LFACE_EXTEND_INDEX] = QCextend; |
| 6923 | } | 6931 | } |
| 6924 | #endif | ||
| 6925 | 6932 | ||
| 6926 | void | 6933 | void |
| 6927 | syms_of_xfaces (void) | 6934 | syms_of_xfaces (void) |
diff --git a/src/xfns.c b/src/xfns.c index dc8f02780ce..05023524a7e 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -973,7 +973,7 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu | |||
| 973 | if (p) | 973 | if (p) |
| 974 | { | 974 | { |
| 975 | window = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); | 975 | window = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); |
| 976 | gdk_x11_window_set_frame_sync_enabled (window, false); | 976 | gdk_x11_window_set_frame_sync_enabled (window, FALSE); |
| 977 | } | 977 | } |
| 978 | #endif | 978 | #endif |
| 979 | unblock_input (); | 979 | unblock_input (); |
| @@ -1261,25 +1261,27 @@ struct mouse_cursor_types { | |||
| 1261 | }; | 1261 | }; |
| 1262 | 1262 | ||
| 1263 | /* This array must stay in sync with enum mouse_cursor above! */ | 1263 | /* This array must stay in sync with enum mouse_cursor above! */ |
| 1264 | static const struct mouse_cursor_types mouse_cursor_types[] = { | 1264 | static const struct mouse_cursor_types mouse_cursor_types[] = |
| 1265 | { "text", &Vx_pointer_shape, XC_xterm }, | 1265 | { |
| 1266 | { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr }, | 1266 | { "text", &Vx_pointer_shape, XC_xterm }, |
| 1267 | { "hourglass", &Vx_hourglass_pointer_shape, XC_watch }, | 1267 | { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr }, |
| 1268 | { "modeline", &Vx_mode_pointer_shape, XC_xterm }, | 1268 | { "hourglass", &Vx_hourglass_pointer_shape, XC_watch }, |
| 1269 | { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 }, | 1269 | { "modeline", &Vx_mode_pointer_shape, XC_xterm }, |
| 1270 | { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow }, | 1270 | { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 }, |
| 1271 | { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow }, | 1271 | { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow }, |
| 1272 | { NULL, &Vx_window_left_edge_shape, XC_left_side }, | 1272 | { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow }, |
| 1273 | { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner }, | 1273 | { NULL, &Vx_window_left_edge_shape, XC_left_side }, |
| 1274 | { NULL, &Vx_window_top_edge_shape, XC_top_side }, | 1274 | { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner }, |
| 1275 | { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner }, | 1275 | { NULL, &Vx_window_top_edge_shape, XC_top_side }, |
| 1276 | { NULL, &Vx_window_right_edge_shape, XC_right_side }, | 1276 | { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner }, |
| 1277 | { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner }, | 1277 | { NULL, &Vx_window_right_edge_shape, XC_right_side }, |
| 1278 | { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side }, | 1278 | { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner }, |
| 1279 | { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner }, | 1279 | { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side }, |
| 1280 | }; | 1280 | { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner }, |
| 1281 | }; | ||
| 1281 | 1282 | ||
| 1282 | struct mouse_cursor_data { | 1283 | struct mouse_cursor_data |
| 1284 | { | ||
| 1283 | /* Last index for which XCreateFontCursor has been called, and thus | 1285 | /* Last index for which XCreateFontCursor has been called, and thus |
| 1284 | the last index for which x_request_serial[] is valid. */ | 1286 | the last index for which x_request_serial[] is valid. */ |
| 1285 | int last_cursor_create_request; | 1287 | int last_cursor_create_request; |
| @@ -1360,8 +1362,10 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 1360 | { | 1362 | { |
| 1361 | cursor_data.x_request_serial[i] = XNextRequest (dpy); | 1363 | cursor_data.x_request_serial[i] = XNextRequest (dpy); |
| 1362 | cursor_data.last_cursor_create_request = i; | 1364 | cursor_data.last_cursor_create_request = i; |
| 1363 | cursor_data.cursor[i] = XCreateFontCursor (dpy, | 1365 | |
| 1364 | cursor_data.cursor_num[i]); | 1366 | cursor_data.cursor[i] |
| 1367 | = x_create_font_cursor (FRAME_DISPLAY_INFO (f), | ||
| 1368 | cursor_data.cursor_num[i]); | ||
| 1365 | } | 1369 | } |
| 1366 | 1370 | ||
| 1367 | /* Now sync up and process all received errors from cursor | 1371 | /* Now sync up and process all received errors from cursor |
| @@ -2372,6 +2376,63 @@ x_set_scroll_bar_default_height (struct frame *f) | |||
| 2372 | #endif | 2376 | #endif |
| 2373 | } | 2377 | } |
| 2374 | 2378 | ||
| 2379 | static void | ||
| 2380 | x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | ||
| 2381 | { | ||
| 2382 | double alpha = 1.0; | ||
| 2383 | double newval[2]; | ||
| 2384 | int i; | ||
| 2385 | Lisp_Object item; | ||
| 2386 | bool alpha_identical_p; | ||
| 2387 | |||
| 2388 | alpha_identical_p = true; | ||
| 2389 | |||
| 2390 | for (i = 0; i < 2; i++) | ||
| 2391 | { | ||
| 2392 | newval[i] = 1.0; | ||
| 2393 | if (CONSP (arg)) | ||
| 2394 | { | ||
| 2395 | item = CAR (arg); | ||
| 2396 | arg = CDR (arg); | ||
| 2397 | |||
| 2398 | alpha_identical_p = false; | ||
| 2399 | } | ||
| 2400 | else | ||
| 2401 | item = arg; | ||
| 2402 | |||
| 2403 | if (NILP (item)) | ||
| 2404 | alpha = - 1.0; | ||
| 2405 | else if (FLOATP (item)) | ||
| 2406 | { | ||
| 2407 | alpha = XFLOAT_DATA (item); | ||
| 2408 | if (! (0 <= alpha && alpha <= 1.0)) | ||
| 2409 | args_out_of_range (make_float (0.0), make_float (1.0)); | ||
| 2410 | } | ||
| 2411 | else if (FIXNUMP (item)) | ||
| 2412 | { | ||
| 2413 | EMACS_INT ialpha = XFIXNUM (item); | ||
| 2414 | if (! (0 <= ialpha && ialpha <= 100)) | ||
| 2415 | args_out_of_range (make_fixnum (0), make_fixnum (100)); | ||
| 2416 | alpha = ialpha / 100.0; | ||
| 2417 | } | ||
| 2418 | else | ||
| 2419 | wrong_type_argument (Qnumberp, item); | ||
| 2420 | newval[i] = alpha; | ||
| 2421 | } | ||
| 2422 | |||
| 2423 | for (i = 0; i < 2; i++) | ||
| 2424 | f->alpha[i] = newval[i]; | ||
| 2425 | |||
| 2426 | FRAME_X_OUTPUT (f)->alpha_identical_p = alpha_identical_p; | ||
| 2427 | |||
| 2428 | if (FRAME_TERMINAL (f)->set_frame_alpha_hook) | ||
| 2429 | { | ||
| 2430 | block_input (); | ||
| 2431 | FRAME_TERMINAL (f)->set_frame_alpha_hook (f); | ||
| 2432 | unblock_input (); | ||
| 2433 | } | ||
| 2434 | } | ||
| 2435 | |||
| 2375 | 2436 | ||
| 2376 | /* Record in frame F the specified or default value according to ALIST | 2437 | /* Record in frame F the specified or default value according to ALIST |
| 2377 | of the parameter named PROP (a Lisp symbol). If no value is | 2438 | of the parameter named PROP (a Lisp symbol). If no value is |
| @@ -2389,7 +2450,7 @@ x_default_scroll_bar_color_parameter (struct frame *f, | |||
| 2389 | 2450 | ||
| 2390 | tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass, | 2451 | tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass, |
| 2391 | RES_TYPE_STRING); | 2452 | RES_TYPE_STRING); |
| 2392 | if (EQ (tem, Qunbound)) | 2453 | if (BASE_EQ (tem, Qunbound)) |
| 2393 | { | 2454 | { |
| 2394 | #ifdef USE_TOOLKIT_SCROLL_BARS | 2455 | #ifdef USE_TOOLKIT_SCROLL_BARS |
| 2395 | 2456 | ||
| @@ -4163,12 +4224,12 @@ x_icon_verify (struct frame *f, Lisp_Object parms) | |||
| 4163 | icons in an icon window. */ | 4224 | icons in an icon window. */ |
| 4164 | icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); | 4225 | icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); |
| 4165 | icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); | 4226 | icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); |
| 4166 | if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) | 4227 | if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound)) |
| 4167 | { | 4228 | { |
| 4168 | CHECK_FIXNUM (icon_x); | 4229 | CHECK_FIXNUM (icon_x); |
| 4169 | CHECK_FIXNUM (icon_y); | 4230 | CHECK_FIXNUM (icon_y); |
| 4170 | } | 4231 | } |
| 4171 | else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) | 4232 | else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound)) |
| 4172 | error ("Both left and top icon corners of icon must be specified"); | 4233 | error ("Both left and top icon corners of icon must be specified"); |
| 4173 | } | 4234 | } |
| 4174 | 4235 | ||
| @@ -4187,8 +4248,8 @@ x_icon (struct frame *f, Lisp_Object parms) | |||
| 4187 | = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); | 4248 | = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); |
| 4188 | int icon_xval, icon_yval; | 4249 | int icon_xval, icon_yval; |
| 4189 | 4250 | ||
| 4190 | bool xgiven = !EQ (icon_x, Qunbound); | 4251 | bool xgiven = !BASE_EQ (icon_x, Qunbound); |
| 4191 | bool ygiven = !EQ (icon_y, Qunbound); | 4252 | bool ygiven = !BASE_EQ (icon_y, Qunbound); |
| 4192 | if (xgiven != ygiven) | 4253 | if (xgiven != ygiven) |
| 4193 | error ("Both left and top icon corners of icon must be specified"); | 4254 | error ("Both left and top icon corners of icon must be specified"); |
| 4194 | if (xgiven) | 4255 | if (xgiven) |
| @@ -4373,7 +4434,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) | |||
| 4373 | Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, | 4434 | Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, |
| 4374 | RES_TYPE_STRING); | 4435 | RES_TYPE_STRING); |
| 4375 | Lisp_Object font = Qnil; | 4436 | Lisp_Object font = Qnil; |
| 4376 | if (EQ (font_param, Qunbound)) | 4437 | if (BASE_EQ (font_param, Qunbound)) |
| 4377 | font_param = Qnil; | 4438 | font_param = Qnil; |
| 4378 | 4439 | ||
| 4379 | if (NILP (font_param)) | 4440 | if (NILP (font_param)) |
| @@ -4490,6 +4551,9 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4490 | struct x_display_info *dpyinfo = NULL; | 4551 | struct x_display_info *dpyinfo = NULL; |
| 4491 | Lisp_Object parent, parent_frame; | 4552 | Lisp_Object parent, parent_frame; |
| 4492 | struct kboard *kb; | 4553 | struct kboard *kb; |
| 4554 | #ifdef HAVE_GTK3 | ||
| 4555 | GdkWindow *gwin; | ||
| 4556 | #endif | ||
| 4493 | 4557 | ||
| 4494 | parms = Fcopy_alist (parms); | 4558 | parms = Fcopy_alist (parms); |
| 4495 | 4559 | ||
| @@ -4499,10 +4563,10 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4499 | 4563 | ||
| 4500 | display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, | 4564 | display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, |
| 4501 | RES_TYPE_NUMBER); | 4565 | RES_TYPE_NUMBER); |
| 4502 | if (EQ (display, Qunbound)) | 4566 | if (BASE_EQ (display, Qunbound)) |
| 4503 | display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, | 4567 | display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, |
| 4504 | RES_TYPE_STRING); | 4568 | RES_TYPE_STRING); |
| 4505 | if (EQ (display, Qunbound)) | 4569 | if (BASE_EQ (display, Qunbound)) |
| 4506 | display = Qnil; | 4570 | display = Qnil; |
| 4507 | dpyinfo = check_x_display_info (display); | 4571 | dpyinfo = check_x_display_info (display); |
| 4508 | kb = dpyinfo->terminal->kboard; | 4572 | kb = dpyinfo->terminal->kboard; |
| @@ -4513,7 +4577,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4513 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 4577 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 4514 | RES_TYPE_STRING); | 4578 | RES_TYPE_STRING); |
| 4515 | if (!STRINGP (name) | 4579 | if (!STRINGP (name) |
| 4516 | && ! EQ (name, Qunbound) | 4580 | && ! BASE_EQ (name, Qunbound) |
| 4517 | && ! NILP (name)) | 4581 | && ! NILP (name)) |
| 4518 | error ("Invalid frame name--not a string or nil"); | 4582 | error ("Invalid frame name--not a string or nil"); |
| 4519 | 4583 | ||
| @@ -4523,7 +4587,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4523 | /* See if parent window is specified. */ | 4587 | /* See if parent window is specified. */ |
| 4524 | parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, | 4588 | parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, |
| 4525 | RES_TYPE_NUMBER); | 4589 | RES_TYPE_NUMBER); |
| 4526 | if (EQ (parent, Qunbound)) | 4590 | if (BASE_EQ (parent, Qunbound)) |
| 4527 | parent = Qnil; | 4591 | parent = Qnil; |
| 4528 | if (! NILP (parent)) | 4592 | if (! NILP (parent)) |
| 4529 | CHECK_FIXNUM (parent); | 4593 | CHECK_FIXNUM (parent); |
| @@ -4552,7 +4616,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4552 | RES_TYPE_SYMBOL); | 4616 | RES_TYPE_SYMBOL); |
| 4553 | /* Accept parent-frame iff parent-id was not specified. */ | 4617 | /* Accept parent-frame iff parent-id was not specified. */ |
| 4554 | if (!NILP (parent) | 4618 | if (!NILP (parent) |
| 4555 | || EQ (parent_frame, Qunbound) | 4619 | || BASE_EQ (parent_frame, Qunbound) |
| 4556 | || NILP (parent_frame) | 4620 | || NILP (parent_frame) |
| 4557 | || !FRAMEP (parent_frame) | 4621 | || !FRAMEP (parent_frame) |
| 4558 | || !FRAME_LIVE_P (XFRAME (parent_frame)) | 4622 | || !FRAME_LIVE_P (XFRAME (parent_frame)) |
| @@ -4568,7 +4632,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4568 | NULL, | 4632 | NULL, |
| 4569 | NULL, | 4633 | NULL, |
| 4570 | RES_TYPE_BOOLEAN))) | 4634 | RES_TYPE_BOOLEAN))) |
| 4571 | && !(EQ (tem, Qunbound))) | 4635 | && !(BASE_EQ (tem, Qunbound))) |
| 4572 | undecorated = true; | 4636 | undecorated = true; |
| 4573 | 4637 | ||
| 4574 | FRAME_UNDECORATED (f) = undecorated; | 4638 | FRAME_UNDECORATED (f) = undecorated; |
| @@ -4580,7 +4644,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4580 | NULL, | 4644 | NULL, |
| 4581 | NULL, | 4645 | NULL, |
| 4582 | RES_TYPE_BOOLEAN))) | 4646 | RES_TYPE_BOOLEAN))) |
| 4583 | && !(EQ (tem, Qunbound))) | 4647 | && !(BASE_EQ (tem, Qunbound))) |
| 4584 | override_redirect = true; | 4648 | override_redirect = true; |
| 4585 | 4649 | ||
| 4586 | FRAME_OVERRIDE_REDIRECT (f) = override_redirect; | 4650 | FRAME_OVERRIDE_REDIRECT (f) = override_redirect; |
| @@ -4661,7 +4725,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4661 | 4725 | ||
| 4662 | /* Set the name; the functions to which we pass f expect the name to | 4726 | /* Set the name; the functions to which we pass f expect the name to |
| 4663 | be set. */ | 4727 | be set. */ |
| 4664 | if (EQ (name, Qunbound) || NILP (name)) | 4728 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 4665 | { | 4729 | { |
| 4666 | fset_name (f, build_string (dpyinfo->x_id_name)); | 4730 | fset_name (f, build_string (dpyinfo->x_id_name)); |
| 4667 | f->explicit_name = false; | 4731 | f->explicit_name = false; |
| @@ -4724,7 +4788,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4724 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 4788 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 4725 | "internalBorder", "internalBorder", | 4789 | "internalBorder", "internalBorder", |
| 4726 | RES_TYPE_NUMBER); | 4790 | RES_TYPE_NUMBER); |
| 4727 | if (! EQ (value, Qunbound)) | 4791 | if (! BASE_EQ (value, Qunbound)) |
| 4728 | parms = Fcons (Fcons (Qinternal_border_width, value), | 4792 | parms = Fcons (Fcons (Qinternal_border_width, value), |
| 4729 | parms); | 4793 | parms); |
| 4730 | } | 4794 | } |
| @@ -4746,7 +4810,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4746 | value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, | 4810 | value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, |
| 4747 | "childFrameBorder", "childFrameBorder", | 4811 | "childFrameBorder", "childFrameBorder", |
| 4748 | RES_TYPE_NUMBER); | 4812 | RES_TYPE_NUMBER); |
| 4749 | if (! EQ (value, Qunbound)) | 4813 | if (! BASE_EQ (value, Qunbound)) |
| 4750 | parms = Fcons (Fcons (Qchild_frame_border_width, value), | 4814 | parms = Fcons (Fcons (Qchild_frame_border_width, value), |
| 4751 | parms); | 4815 | parms); |
| 4752 | } | 4816 | } |
| @@ -4917,6 +4981,10 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4917 | gtk_container_set_resize_mode | 4981 | gtk_container_set_resize_mode |
| 4918 | (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE); | 4982 | (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE); |
| 4919 | #endif | 4983 | #endif |
| 4984 | #ifdef HAVE_GTK3 | ||
| 4985 | gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); | ||
| 4986 | gdk_x11_window_set_frame_sync_enabled (gwin, FALSE); | ||
| 4987 | #endif | ||
| 4920 | unblock_input (); | 4988 | unblock_input (); |
| 4921 | } | 4989 | } |
| 4922 | 4990 | ||
| @@ -4984,7 +5052,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4984 | } | 5052 | } |
| 4985 | else | 5053 | else |
| 4986 | { | 5054 | { |
| 4987 | if (EQ (visibility, Qunbound)) | 5055 | if (BASE_EQ (visibility, Qunbound)) |
| 4988 | visibility = Qt; | 5056 | visibility = Qt; |
| 4989 | 5057 | ||
| 4990 | if (!NILP (visibility)) | 5058 | if (!NILP (visibility)) |
| @@ -4998,7 +5066,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4998 | from `x-create-frame-with-faces' (see above comment). */ | 5066 | from `x-create-frame-with-faces' (see above comment). */ |
| 4999 | f->was_invisible | 5067 | f->was_invisible |
| 5000 | = (f->was_invisible | 5068 | = (f->was_invisible |
| 5001 | && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); | 5069 | && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound))); |
| 5002 | 5070 | ||
| 5003 | store_frame_param (f, Qvisibility, visibility); | 5071 | store_frame_param (f, Qvisibility, visibility); |
| 5004 | } | 5072 | } |
| @@ -5366,6 +5434,9 @@ for each physical monitor, use `display-monitor-attributes-list'. */) | |||
| 5366 | { | 5434 | { |
| 5367 | struct x_display_info *dpyinfo = check_x_display_info (terminal); | 5435 | struct x_display_info *dpyinfo = check_x_display_info (terminal); |
| 5368 | 5436 | ||
| 5437 | if (dpyinfo->screen_mm_height) | ||
| 5438 | return make_fixnum (dpyinfo->screen_mm_height); | ||
| 5439 | |||
| 5369 | return make_fixnum (HeightMMOfScreen (dpyinfo->screen)); | 5440 | return make_fixnum (HeightMMOfScreen (dpyinfo->screen)); |
| 5370 | } | 5441 | } |
| 5371 | 5442 | ||
| @@ -5383,6 +5454,9 @@ for each physical monitor, use `display-monitor-attributes-list'. */) | |||
| 5383 | { | 5454 | { |
| 5384 | struct x_display_info *dpyinfo = check_x_display_info (terminal); | 5455 | struct x_display_info *dpyinfo = check_x_display_info (terminal); |
| 5385 | 5456 | ||
| 5457 | if (dpyinfo->screen_mm_width) | ||
| 5458 | return make_fixnum (dpyinfo->screen_mm_width); | ||
| 5459 | |||
| 5386 | return make_fixnum (WidthMMOfScreen (dpyinfo->screen)); | 5460 | return make_fixnum (WidthMMOfScreen (dpyinfo->screen)); |
| 5387 | } | 5461 | } |
| 5388 | 5462 | ||
| @@ -6526,17 +6600,61 @@ menu bar or tool bar of FRAME. */) | |||
| 6526 | * WINDOW to FRAMES and return FRAMES. | 6600 | * WINDOW to FRAMES and return FRAMES. |
| 6527 | */ | 6601 | */ |
| 6528 | static Lisp_Object | 6602 | static Lisp_Object |
| 6529 | x_frame_list_z_order (Display* dpy, Window window) | 6603 | x_frame_list_z_order (struct x_display_info *dpyinfo, Window window) |
| 6530 | { | 6604 | { |
| 6605 | Display *dpy; | ||
| 6531 | Window root, parent, *children; | 6606 | Window root, parent, *children; |
| 6532 | unsigned int nchildren; | 6607 | unsigned int nchildren; |
| 6533 | int i; | 6608 | unsigned long i; |
| 6534 | Lisp_Object frames = Qnil; | 6609 | Lisp_Object frames, val; |
| 6610 | Atom type; | ||
| 6611 | Window *toplevels; | ||
| 6612 | int format, rc; | ||
| 6613 | unsigned long nitems, bytes_after; | ||
| 6614 | unsigned char *data; | ||
| 6615 | struct frame *f; | ||
| 6616 | |||
| 6617 | dpy = dpyinfo->display; | ||
| 6618 | data = NULL; | ||
| 6619 | frames = Qnil; | ||
| 6620 | |||
| 6621 | if (window == dpyinfo->root_window | ||
| 6622 | && x_wm_supports_1 (dpyinfo, | ||
| 6623 | dpyinfo->Xatom_net_client_list_stacking)) | ||
| 6624 | { | ||
| 6625 | rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, | ||
| 6626 | dpyinfo->Xatom_net_client_list_stacking, | ||
| 6627 | 0, LONG_MAX, False, XA_WINDOW, &type, | ||
| 6628 | &format, &nitems, &bytes_after, &data); | ||
| 6629 | |||
| 6630 | if (rc != Success) | ||
| 6631 | return Qnil; | ||
| 6632 | |||
| 6633 | if (format != 32 || type != XA_WINDOW) | ||
| 6634 | { | ||
| 6635 | XFree (data); | ||
| 6636 | return Qnil; | ||
| 6637 | } | ||
| 6638 | |||
| 6639 | toplevels = (Window *) data; | ||
| 6640 | |||
| 6641 | for (i = 0; i < nitems; ++i) | ||
| 6642 | { | ||
| 6643 | f = x_top_window_to_frame (dpyinfo, toplevels[i]); | ||
| 6644 | |||
| 6645 | if (f) | ||
| 6646 | { | ||
| 6647 | XSETFRAME (val, f); | ||
| 6648 | frames = Fcons (val, frames); | ||
| 6649 | } | ||
| 6650 | } | ||
| 6651 | |||
| 6652 | XFree (data); | ||
| 6653 | return frames; | ||
| 6654 | } | ||
| 6535 | 6655 | ||
| 6536 | block_input (); | ||
| 6537 | if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren)) | 6656 | if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren)) |
| 6538 | { | 6657 | { |
| 6539 | unblock_input (); | ||
| 6540 | for (i = 0; i < nchildren; i++) | 6658 | for (i = 0; i < nchildren; i++) |
| 6541 | { | 6659 | { |
| 6542 | Lisp_Object frame, tail; | 6660 | Lisp_Object frame, tail; |
| @@ -6554,10 +6672,9 @@ x_frame_list_z_order (Display* dpy, Window window) | |||
| 6554 | } | 6672 | } |
| 6555 | } | 6673 | } |
| 6556 | 6674 | ||
| 6557 | if (children) XFree ((char *)children); | 6675 | if (children) |
| 6676 | XFree (children); | ||
| 6558 | } | 6677 | } |
| 6559 | else | ||
| 6560 | unblock_input (); | ||
| 6561 | 6678 | ||
| 6562 | return frames; | 6679 | return frames; |
| 6563 | } | 6680 | } |
| @@ -6578,7 +6695,6 @@ Frames are listed from topmost (first) to bottommost (last). */) | |||
| 6578 | (Lisp_Object terminal) | 6695 | (Lisp_Object terminal) |
| 6579 | { | 6696 | { |
| 6580 | struct x_display_info *dpyinfo = check_x_display_info (terminal); | 6697 | struct x_display_info *dpyinfo = check_x_display_info (terminal); |
| 6581 | Display *dpy = dpyinfo->display; | ||
| 6582 | Window window; | 6698 | Window window; |
| 6583 | 6699 | ||
| 6584 | if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) | 6700 | if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) |
| @@ -6586,7 +6702,7 @@ Frames are listed from topmost (first) to bottommost (last). */) | |||
| 6586 | else | 6702 | else |
| 6587 | window = dpyinfo->root_window; | 6703 | window = dpyinfo->root_window; |
| 6588 | 6704 | ||
| 6589 | return x_frame_list_z_order (dpy, window); | 6705 | return x_frame_list_z_order (dpyinfo, window); |
| 6590 | } | 6706 | } |
| 6591 | 6707 | ||
| 6592 | /** | 6708 | /** |
| @@ -6715,7 +6831,7 @@ The coordinates X and Y are interpreted in pixels relative to a position | |||
| 6715 | return Qnil; | 6831 | return Qnil; |
| 6716 | } | 6832 | } |
| 6717 | 6833 | ||
| 6718 | DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 5, 0, | 6834 | DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 6, 0, |
| 6719 | doc: /* Begin dragging contents on FRAME, with targets TARGETS. | 6835 | doc: /* Begin dragging contents on FRAME, with targets TARGETS. |
| 6720 | TARGETS is a list of strings, which defines the X selection targets | 6836 | TARGETS is a list of strings, which defines the X selection targets |
| 6721 | that will be available to the drop target. Block until the mouse | 6837 | that will be available to the drop target. Block until the mouse |
| @@ -6724,8 +6840,9 @@ buttons are released, then return the action chosen by the target, or | |||
| 6724 | starts when the mouse is pressed on FRAME, and the contents of the | 6840 | starts when the mouse is pressed on FRAME, and the contents of the |
| 6725 | selection `XdndSelection' will be sent to the X window underneath the | 6841 | selection `XdndSelection' will be sent to the X window underneath the |
| 6726 | mouse pointer (the drop target) when the mouse button is released. | 6842 | mouse pointer (the drop target) when the mouse button is released. |
| 6727 | ACTION is a symbol which tells the target what the source will do, and | 6843 | |
| 6728 | can be one of the following: | 6844 | ACTION is a symbol which tells the target what it should do, and can |
| 6845 | be one of the following: | ||
| 6729 | 6846 | ||
| 6730 | - `XdndActionCopy', which means to copy the contents from the drag | 6847 | - `XdndActionCopy', which means to copy the contents from the drag |
| 6731 | source (FRAME) to the drop target. | 6848 | source (FRAME) to the drop target. |
| @@ -6737,6 +6854,10 @@ can be one of the following: | |||
| 6737 | `XdndActionPrivate' is also a valid return value, and means that the | 6854 | `XdndActionPrivate' is also a valid return value, and means that the |
| 6738 | drop target chose to perform an unspecified or unknown action. | 6855 | drop target chose to perform an unspecified or unknown action. |
| 6739 | 6856 | ||
| 6857 | The source is also expected to cooperate with the target to perform | ||
| 6858 | the action chosen by the target. For example, callers should delete | ||
| 6859 | the buffer text that was dragged if `XdndActionMove' is returned. | ||
| 6860 | |||
| 6740 | There are also some other valid values of ACTION that depend on | 6861 | There are also some other valid values of ACTION that depend on |
| 6741 | details of both the drop target's implementation details and that of | 6862 | details of both the drop target's implementation details and that of |
| 6742 | Emacs. For that reason, they are not mentioned here. Consult | 6863 | Emacs. For that reason, they are not mentioned here. Consult |
| @@ -6759,20 +6880,29 @@ instead. | |||
| 6759 | 6880 | ||
| 6760 | If ALLOW-CURRENT-FRAME is not specified or nil, then the drop target | 6881 | If ALLOW-CURRENT-FRAME is not specified or nil, then the drop target |
| 6761 | is allowed to be FRAME. Otherwise, no action will be taken if the | 6882 | is allowed to be FRAME. Otherwise, no action will be taken if the |
| 6762 | mouse buttons are released on top of FRAME. */) | 6883 | mouse buttons are released on top of FRAME. |
| 6884 | |||
| 6885 | If FOLLOW-TOOLTIP is non-nil, any tooltip currently being displayed | ||
| 6886 | will be moved to follow the mouse pointer while the drag is in | ||
| 6887 | progress. Note that this does not work with system tooltips (tooltips | ||
| 6888 | created when `use-system-tooltips' is non-nil). | ||
| 6889 | |||
| 6890 | This function will sometimes return immediately if no mouse buttons | ||
| 6891 | are currently held down. It should only be called when it is known | ||
| 6892 | that mouse buttons are being held down, such as immediately after a | ||
| 6893 | `down-mouse-1' (or similar) event. */) | ||
| 6763 | (Lisp_Object targets, Lisp_Object action, Lisp_Object frame, | 6894 | (Lisp_Object targets, Lisp_Object action, Lisp_Object frame, |
| 6764 | Lisp_Object return_frame, Lisp_Object allow_current_frame) | 6895 | Lisp_Object return_frame, Lisp_Object allow_current_frame, |
| 6896 | Lisp_Object follow_tooltip) | ||
| 6765 | { | 6897 | { |
| 6766 | struct frame *f = decode_window_system_frame (frame); | 6898 | struct frame *f = decode_window_system_frame (frame); |
| 6767 | int ntargets = 0, nnames = 0; | 6899 | int ntargets = 0, nnames = 0; |
| 6768 | ptrdiff_t len; | ||
| 6769 | char *target_names[2048]; | 6900 | char *target_names[2048]; |
| 6770 | Atom *target_atoms; | 6901 | Atom *target_atoms; |
| 6771 | Lisp_Object lval, original, tem, t1, t2; | 6902 | Lisp_Object lval, original, tem, t1, t2; |
| 6772 | Atom xaction; | 6903 | Atom xaction; |
| 6773 | Atom action_list[2048]; | 6904 | Atom action_list[2048]; |
| 6774 | char *name_list[2048]; | 6905 | char *name_list[2048]; |
| 6775 | char *scratch; | ||
| 6776 | 6906 | ||
| 6777 | USE_SAFE_ALLOCA; | 6907 | USE_SAFE_ALLOCA; |
| 6778 | 6908 | ||
| @@ -6786,10 +6916,8 @@ mouse buttons are released on top of FRAME. */) | |||
| 6786 | 6916 | ||
| 6787 | if (ntargets < 2048) | 6917 | if (ntargets < 2048) |
| 6788 | { | 6918 | { |
| 6789 | scratch = SSDATA (XCAR (targets)); | 6919 | SAFE_ALLOCA_STRING (target_names[ntargets], |
| 6790 | len = strlen (scratch); | 6920 | XCAR (targets)); |
| 6791 | target_names[ntargets] = SAFE_ALLOCA (len + 1); | ||
| 6792 | strncpy (target_names[ntargets], scratch, len + 1); | ||
| 6793 | ntargets++; | 6921 | ntargets++; |
| 6794 | } | 6922 | } |
| 6795 | else | 6923 | else |
| @@ -6839,10 +6967,8 @@ mouse buttons are released on top of FRAME. */) | |||
| 6839 | else | 6967 | else |
| 6840 | signal_error ("Invalid drag-and-drop action", tem); | 6968 | signal_error ("Invalid drag-and-drop action", tem); |
| 6841 | 6969 | ||
| 6842 | scratch = SSDATA (ENCODE_UTF_8 (t2)); | 6970 | SAFE_ALLOCA_STRING (name_list[nnames], |
| 6843 | len = strlen (scratch); | 6971 | ENCODE_SYSTEM (t2)); |
| 6844 | name_list[nnames] = SAFE_ALLOCA (len + 1); | ||
| 6845 | strncpy (name_list[nnames], scratch, len + 1); | ||
| 6846 | 6972 | ||
| 6847 | nnames++; | 6973 | nnames++; |
| 6848 | } | 6974 | } |
| @@ -6854,18 +6980,22 @@ mouse buttons are released on top of FRAME. */) | |||
| 6854 | else | 6980 | else |
| 6855 | signal_error ("Invalid drag-and-drop action", action); | 6981 | signal_error ("Invalid drag-and-drop action", action); |
| 6856 | 6982 | ||
| 6857 | target_atoms = xmalloc (ntargets * sizeof *target_atoms); | 6983 | target_atoms = SAFE_ALLOCA (ntargets * sizeof *target_atoms); |
| 6858 | 6984 | ||
| 6859 | block_input (); | 6985 | /* Catch errors since interning lots of targets can potentially |
| 6986 | generate a BadAlloc error. */ | ||
| 6987 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 6860 | XInternAtoms (FRAME_X_DISPLAY (f), target_names, | 6988 | XInternAtoms (FRAME_X_DISPLAY (f), target_names, |
| 6861 | ntargets, False, target_atoms); | 6989 | ntargets, False, target_atoms); |
| 6862 | unblock_input (); | 6990 | x_check_errors (FRAME_X_DISPLAY (f), |
| 6991 | "Failed to intern target atoms: %s"); | ||
| 6992 | x_uncatch_errors_after_check (); | ||
| 6863 | 6993 | ||
| 6864 | x_set_dnd_targets (target_atoms, ntargets); | ||
| 6865 | lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, | 6994 | lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, |
| 6866 | xaction, return_frame, action_list, | 6995 | xaction, return_frame, action_list, |
| 6867 | (const char **) &name_list, nnames, | 6996 | (const char **) &name_list, nnames, |
| 6868 | !NILP (allow_current_frame)); | 6997 | !NILP (allow_current_frame), target_atoms, |
| 6998 | ntargets, original, !NILP (follow_tooltip)); | ||
| 6869 | 6999 | ||
| 6870 | SAFE_FREE (); | 7000 | SAFE_FREE (); |
| 6871 | return lval; | 7001 | return lval; |
| @@ -7184,19 +7314,28 @@ converted to an atom and the value of the atom is used. If an element | |||
| 7184 | is a cons, it is converted to a 32 bit number where the car is the 16 | 7314 | is a cons, it is converted to a 32 bit number where the car is the 16 |
| 7185 | top bits and the cdr is the lower 16 bits. | 7315 | top bits and the cdr is the lower 16 bits. |
| 7186 | 7316 | ||
| 7187 | FRAME nil or omitted means use the selected frame. | 7317 | FRAME nil or omitted means use the selected frame. If TYPE is given |
| 7188 | If TYPE is given and non-nil, it is the name of the type of VALUE. | 7318 | and non-nil, it is the name of the type of VALUE. If TYPE is not |
| 7189 | If TYPE is not given or nil, the type is STRING. | 7319 | given or nil, the type is STRING. |
| 7190 | FORMAT gives the size in bits of each element if VALUE is a list. | 7320 | |
| 7191 | It must be one of 8, 16 or 32. | 7321 | FORMAT gives the size in bits of each element if VALUE is a list. It |
| 7192 | If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8. | 7322 | must be one of 8, 16 or 32. |
| 7193 | If OUTER-P is non-nil, the property is changed for the outer X window of | 7323 | |
| 7194 | FRAME. Default is to change on the edit X window. | 7324 | If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to |
| 7195 | If WINDOW-ID is non-nil, change the property of that window instead | 7325 | 8. If OUTER-P is non-nil, the property is changed for the outer X |
| 7196 | of FRAME's X window; the number 0 denotes the root window. This argument | 7326 | window of FRAME. Default is to change on the edit X window. |
| 7197 | is separate from FRAME because window IDs are not unique across X | 7327 | |
| 7198 | displays or screens on the same display, so FRAME provides context | 7328 | If WINDOW-ID is non-nil, change the property of that window instead of |
| 7199 | for the window ID. */) | 7329 | FRAME's X window; the number 0 denotes the root window. This argument |
| 7330 | is separate from FRAME because window IDs are not unique across X | ||
| 7331 | displays or screens on the same display, so FRAME provides context for | ||
| 7332 | the window ID. | ||
| 7333 | |||
| 7334 | If VALUE is a string and FORMAT is 32, then the format of VALUE is | ||
| 7335 | system-specific. VALUE must contain unsigned integer data in native | ||
| 7336 | endian-ness in multiples of the size of the C type 'long': the low 32 | ||
| 7337 | bits of each such number are used as the value of each element of the | ||
| 7338 | property. */) | ||
| 7200 | (Lisp_Object prop, Lisp_Object value, Lisp_Object frame, | 7339 | (Lisp_Object prop, Lisp_Object value, Lisp_Object frame, |
| 7201 | Lisp_Object type, Lisp_Object format, Lisp_Object outer_p, | 7340 | Lisp_Object type, Lisp_Object format, Lisp_Object outer_p, |
| 7202 | Lisp_Object window_id) | 7341 | Lisp_Object window_id) |
| @@ -7209,6 +7348,8 @@ If WINDOW-ID is non-nil, change the property of that window instead | |||
| 7209 | int nelements; | 7348 | int nelements; |
| 7210 | Window target_window; | 7349 | Window target_window; |
| 7211 | #ifdef USE_XCB | 7350 | #ifdef USE_XCB |
| 7351 | bool intern_prop; | ||
| 7352 | bool intern_target; | ||
| 7212 | xcb_intern_atom_cookie_t prop_atom_cookie; | 7353 | xcb_intern_atom_cookie_t prop_atom_cookie; |
| 7213 | xcb_intern_atom_cookie_t target_type_cookie; | 7354 | xcb_intern_atom_cookie_t target_type_cookie; |
| 7214 | xcb_intern_atom_reply_t *reply; | 7355 | xcb_intern_atom_reply_t *reply; |
| @@ -7279,41 +7420,62 @@ If WINDOW-ID is non-nil, change the property of that window instead | |||
| 7279 | 7420 | ||
| 7280 | block_input (); | 7421 | block_input (); |
| 7281 | #ifndef USE_XCB | 7422 | #ifndef USE_XCB |
| 7282 | prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); | 7423 | prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7424 | SSDATA (prop), false); | ||
| 7283 | if (! NILP (type)) | 7425 | if (! NILP (type)) |
| 7284 | { | 7426 | { |
| 7285 | CHECK_STRING (type); | 7427 | CHECK_STRING (type); |
| 7286 | target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); | 7428 | target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7429 | SSDATA (type), false); | ||
| 7287 | } | 7430 | } |
| 7288 | #else | 7431 | #else |
| 7289 | rc = true; | 7432 | rc = true; |
| 7290 | prop_atom_cookie | 7433 | intern_target = true; |
| 7291 | = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, | 7434 | intern_prop = true; |
| 7292 | 0, SBYTES (prop), SSDATA (prop)); | 7435 | |
| 7436 | prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), | ||
| 7437 | SSDATA (prop), true); | ||
| 7438 | |||
| 7439 | if (prop_atom != None) | ||
| 7440 | intern_prop = false; | ||
| 7441 | else | ||
| 7442 | prop_atom_cookie | ||
| 7443 | = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, | ||
| 7444 | 0, SBYTES (prop), SSDATA (prop)); | ||
| 7293 | 7445 | ||
| 7294 | if (!NILP (type)) | 7446 | if (!NILP (type)) |
| 7295 | { | 7447 | { |
| 7296 | CHECK_STRING (type); | 7448 | CHECK_STRING (type); |
| 7297 | target_type_cookie | ||
| 7298 | = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, | ||
| 7299 | 0, SBYTES (type), SSDATA (type)); | ||
| 7300 | } | ||
| 7301 | 7449 | ||
| 7302 | reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, | 7450 | target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7303 | prop_atom_cookie, &generic_error); | 7451 | SSDATA (type), true); |
| 7304 | 7452 | ||
| 7305 | if (reply) | 7453 | if (target_type) |
| 7306 | { | 7454 | intern_target = false; |
| 7307 | prop_atom = (Atom) reply->atom; | 7455 | else |
| 7308 | free (reply); | 7456 | target_type_cookie |
| 7457 | = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, | ||
| 7458 | 0, SBYTES (type), SSDATA (type)); | ||
| 7309 | } | 7459 | } |
| 7310 | else | 7460 | |
| 7461 | if (intern_prop) | ||
| 7311 | { | 7462 | { |
| 7312 | free (generic_error); | 7463 | reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, |
| 7313 | rc = false; | 7464 | prop_atom_cookie, &generic_error); |
| 7465 | |||
| 7466 | if (reply) | ||
| 7467 | { | ||
| 7468 | prop_atom = (Atom) reply->atom; | ||
| 7469 | free (reply); | ||
| 7470 | } | ||
| 7471 | else | ||
| 7472 | { | ||
| 7473 | free (generic_error); | ||
| 7474 | rc = false; | ||
| 7475 | } | ||
| 7314 | } | 7476 | } |
| 7315 | 7477 | ||
| 7316 | if (!NILP (type)) | 7478 | if (!NILP (type) && intern_target) |
| 7317 | { | 7479 | { |
| 7318 | reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, | 7480 | reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, |
| 7319 | target_type_cookie, &generic_error); | 7481 | target_type_cookie, &generic_error); |
| @@ -7334,16 +7496,17 @@ If WINDOW-ID is non-nil, change the property of that window instead | |||
| 7334 | error ("Failed to intern type or property atom"); | 7496 | error ("Failed to intern type or property atom"); |
| 7335 | #endif | 7497 | #endif |
| 7336 | 7498 | ||
| 7499 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 7337 | XChangeProperty (FRAME_X_DISPLAY (f), target_window, | 7500 | XChangeProperty (FRAME_X_DISPLAY (f), target_window, |
| 7338 | prop_atom, target_type, element_format, PropModeReplace, | 7501 | prop_atom, target_type, element_format, PropModeReplace, |
| 7339 | data, nelements); | 7502 | data, nelements); |
| 7340 | 7503 | ||
| 7341 | if (CONSP (value)) xfree (data); | 7504 | if (CONSP (value)) xfree (data); |
| 7505 | x_check_errors (FRAME_X_DISPLAY (f), | ||
| 7506 | "Couldn't change window property: %s"); | ||
| 7507 | x_uncatch_errors_after_check (); | ||
| 7342 | 7508 | ||
| 7343 | /* Make sure the property is set when we return. */ | ||
| 7344 | XFlush (FRAME_X_DISPLAY (f)); | ||
| 7345 | unblock_input (); | 7509 | unblock_input (); |
| 7346 | |||
| 7347 | return value; | 7510 | return value; |
| 7348 | } | 7511 | } |
| 7349 | 7512 | ||
| @@ -7375,13 +7538,16 @@ Value is PROP. */) | |||
| 7375 | } | 7538 | } |
| 7376 | 7539 | ||
| 7377 | block_input (); | 7540 | block_input (); |
| 7378 | prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); | 7541 | prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7542 | SSDATA (prop), false); | ||
| 7543 | |||
| 7544 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 7379 | XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom); | 7545 | XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom); |
| 7546 | x_check_errors (FRAME_X_DISPLAY (f), | ||
| 7547 | "Couldn't delete window property: %s"); | ||
| 7548 | x_uncatch_errors_after_check (); | ||
| 7380 | 7549 | ||
| 7381 | /* Make sure the property is removed when we return. */ | ||
| 7382 | XFlush (FRAME_X_DISPLAY (f)); | ||
| 7383 | unblock_input (); | 7550 | unblock_input (); |
| 7384 | |||
| 7385 | return prop; | 7551 | return prop; |
| 7386 | } | 7552 | } |
| 7387 | 7553 | ||
| @@ -7501,15 +7667,19 @@ if PROP has no value of TYPE (always a string in the MS Windows case). */) | |||
| 7501 | } | 7667 | } |
| 7502 | 7668 | ||
| 7503 | block_input (); | 7669 | block_input (); |
| 7670 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 7671 | |||
| 7504 | if (STRINGP (type)) | 7672 | if (STRINGP (type)) |
| 7505 | { | 7673 | { |
| 7506 | if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) | 7674 | if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) |
| 7507 | target_type = AnyPropertyType; | 7675 | target_type = AnyPropertyType; |
| 7508 | else | 7676 | else |
| 7509 | target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); | 7677 | target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7678 | SSDATA (type), false); | ||
| 7510 | } | 7679 | } |
| 7511 | 7680 | ||
| 7512 | prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); | 7681 | prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), |
| 7682 | SSDATA (prop), false); | ||
| 7513 | prop_value = x_window_property_intern (f, | 7683 | prop_value = x_window_property_intern (f, |
| 7514 | target_window, | 7684 | target_window, |
| 7515 | prop_atom, | 7685 | prop_atom, |
| @@ -7531,6 +7701,9 @@ if PROP has no value of TYPE (always a string in the MS Windows case). */) | |||
| 7531 | &found); | 7701 | &found); |
| 7532 | } | 7702 | } |
| 7533 | 7703 | ||
| 7704 | x_check_errors (FRAME_X_DISPLAY (f), | ||
| 7705 | "Can't retrieve window property: %s"); | ||
| 7706 | x_uncatch_errors_after_check (); | ||
| 7534 | 7707 | ||
| 7535 | unblock_input (); | 7708 | unblock_input (); |
| 7536 | return prop_value; | 7709 | return prop_value; |
| @@ -7576,7 +7749,9 @@ Otherwise, the return value is a vector with the following fields: | |||
| 7576 | 7749 | ||
| 7577 | block_input (); | 7750 | block_input (); |
| 7578 | 7751 | ||
| 7579 | prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); | 7752 | x_catch_errors (FRAME_X_DISPLAY (f)); |
| 7753 | prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), | ||
| 7754 | SSDATA (prop), false); | ||
| 7580 | rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, | 7755 | rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, |
| 7581 | prop_atom, 0, 0, False, AnyPropertyType, | 7756 | prop_atom, 0, 0, False, AnyPropertyType, |
| 7582 | &actual_type, &actual_format, &actual_size, | 7757 | &actual_type, &actual_format, &actual_size, |
| @@ -7606,6 +7781,10 @@ Otherwise, the return value is a vector with the following fields: | |||
| 7606 | make_fixnum (bytes_remaining / (actual_format >> 3))); | 7781 | make_fixnum (bytes_remaining / (actual_format >> 3))); |
| 7607 | } | 7782 | } |
| 7608 | 7783 | ||
| 7784 | x_check_errors (FRAME_X_DISPLAY (f), | ||
| 7785 | "Can't retrieve window property: %s"); | ||
| 7786 | x_uncatch_errors_after_check (); | ||
| 7787 | |||
| 7609 | unblock_input (); | 7788 | unblock_input (); |
| 7610 | return prop_attr; | 7789 | return prop_attr; |
| 7611 | } | 7790 | } |
| @@ -7618,12 +7797,15 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, | |||
| 7618 | Lisp_Object, int, int, int *, int *); | 7797 | Lisp_Object, int, int, int *, int *); |
| 7619 | 7798 | ||
| 7620 | /* The frame of the currently visible tooltip, or nil if none. */ | 7799 | /* The frame of the currently visible tooltip, or nil if none. */ |
| 7621 | static Lisp_Object tip_frame; | 7800 | Lisp_Object tip_frame; |
| 7622 | 7801 | ||
| 7623 | /* The window-system window corresponding to the frame of the | 7802 | /* The window-system window corresponding to the frame of the |
| 7624 | currently visible tooltip. */ | 7803 | currently visible tooltip. */ |
| 7625 | Window tip_window; | 7804 | Window tip_window; |
| 7626 | 7805 | ||
| 7806 | /* The X and Y deltas of the last call to `x-show-tip'. */ | ||
| 7807 | Lisp_Object tip_dx, tip_dy; | ||
| 7808 | |||
| 7627 | /* A timer that hides or deletes the currently visible tooltip when it | 7809 | /* A timer that hides or deletes the currently visible tooltip when it |
| 7628 | fires. */ | 7810 | fires. */ |
| 7629 | static Lisp_Object tip_timer; | 7811 | static Lisp_Object tip_timer; |
| @@ -7679,7 +7861,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) | |||
| 7679 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", | 7861 | name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", |
| 7680 | RES_TYPE_STRING); | 7862 | RES_TYPE_STRING); |
| 7681 | if (!STRINGP (name) | 7863 | if (!STRINGP (name) |
| 7682 | && !EQ (name, Qunbound) | 7864 | && !BASE_EQ (name, Qunbound) |
| 7683 | && !NILP (name)) | 7865 | && !NILP (name)) |
| 7684 | error ("Invalid frame name--not a string or nil"); | 7866 | error ("Invalid frame name--not a string or nil"); |
| 7685 | 7867 | ||
| @@ -7746,7 +7928,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) | |||
| 7746 | 7928 | ||
| 7747 | /* Set the name; the functions to which we pass f expect the name to | 7929 | /* Set the name; the functions to which we pass f expect the name to |
| 7748 | be set. */ | 7930 | be set. */ |
| 7749 | if (EQ (name, Qunbound) || NILP (name)) | 7931 | if (BASE_EQ (name, Qunbound) || NILP (name)) |
| 7750 | { | 7932 | { |
| 7751 | fset_name (f, build_string (dpyinfo->x_id_name)); | 7933 | fset_name (f, build_string (dpyinfo->x_id_name)); |
| 7752 | f->explicit_name = false; | 7934 | f->explicit_name = false; |
| @@ -7802,7 +7984,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) | |||
| 7802 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, | 7984 | value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, |
| 7803 | "internalBorder", "internalBorder", | 7985 | "internalBorder", "internalBorder", |
| 7804 | RES_TYPE_NUMBER); | 7986 | RES_TYPE_NUMBER); |
| 7805 | if (! EQ (value, Qunbound)) | 7987 | if (! BASE_EQ (value, Qunbound)) |
| 7806 | parms = Fcons (Fcons (Qinternal_border_width, value), | 7988 | parms = Fcons (Fcons (Qinternal_border_width, value), |
| 7807 | parms); | 7989 | parms); |
| 7808 | } | 7990 | } |
| @@ -8029,9 +8211,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) | |||
| 8029 | the display in *ROOT_X, and *ROOT_Y. */ | 8211 | the display in *ROOT_X, and *ROOT_Y. */ |
| 8030 | 8212 | ||
| 8031 | static void | 8213 | static void |
| 8032 | compute_tip_xy (struct frame *f, | 8214 | compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, |
| 8033 | Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, | 8215 | Lisp_Object dy, int width, int height, int *root_x, |
| 8034 | int width, int height, int *root_x, int *root_y) | 8216 | int *root_y) |
| 8035 | { | 8217 | { |
| 8036 | Lisp_Object left, top, right, bottom; | 8218 | Lisp_Object left, top, right, bottom; |
| 8037 | int win_x, win_y; | 8219 | int win_x, win_y; |
| @@ -8057,7 +8239,7 @@ compute_tip_xy (struct frame *f, | |||
| 8057 | &root, &child, root_x, root_y, &win_x, &win_y, &pmask); | 8239 | &root, &child, root_x, root_y, &win_x, &win_y, &pmask); |
| 8058 | unblock_input (); | 8240 | unblock_input (); |
| 8059 | 8241 | ||
| 8060 | XSETFRAME(frame, f); | 8242 | XSETFRAME (frame, f); |
| 8061 | attributes = Fx_display_monitor_attributes_list (frame); | 8243 | attributes = Fx_display_monitor_attributes_list (frame); |
| 8062 | 8244 | ||
| 8063 | /* Try to determine the monitor where the mouse pointer is and | 8245 | /* Try to determine the monitor where the mouse pointer is and |
| @@ -8072,11 +8254,13 @@ compute_tip_xy (struct frame *f, | |||
| 8072 | min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); | 8254 | min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); |
| 8073 | max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); | 8255 | max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); |
| 8074 | max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); | 8256 | max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); |
| 8257 | |||
| 8075 | if (min_x <= *root_x && *root_x < max_x | 8258 | if (min_x <= *root_x && *root_x < max_x |
| 8076 | && min_y <= *root_y && *root_y < max_y) | 8259 | && min_y <= *root_y && *root_y < max_y) |
| 8077 | { | 8260 | { |
| 8078 | break; | 8261 | break; |
| 8079 | } | 8262 | } |
| 8263 | |||
| 8080 | max_y = -1; | 8264 | max_y = -1; |
| 8081 | } | 8265 | } |
| 8082 | 8266 | ||
| @@ -8086,7 +8270,7 @@ compute_tip_xy (struct frame *f, | |||
| 8086 | 8270 | ||
| 8087 | /* It was not possible to determine the monitor's geometry, so we | 8271 | /* It was not possible to determine the monitor's geometry, so we |
| 8088 | assign some sane defaults here: */ | 8272 | assign some sane defaults here: */ |
| 8089 | if ( max_y < 0 ) | 8273 | if (max_y < 0) |
| 8090 | { | 8274 | { |
| 8091 | min_x = 0; | 8275 | min_x = 0; |
| 8092 | min_y = 0; | 8276 | min_y = 0; |
| @@ -8335,6 +8519,9 @@ Text larger than the specified size is clipped. */) | |||
| 8335 | else | 8519 | else |
| 8336 | CHECK_FIXNUM (dy); | 8520 | CHECK_FIXNUM (dy); |
| 8337 | 8521 | ||
| 8522 | tip_dx = dx; | ||
| 8523 | tip_dy = dy; | ||
| 8524 | |||
| 8338 | #ifdef USE_GTK | 8525 | #ifdef USE_GTK |
| 8339 | if (use_system_tooltips) | 8526 | if (use_system_tooltips) |
| 8340 | { | 8527 | { |
| @@ -8360,7 +8547,7 @@ Text larger than the specified size is clipped. */) | |||
| 8360 | if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) | 8547 | if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) |
| 8361 | { | 8548 | { |
| 8362 | if (FRAME_VISIBLE_P (XFRAME (tip_frame)) | 8549 | if (FRAME_VISIBLE_P (XFRAME (tip_frame)) |
| 8363 | && EQ (frame, tip_last_frame) | 8550 | && BASE_EQ (frame, tip_last_frame) |
| 8364 | && !NILP (Fequal_including_properties (tip_last_string, string)) | 8551 | && !NILP (Fequal_including_properties (tip_last_string, string)) |
| 8365 | && !NILP (Fequal (tip_last_parms, parms))) | 8552 | && !NILP (Fequal (tip_last_parms, parms))) |
| 8366 | { | 8553 | { |
| @@ -8381,7 +8568,7 @@ Text larger than the specified size is clipped. */) | |||
| 8381 | 8568 | ||
| 8382 | goto start_timer; | 8569 | goto start_timer; |
| 8383 | } | 8570 | } |
| 8384 | else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame)) | 8571 | else if (tooltip_reuse_hidden_frame && BASE_EQ (frame, tip_last_frame)) |
| 8385 | { | 8572 | { |
| 8386 | bool delete = false; | 8573 | bool delete = false; |
| 8387 | Lisp_Object tail, elt, parm, last; | 8574 | Lisp_Object tail, elt, parm, last; |
| @@ -8714,6 +8901,9 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, | |||
| 8714 | /* Prevent redisplay. */ | 8901 | /* Prevent redisplay. */ |
| 8715 | specbind (Qinhibit_redisplay, Qt); | 8902 | specbind (Qinhibit_redisplay, Qt); |
| 8716 | 8903 | ||
| 8904 | /* Defer selection requests. */ | ||
| 8905 | DEFER_SELECTIONS; | ||
| 8906 | |||
| 8717 | block_input (); | 8907 | block_input (); |
| 8718 | 8908 | ||
| 8719 | /* Create the dialog with PROMPT as title, using DIR as initial | 8909 | /* Create the dialog with PROMPT as title, using DIR as initial |
| @@ -9368,7 +9558,7 @@ frame_parm_handler x_frame_parm_handlers[] = | |||
| 9368 | x_set_wait_for_wm, | 9558 | x_set_wait_for_wm, |
| 9369 | gui_set_fullscreen, | 9559 | gui_set_fullscreen, |
| 9370 | gui_set_font_backend, | 9560 | gui_set_font_backend, |
| 9371 | gui_set_alpha, | 9561 | x_set_alpha, |
| 9372 | x_set_sticky, | 9562 | x_set_sticky, |
| 9373 | x_set_tool_bar_position, | 9563 | x_set_tool_bar_position, |
| 9374 | #ifdef HAVE_XDBE | 9564 | #ifdef HAVE_XDBE |
| @@ -9638,11 +9828,11 @@ default and usually works with most desktops. Some desktop environments | |||
| 9638 | however, may refuse to resize a child frame when Emacs is built with | 9828 | however, may refuse to resize a child frame when Emacs is built with |
| 9639 | GTK3. For those environments, the two settings below are provided. | 9829 | GTK3. For those environments, the two settings below are provided. |
| 9640 | 9830 | ||
| 9641 | If this equals the symbol 'hide', Emacs temporarily hides the child | 9831 | If this equals the symbol `hide', Emacs temporarily hides the child |
| 9642 | frame during resizing. This approach seems to work reliably, may | 9832 | frame during resizing. This approach seems to work reliably, may |
| 9643 | however induce some flicker when the frame is made visible again. | 9833 | however induce some flicker when the frame is made visible again. |
| 9644 | 9834 | ||
| 9645 | If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to | 9835 | If this equals the symbol `resize-mode', Emacs uses GTK's resize mode to |
| 9646 | always trigger an immediate resize of the child frame. This method is | 9836 | always trigger an immediate resize of the child frame. This method is |
| 9647 | deprecated by GTK and may not work in future versions of that toolkit. | 9837 | deprecated by GTK and may not work in future versions of that toolkit. |
| 9648 | It also may freeze Emacs when used with other desktop environments. It | 9838 | It also may freeze Emacs when used with other desktop environments. It |
| @@ -9757,6 +9947,10 @@ eliminated in future versions of Emacs. */); | |||
| 9757 | staticpro (&tip_last_string); | 9947 | staticpro (&tip_last_string); |
| 9758 | tip_last_parms = Qnil; | 9948 | tip_last_parms = Qnil; |
| 9759 | staticpro (&tip_last_parms); | 9949 | staticpro (&tip_last_parms); |
| 9950 | tip_dx = Qnil; | ||
| 9951 | staticpro (&tip_dx); | ||
| 9952 | tip_dy = Qnil; | ||
| 9953 | staticpro (&tip_dy); | ||
| 9760 | 9954 | ||
| 9761 | defsubr (&Sx_uses_old_gtk_dialog); | 9955 | defsubr (&Sx_uses_old_gtk_dialog); |
| 9762 | #if defined (USE_MOTIF) || defined (USE_GTK) | 9956 | #if defined (USE_MOTIF) || defined (USE_GTK) |
diff --git a/src/xfont.c b/src/xfont.c index 684c28ab21a..74237e8aa88 100644 --- a/src/xfont.c +++ b/src/xfont.c | |||
| @@ -295,7 +295,7 @@ xfont_list_pattern (Display *display, const char *pattern, | |||
| 295 | { | 295 | { |
| 296 | Lisp_Object list = Qnil; | 296 | Lisp_Object list = Qnil; |
| 297 | Lisp_Object chars = Qnil; | 297 | Lisp_Object chars = Qnil; |
| 298 | struct charset *encoding, *repertory = NULL; | 298 | struct charset *encoding = NULL, *repertory = NULL; |
| 299 | int i, limit, num_fonts; | 299 | int i, limit, num_fonts; |
| 300 | char **names; | 300 | char **names; |
| 301 | /* Large enough to decode the longest XLFD (255 bytes). */ | 301 | /* Large enough to decode the longest XLFD (255 bytes). */ |
diff --git a/src/xftfont.c b/src/xftfont.c index 31fb877c35b..6043ef9f94f 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -797,6 +797,15 @@ syms_of_xftfont (void) | |||
| 797 | This is needed with some fonts to correct vertical overlap of glyphs. */); | 797 | This is needed with some fonts to correct vertical overlap of glyphs. */); |
| 798 | xft_font_ascent_descent_override = 0; | 798 | xft_font_ascent_descent_override = 0; |
| 799 | 799 | ||
| 800 | DEFVAR_LISP ("xft-color-font-whitelist", Vxft_color_font_whitelist, | ||
| 801 | doc: /* List of "color" font families that don't actually have color glyphs. | ||
| 802 | Some fonts (such as Source Code Pro) are reported as color fonts, but | ||
| 803 | do not actually have glyphs with colors that can cause Xft crashes. | ||
| 804 | |||
| 805 | The font families in this list will not be ignored when | ||
| 806 | `xft-ignore-color-fonts' is non-nil. */); | ||
| 807 | Vxft_color_font_whitelist = list1 (build_pure_c_string ("Source Code Pro")); | ||
| 808 | |||
| 800 | pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper); | 809 | pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper); |
| 801 | } | 810 | } |
| 802 | 811 | ||
diff --git a/src/xgselect.c b/src/xgselect.c index 7252210c686..6e09a15fa84 100644 --- a/src/xgselect.c +++ b/src/xgselect.c | |||
| @@ -33,6 +33,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 33 | static ptrdiff_t threads_holding_glib_lock; | 33 | static ptrdiff_t threads_holding_glib_lock; |
| 34 | static GMainContext *glib_main_context; | 34 | static GMainContext *glib_main_context; |
| 35 | 35 | ||
| 36 | /* The depth of xg_select suppression. */ | ||
| 37 | static int xg_select_suppress_count; | ||
| 38 | |||
| 36 | void | 39 | void |
| 37 | release_select_lock (void) | 40 | release_select_lock (void) |
| 38 | { | 41 | { |
| @@ -69,6 +72,23 @@ acquire_select_lock (GMainContext *context) | |||
| 69 | #endif | 72 | #endif |
| 70 | } | 73 | } |
| 71 | 74 | ||
| 75 | /* Call this to not use xg_select when using it would be a bad idea, | ||
| 76 | i.e. during drag-and-drop. */ | ||
| 77 | void | ||
| 78 | suppress_xg_select (void) | ||
| 79 | { | ||
| 80 | ++xg_select_suppress_count; | ||
| 81 | } | ||
| 82 | |||
| 83 | void | ||
| 84 | release_xg_select (void) | ||
| 85 | { | ||
| 86 | if (!xg_select_suppress_count) | ||
| 87 | emacs_abort (); | ||
| 88 | |||
| 89 | --xg_select_suppress_count; | ||
| 90 | } | ||
| 91 | |||
| 72 | /* `xg_select' is a `pselect' replacement. Why do we need a separate function? | 92 | /* `xg_select' is a `pselect' replacement. Why do we need a separate function? |
| 73 | 1. Timeouts. Glib and Gtk rely on timer events. If we did pselect | 93 | 1. Timeouts. Glib and Gtk rely on timer events. If we did pselect |
| 74 | with a greater timeout then the one scheduled by Glib, we would | 94 | with a greater timeout then the one scheduled by Glib, we would |
| @@ -100,6 +120,9 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
| 100 | bool already_has_events; | 120 | bool already_has_events; |
| 101 | #endif | 121 | #endif |
| 102 | 122 | ||
| 123 | if (xg_select_suppress_count) | ||
| 124 | return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask); | ||
| 125 | |||
| 103 | context = g_main_context_default (); | 126 | context = g_main_context_default (); |
| 104 | acquire_select_lock (context); | 127 | acquire_select_lock (context); |
| 105 | 128 | ||
diff --git a/src/xgselect.h b/src/xgselect.h index 15482cbf922..156d4bde59f 100644 --- a/src/xgselect.h +++ b/src/xgselect.h | |||
| @@ -25,9 +25,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 25 | 25 | ||
| 26 | struct timespec; | 26 | struct timespec; |
| 27 | 27 | ||
| 28 | extern int xg_select (int max_fds, | 28 | extern int xg_select (int, fd_set *, fd_set *, fd_set *, |
| 29 | fd_set *rfds, fd_set *wfds, fd_set *efds, | 29 | struct timespec *, sigset_t *); |
| 30 | struct timespec *timeout, sigset_t *sigmask); | 30 | extern void suppress_xg_select (void); |
| 31 | extern void release_xg_select (void); | ||
| 31 | 32 | ||
| 32 | extern void release_select_lock (void); | 33 | extern void release_select_lock (void); |
| 33 | 34 | ||
diff --git a/src/xmenu.c b/src/xmenu.c index aaf53569a72..7134bf22c83 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -198,6 +198,10 @@ x_menu_wait_for_event (void *data) | |||
| 198 | struct x_display_info *dpyinfo; | 198 | struct x_display_info *dpyinfo; |
| 199 | int n = 0; | 199 | int n = 0; |
| 200 | 200 | ||
| 201 | /* ISTM that if timer_check is okay, this should be too, since | ||
| 202 | both can run random Lisp. */ | ||
| 203 | x_handle_pending_selection_requests (); | ||
| 204 | |||
| 201 | FD_ZERO (&read_fds); | 205 | FD_ZERO (&read_fds); |
| 202 | for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) | 206 | for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) |
| 203 | { | 207 | { |
| @@ -1579,6 +1583,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, | |||
| 1579 | } | 1583 | } |
| 1580 | #endif | 1584 | #endif |
| 1581 | 1585 | ||
| 1586 | DEFER_SELECTIONS; | ||
| 1587 | |||
| 1582 | /* Display the menu. */ | 1588 | /* Display the menu. */ |
| 1583 | gtk_widget_show_all (menu); | 1589 | gtk_widget_show_all (menu); |
| 1584 | 1590 | ||
| @@ -1868,6 +1874,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, | |||
| 1868 | { | 1874 | { |
| 1869 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 1875 | specpdl_ref specpdl_count = SPECPDL_INDEX (); |
| 1870 | 1876 | ||
| 1877 | DEFER_SELECTIONS; | ||
| 1878 | |||
| 1871 | record_unwind_protect_int (pop_down_menu, (int) menu_id); | 1879 | record_unwind_protect_int (pop_down_menu, (int) menu_id); |
| 1872 | #ifdef HAVE_XINPUT2 | 1880 | #ifdef HAVE_XINPUT2 |
| 1873 | record_unwind_protect_ptr (leave_toolkit_menu, f); | 1881 | record_unwind_protect_ptr (leave_toolkit_menu, f); |
| @@ -1894,13 +1902,19 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 1894 | { | 1902 | { |
| 1895 | int i; | 1903 | int i; |
| 1896 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 1904 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 1897 | widget_value **submenu_stack | 1905 | widget_value **submenu_stack; |
| 1898 | = alloca (menu_items_used * sizeof *submenu_stack); | 1906 | Lisp_Object *subprefix_stack; |
| 1899 | Lisp_Object *subprefix_stack | ||
| 1900 | = alloca (menu_items_used * sizeof *subprefix_stack); | ||
| 1901 | int submenu_depth = 0; | 1907 | int submenu_depth = 0; |
| 1908 | specpdl_ref specpdl_count; | ||
| 1902 | 1909 | ||
| 1903 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 1910 | USE_SAFE_ALLOCA; |
| 1911 | |||
| 1912 | submenu_stack = SAFE_ALLOCA (menu_items_used | ||
| 1913 | * sizeof *submenu_stack); | ||
| 1914 | subprefix_stack = SAFE_ALLOCA (menu_items_used | ||
| 1915 | * sizeof *subprefix_stack); | ||
| 1916 | |||
| 1917 | specpdl_count = SPECPDL_INDEX (); | ||
| 1904 | 1918 | ||
| 1905 | eassert (FRAME_X_P (f)); | 1919 | eassert (FRAME_X_P (f)); |
| 1906 | 1920 | ||
| @@ -1909,6 +1923,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 1909 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) | 1923 | if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) |
| 1910 | { | 1924 | { |
| 1911 | *error_name = "Empty menu"; | 1925 | *error_name = "Empty menu"; |
| 1926 | SAFE_FREE (); | ||
| 1912 | return Qnil; | 1927 | return Qnil; |
| 1913 | } | 1928 | } |
| 1914 | 1929 | ||
| @@ -2141,6 +2156,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 2141 | entry = Fcons (subprefix_stack[j], entry); | 2156 | entry = Fcons (subprefix_stack[j], entry); |
| 2142 | } | 2157 | } |
| 2143 | unblock_input (); | 2158 | unblock_input (); |
| 2159 | |||
| 2160 | SAFE_FREE (); | ||
| 2144 | return entry; | 2161 | return entry; |
| 2145 | } | 2162 | } |
| 2146 | i += MENU_ITEMS_ITEM_LENGTH; | 2163 | i += MENU_ITEMS_ITEM_LENGTH; |
| @@ -2155,6 +2172,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 2155 | } | 2172 | } |
| 2156 | 2173 | ||
| 2157 | unblock_input (); | 2174 | unblock_input (); |
| 2175 | |||
| 2176 | SAFE_FREE (); | ||
| 2158 | return Qnil; | 2177 | return Qnil; |
| 2159 | } | 2178 | } |
| 2160 | 2179 | ||
| @@ -2188,6 +2207,8 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) | |||
| 2188 | if (menu) | 2207 | if (menu) |
| 2189 | { | 2208 | { |
| 2190 | specpdl_ref specpdl_count = SPECPDL_INDEX (); | 2209 | specpdl_ref specpdl_count = SPECPDL_INDEX (); |
| 2210 | |||
| 2211 | DEFER_SELECTIONS; | ||
| 2191 | record_unwind_protect_ptr (pop_down_menu, menu); | 2212 | record_unwind_protect_ptr (pop_down_menu, menu); |
| 2192 | 2213 | ||
| 2193 | /* Display the menu. */ | 2214 | /* Display the menu. */ |
| @@ -2244,6 +2265,8 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) | |||
| 2244 | { | 2265 | { |
| 2245 | specpdl_ref count = SPECPDL_INDEX (); | 2266 | specpdl_ref count = SPECPDL_INDEX (); |
| 2246 | 2267 | ||
| 2268 | DEFER_SELECTIONS; | ||
| 2269 | |||
| 2247 | /* xdialog_show_unwind is responsible for popping the dialog box down. */ | 2270 | /* xdialog_show_unwind is responsible for popping the dialog box down. */ |
| 2248 | 2271 | ||
| 2249 | record_unwind_protect_int (pop_down_menu, (int) dialog_id); | 2272 | record_unwind_protect_int (pop_down_menu, (int) dialog_id); |
| @@ -2704,18 +2727,18 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 2704 | y = max (y, 1); | 2727 | y = max (y, 1); |
| 2705 | XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y, | 2728 | XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y, |
| 2706 | &ulx, &uly, &width, &height); | 2729 | &ulx, &uly, &width, &height); |
| 2707 | if (ulx+width > dispwidth) | 2730 | if (ulx + width > dispwidth) |
| 2708 | { | 2731 | { |
| 2709 | x -= (ulx + width) - dispwidth; | 2732 | x -= (ulx + width) - dispwidth; |
| 2710 | ulx = dispwidth - width; | 2733 | ulx = dispwidth - width; |
| 2711 | } | 2734 | } |
| 2712 | if (uly+height > dispheight) | 2735 | if (uly + height > dispheight) |
| 2713 | { | 2736 | { |
| 2714 | y -= (uly + height) - dispheight; | 2737 | y -= (uly + height) - dispheight; |
| 2715 | uly = dispheight - height; | 2738 | uly = dispheight - height; |
| 2716 | } | 2739 | } |
| 2717 | #ifndef HAVE_X_WINDOWS | 2740 | #ifndef HAVE_X_WINDOWS |
| 2718 | if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1) | 2741 | if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 1) |
| 2719 | { | 2742 | { |
| 2720 | /* Move the menu away of the echo area, to avoid overwriting the | 2743 | /* Move the menu away of the echo area, to avoid overwriting the |
| 2721 | menu with help echo messages or vice versa. */ | 2744 | menu with help echo messages or vice versa. */ |
| @@ -2739,8 +2762,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 2739 | /* If position was not given by a mouse click, adjust so upper left | 2762 | /* If position was not given by a mouse click, adjust so upper left |
| 2740 | corner of the menu as a whole ends up at given coordinates. This | 2763 | corner of the menu as a whole ends up at given coordinates. This |
| 2741 | is what x-popup-menu says in its documentation. */ | 2764 | is what x-popup-menu says in its documentation. */ |
| 2742 | x += width/2; | 2765 | x += width / 2; |
| 2743 | y += 1.5*height/(maxlines+2); | 2766 | y += 1.5 * height/ (maxlines + 2); |
| 2744 | } | 2767 | } |
| 2745 | 2768 | ||
| 2746 | XMenuSetAEQ (menu, true); | 2769 | XMenuSetAEQ (menu, true); |
| @@ -2748,6 +2771,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 2748 | pane = selidx = 0; | 2771 | pane = selidx = 0; |
| 2749 | 2772 | ||
| 2750 | #ifndef MSDOS | 2773 | #ifndef MSDOS |
| 2774 | DEFER_SELECTIONS; | ||
| 2775 | |||
| 2751 | XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f)); | 2776 | XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f)); |
| 2752 | #ifdef HAVE_XINPUT2 | 2777 | #ifdef HAVE_XINPUT2 |
| 2753 | XMenuActivateSetTranslateFunction (x_menu_translate_generic_event); | 2778 | XMenuActivateSetTranslateFunction (x_menu_translate_generic_event); |
diff --git a/src/xrdb.c b/src/xrdb.c index aa79d719c8c..faeea04a539 100644 --- a/src/xrdb.c +++ b/src/xrdb.c | |||
| @@ -486,11 +486,7 @@ x_get_resource (XrmDatabase rdb, const char *name, const char *class, | |||
| 486 | if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True | 486 | if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True |
| 487 | && (type == expected_type)) | 487 | && (type == expected_type)) |
| 488 | { | 488 | { |
| 489 | if (type == x_rm_string) | 489 | *ret_value = value; |
| 490 | ret_value->addr = (char *) value.addr; | ||
| 491 | else | ||
| 492 | memcpy (ret_value->addr, value.addr, ret_value->size); | ||
| 493 | |||
| 494 | return value.size; | 490 | return value.size; |
| 495 | } | 491 | } |
| 496 | 492 | ||
diff --git a/src/xselect.c b/src/xselect.c index 3acfcbe94b0..96c1e9830fb 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -112,96 +112,10 @@ selection_quantum (Display *display) | |||
| 112 | : MAX_SELECTION_QUANTUM); | 112 | : MAX_SELECTION_QUANTUM); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | #define LOCAL_SELECTION(selection_symbol,dpyinfo) \ | 115 | #define LOCAL_SELECTION(selection_symbol, dpyinfo) \ |
| 116 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) | 116 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) |
| 117 | 117 | ||
| 118 | 118 | ||
| 119 | /* Define a queue to save up SELECTION_REQUEST_EVENT events for later | ||
| 120 | handling. */ | ||
| 121 | |||
| 122 | struct selection_event_queue | ||
| 123 | { | ||
| 124 | struct selection_input_event event; | ||
| 125 | struct selection_event_queue *next; | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct selection_event_queue *selection_queue; | ||
| 129 | |||
| 130 | /* Nonzero means queue up SELECTION_REQUEST_EVENT events. */ | ||
| 131 | |||
| 132 | static int x_queue_selection_requests; | ||
| 133 | |||
| 134 | /* True if the input events are duplicates. */ | ||
| 135 | |||
| 136 | static bool | ||
| 137 | selection_input_event_equal (struct selection_input_event *a, | ||
| 138 | struct selection_input_event *b) | ||
| 139 | { | ||
| 140 | return (a->kind == b->kind && a->dpyinfo == b->dpyinfo | ||
| 141 | && a->requestor == b->requestor && a->selection == b->selection | ||
| 142 | && a->target == b->target && a->property == b->property | ||
| 143 | && a->time == b->time); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */ | ||
| 147 | |||
| 148 | static void | ||
| 149 | x_queue_event (struct selection_input_event *event) | ||
| 150 | { | ||
| 151 | struct selection_event_queue *queue_tmp; | ||
| 152 | |||
| 153 | /* Don't queue repeated requests. | ||
| 154 | This only happens for large requests which uses the incremental protocol. */ | ||
| 155 | for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next) | ||
| 156 | { | ||
| 157 | if (selection_input_event_equal (event, &queue_tmp->event)) | ||
| 158 | { | ||
| 159 | TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp); | ||
| 160 | x_decline_selection_request (event); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | queue_tmp = xmalloc (sizeof *queue_tmp); | ||
| 166 | TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp); | ||
| 167 | queue_tmp->event = *event; | ||
| 168 | queue_tmp->next = selection_queue; | ||
| 169 | selection_queue = queue_tmp; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* Start queuing SELECTION_REQUEST_EVENT events. */ | ||
| 173 | |||
| 174 | static void | ||
| 175 | x_start_queuing_selection_requests (void) | ||
| 176 | { | ||
| 177 | if (x_queue_selection_requests) | ||
| 178 | emacs_abort (); | ||
| 179 | |||
| 180 | x_queue_selection_requests++; | ||
| 181 | TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests); | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Stop queuing SELECTION_REQUEST_EVENT events. */ | ||
| 185 | |||
| 186 | static void | ||
| 187 | x_stop_queuing_selection_requests (void) | ||
| 188 | { | ||
| 189 | TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests); | ||
| 190 | --x_queue_selection_requests; | ||
| 191 | |||
| 192 | /* Take all the queued events and put them back | ||
| 193 | so that they get processed afresh. */ | ||
| 194 | |||
| 195 | while (selection_queue != NULL) | ||
| 196 | { | ||
| 197 | struct selection_event_queue *queue_tmp = selection_queue; | ||
| 198 | TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp); | ||
| 199 | kbd_buffer_unget_event (&queue_tmp->event); | ||
| 200 | selection_queue = queue_tmp->next; | ||
| 201 | xfree (queue_tmp); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | 119 | ||
| 206 | /* This converts a Lisp symbol to a server Atom, avoiding a server | 120 | /* This converts a Lisp symbol to a server Atom, avoiding a server |
| 207 | roundtrip whenever possible. */ | 121 | roundtrip whenever possible. */ |
| @@ -256,7 +170,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) | |||
| 256 | 170 | ||
| 257 | TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym))); | 171 | TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym))); |
| 258 | block_input (); | 172 | block_input (); |
| 259 | val = XInternAtom (dpyinfo->display, SSDATA (SYMBOL_NAME (sym)), False); | 173 | val = x_intern_cached_atom (dpyinfo, SSDATA (SYMBOL_NAME (sym)), false); |
| 260 | unblock_input (); | 174 | unblock_input (); |
| 261 | return val; | 175 | return val; |
| 262 | } | 176 | } |
| @@ -265,7 +179,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) | |||
| 265 | /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips | 179 | /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips |
| 266 | and calls to intern whenever possible. */ | 180 | and calls to intern whenever possible. */ |
| 267 | 181 | ||
| 268 | static Lisp_Object | 182 | Lisp_Object |
| 269 | x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) | 183 | x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) |
| 270 | { | 184 | { |
| 271 | char *str; | 185 | char *str; |
| @@ -319,18 +233,17 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) | |||
| 319 | if (atom == dpyinfo->Xatom_XmTRANSFER_FAILURE) | 233 | if (atom == dpyinfo->Xatom_XmTRANSFER_FAILURE) |
| 320 | return QXmTRANSFER_FAILURE; | 234 | return QXmTRANSFER_FAILURE; |
| 321 | 235 | ||
| 322 | block_input (); | ||
| 323 | x_catch_errors (dpyinfo->display); | 236 | x_catch_errors (dpyinfo->display); |
| 324 | str = XGetAtomName (dpyinfo->display, atom); | 237 | str = x_get_atom_name (dpyinfo, atom, NULL); |
| 325 | x_uncatch_errors (); | 238 | x_uncatch_errors (); |
| 326 | unblock_input (); | 239 | |
| 240 | TRACE0 ("XGetAtomName --> NULL"); | ||
| 241 | if (!str) | ||
| 242 | return Qnil; | ||
| 327 | TRACE1 ("XGetAtomName --> %s", str); | 243 | TRACE1 ("XGetAtomName --> %s", str); |
| 328 | if (! str) return Qnil; | 244 | |
| 329 | val = intern (str); | 245 | val = intern (str); |
| 330 | block_input (); | 246 | xfree (str); |
| 331 | /* This was allocated by Xlib, so use XFree. */ | ||
| 332 | XFree (str); | ||
| 333 | unblock_input (); | ||
| 334 | return val; | 247 | return val; |
| 335 | } | 248 | } |
| 336 | 249 | ||
| @@ -399,7 +312,7 @@ static Lisp_Object | |||
| 399 | x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | 312 | x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, |
| 400 | bool local_request, struct x_display_info *dpyinfo) | 313 | bool local_request, struct x_display_info *dpyinfo) |
| 401 | { | 314 | { |
| 402 | Lisp_Object local_value; | 315 | Lisp_Object local_value, tem; |
| 403 | Lisp_Object handler_fn, value, check; | 316 | Lisp_Object handler_fn, value, check; |
| 404 | 317 | ||
| 405 | local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); | 318 | local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); |
| @@ -426,10 +339,24 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | |||
| 426 | if (CONSP (handler_fn)) | 339 | if (CONSP (handler_fn)) |
| 427 | handler_fn = XCDR (handler_fn); | 340 | handler_fn = XCDR (handler_fn); |
| 428 | 341 | ||
| 342 | tem = XCAR (XCDR (local_value)); | ||
| 343 | |||
| 344 | if (STRINGP (tem)) | ||
| 345 | { | ||
| 346 | local_value = Fget_text_property (make_fixnum (0), | ||
| 347 | target_type, tem); | ||
| 348 | |||
| 349 | if (!NILP (local_value)) | ||
| 350 | tem = local_value; | ||
| 351 | } | ||
| 352 | |||
| 429 | if (!NILP (handler_fn)) | 353 | if (!NILP (handler_fn)) |
| 430 | value = call3 (handler_fn, | 354 | value = call3 (handler_fn, selection_symbol, |
| 431 | selection_symbol, (local_request ? Qnil : target_type), | 355 | ((local_request |
| 432 | XCAR (XCDR (local_value))); | 356 | && NILP (Vx_treat_local_requests_remotely)) |
| 357 | ? Qnil | ||
| 358 | : target_type), | ||
| 359 | tem); | ||
| 433 | else | 360 | else |
| 434 | value = Qnil; | 361 | value = Qnil; |
| 435 | value = unbind_to (count, value); | 362 | value = unbind_to (count, value); |
| @@ -492,14 +419,6 @@ x_decline_selection_request (struct selection_input_event *event) | |||
| 492 | unblock_input (); | 419 | unblock_input (); |
| 493 | } | 420 | } |
| 494 | 421 | ||
| 495 | /* This is the selection request currently being processed. | ||
| 496 | It is set to zero when the request is fully processed. */ | ||
| 497 | static struct selection_input_event *x_selection_current_request; | ||
| 498 | |||
| 499 | /* Display info in x_selection_request. */ | ||
| 500 | |||
| 501 | static struct x_display_info *selection_request_dpyinfo; | ||
| 502 | |||
| 503 | /* Raw selection data, for sending to a requestor window. */ | 422 | /* Raw selection data, for sending to a requestor window. */ |
| 504 | 423 | ||
| 505 | struct selection_data | 424 | struct selection_data |
| @@ -517,12 +436,59 @@ struct selection_data | |||
| 517 | struct selection_data *next; | 436 | struct selection_data *next; |
| 518 | }; | 437 | }; |
| 519 | 438 | ||
| 520 | /* Linked list of the above (in support of MULTIPLE targets). */ | 439 | struct x_selection_request |
| 440 | { | ||
| 441 | /* The last element in this stack. */ | ||
| 442 | struct x_selection_request *last; | ||
| 443 | |||
| 444 | /* Its display info. */ | ||
| 445 | struct x_display_info *dpyinfo; | ||
| 446 | |||
| 447 | /* Its selection input event. */ | ||
| 448 | struct selection_input_event *request; | ||
| 449 | |||
| 450 | /* Linked list of the above (in support of MULTIPLE targets). */ | ||
| 451 | struct selection_data *converted_selections; | ||
| 452 | |||
| 453 | /* "Data" to send a requestor for a failed MULTIPLE subtarget. */ | ||
| 454 | Atom conversion_fail_tag; | ||
| 455 | |||
| 456 | /* Whether or not conversion was successful. */ | ||
| 457 | bool converted; | ||
| 458 | }; | ||
| 459 | |||
| 460 | /* Stack of selections currently being processed. | ||
| 461 | NULL if all requests have been fully processed. */ | ||
| 521 | 462 | ||
| 522 | static struct selection_data *converted_selections; | 463 | struct x_selection_request *selection_request_stack; |
| 523 | 464 | ||
| 524 | /* "Data" to send a requestor for a failed MULTIPLE subtarget. */ | 465 | static void |
| 525 | static Atom conversion_fail_tag; | 466 | x_push_current_selection_request (struct selection_input_event *se, |
| 467 | struct x_display_info *dpyinfo) | ||
| 468 | { | ||
| 469 | struct x_selection_request *frame; | ||
| 470 | |||
| 471 | frame = xmalloc (sizeof *frame); | ||
| 472 | frame->converted = false; | ||
| 473 | frame->last = selection_request_stack; | ||
| 474 | frame->request = se; | ||
| 475 | frame->dpyinfo = dpyinfo; | ||
| 476 | frame->converted_selections = NULL; | ||
| 477 | frame->conversion_fail_tag = None; | ||
| 478 | |||
| 479 | selection_request_stack = frame; | ||
| 480 | } | ||
| 481 | |||
| 482 | static void | ||
| 483 | x_pop_current_selection_request (void) | ||
| 484 | { | ||
| 485 | struct x_selection_request *tem; | ||
| 486 | |||
| 487 | tem = selection_request_stack; | ||
| 488 | selection_request_stack = selection_request_stack->last; | ||
| 489 | |||
| 490 | xfree (tem); | ||
| 491 | } | ||
| 526 | 492 | ||
| 527 | /* Used as an unwind-protect clause so that, if a selection-converter signals | 493 | /* Used as an unwind-protect clause so that, if a selection-converter signals |
| 528 | an error, we tell the requestor that we were unable to do what they wanted | 494 | an error, we tell the requestor that we were unable to do what they wanted |
| @@ -532,19 +498,21 @@ static void | |||
| 532 | x_selection_request_lisp_error (void) | 498 | x_selection_request_lisp_error (void) |
| 533 | { | 499 | { |
| 534 | struct selection_data *cs, *next; | 500 | struct selection_data *cs, *next; |
| 501 | struct x_selection_request *frame; | ||
| 502 | |||
| 503 | frame = selection_request_stack; | ||
| 535 | 504 | ||
| 536 | for (cs = converted_selections; cs; cs = next) | 505 | for (cs = frame->converted_selections; cs; cs = next) |
| 537 | { | 506 | { |
| 538 | next = cs->next; | 507 | next = cs->next; |
| 539 | if (! cs->nofree && cs->data) | 508 | if (! cs->nofree && cs->data) |
| 540 | xfree (cs->data); | 509 | xfree (cs->data); |
| 541 | xfree (cs); | 510 | xfree (cs); |
| 542 | } | 511 | } |
| 543 | converted_selections = NULL; | 512 | frame->converted_selections = NULL; |
| 544 | 513 | ||
| 545 | if (x_selection_current_request != 0 | 514 | if (!frame->converted && frame->dpyinfo->display) |
| 546 | && selection_request_dpyinfo->display) | 515 | x_decline_selection_request (frame->request); |
| 547 | x_decline_selection_request (x_selection_current_request); | ||
| 548 | } | 516 | } |
| 549 | 517 | ||
| 550 | static void | 518 | static void |
| @@ -610,6 +578,9 @@ x_reply_selection_request (struct selection_input_event *event, | |||
| 610 | int max_bytes = selection_quantum (display); | 578 | int max_bytes = selection_quantum (display); |
| 611 | specpdl_ref count = SPECPDL_INDEX (); | 579 | specpdl_ref count = SPECPDL_INDEX (); |
| 612 | struct selection_data *cs; | 580 | struct selection_data *cs; |
| 581 | struct x_selection_request *frame; | ||
| 582 | |||
| 583 | frame = selection_request_stack; | ||
| 613 | 584 | ||
| 614 | reply->type = SelectionNotify; | 585 | reply->type = SelectionNotify; |
| 615 | reply->display = display; | 586 | reply->display = display; |
| @@ -633,7 +604,7 @@ x_reply_selection_request (struct selection_input_event *event, | |||
| 633 | (section 2.7.2 of ICCCM). Note that we store the data for a | 604 | (section 2.7.2 of ICCCM). Note that we store the data for a |
| 634 | MULTIPLE request in the opposite order; the ICCM says only that | 605 | MULTIPLE request in the opposite order; the ICCM says only that |
| 635 | the conversion itself must be done in the same order. */ | 606 | the conversion itself must be done in the same order. */ |
| 636 | for (cs = converted_selections; cs; cs = cs->next) | 607 | for (cs = frame->converted_selections; cs; cs = cs->next) |
| 637 | { | 608 | { |
| 638 | if (cs->property == None) | 609 | if (cs->property == None) |
| 639 | continue; | 610 | continue; |
| @@ -688,7 +659,7 @@ x_reply_selection_request (struct selection_input_event *event, | |||
| 688 | be improved; there's a chance of deadlock if more than one | 659 | be improved; there's a chance of deadlock if more than one |
| 689 | subtarget in a MULTIPLE selection requires an INCR transfer, and | 660 | subtarget in a MULTIPLE selection requires an INCR transfer, and |
| 690 | the requestor and Emacs loop waiting on different transfers. */ | 661 | the requestor and Emacs loop waiting on different transfers. */ |
| 691 | for (cs = converted_selections; cs; cs = cs->next) | 662 | for (cs = frame->converted_selections; cs; cs = cs->next) |
| 692 | if (cs->wait_object) | 663 | if (cs->wait_object) |
| 693 | { | 664 | { |
| 694 | int format_bytes = cs->format / 8; | 665 | int format_bytes = cs->format / 8; |
| @@ -793,7 +764,6 @@ static void | |||
| 793 | x_handle_selection_request (struct selection_input_event *event) | 764 | x_handle_selection_request (struct selection_input_event *event) |
| 794 | { | 765 | { |
| 795 | Time local_selection_time; | 766 | Time local_selection_time; |
| 796 | |||
| 797 | struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); | 767 | struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); |
| 798 | Atom selection = SELECTION_EVENT_SELECTION (event); | 768 | Atom selection = SELECTION_EVENT_SELECTION (event); |
| 799 | Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection); | 769 | Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection); |
| @@ -803,8 +773,12 @@ x_handle_selection_request (struct selection_input_event *event) | |||
| 803 | Lisp_Object local_selection_data; | 773 | Lisp_Object local_selection_data; |
| 804 | bool success = false; | 774 | bool success = false; |
| 805 | specpdl_ref count = SPECPDL_INDEX (); | 775 | specpdl_ref count = SPECPDL_INDEX (); |
| 776 | bool pushed; | ||
| 777 | |||
| 778 | pushed = false; | ||
| 806 | 779 | ||
| 807 | if (!dpyinfo) goto DONE; | 780 | if (!dpyinfo) |
| 781 | goto DONE; | ||
| 808 | 782 | ||
| 809 | /* This is how the XDND protocol recommends dropping text onto a | 783 | /* This is how the XDND protocol recommends dropping text onto a |
| 810 | target that doesn't support XDND. */ | 784 | target that doesn't support XDND. */ |
| @@ -824,14 +798,12 @@ x_handle_selection_request (struct selection_input_event *event) | |||
| 824 | && local_selection_time > SELECTION_EVENT_TIME (event)) | 798 | && local_selection_time > SELECTION_EVENT_TIME (event)) |
| 825 | goto DONE; | 799 | goto DONE; |
| 826 | 800 | ||
| 827 | x_selection_current_request = event; | 801 | block_input (); |
| 828 | selection_request_dpyinfo = dpyinfo; | 802 | pushed = true; |
| 803 | x_push_current_selection_request (event, dpyinfo); | ||
| 804 | record_unwind_protect_void (x_pop_current_selection_request); | ||
| 829 | record_unwind_protect_void (x_selection_request_lisp_error); | 805 | record_unwind_protect_void (x_selection_request_lisp_error); |
| 830 | 806 | unblock_input (); | |
| 831 | /* We might be able to handle nested x_handle_selection_requests, | ||
| 832 | but this is difficult to test, and seems unimportant. */ | ||
| 833 | x_start_queuing_selection_requests (); | ||
| 834 | record_unwind_protect_void (x_stop_queuing_selection_requests); | ||
| 835 | 807 | ||
| 836 | TRACE2 ("x_handle_selection_request: selection=%s, target=%s", | 808 | TRACE2 ("x_handle_selection_request: selection=%s, target=%s", |
| 837 | SDATA (SYMBOL_NAME (selection_symbol)), | 809 | SDATA (SYMBOL_NAME (selection_symbol)), |
| @@ -888,15 +860,17 @@ x_handle_selection_request (struct selection_input_event *event) | |||
| 888 | 860 | ||
| 889 | DONE: | 861 | DONE: |
| 890 | 862 | ||
| 863 | if (pushed) | ||
| 864 | selection_request_stack->converted = true; | ||
| 865 | |||
| 891 | if (success) | 866 | if (success) |
| 892 | x_reply_selection_request (event, dpyinfo); | 867 | x_reply_selection_request (event, dpyinfo); |
| 893 | else | 868 | else |
| 894 | x_decline_selection_request (event); | 869 | x_decline_selection_request (event); |
| 895 | x_selection_current_request = 0; | ||
| 896 | 870 | ||
| 897 | /* Run the `x-sent-selection-functions' abnormal hook. */ | 871 | /* Run the `x-sent-selection-functions' abnormal hook. */ |
| 898 | if (!NILP (Vx_sent_selection_functions) | 872 | if (!NILP (Vx_sent_selection_functions) |
| 899 | && !EQ (Vx_sent_selection_functions, Qunbound)) | 873 | && !BASE_EQ (Vx_sent_selection_functions, Qunbound)) |
| 900 | CALLN (Frun_hook_with_args, Qx_sent_selection_functions, | 874 | CALLN (Frun_hook_with_args, Qx_sent_selection_functions, |
| 901 | selection_symbol, target_symbol, success ? Qt : Qnil); | 875 | selection_symbol, target_symbol, success ? Qt : Qnil); |
| 902 | 876 | ||
| @@ -917,11 +891,14 @@ x_convert_selection (Lisp_Object selection_symbol, | |||
| 917 | { | 891 | { |
| 918 | Lisp_Object lisp_selection; | 892 | Lisp_Object lisp_selection; |
| 919 | struct selection_data *cs; | 893 | struct selection_data *cs; |
| 894 | struct x_selection_request *frame; | ||
| 920 | 895 | ||
| 921 | lisp_selection | 896 | lisp_selection |
| 922 | = x_get_local_selection (selection_symbol, target_symbol, | 897 | = x_get_local_selection (selection_symbol, target_symbol, |
| 923 | false, dpyinfo); | 898 | false, dpyinfo); |
| 924 | 899 | ||
| 900 | frame = selection_request_stack; | ||
| 901 | |||
| 925 | /* A nil return value means we can't perform the conversion. */ | 902 | /* A nil return value means we can't perform the conversion. */ |
| 926 | if (NILP (lisp_selection) | 903 | if (NILP (lisp_selection) |
| 927 | || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection)))) | 904 | || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection)))) |
| @@ -929,15 +906,16 @@ x_convert_selection (Lisp_Object selection_symbol, | |||
| 929 | if (for_multiple) | 906 | if (for_multiple) |
| 930 | { | 907 | { |
| 931 | cs = xmalloc (sizeof *cs); | 908 | cs = xmalloc (sizeof *cs); |
| 932 | cs->data = (unsigned char *) &conversion_fail_tag; | 909 | cs->data = ((unsigned char *) |
| 910 | &selection_request_stack->conversion_fail_tag); | ||
| 933 | cs->size = 1; | 911 | cs->size = 1; |
| 934 | cs->format = 32; | 912 | cs->format = 32; |
| 935 | cs->type = XA_ATOM; | 913 | cs->type = XA_ATOM; |
| 936 | cs->nofree = true; | 914 | cs->nofree = true; |
| 937 | cs->property = property; | 915 | cs->property = property; |
| 938 | cs->wait_object = NULL; | 916 | cs->wait_object = NULL; |
| 939 | cs->next = converted_selections; | 917 | cs->next = frame->converted_selections; |
| 940 | converted_selections = cs; | 918 | frame->converted_selections = cs; |
| 941 | } | 919 | } |
| 942 | 920 | ||
| 943 | return false; | 921 | return false; |
| @@ -949,8 +927,8 @@ x_convert_selection (Lisp_Object selection_symbol, | |||
| 949 | cs->nofree = true; | 927 | cs->nofree = true; |
| 950 | cs->property = property; | 928 | cs->property = property; |
| 951 | cs->wait_object = NULL; | 929 | cs->wait_object = NULL; |
| 952 | cs->next = converted_selections; | 930 | cs->next = frame->converted_selections; |
| 953 | converted_selections = cs; | 931 | frame->converted_selections = cs; |
| 954 | lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); | 932 | lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); |
| 955 | return true; | 933 | return true; |
| 956 | } | 934 | } |
| @@ -1008,6 +986,12 @@ x_handle_selection_clear (struct selection_input_event *event) | |||
| 1008 | /* Run the `x-lost-selection-functions' abnormal hook. */ | 986 | /* Run the `x-lost-selection-functions' abnormal hook. */ |
| 1009 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol); | 987 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol); |
| 1010 | 988 | ||
| 989 | /* If Emacs lost ownership of XdndSelection during drag-and-drop, | ||
| 990 | there is no point in continuing the drag-and-drop session. */ | ||
| 991 | if (x_dnd_in_progress | ||
| 992 | && EQ (selection_symbol, QXdndSelection)) | ||
| 993 | error ("Lost ownership of XdndSelection"); | ||
| 994 | |||
| 1011 | redisplay_preserve_echo_area (20); | 995 | redisplay_preserve_echo_area (20); |
| 1012 | } | 996 | } |
| 1013 | 997 | ||
| @@ -1017,8 +1001,6 @@ x_handle_selection_event (struct selection_input_event *event) | |||
| 1017 | TRACE0 ("x_handle_selection_event"); | 1001 | TRACE0 ("x_handle_selection_event"); |
| 1018 | if (event->kind != SELECTION_REQUEST_EVENT) | 1002 | if (event->kind != SELECTION_REQUEST_EVENT) |
| 1019 | x_handle_selection_clear (event); | 1003 | x_handle_selection_clear (event); |
| 1020 | else if (x_queue_selection_requests) | ||
| 1021 | x_queue_event (event); | ||
| 1022 | else | 1004 | else |
| 1023 | x_handle_selection_request (event); | 1005 | x_handle_selection_request (event); |
| 1024 | } | 1006 | } |
| @@ -1148,8 +1130,13 @@ wait_for_property_change (struct prop_location *location) | |||
| 1148 | intmax_t secs = timeout / 1000; | 1130 | intmax_t secs = timeout / 1000; |
| 1149 | int nsecs = (timeout % 1000) * 1000000; | 1131 | int nsecs = (timeout % 1000) * 1000000; |
| 1150 | TRACE2 (" Waiting %"PRIdMAX" secs, %d nsecs", secs, nsecs); | 1132 | TRACE2 (" Waiting %"PRIdMAX" secs, %d nsecs", secs, nsecs); |
| 1151 | wait_reading_process_output (secs, nsecs, 0, false, | 1133 | |
| 1152 | property_change_reply, NULL, 0); | 1134 | if (!input_blocked_p ()) |
| 1135 | wait_reading_process_output (secs, nsecs, 0, false, | ||
| 1136 | property_change_reply, NULL, 0); | ||
| 1137 | else | ||
| 1138 | x_wait_for_cell_change (property_change_reply, | ||
| 1139 | make_timespec (secs, nsecs)); | ||
| 1153 | 1140 | ||
| 1154 | if (NILP (XCAR (property_change_reply))) | 1141 | if (NILP (XCAR (property_change_reply))) |
| 1155 | { | 1142 | { |
| @@ -1256,9 +1243,22 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | |||
| 1256 | intmax_t secs = timeout / 1000; | 1243 | intmax_t secs = timeout / 1000; |
| 1257 | int nsecs = (timeout % 1000) * 1000000; | 1244 | int nsecs = (timeout % 1000) * 1000000; |
| 1258 | TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify", secs); | 1245 | TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify", secs); |
| 1259 | wait_reading_process_output (secs, nsecs, 0, false, | 1246 | /* This function can be called with input blocked inside Xt or GTK |
| 1260 | reading_selection_reply, NULL, 0); | 1247 | timeouts run inside popup menus, so use a function that works |
| 1261 | TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply))); | 1248 | when input is blocked. Prefer wait_reading_process_output |
| 1249 | otherwise, or the toolkit might not get some events. | ||
| 1250 | (bug#22214) */ | ||
| 1251 | if (!input_blocked_p ()) | ||
| 1252 | wait_reading_process_output (secs, nsecs, 0, false, | ||
| 1253 | reading_selection_reply, NULL, 0); | ||
| 1254 | else | ||
| 1255 | x_wait_for_cell_change (reading_selection_reply, | ||
| 1256 | make_timespec (secs, nsecs)); | ||
| 1257 | TRACE1 (" Got event = %s", (!NILP (XCAR (reading_selection_reply)) | ||
| 1258 | ? (SYMBOLP (XCAR (reading_selection_reply)) | ||
| 1259 | ? SSDATA (SYMBOL_NAME (XCAR (reading_selection_reply))) | ||
| 1260 | : "YES") | ||
| 1261 | : "NO")); | ||
| 1262 | 1262 | ||
| 1263 | if (NILP (XCAR (reading_selection_reply))) | 1263 | if (NILP (XCAR (reading_selection_reply))) |
| 1264 | error ("Timed out waiting for reply from selection owner"); | 1264 | error ("Timed out waiting for reply from selection owner"); |
| @@ -1953,7 +1953,7 @@ x_handle_selection_notify (const XSelectionEvent *event) | |||
| 1953 | if (event->selection != reading_which_selection) | 1953 | if (event->selection != reading_which_selection) |
| 1954 | return; | 1954 | return; |
| 1955 | 1955 | ||
| 1956 | TRACE0 ("Received SelectionNotify"); | 1956 | TRACE1 ("Received SelectionNotify: %d", (int) event->property); |
| 1957 | XSETCAR (reading_selection_reply, | 1957 | XSETCAR (reading_selection_reply, |
| 1958 | (event->property != 0 ? Qt : Qlambda)); | 1958 | (event->property != 0 ? Qt : Qlambda)); |
| 1959 | } | 1959 | } |
| @@ -2454,28 +2454,29 @@ If the value is 0 or the atom is not known, return the empty string. */) | |||
| 2454 | (Lisp_Object value, Lisp_Object frame) | 2454 | (Lisp_Object value, Lisp_Object frame) |
| 2455 | { | 2455 | { |
| 2456 | struct frame *f = decode_window_system_frame (frame); | 2456 | struct frame *f = decode_window_system_frame (frame); |
| 2457 | char *name = 0; | ||
| 2458 | char empty[] = ""; | ||
| 2459 | Lisp_Object ret = Qnil; | ||
| 2460 | Display *dpy = FRAME_X_DISPLAY (f); | 2457 | Display *dpy = FRAME_X_DISPLAY (f); |
| 2458 | struct x_display_info *dpyinfo; | ||
| 2461 | Atom atom; | 2459 | Atom atom; |
| 2462 | bool had_errors_p; | 2460 | bool had_errors_p, need_sync; |
| 2461 | char *name; | ||
| 2462 | Lisp_Object ret; | ||
| 2463 | 2463 | ||
| 2464 | dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 2464 | CONS_TO_INTEGER (value, Atom, atom); | 2465 | CONS_TO_INTEGER (value, Atom, atom); |
| 2465 | 2466 | ||
| 2466 | block_input (); | ||
| 2467 | x_catch_errors (dpy); | 2467 | x_catch_errors (dpy); |
| 2468 | name = atom ? XGetAtomName (dpy, atom) : empty; | 2468 | name = x_get_atom_name (dpyinfo, atom, &need_sync); |
| 2469 | had_errors_p = x_had_errors_p (dpy); | 2469 | had_errors_p = need_sync && x_had_errors_p (dpy); |
| 2470 | x_uncatch_errors_after_check (); | 2470 | x_uncatch_errors_after_check (); |
| 2471 | 2471 | ||
| 2472 | if (!had_errors_p) | 2472 | ret = empty_unibyte_string; |
| 2473 | ret = build_string (name); | ||
| 2474 | 2473 | ||
| 2475 | if (atom && name) XFree (name); | 2474 | if (name) |
| 2476 | if (NILP (ret)) ret = empty_unibyte_string; | 2475 | { |
| 2477 | 2476 | if (!had_errors_p) | |
| 2478 | unblock_input (); | 2477 | ret = build_string (name); |
| 2478 | xfree (name); | ||
| 2479 | } | ||
| 2479 | 2480 | ||
| 2480 | return ret; | 2481 | return ret; |
| 2481 | } | 2482 | } |
| @@ -2492,13 +2493,13 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) | |||
| 2492 | ptrdiff_t i; | 2493 | ptrdiff_t i; |
| 2493 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 2494 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 2494 | 2495 | ||
| 2495 | |||
| 2496 | if (SYMBOLP (atom)) | 2496 | if (SYMBOLP (atom)) |
| 2497 | x_atom = symbol_to_x_atom (dpyinfo, atom); | 2497 | x_atom = symbol_to_x_atom (dpyinfo, atom); |
| 2498 | else if (STRINGP (atom)) | 2498 | else if (STRINGP (atom)) |
| 2499 | { | 2499 | { |
| 2500 | block_input (); | 2500 | block_input (); |
| 2501 | x_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (atom), False); | 2501 | x_atom = x_intern_cached_atom (dpyinfo, SSDATA (atom), |
| 2502 | false); | ||
| 2502 | unblock_input (); | 2503 | unblock_input (); |
| 2503 | } | 2504 | } |
| 2504 | else | 2505 | else |
| @@ -2521,7 +2522,8 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) | |||
| 2521 | 2522 | ||
| 2522 | bool | 2523 | bool |
| 2523 | x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, | 2524 | x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, |
| 2524 | struct x_display_info *dpyinfo, struct input_event *bufp) | 2525 | struct x_display_info *dpyinfo, struct input_event *bufp, |
| 2526 | bool root_window_coords, int root_x, int root_y) | ||
| 2525 | { | 2527 | { |
| 2526 | Lisp_Object vec; | 2528 | Lisp_Object vec; |
| 2527 | Lisp_Object frame; | 2529 | Lisp_Object frame; |
| @@ -2531,6 +2533,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, | |||
| 2531 | unsigned char *data = (unsigned char *) event->data.b; | 2533 | unsigned char *data = (unsigned char *) event->data.b; |
| 2532 | int idata[5]; | 2534 | int idata[5]; |
| 2533 | ptrdiff_t i; | 2535 | ptrdiff_t i; |
| 2536 | Window child_return; | ||
| 2534 | 2537 | ||
| 2535 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) | 2538 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) |
| 2536 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; | 2539 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; |
| @@ -2562,7 +2565,15 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, | |||
| 2562 | event->format, | 2565 | event->format, |
| 2563 | size)); | 2566 | size)); |
| 2564 | 2567 | ||
| 2565 | x_relative_mouse_position (f, &x, &y); | 2568 | if (!root_window_coords) |
| 2569 | x_relative_mouse_position (f, &x, &y); | ||
| 2570 | else | ||
| 2571 | XTranslateCoordinates (dpyinfo->display, | ||
| 2572 | dpyinfo->root_window, | ||
| 2573 | FRAME_X_WINDOW (f), | ||
| 2574 | root_x, root_y, | ||
| 2575 | &x, &y, &child_return); | ||
| 2576 | |||
| 2566 | bufp->kind = DRAG_N_DROP_EVENT; | 2577 | bufp->kind = DRAG_N_DROP_EVENT; |
| 2567 | bufp->frame_or_window = frame; | 2578 | bufp->frame_or_window = frame; |
| 2568 | bufp->timestamp = CurrentTime; | 2579 | bufp->timestamp = CurrentTime; |
| @@ -2799,6 +2810,14 @@ A value of 0 means wait as long as necessary. This is initialized from the | |||
| 2799 | \"*selectionTimeout\" resource. */); | 2810 | \"*selectionTimeout\" resource. */); |
| 2800 | x_selection_timeout = 0; | 2811 | x_selection_timeout = 0; |
| 2801 | 2812 | ||
| 2813 | DEFVAR_LISP ("x-treat-local-requests-remotely", Vx_treat_local_requests_remotely, | ||
| 2814 | doc: /* Whether to treat local selection requests as remote ones. | ||
| 2815 | |||
| 2816 | If non-nil, selection converters for string types (`STRING', | ||
| 2817 | `UTF8_STRING', `COMPOUND_TEXT', etc) will encode the strings, even | ||
| 2818 | when Emacs itself is converting the selection. */); | ||
| 2819 | Vx_treat_local_requests_remotely = Qnil; | ||
| 2820 | |||
| 2802 | /* QPRIMARY is defined in keyboard.c. */ | 2821 | /* QPRIMARY is defined in keyboard.c. */ |
| 2803 | DEFSYM (QSECONDARY, "SECONDARY"); | 2822 | DEFSYM (QSECONDARY, "SECONDARY"); |
| 2804 | DEFSYM (QSTRING, "STRING"); | 2823 | DEFSYM (QSTRING, "STRING"); |
| @@ -2838,6 +2857,4 @@ syms_of_xselect_for_pdumper (void) | |||
| 2838 | property_change_wait_list = 0; | 2857 | property_change_wait_list = 0; |
| 2839 | prop_location_identifier = 0; | 2858 | prop_location_identifier = 0; |
| 2840 | property_change_reply = Fcons (Qnil, Qnil); | 2859 | property_change_reply = Fcons (Qnil, Qnil); |
| 2841 | converted_selections = NULL; | ||
| 2842 | conversion_fail_tag = None; | ||
| 2843 | } | 2860 | } |
diff --git a/src/xsettings.c b/src/xsettings.c index 71d02e61525..c29a844e0a8 100644 --- a/src/xsettings.c +++ b/src/xsettings.c | |||
| @@ -206,6 +206,11 @@ struct xsettings | |||
| 206 | unsigned seen; | 206 | unsigned seen; |
| 207 | }; | 207 | }; |
| 208 | 208 | ||
| 209 | #ifdef HAVE_PGTK | ||
| 210 | /* The cairo font_options as obtained using gsettings. */ | ||
| 211 | static cairo_font_options_t *font_options; | ||
| 212 | #endif | ||
| 213 | |||
| 209 | #ifdef HAVE_GSETTINGS | 214 | #ifdef HAVE_GSETTINGS |
| 210 | #define GSETTINGS_SCHEMA "org.gnome.desktop.interface" | 215 | #define GSETTINGS_SCHEMA "org.gnome.desktop.interface" |
| 211 | #define GSETTINGS_TOOL_BAR_STYLE "toolbar-style" | 216 | #define GSETTINGS_TOOL_BAR_STYLE "toolbar-style" |
| @@ -215,11 +220,162 @@ struct xsettings | |||
| 215 | #define GSETTINGS_FONT_NAME "font-name" | 220 | #define GSETTINGS_FONT_NAME "font-name" |
| 216 | #endif | 221 | #endif |
| 217 | 222 | ||
| 223 | #ifdef HAVE_PGTK | ||
| 224 | #define GSETTINGS_FONT_ANTIALIASING "font-antialiasing" | ||
| 225 | #define GSETTINGS_FONT_RGBA_ORDER "font-rgba-order" | ||
| 226 | #define GSETTINGS_FONT_HINTING "font-hinting" | ||
| 227 | #endif | ||
| 218 | 228 | ||
| 219 | /* The single GSettings instance, or NULL if not connected to GSettings. */ | 229 | /* The single GSettings instance, or NULL if not connected to GSettings. */ |
| 220 | 230 | ||
| 221 | static GSettings *gsettings_client; | 231 | static GSettings *gsettings_client; |
| 222 | 232 | ||
| 233 | #if defined HAVE_PGTK && defined HAVE_GSETTINGS | ||
| 234 | |||
| 235 | static bool | ||
| 236 | xg_settings_key_valid_p (GSettings *settings, const char *key) | ||
| 237 | { | ||
| 238 | #ifdef GLIB_VERSION_2_32 | ||
| 239 | GSettingsSchema *schema; | ||
| 240 | bool rc; | ||
| 241 | |||
| 242 | g_object_get (G_OBJECT (settings), | ||
| 243 | "settings-schema", &schema, | ||
| 244 | NULL); | ||
| 245 | |||
| 246 | if (!schema) | ||
| 247 | return false; | ||
| 248 | |||
| 249 | rc = g_settings_schema_has_key (schema, key); | ||
| 250 | g_settings_schema_unref (schema); | ||
| 251 | |||
| 252 | return rc; | ||
| 253 | #else | ||
| 254 | return false; | ||
| 255 | #endif | ||
| 256 | } | ||
| 257 | |||
| 258 | #endif | ||
| 259 | |||
| 260 | #ifdef HAVE_PGTK | ||
| 261 | /* Store an event for re-rendering of the fonts. */ | ||
| 262 | static void | ||
| 263 | store_font_options_changed (void) | ||
| 264 | { | ||
| 265 | if (dpyinfo_valid (first_dpyinfo)) | ||
| 266 | store_config_changed_event (Qfont_render, | ||
| 267 | XCAR (first_dpyinfo->name_list_element)); | ||
| 268 | } | ||
| 269 | |||
| 270 | /* Apply changes in the hinting system setting. */ | ||
| 271 | static void | ||
| 272 | apply_gsettings_font_hinting (GSettings *settings) | ||
| 273 | { | ||
| 274 | GVariant *val; | ||
| 275 | const char *hinting; | ||
| 276 | |||
| 277 | if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_HINTING)) | ||
| 278 | return; | ||
| 279 | |||
| 280 | val = g_settings_get_value (settings, GSETTINGS_FONT_HINTING); | ||
| 281 | |||
| 282 | if (val) | ||
| 283 | { | ||
| 284 | g_variant_ref_sink (val); | ||
| 285 | |||
| 286 | if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) | ||
| 287 | { | ||
| 288 | hinting = g_variant_get_string (val, NULL); | ||
| 289 | |||
| 290 | if (!strcmp (hinting, "full")) | ||
| 291 | cairo_font_options_set_hint_style (font_options, | ||
| 292 | CAIRO_HINT_STYLE_FULL); | ||
| 293 | else if (!strcmp (hinting, "medium")) | ||
| 294 | cairo_font_options_set_hint_style (font_options, | ||
| 295 | CAIRO_HINT_STYLE_MEDIUM); | ||
| 296 | else if (!strcmp (hinting, "slight")) | ||
| 297 | cairo_font_options_set_hint_style (font_options, | ||
| 298 | CAIRO_HINT_STYLE_SLIGHT); | ||
| 299 | else if (!strcmp (hinting, "none")) | ||
| 300 | cairo_font_options_set_hint_style (font_options, | ||
| 301 | CAIRO_HINT_STYLE_NONE); | ||
| 302 | } | ||
| 303 | g_variant_unref (val); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Apply changes in the antialiasing system setting. */ | ||
| 308 | static void | ||
| 309 | apply_gsettings_font_antialias (GSettings *settings) | ||
| 310 | { | ||
| 311 | GVariant *val; | ||
| 312 | const char *antialias; | ||
| 313 | |||
| 314 | if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_ANTIALIASING)) | ||
| 315 | return; | ||
| 316 | |||
| 317 | val = g_settings_get_value (settings, GSETTINGS_FONT_ANTIALIASING); | ||
| 318 | |||
| 319 | if (val) | ||
| 320 | { | ||
| 321 | g_variant_ref_sink (val); | ||
| 322 | if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) | ||
| 323 | { | ||
| 324 | antialias = g_variant_get_string (val, NULL); | ||
| 325 | |||
| 326 | if (!strcmp (antialias, "none")) | ||
| 327 | cairo_font_options_set_antialias (font_options, | ||
| 328 | CAIRO_ANTIALIAS_NONE); | ||
| 329 | else if (!strcmp (antialias, "grayscale")) | ||
| 330 | cairo_font_options_set_antialias (font_options, | ||
| 331 | CAIRO_ANTIALIAS_GRAY); | ||
| 332 | else if (!strcmp (antialias, "rgba")) | ||
| 333 | cairo_font_options_set_antialias (font_options, | ||
| 334 | CAIRO_ANTIALIAS_SUBPIXEL); | ||
| 335 | } | ||
| 336 | g_variant_unref (val); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | /* Apply the settings for the rgb element ordering. */ | ||
| 341 | static void | ||
| 342 | apply_gsettings_font_rgba_order (GSettings *settings) | ||
| 343 | { | ||
| 344 | GVariant *val; | ||
| 345 | const char *rgba_order; | ||
| 346 | |||
| 347 | if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_RGBA_ORDER)) | ||
| 348 | return; | ||
| 349 | |||
| 350 | val = g_settings_get_value (settings, | ||
| 351 | GSETTINGS_FONT_RGBA_ORDER); | ||
| 352 | |||
| 353 | if (val) | ||
| 354 | { | ||
| 355 | g_variant_ref_sink (val); | ||
| 356 | |||
| 357 | if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) | ||
| 358 | { | ||
| 359 | rgba_order = g_variant_get_string (val, NULL); | ||
| 360 | |||
| 361 | if (!strcmp (rgba_order, "rgb")) | ||
| 362 | cairo_font_options_set_subpixel_order (font_options, | ||
| 363 | CAIRO_SUBPIXEL_ORDER_RGB); | ||
| 364 | else if (!strcmp (rgba_order, "bgr")) | ||
| 365 | cairo_font_options_set_subpixel_order (font_options, | ||
| 366 | CAIRO_SUBPIXEL_ORDER_BGR); | ||
| 367 | else if (!strcmp (rgba_order, "vrgb")) | ||
| 368 | cairo_font_options_set_subpixel_order (font_options, | ||
| 369 | CAIRO_SUBPIXEL_ORDER_VRGB); | ||
| 370 | else if (!strcmp (rgba_order, "vbgr")) | ||
| 371 | cairo_font_options_set_subpixel_order (font_options, | ||
| 372 | CAIRO_SUBPIXEL_ORDER_VBGR); | ||
| 373 | } | ||
| 374 | g_variant_unref (val); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | #endif /* HAVE_PGTK */ | ||
| 378 | |||
| 223 | /* Callback called when something changed in GSettings. */ | 379 | /* Callback called when something changed in GSettings. */ |
| 224 | 380 | ||
| 225 | static void | 381 | static void |
| @@ -273,6 +429,23 @@ something_changed_gsettingsCB (GSettings *settings, | |||
| 273 | } | 429 | } |
| 274 | } | 430 | } |
| 275 | #endif /* USE_CAIRO || HAVE_XFT */ | 431 | #endif /* USE_CAIRO || HAVE_XFT */ |
| 432 | #ifdef HAVE_PGTK | ||
| 433 | else if (!strcmp (key, GSETTINGS_FONT_ANTIALIASING)) | ||
| 434 | { | ||
| 435 | apply_gsettings_font_antialias (settings); | ||
| 436 | store_font_options_changed (); | ||
| 437 | } | ||
| 438 | else if (!strcmp (key, GSETTINGS_FONT_HINTING)) | ||
| 439 | { | ||
| 440 | apply_gsettings_font_hinting (settings); | ||
| 441 | store_font_options_changed (); | ||
| 442 | } | ||
| 443 | else if (!strcmp (key, GSETTINGS_FONT_RGBA_ORDER)) | ||
| 444 | { | ||
| 445 | apply_gsettings_font_rgba_order (settings); | ||
| 446 | store_font_options_changed (); | ||
| 447 | } | ||
| 448 | #endif /* HAVE_PGTK */ | ||
| 276 | } | 449 | } |
| 277 | 450 | ||
| 278 | #endif /* HAVE_GSETTINGS */ | 451 | #endif /* HAVE_GSETTINGS */ |
| @@ -900,6 +1073,16 @@ init_gsettings (void) | |||
| 900 | dupstring (¤t_font, g_variant_get_string (val, NULL)); | 1073 | dupstring (¤t_font, g_variant_get_string (val, NULL)); |
| 901 | g_variant_unref (val); | 1074 | g_variant_unref (val); |
| 902 | } | 1075 | } |
| 1076 | |||
| 1077 | /* Only use the gsettings font entries for the Cairo backend | ||
| 1078 | running on PGTK. */ | ||
| 1079 | #ifdef HAVE_PGTK | ||
| 1080 | font_options = cairo_font_options_create (); | ||
| 1081 | apply_gsettings_font_antialias (gsettings_client); | ||
| 1082 | apply_gsettings_font_hinting (gsettings_client); | ||
| 1083 | apply_gsettings_font_rgba_order (gsettings_client); | ||
| 1084 | #endif /* HAVE_PGTK */ | ||
| 1085 | |||
| 903 | #endif /* USE_CAIRO || HAVE_XFT */ | 1086 | #endif /* USE_CAIRO || HAVE_XFT */ |
| 904 | 1087 | ||
| 905 | #endif /* HAVE_GSETTINGS */ | 1088 | #endif /* HAVE_GSETTINGS */ |
| @@ -1021,6 +1204,21 @@ xsettings_get_system_normal_font (void) | |||
| 1021 | } | 1204 | } |
| 1022 | #endif | 1205 | #endif |
| 1023 | 1206 | ||
| 1207 | #ifdef HAVE_PGTK | ||
| 1208 | /* Return the cairo font options, updated from the gsettings font | ||
| 1209 | config entries. The caller should call cairo_font_options_destroy | ||
| 1210 | on the result. */ | ||
| 1211 | cairo_font_options_t * | ||
| 1212 | xsettings_get_font_options (void) | ||
| 1213 | { | ||
| 1214 | if (font_options != NULL) | ||
| 1215 | return cairo_font_options_copy (font_options); | ||
| 1216 | else | ||
| 1217 | /* GSettings is not configured. */ | ||
| 1218 | return cairo_font_options_create (); | ||
| 1219 | } | ||
| 1220 | #endif | ||
| 1221 | |||
| 1024 | DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font, | 1222 | DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font, |
| 1025 | Sfont_get_system_normal_font, | 1223 | Sfont_get_system_normal_font, |
| 1026 | 0, 0, 0, | 1224 | 0, 0, 0, |
| @@ -1073,6 +1271,10 @@ syms_of_xsettings (void) | |||
| 1073 | gconf_client = NULL; | 1271 | gconf_client = NULL; |
| 1074 | PDUMPER_IGNORE (gconf_client); | 1272 | PDUMPER_IGNORE (gconf_client); |
| 1075 | #endif | 1273 | #endif |
| 1274 | #ifdef HAVE_PGTK | ||
| 1275 | font_options = NULL; | ||
| 1276 | PDUMPER_IGNORE (font_options); | ||
| 1277 | #endif | ||
| 1076 | 1278 | ||
| 1077 | DEFSYM (Qmonospace_font_name, "monospace-font-name"); | 1279 | DEFSYM (Qmonospace_font_name, "monospace-font-name"); |
| 1078 | DEFSYM (Qfont_name, "font-name"); | 1280 | DEFSYM (Qfont_name, "font-name"); |
diff --git a/src/xsettings.h b/src/xsettings.h index ccaa36489d0..5e5df37062b 100644 --- a/src/xsettings.h +++ b/src/xsettings.h | |||
| @@ -23,6 +23,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 23 | #ifndef HAVE_PGTK | 23 | #ifndef HAVE_PGTK |
| 24 | #include "dispextern.h" | 24 | #include "dispextern.h" |
| 25 | #include <X11/Xlib.h> | 25 | #include <X11/Xlib.h> |
| 26 | #else | ||
| 27 | #include <cairo.h> | ||
| 26 | #endif | 28 | #endif |
| 27 | 29 | ||
| 28 | struct x_display_info; | 30 | struct x_display_info; |
| @@ -41,5 +43,8 @@ extern const char *xsettings_get_system_font (void); | |||
| 41 | extern const char *xsettings_get_system_normal_font (void); | 43 | extern const char *xsettings_get_system_normal_font (void); |
| 42 | #endif | 44 | #endif |
| 43 | 45 | ||
| 46 | #ifdef HAVE_PGTK | ||
| 47 | extern cairo_font_options_t *xsettings_get_font_options (void); | ||
| 48 | #endif | ||
| 44 | 49 | ||
| 45 | #endif /* XSETTINGS_H */ | 50 | #endif /* XSETTINGS_H */ |
diff --git a/src/xterm.c b/src/xterm.c index 2141964c747..2cc17b455da 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -78,7 +78,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 78 | INPUT FOCUS | 78 | INPUT FOCUS |
| 79 | 79 | ||
| 80 | Under X, the window where keyboard input is sent is not always | 80 | Under X, the window where keyboard input is sent is not always |
| 81 | explictly defined. When there is a focus window, it receives what | 81 | explicitly defined. When there is a focus window, it receives what |
| 82 | is referred to as "explicit focus", but when there is none, it | 82 | is referred to as "explicit focus", but when there is none, it |
| 83 | receives "implicit focus" whenever the pointer enters it, and loses | 83 | receives "implicit focus" whenever the pointer enters it, and loses |
| 84 | that focus when the pointer leaves. When the toplevel window of a | 84 | that focus when the pointer leaves. When the toplevel window of a |
| @@ -550,6 +550,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 550 | #include <config.h> | 550 | #include <config.h> |
| 551 | #include <stdlib.h> | 551 | #include <stdlib.h> |
| 552 | #include <math.h> | 552 | #include <math.h> |
| 553 | #include <signal.h> | ||
| 553 | 554 | ||
| 554 | #include "lisp.h" | 555 | #include "lisp.h" |
| 555 | #include "blockinput.h" | 556 | #include "blockinput.h" |
| @@ -699,6 +700,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 699 | #endif | 700 | #endif |
| 700 | #endif | 701 | #endif |
| 701 | 702 | ||
| 703 | #ifdef USE_GTK | ||
| 704 | #include <xgselect.h> | ||
| 705 | #endif | ||
| 706 | |||
| 702 | #include "bitmaps/gray.xbm" | 707 | #include "bitmaps/gray.xbm" |
| 703 | 708 | ||
| 704 | #ifdef HAVE_XKB | 709 | #ifdef HAVE_XKB |
| @@ -784,6 +789,227 @@ static int current_finish; | |||
| 784 | static struct input_event *current_hold_quit; | 789 | static struct input_event *current_hold_quit; |
| 785 | #endif | 790 | #endif |
| 786 | 791 | ||
| 792 | /* Queue selection requests in `pending_selection_requests' if more | ||
| 793 | than 0. */ | ||
| 794 | static int x_use_pending_selection_requests; | ||
| 795 | |||
| 796 | static void x_push_selection_request (struct selection_input_event *); | ||
| 797 | |||
| 798 | /* Defer selection requests. Between this and | ||
| 799 | x_release_selection_requests, any selection requests can be | ||
| 800 | processed by calling `x_handle_pending_selection_requests'. | ||
| 801 | |||
| 802 | Also run through and queue all the selection events already in the | ||
| 803 | keyboard buffer. */ | ||
| 804 | void | ||
| 805 | x_defer_selection_requests (void) | ||
| 806 | { | ||
| 807 | union buffered_input_event *event; | ||
| 808 | bool between; | ||
| 809 | |||
| 810 | between = false; | ||
| 811 | |||
| 812 | block_input (); | ||
| 813 | if (!x_use_pending_selection_requests) | ||
| 814 | { | ||
| 815 | event = kbd_fetch_ptr; | ||
| 816 | |||
| 817 | while (event != kbd_store_ptr) | ||
| 818 | { | ||
| 819 | if (event->ie.kind == SELECTION_REQUEST_EVENT | ||
| 820 | || event->ie.kind == SELECTION_CLEAR_EVENT) | ||
| 821 | { | ||
| 822 | x_push_selection_request (&event->sie); | ||
| 823 | |||
| 824 | /* Mark this selection event as invalid. */ | ||
| 825 | SELECTION_EVENT_DPYINFO (&event->sie) = NULL; | ||
| 826 | |||
| 827 | /* Move the kbd_fetch_ptr along if doing so would not | ||
| 828 | result in any other events being skipped. This | ||
| 829 | avoids exhausting the keyboard buffer with some | ||
| 830 | over-enthusiastic clipboard managers. */ | ||
| 831 | if (!between) | ||
| 832 | kbd_fetch_ptr = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 833 | ? kbd_buffer : event + 1); | ||
| 834 | } | ||
| 835 | else | ||
| 836 | between = true; | ||
| 837 | |||
| 838 | event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 839 | ? kbd_buffer : event + 1); | ||
| 840 | } | ||
| 841 | } | ||
| 842 | |||
| 843 | x_use_pending_selection_requests++; | ||
| 844 | unblock_input (); | ||
| 845 | } | ||
| 846 | |||
| 847 | static void | ||
| 848 | x_release_selection_requests (void) | ||
| 849 | { | ||
| 850 | x_use_pending_selection_requests--; | ||
| 851 | } | ||
| 852 | |||
| 853 | void | ||
| 854 | x_release_selection_requests_and_flush (void) | ||
| 855 | { | ||
| 856 | x_release_selection_requests (); | ||
| 857 | |||
| 858 | if (!x_use_pending_selection_requests) | ||
| 859 | x_handle_pending_selection_requests (); | ||
| 860 | } | ||
| 861 | |||
| 862 | struct x_selection_request_event | ||
| 863 | { | ||
| 864 | /* The selection request event. */ | ||
| 865 | struct selection_input_event se; | ||
| 866 | |||
| 867 | /* The next unprocessed selection request event. */ | ||
| 868 | struct x_selection_request_event *next; | ||
| 869 | }; | ||
| 870 | |||
| 871 | /* Chain of unprocessed selection request events. Used to handle | ||
| 872 | selection requests inside long-lasting modal event loops, such as | ||
| 873 | the drag-and-drop loop. */ | ||
| 874 | |||
| 875 | struct x_selection_request_event *pending_selection_requests; | ||
| 876 | |||
| 877 | /* Compare two request serials A and B with OP, handling | ||
| 878 | wraparound. */ | ||
| 879 | #define X_COMPARE_SERIALS(a, op ,b) \ | ||
| 880 | (((long) (a) - (long) (b)) op 0) | ||
| 881 | |||
| 882 | struct x_atom_ref | ||
| 883 | { | ||
| 884 | /* Atom name. */ | ||
| 885 | const char *name; | ||
| 886 | |||
| 887 | /* Offset of atom in the display info structure. */ | ||
| 888 | int offset; | ||
| 889 | }; | ||
| 890 | |||
| 891 | /* List of all atoms that should be interned when connecting to a | ||
| 892 | display. */ | ||
| 893 | static const struct x_atom_ref x_atom_refs[] = | ||
| 894 | { | ||
| 895 | #define ATOM_REFS_INIT(string, member) \ | ||
| 896 | { string, offsetof (struct x_display_info, member) }, | ||
| 897 | ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols) | ||
| 898 | ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus) | ||
| 899 | ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself) | ||
| 900 | ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window) | ||
| 901 | ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state) | ||
| 902 | ATOM_REFS_INIT ("WM_STATE", Xatom_wm_state) | ||
| 903 | ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied) | ||
| 904 | ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved) | ||
| 905 | ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader) | ||
| 906 | ATOM_REFS_INIT ("WM_TRANSIENT_FOR", Xatom_wm_transient_for) | ||
| 907 | ATOM_REFS_INIT ("Editres", Xatom_editres) | ||
| 908 | ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD) | ||
| 909 | ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP) | ||
| 910 | ATOM_REFS_INIT ("TEXT", Xatom_TEXT) | ||
| 911 | ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT) | ||
| 912 | ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING) | ||
| 913 | ATOM_REFS_INIT ("DELETE", Xatom_DELETE) | ||
| 914 | ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE) | ||
| 915 | ATOM_REFS_INIT ("INCR", Xatom_INCR) | ||
| 916 | ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP) | ||
| 917 | ATOM_REFS_INIT ("EMACS_SERVER_TIME_PROP", Xatom_EMACS_SERVER_TIME_PROP) | ||
| 918 | ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS) | ||
| 919 | ATOM_REFS_INIT ("NULL", Xatom_NULL) | ||
| 920 | ATOM_REFS_INIT ("ATOM", Xatom_ATOM) | ||
| 921 | ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR) | ||
| 922 | ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) | ||
| 923 | ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) | ||
| 924 | ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS) | ||
| 925 | /* For properties of font. */ | ||
| 926 | ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE) | ||
| 927 | ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH) | ||
| 928 | ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET) | ||
| 929 | ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE) | ||
| 930 | ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT) | ||
| 931 | /* Ghostscript support. */ | ||
| 932 | ATOM_REFS_INIT ("DONE", Xatom_DONE) | ||
| 933 | ATOM_REFS_INIT ("PAGE", Xatom_PAGE) | ||
| 934 | ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) | ||
| 935 | ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar) | ||
| 936 | ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) | ||
| 937 | /* EWMH */ | ||
| 938 | ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) | ||
| 939 | ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen) | ||
| 940 | ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ", | ||
| 941 | Xatom_net_wm_state_maximized_horz) | ||
| 942 | ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT", | ||
| 943 | Xatom_net_wm_state_maximized_vert) | ||
| 944 | ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky) | ||
| 945 | ATOM_REFS_INIT ("_NET_WM_STATE_SHADED", Xatom_net_wm_state_shaded) | ||
| 946 | ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden) | ||
| 947 | ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type) | ||
| 948 | ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP", | ||
| 949 | Xatom_net_window_type_tooltip) | ||
| 950 | ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name) | ||
| 951 | ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name) | ||
| 952 | ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported) | ||
| 953 | ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check) | ||
| 954 | ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity) | ||
| 955 | ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window) | ||
| 956 | ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents) | ||
| 957 | ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop) | ||
| 958 | ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea) | ||
| 959 | ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request) | ||
| 960 | ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter) | ||
| 961 | ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn) | ||
| 962 | ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time) | ||
| 963 | ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window) | ||
| 964 | ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking) | ||
| 965 | /* Session management */ | ||
| 966 | ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) | ||
| 967 | ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) | ||
| 968 | ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) | ||
| 969 | ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar) | ||
| 970 | ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above) | ||
| 971 | ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below) | ||
| 972 | ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region) | ||
| 973 | ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping) | ||
| 974 | ATOM_REFS_INIT ("_NET_WM_PID", Xatom_net_wm_pid) | ||
| 975 | #ifdef HAVE_XKB | ||
| 976 | ATOM_REFS_INIT ("Meta", Xatom_Meta) | ||
| 977 | ATOM_REFS_INIT ("Super", Xatom_Super) | ||
| 978 | ATOM_REFS_INIT ("Hyper", Xatom_Hyper) | ||
| 979 | ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock) | ||
| 980 | ATOM_REFS_INIT ("Alt", Xatom_Alt) | ||
| 981 | #endif | ||
| 982 | /* DND source. */ | ||
| 983 | ATOM_REFS_INIT ("XdndAware", Xatom_XdndAware) | ||
| 984 | ATOM_REFS_INIT ("XdndSelection", Xatom_XdndSelection) | ||
| 985 | ATOM_REFS_INIT ("XdndTypeList", Xatom_XdndTypeList) | ||
| 986 | ATOM_REFS_INIT ("XdndActionCopy", Xatom_XdndActionCopy) | ||
| 987 | ATOM_REFS_INIT ("XdndActionMove", Xatom_XdndActionMove) | ||
| 988 | ATOM_REFS_INIT ("XdndActionLink", Xatom_XdndActionLink) | ||
| 989 | ATOM_REFS_INIT ("XdndActionAsk", Xatom_XdndActionAsk) | ||
| 990 | ATOM_REFS_INIT ("XdndActionPrivate", Xatom_XdndActionPrivate) | ||
| 991 | ATOM_REFS_INIT ("XdndActionList", Xatom_XdndActionList) | ||
| 992 | ATOM_REFS_INIT ("XdndActionDescription", Xatom_XdndActionDescription) | ||
| 993 | ATOM_REFS_INIT ("XdndProxy", Xatom_XdndProxy) | ||
| 994 | ATOM_REFS_INIT ("XdndEnter", Xatom_XdndEnter) | ||
| 995 | ATOM_REFS_INIT ("XdndPosition", Xatom_XdndPosition) | ||
| 996 | ATOM_REFS_INIT ("XdndStatus", Xatom_XdndStatus) | ||
| 997 | ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave) | ||
| 998 | ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop) | ||
| 999 | ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished) | ||
| 1000 | /* Motif drop protocol support. */ | ||
| 1001 | ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW) | ||
| 1002 | ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS) | ||
| 1003 | ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE", | ||
| 1004 | Xatom_MOTIF_DRAG_AND_DROP_MESSAGE) | ||
| 1005 | ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO", | ||
| 1006 | Xatom_MOTIF_DRAG_INITIATOR_INFO) | ||
| 1007 | ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO", | ||
| 1008 | Xatom_MOTIF_DRAG_RECEIVER_INFO) | ||
| 1009 | ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS) | ||
| 1010 | ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE) | ||
| 1011 | }; | ||
| 1012 | |||
| 787 | enum | 1013 | enum |
| 788 | { | 1014 | { |
| 789 | X_EVENT_NORMAL, | 1015 | X_EVENT_NORMAL, |
| @@ -863,19 +1089,39 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar | |||
| 863 | static int x_filter_event (struct x_display_info *, XEvent *); | 1089 | static int x_filter_event (struct x_display_info *, XEvent *); |
| 864 | #endif | 1090 | #endif |
| 865 | 1091 | ||
| 1092 | static struct frame *x_tooltip_window_to_frame (struct x_display_info *, | ||
| 1093 | Window, bool *); | ||
| 1094 | static Window x_get_window_below (Display *, Window, int, int, int *, int *); | ||
| 1095 | |||
| 866 | /* Global state maintained during a drag-and-drop operation. */ | 1096 | /* Global state maintained during a drag-and-drop operation. */ |
| 867 | 1097 | ||
| 868 | /* Flag that indicates if a drag-and-drop operation is in progress. */ | 1098 | /* Flag that indicates if a drag-and-drop operation is in progress. */ |
| 869 | bool x_dnd_in_progress; | 1099 | bool x_dnd_in_progress; |
| 870 | 1100 | ||
| 1101 | /* Number that indicates the last "generation" of | ||
| 1102 | UNSUPPORTED_DROP_EVENTs handled. */ | ||
| 1103 | unsigned x_dnd_unsupported_event_level; | ||
| 1104 | |||
| 871 | /* The frame where the drag-and-drop operation originated. */ | 1105 | /* The frame where the drag-and-drop operation originated. */ |
| 872 | struct frame *x_dnd_frame; | 1106 | struct frame *x_dnd_frame; |
| 873 | 1107 | ||
| 1108 | /* That frame, but set when x_dnd_waiting_for_finish is true. Used to | ||
| 1109 | prevent the frame from being deleted inside selection handlers and | ||
| 1110 | other callbacks. */ | ||
| 1111 | struct frame *x_dnd_finish_frame; | ||
| 1112 | |||
| 874 | /* Flag that indicates if a drag-and-drop operation is no longer in | 1113 | /* Flag that indicates if a drag-and-drop operation is no longer in |
| 875 | progress, but the nested event loop should continue to run, because | 1114 | progress, but the nested event loop should continue to run, because |
| 876 | handle_one_xevent is waiting for the drop target to return some | 1115 | handle_one_xevent is waiting for the drop target to return some |
| 877 | important information. */ | 1116 | important information. */ |
| 878 | static bool x_dnd_waiting_for_finish; | 1117 | bool x_dnd_waiting_for_finish; |
| 1118 | |||
| 1119 | /* Whether or not to move the tooltip along with the mouse pointer | ||
| 1120 | during drag-and-drop. */ | ||
| 1121 | static bool x_dnd_update_tooltip; | ||
| 1122 | |||
| 1123 | /* Monitor attribute list used for updating the tooltip position. */ | ||
| 1124 | static Lisp_Object x_dnd_monitors; | ||
| 879 | 1125 | ||
| 880 | /* The display the drop target that is supposed to send information is | 1126 | /* The display the drop target that is supposed to send information is |
| 881 | on. */ | 1127 | on. */ |
| @@ -916,6 +1162,10 @@ static int x_dnd_waiting_for_finish_proto; | |||
| 916 | where the drag-and-drop operation originated. */ | 1162 | where the drag-and-drop operation originated. */ |
| 917 | static bool x_dnd_allow_current_frame; | 1163 | static bool x_dnd_allow_current_frame; |
| 918 | 1164 | ||
| 1165 | /* Whether or not the `XdndTypeList' property has already been set on | ||
| 1166 | the drag frame. */ | ||
| 1167 | static bool x_dnd_init_type_lists; | ||
| 1168 | |||
| 919 | /* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'. | 1169 | /* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'. |
| 920 | 1170 | ||
| 921 | 0 means to do nothing. 1 means to wait for the mouse to first exit | 1171 | 0 means to do nothing. 1 means to wait for the mouse to first exit |
| @@ -943,6 +1193,10 @@ static Window x_dnd_end_window; | |||
| 943 | did not support XDND. */ | 1193 | did not support XDND. */ |
| 944 | static int x_dnd_last_protocol_version; | 1194 | static int x_dnd_last_protocol_version; |
| 945 | 1195 | ||
| 1196 | /* Whether or not the last seen window is actually one of our | ||
| 1197 | frames. */ | ||
| 1198 | static bool x_dnd_last_window_is_frame; | ||
| 1199 | |||
| 946 | /* The Motif drag and drop protocol style of `x_dnd_last_seen_window'. | 1200 | /* The Motif drag and drop protocol style of `x_dnd_last_seen_window'. |
| 947 | XM_DRAG_STYLE_NONE means the window does not support the Motif drag | 1201 | XM_DRAG_STYLE_NONE means the window does not support the Motif drag |
| 948 | or drop protocol. XM_DRAG_STYLE_DROP_ONLY means the window does | 1202 | or drop protocol. XM_DRAG_STYLE_DROP_ONLY means the window does |
| @@ -974,13 +1228,25 @@ static XRectangle x_dnd_mouse_rect; | |||
| 974 | protocol, this is set to the atom XdndActionPrivate. */ | 1228 | protocol, this is set to the atom XdndActionPrivate. */ |
| 975 | static Atom x_dnd_action; | 1229 | static Atom x_dnd_action; |
| 976 | 1230 | ||
| 1231 | /* The symbol to return from `x-begin-drag' if non-nil. Takes | ||
| 1232 | precedence over `x_dnd_action`. */ | ||
| 1233 | static Lisp_Object x_dnd_action_symbol; | ||
| 1234 | |||
| 977 | /* The action we want the drop target to perform. The drop target may | 1235 | /* The action we want the drop target to perform. The drop target may |
| 978 | elect to perform some different action, which is guaranteed to be | 1236 | elect to perform some different action, which is guaranteed to be |
| 979 | in `x_dnd_action' upon completion of a drop. */ | 1237 | in `x_dnd_action' upon completion of a drop. */ |
| 980 | static Atom x_dnd_wanted_action; | 1238 | static Atom x_dnd_wanted_action; |
| 981 | 1239 | ||
| 1240 | /* The set of optional actions available to a Motif drop target | ||
| 1241 | computed at the start of the drag-and-drop operation. */ | ||
| 1242 | static uint8_t x_dnd_motif_operations; | ||
| 1243 | |||
| 1244 | /* The preferred optional action out of that set. Only takes effect | ||
| 1245 | if `x_dnd_action' is XdndAsk. */ | ||
| 1246 | static uint8_t x_dnd_first_motif_operation; | ||
| 1247 | |||
| 982 | /* Array of selection targets available to the drop target. */ | 1248 | /* Array of selection targets available to the drop target. */ |
| 983 | static Atom *x_dnd_targets = NULL; | 1249 | static Atom *x_dnd_targets; |
| 984 | 1250 | ||
| 985 | /* The number of elements in that array. */ | 1251 | /* The number of elements in that array. */ |
| 986 | static int x_dnd_n_targets; | 1252 | static int x_dnd_n_targets; |
| @@ -1009,42 +1275,86 @@ static unsigned int x_dnd_keyboard_state; | |||
| 1009 | 1275 | ||
| 1010 | /* jmp_buf that gets us out of the IO error handler if an error occurs | 1276 | /* jmp_buf that gets us out of the IO error handler if an error occurs |
| 1011 | terminating DND as part of the display disconnect handler. */ | 1277 | terminating DND as part of the display disconnect handler. */ |
| 1012 | static jmp_buf x_dnd_disconnect_handler; | 1278 | static sigjmp_buf x_dnd_disconnect_handler; |
| 1279 | |||
| 1280 | /* Whether or not the current invocation of handle_one_xevent | ||
| 1281 | happened inside the drag_and_drop event loop. */ | ||
| 1282 | static bool x_dnd_inside_handle_one_xevent; | ||
| 1283 | |||
| 1284 | /* The recursive edit depth when the drag-and-drop operation was | ||
| 1285 | started. */ | ||
| 1286 | static int x_dnd_recursion_depth; | ||
| 1013 | 1287 | ||
| 1288 | /* Structure describing a single window that can be the target of | ||
| 1289 | drag-and-drop operations. */ | ||
| 1014 | struct x_client_list_window | 1290 | struct x_client_list_window |
| 1015 | { | 1291 | { |
| 1292 | /* The window itself. */ | ||
| 1016 | Window window; | 1293 | Window window; |
| 1294 | |||
| 1295 | /* The display that window is on. */ | ||
| 1017 | Display *dpy; | 1296 | Display *dpy; |
| 1297 | |||
| 1298 | /* Its X and Y coordinates from the root window. */ | ||
| 1018 | int x, y; | 1299 | int x, y; |
| 1300 | |||
| 1301 | /* The width and height of the window. */ | ||
| 1019 | int width, height; | 1302 | int width, height; |
| 1303 | |||
| 1304 | /* Whether or not the window is mapped. */ | ||
| 1020 | bool mapped_p; | 1305 | bool mapped_p; |
| 1306 | |||
| 1307 | /* A bitmask describing events Emacs was listening for from the | ||
| 1308 | window before some extra events were added in | ||
| 1309 | `x_dnd_compute_toplevels'. */ | ||
| 1021 | long previous_event_mask; | 1310 | long previous_event_mask; |
| 1311 | |||
| 1312 | /* The window manager state of the window. */ | ||
| 1022 | unsigned long wm_state; | 1313 | unsigned long wm_state; |
| 1023 | 1314 | ||
| 1315 | /* The next window in this list. */ | ||
| 1024 | struct x_client_list_window *next; | 1316 | struct x_client_list_window *next; |
| 1317 | |||
| 1318 | /* The Motif protocol style of this window, if any. */ | ||
| 1025 | uint8_t xm_protocol_style; | 1319 | uint8_t xm_protocol_style; |
| 1026 | 1320 | ||
| 1321 | /* The extents of the frame window in each direction. */ | ||
| 1027 | int frame_extents_left; | 1322 | int frame_extents_left; |
| 1028 | int frame_extents_right; | 1323 | int frame_extents_right; |
| 1029 | int frame_extents_top; | 1324 | int frame_extents_top; |
| 1030 | int frame_extents_bottom; | 1325 | int frame_extents_bottom; |
| 1031 | 1326 | ||
| 1032 | #ifdef HAVE_XSHAPE | 1327 | #ifdef HAVE_XSHAPE |
| 1328 | /* The border width of this window. */ | ||
| 1033 | int border_width; | 1329 | int border_width; |
| 1034 | 1330 | ||
| 1331 | /* The rectangles making up the input shape. */ | ||
| 1035 | XRectangle *input_rects; | 1332 | XRectangle *input_rects; |
| 1333 | |||
| 1334 | /* The number of rectangles composing the input shape. */ | ||
| 1036 | int n_input_rects; | 1335 | int n_input_rects; |
| 1037 | 1336 | ||
| 1337 | /* The rectangles making up the bounding shape. */ | ||
| 1038 | XRectangle *bounding_rects; | 1338 | XRectangle *bounding_rects; |
| 1339 | |||
| 1340 | /* The number of rectangles composing the bounding shape. */ | ||
| 1039 | int n_bounding_rects; | 1341 | int n_bounding_rects; |
| 1040 | #endif | 1342 | #endif |
| 1041 | }; | 1343 | }; |
| 1042 | 1344 | ||
| 1043 | static struct x_client_list_window *x_dnd_toplevels = NULL; | 1345 | /* List of all toplevels in stacking order, from top to bottom. */ |
| 1346 | static struct x_client_list_window *x_dnd_toplevels; | ||
| 1347 | |||
| 1348 | /* Whether or not the window manager supports the required features | ||
| 1349 | for `x_dnd_toplevels' to work. */ | ||
| 1044 | static bool x_dnd_use_toplevels; | 1350 | static bool x_dnd_use_toplevels; |
| 1045 | 1351 | ||
| 1046 | /* Motif drag-and-drop protocol support. */ | 1352 | /* Motif drag-and-drop protocol support. */ |
| 1047 | 1353 | ||
| 1354 | /* Pointer to a variable which stores whether or not an X error | ||
| 1355 | occured while trying to create the Motif drag window. */ | ||
| 1356 | static volatile bool *xm_drag_window_error; | ||
| 1357 | |||
| 1048 | typedef enum xm_byte_order | 1358 | typedef enum xm_byte_order |
| 1049 | { | 1359 | { |
| 1050 | XM_BYTE_ORDER_LSB_FIRST = 'l', | 1360 | XM_BYTE_ORDER_LSB_FIRST = 'l', |
| @@ -1078,8 +1388,8 @@ typedef enum xm_byte_order | |||
| 1078 | } | 1388 | } |
| 1079 | 1389 | ||
| 1080 | #else | 1390 | #else |
| 1081 | #define SWAPCARD32(l) bswap_32 (l) | 1391 | #define SWAPCARD32(l) ((l) = bswap_32 (l)) |
| 1082 | #define SWAPCARD16(l) bswap_16 (l) | 1392 | #define SWAPCARD16(l) ((l) = bswap_16 (l)) |
| 1083 | #endif | 1393 | #endif |
| 1084 | 1394 | ||
| 1085 | typedef struct xm_targets_table_header | 1395 | typedef struct xm_targets_table_header |
| @@ -1181,34 +1491,50 @@ typedef struct xm_top_level_leave_message | |||
| 1181 | /* #define XM_DRAG_SIDE_EFFECT_OPERATIONS(effect) (((effect) & 0xf00) >> 8) */ | 1491 | /* #define XM_DRAG_SIDE_EFFECT_OPERATIONS(effect) (((effect) & 0xf00) >> 8) */ |
| 1182 | #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12) | 1492 | #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12) |
| 1183 | 1493 | ||
| 1184 | #define XM_DRAG_NOOP 0 | 1494 | enum xm_drag_operation |
| 1185 | #define XM_DRAG_MOVE (1L << 0) | 1495 | { |
| 1186 | #define XM_DRAG_COPY (1L << 1) | 1496 | XM_DRAG_NOOP = 0, |
| 1187 | #define XM_DRAG_LINK (1L << 2) | 1497 | XM_DRAG_MOVE = (1L << 0), |
| 1498 | XM_DRAG_COPY = (1L << 1), | ||
| 1499 | XM_DRAG_LINK = (1L << 2), | ||
| 1500 | }; | ||
| 1188 | 1501 | ||
| 1189 | #define XM_DROP_ACTION_DROP 0 | 1502 | enum xm_drag_action |
| 1190 | #define XM_DROP_ACTION_DROP_HELP 1 | 1503 | { |
| 1191 | #define XM_DROP_ACTION_DROP_CANCEL 2 | 1504 | XM_DROP_ACTION_DROP = 0, |
| 1505 | XM_DROP_ACTION_DROP_HELP = 1, | ||
| 1506 | XM_DROP_ACTION_DROP_CANCEL = 2, | ||
| 1507 | }; | ||
| 1192 | 1508 | ||
| 1193 | #define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7)) | 1509 | #define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7)) |
| 1194 | #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0) | 1510 | #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0) |
| 1195 | #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f) | 1511 | #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f) |
| 1196 | 1512 | ||
| 1197 | #define XM_DRAG_REASON_DROP_START 5 | 1513 | enum xm_drag_reason |
| 1198 | #define XM_DRAG_REASON_TOP_LEVEL_ENTER 0 | 1514 | { |
| 1199 | #define XM_DRAG_REASON_TOP_LEVEL_LEAVE 1 | 1515 | XM_DRAG_REASON_DROP_START = 5, |
| 1200 | #define XM_DRAG_REASON_DRAG_MOTION 2 | 1516 | XM_DRAG_REASON_TOP_LEVEL_ENTER = 0, |
| 1201 | #define XM_DRAG_ORIGINATOR_INITIATOR 0 | 1517 | XM_DRAG_REASON_TOP_LEVEL_LEAVE = 1, |
| 1202 | #define XM_DRAG_ORIGINATOR_RECEIVER 1 | 1518 | XM_DRAG_REASON_DRAG_MOTION = 2, |
| 1203 | 1519 | }; | |
| 1204 | #define XM_DRAG_STYLE_NONE 0 | ||
| 1205 | 1520 | ||
| 1206 | #define XM_DRAG_STYLE_DROP_ONLY 1 | 1521 | enum xm_drag_originator |
| 1207 | #define XM_DRAG_STYLE_DROP_ONLY_REC 3 | 1522 | { |
| 1523 | XM_DRAG_ORIGINATOR_INITIATOR = 0, | ||
| 1524 | XM_DRAG_ORIGINATOR_RECEIVER = 1, | ||
| 1525 | }; | ||
| 1208 | 1526 | ||
| 1209 | #define XM_DRAG_STYLE_DYNAMIC 5 | 1527 | enum xm_drag_style |
| 1210 | #define XM_DRAG_STYLE_DYNAMIC_REC 2 | 1528 | { |
| 1211 | #define XM_DRAG_STYLE_DYNAMIC_REC1 4 | 1529 | /* The values ending with _REC should be treated as equivalent to |
| 1530 | the ones without in messages from the receiver. */ | ||
| 1531 | XM_DRAG_STYLE_NONE = 0, | ||
| 1532 | XM_DRAG_STYLE_DROP_ONLY = 1, | ||
| 1533 | XM_DRAG_STYLE_DROP_ONLY_REC = 3, | ||
| 1534 | XM_DRAG_STYLE_DYNAMIC = 5, | ||
| 1535 | XM_DRAG_STYLE_DYNAMIC_REC = 2, | ||
| 1536 | XM_DRAG_STYLE_DYNAMIC_REC1 = 4, | ||
| 1537 | }; | ||
| 1212 | 1538 | ||
| 1213 | #define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \ | 1539 | #define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \ |
| 1214 | || (n) == XM_DRAG_STYLE_DROP_ONLY_REC) | 1540 | || (n) == XM_DRAG_STYLE_DROP_ONLY_REC) |
| @@ -1216,9 +1542,16 @@ typedef struct xm_top_level_leave_message | |||
| 1216 | || (n) == XM_DRAG_STYLE_DYNAMIC_REC \ | 1542 | || (n) == XM_DRAG_STYLE_DYNAMIC_REC \ |
| 1217 | || (n) == XM_DRAG_STYLE_DYNAMIC_REC1) | 1543 | || (n) == XM_DRAG_STYLE_DYNAMIC_REC1) |
| 1218 | 1544 | ||
| 1219 | #define XM_DROP_SITE_VALID 3 | 1545 | enum xm_drop_site_status |
| 1220 | /* #define XM_DROP_SITE_INVALID 2 */ | 1546 | { |
| 1221 | #define XM_DROP_SITE_NONE 1 | 1547 | XM_DROP_SITE_VALID = 3, |
| 1548 | XM_DROP_SITE_INVALID = 2, | ||
| 1549 | XM_DROP_SITE_NONE = 1, | ||
| 1550 | }; | ||
| 1551 | |||
| 1552 | /* The version of the Motif drag-and-drop protocols that Emacs | ||
| 1553 | supports. */ | ||
| 1554 | #define XM_DRAG_PROTOCOL_VERSION 0 | ||
| 1222 | 1555 | ||
| 1223 | static uint8_t | 1556 | static uint8_t |
| 1224 | xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action) | 1557 | xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action) |
| @@ -1229,10 +1562,34 @@ xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action) | |||
| 1229 | return XM_DRAG_MOVE; | 1562 | return XM_DRAG_MOVE; |
| 1230 | else if (action == dpyinfo->Xatom_XdndActionLink) | 1563 | else if (action == dpyinfo->Xatom_XdndActionLink) |
| 1231 | return XM_DRAG_LINK; | 1564 | return XM_DRAG_LINK; |
| 1565 | else if (action == dpyinfo->Xatom_XdndActionAsk) | ||
| 1566 | return x_dnd_first_motif_operation; | ||
| 1232 | 1567 | ||
| 1233 | return XM_DRAG_NOOP; | 1568 | return XM_DRAG_NOOP; |
| 1234 | } | 1569 | } |
| 1235 | 1570 | ||
| 1571 | static uint8_t | ||
| 1572 | xm_operations_from_actions (struct x_display_info *dpyinfo, | ||
| 1573 | Atom *ask_actions, int n_ask_actions) | ||
| 1574 | { | ||
| 1575 | int i; | ||
| 1576 | uint8_t flags; | ||
| 1577 | |||
| 1578 | flags = 0; | ||
| 1579 | |||
| 1580 | for (i = 0; i < n_ask_actions; ++i) | ||
| 1581 | { | ||
| 1582 | if (ask_actions[i] == dpyinfo->Xatom_XdndActionCopy) | ||
| 1583 | flags |= XM_DRAG_COPY; | ||
| 1584 | else if (ask_actions[i] == dpyinfo->Xatom_XdndActionMove) | ||
| 1585 | flags |= XM_DRAG_MOVE; | ||
| 1586 | else if (ask_actions[i] == dpyinfo->Xatom_XdndActionLink) | ||
| 1587 | flags |= XM_DRAG_LINK; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | return flags; | ||
| 1591 | } | ||
| 1592 | |||
| 1236 | static int | 1593 | static int |
| 1237 | xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length, | 1594 | xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length, |
| 1238 | xm_targets_table_header *header_return, | 1595 | xm_targets_table_header *header_return, |
| @@ -1396,6 +1753,9 @@ xm_write_drag_initiator_info (Display *dpy, Window wdesc, | |||
| 1396 | static int | 1753 | static int |
| 1397 | xm_drag_window_error_handler (Display *display, XErrorEvent *event) | 1754 | xm_drag_window_error_handler (Display *display, XErrorEvent *event) |
| 1398 | { | 1755 | { |
| 1756 | if (xm_drag_window_error) | ||
| 1757 | *xm_drag_window_error = true; | ||
| 1758 | |||
| 1399 | return 0; | 1759 | return 0; |
| 1400 | } | 1760 | } |
| 1401 | 1761 | ||
| @@ -1404,7 +1764,7 @@ xm_drag_window_io_error_handler (Display *dpy) | |||
| 1404 | { | 1764 | { |
| 1405 | /* DPY isn't created through GDK, so it doesn't matter if we don't | 1765 | /* DPY isn't created through GDK, so it doesn't matter if we don't |
| 1406 | crash here. */ | 1766 | crash here. */ |
| 1407 | longjmp (x_dnd_disconnect_handler, 1); | 1767 | siglongjmp (x_dnd_disconnect_handler, 1); |
| 1408 | } | 1768 | } |
| 1409 | 1769 | ||
| 1410 | static Window | 1770 | static Window |
| @@ -1418,6 +1778,9 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1418 | XSetWindowAttributes attrs; | 1778 | XSetWindowAttributes attrs; |
| 1419 | Display *temp_display; | 1779 | Display *temp_display; |
| 1420 | void *old_handler, *old_io_handler; | 1780 | void *old_handler, *old_io_handler; |
| 1781 | /* These are volatile because GCC mistakenly warns about them being | ||
| 1782 | clobbered by longjmp. */ | ||
| 1783 | volatile bool error, created; | ||
| 1421 | 1784 | ||
| 1422 | drag_window = None; | 1785 | drag_window = None; |
| 1423 | rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, | 1786 | rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, |
| @@ -1473,6 +1836,9 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1473 | return None; | 1836 | return None; |
| 1474 | } | 1837 | } |
| 1475 | 1838 | ||
| 1839 | error = false; | ||
| 1840 | xm_drag_window_error = &error; | ||
| 1841 | |||
| 1476 | XGrabServer (temp_display); | 1842 | XGrabServer (temp_display); |
| 1477 | XSetCloseDownMode (temp_display, RetainPermanent); | 1843 | XSetCloseDownMode (temp_display, RetainPermanent); |
| 1478 | 1844 | ||
| @@ -1483,6 +1849,9 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1483 | _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, | 1849 | _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, |
| 1484 | "_MOTIF_DRAG_WINDOW", False); | 1850 | "_MOTIF_DRAG_WINDOW", False); |
| 1485 | 1851 | ||
| 1852 | if (error) | ||
| 1853 | goto give_up; | ||
| 1854 | |||
| 1486 | /* Some other program might've created a drag window between now | 1855 | /* Some other program might've created a drag window between now |
| 1487 | and when we first looked. Use that if it exists. */ | 1856 | and when we first looked. Use that if it exists. */ |
| 1488 | 1857 | ||
| @@ -1500,8 +1869,12 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1500 | if (tmp_data) | 1869 | if (tmp_data) |
| 1501 | XFree (tmp_data); | 1870 | XFree (tmp_data); |
| 1502 | 1871 | ||
| 1872 | error = false; | ||
| 1873 | |||
| 1503 | if (drag_window == None) | 1874 | if (drag_window == None) |
| 1504 | { | 1875 | { |
| 1876 | created = true; | ||
| 1877 | |||
| 1505 | attrs.override_redirect = True; | 1878 | attrs.override_redirect = True; |
| 1506 | drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), | 1879 | drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), |
| 1507 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, | 1880 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, |
| @@ -1510,8 +1883,41 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1510 | _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, | 1883 | _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, |
| 1511 | (unsigned char *) &drag_window, 1); | 1884 | (unsigned char *) &drag_window, 1); |
| 1512 | } | 1885 | } |
| 1886 | else | ||
| 1887 | created = false; | ||
| 1888 | |||
| 1889 | /* Handle all errors now. */ | ||
| 1890 | XSync (temp_display, False); | ||
| 1513 | 1891 | ||
| 1892 | give_up: | ||
| 1893 | |||
| 1894 | /* Some part of the drag window creation process failed, so | ||
| 1895 | punt. */ | ||
| 1896 | if (error) | ||
| 1897 | { | ||
| 1898 | /* If the drag window was actually created, delete it now. | ||
| 1899 | Probably, a BadAlloc happened during the XChangeProperty | ||
| 1900 | request. */ | ||
| 1901 | if (created) | ||
| 1902 | { | ||
| 1903 | if (drag_window != None) | ||
| 1904 | XDestroyWindow (temp_display, drag_window); | ||
| 1905 | |||
| 1906 | XDeleteProperty (temp_display, DefaultRootWindow (temp_display), | ||
| 1907 | _MOTIF_DRAG_WINDOW); | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | drag_window = None; | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | xm_drag_window_error = NULL; | ||
| 1914 | |||
| 1915 | /* FIXME: why does XCloseDisplay hang if SIGIO arrives and there | ||
| 1916 | are multiple displays? */ | ||
| 1917 | unrequest_sigio (); | ||
| 1514 | XCloseDisplay (temp_display); | 1918 | XCloseDisplay (temp_display); |
| 1919 | request_sigio (); | ||
| 1920 | |||
| 1515 | XSetErrorHandler (old_handler); | 1921 | XSetErrorHandler (old_handler); |
| 1516 | XSetIOErrorHandler (old_io_handler); | 1922 | XSetIOErrorHandler (old_io_handler); |
| 1517 | 1923 | ||
| @@ -1633,7 +2039,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, | |||
| 1633 | if (!rc) | 2039 | if (!rc) |
| 1634 | { | 2040 | { |
| 1635 | header.byte_order = XM_BYTE_ORDER_CUR_FIRST; | 2041 | header.byte_order = XM_BYTE_ORDER_CUR_FIRST; |
| 1636 | header.protocol = 0; | 2042 | header.protocol = XM_DRAG_PROTOCOL_VERSION; |
| 1637 | header.target_list_count = 1; | 2043 | header.target_list_count = 1; |
| 1638 | header.total_data_size = 8 + 2 + ntargets * 4; | 2044 | header.total_data_size = 8 + 2 + ntargets * 4; |
| 1639 | 2045 | ||
| @@ -1678,7 +2084,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, | |||
| 1678 | xfree (recs); | 2084 | xfree (recs); |
| 1679 | 2085 | ||
| 1680 | header.byte_order = XM_BYTE_ORDER_CUR_FIRST; | 2086 | header.byte_order = XM_BYTE_ORDER_CUR_FIRST; |
| 1681 | header.protocol = 0; | 2087 | header.protocol = XM_DRAG_PROTOCOL_VERSION; |
| 1682 | header.target_list_count = 1; | 2088 | header.target_list_count = 1; |
| 1683 | header.total_data_size = 8 + 2 + ntargets * 4; | 2089 | header.total_data_size = 8 + 2 + ntargets * 4; |
| 1684 | 2090 | ||
| @@ -1715,10 +2121,17 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, | |||
| 1715 | data format. To avoid confusing Motif when that happens, set | 2121 | data format. To avoid confusing Motif when that happens, set |
| 1716 | it back to 0. There will probably be no more updates to the | 2122 | it back to 0. There will probably be no more updates to the |
| 1717 | protocol either. */ | 2123 | protocol either. */ |
| 1718 | header.protocol = 0; | 2124 | header.protocol = XM_DRAG_PROTOCOL_VERSION; |
| 2125 | |||
| 2126 | x_catch_errors (dpyinfo->display); | ||
| 1719 | xm_write_targets_table (dpyinfo->display, drag_window, | 2127 | xm_write_targets_table (dpyinfo->display, drag_window, |
| 1720 | dpyinfo->Xatom_MOTIF_DRAG_TARGETS, | 2128 | dpyinfo->Xatom_MOTIF_DRAG_TARGETS, |
| 1721 | &header, recs); | 2129 | &header, recs); |
| 2130 | /* Presumably we got a BadAlloc upon writing the targets | ||
| 2131 | table. */ | ||
| 2132 | if (x_had_errors_p (dpyinfo->display)) | ||
| 2133 | idx = -1; | ||
| 2134 | x_uncatch_errors_after_check (); | ||
| 1722 | } | 2135 | } |
| 1723 | 2136 | ||
| 1724 | XUngrabServer (dpyinfo->display); | 2137 | XUngrabServer (dpyinfo->display); |
| @@ -1745,7 +2158,7 @@ xm_setup_drag_info (struct x_display_info *dpyinfo, | |||
| 1745 | if (idx != -1) | 2158 | if (idx != -1) |
| 1746 | { | 2159 | { |
| 1747 | drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST; | 2160 | drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST; |
| 1748 | drag_initiator_info.protocol = 0; | 2161 | drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION; |
| 1749 | drag_initiator_info.table_index = idx; | 2162 | drag_initiator_info.table_index = idx; |
| 1750 | drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection; | 2163 | drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection; |
| 1751 | 2164 | ||
| @@ -1862,7 +2275,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source, | |||
| 1862 | mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; | 2275 | mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; |
| 1863 | mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 2276 | mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 1864 | x_dnd_wanted_action), | 2277 | x_dnd_wanted_action), |
| 1865 | XM_DROP_SITE_NONE, XM_DRAG_NOOP, | 2278 | XM_DROP_SITE_NONE, x_dnd_motif_operations, |
| 1866 | XM_DROP_ACTION_DROP_CANCEL); | 2279 | XM_DROP_ACTION_DROP_CANCEL); |
| 1867 | mmsg.timestamp = dmsg->timestamp; | 2280 | mmsg.timestamp = dmsg->timestamp; |
| 1868 | mmsg.x = 65535; | 2281 | mmsg.x = 65535; |
| @@ -1927,6 +2340,44 @@ xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply) | |||
| 1927 | } | 2340 | } |
| 1928 | 2341 | ||
| 1929 | static int | 2342 | static int |
| 2343 | xm_read_drop_start_message (const XEvent *msg, | ||
| 2344 | xm_drop_start_message *dmsg) | ||
| 2345 | { | ||
| 2346 | const uint8_t *data; | ||
| 2347 | |||
| 2348 | data = (const uint8_t *) &msg->xclient.data.b[0]; | ||
| 2349 | |||
| 2350 | if ((XM_DRAG_REASON_ORIGINATOR (data[0]) | ||
| 2351 | != XM_DRAG_ORIGINATOR_INITIATOR) | ||
| 2352 | || (XM_DRAG_REASON_CODE (data[0]) | ||
| 2353 | != XM_DRAG_REASON_DROP_START)) | ||
| 2354 | return 1; | ||
| 2355 | |||
| 2356 | dmsg->reason = *(data++); | ||
| 2357 | dmsg->byte_order = *(data++); | ||
| 2358 | dmsg->side_effects = *(uint16_t *) data; | ||
| 2359 | dmsg->timestamp = *(uint32_t *) (data + 2); | ||
| 2360 | dmsg->x = *(uint16_t *) (data + 6); | ||
| 2361 | dmsg->y = *(uint16_t *) (data + 8); | ||
| 2362 | dmsg->index_atom = *(uint32_t *) (data + 10); | ||
| 2363 | dmsg->source_window = *(uint32_t *) (data + 14); | ||
| 2364 | |||
| 2365 | if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST) | ||
| 2366 | { | ||
| 2367 | SWAPCARD16 (dmsg->side_effects); | ||
| 2368 | SWAPCARD32 (dmsg->timestamp); | ||
| 2369 | SWAPCARD16 (dmsg->x); | ||
| 2370 | SWAPCARD16 (dmsg->y); | ||
| 2371 | SWAPCARD32 (dmsg->index_atom); | ||
| 2372 | SWAPCARD32 (dmsg->source_window); | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST; | ||
| 2376 | |||
| 2377 | return 0; | ||
| 2378 | } | ||
| 2379 | |||
| 2380 | static int | ||
| 1930 | xm_read_drag_receiver_info (struct x_display_info *dpyinfo, | 2381 | xm_read_drag_receiver_info (struct x_display_info *dpyinfo, |
| 1931 | Window wdesc, xm_drag_receiver_info *rec) | 2382 | Window wdesc, xm_drag_receiver_info *rec) |
| 1932 | { | 2383 | { |
| @@ -1955,6 +2406,9 @@ xm_read_drag_receiver_info (struct x_display_info *dpyinfo, | |||
| 1955 | { | 2406 | { |
| 1956 | data = (uint8_t *) tmp_data; | 2407 | data = (uint8_t *) tmp_data; |
| 1957 | 2408 | ||
| 2409 | if (data[1] > XM_DRAG_PROTOCOL_VERSION) | ||
| 2410 | return 1; | ||
| 2411 | |||
| 1958 | rec->byteorder = data[0]; | 2412 | rec->byteorder = data[0]; |
| 1959 | rec->protocol = data[1]; | 2413 | rec->protocol = data[1]; |
| 1960 | rec->protocol_style = data[2]; | 2414 | rec->protocol_style = data[2]; |
| @@ -1979,6 +2433,40 @@ xm_read_drag_receiver_info (struct x_display_info *dpyinfo, | |||
| 1979 | return !rc; | 2433 | return !rc; |
| 1980 | } | 2434 | } |
| 1981 | 2435 | ||
| 2436 | static int | ||
| 2437 | xm_read_drag_motion_message (const XEvent *msg, | ||
| 2438 | xm_drag_motion_message *dmsg) | ||
| 2439 | { | ||
| 2440 | const uint8_t *data; | ||
| 2441 | |||
| 2442 | data = (const uint8_t *) &msg->xclient.data.b[0]; | ||
| 2443 | |||
| 2444 | if ((XM_DRAG_REASON_CODE (data[0]) | ||
| 2445 | != XM_DRAG_REASON_DRAG_MOTION) | ||
| 2446 | || (XM_DRAG_REASON_ORIGINATOR (data[0]) | ||
| 2447 | != XM_DRAG_ORIGINATOR_INITIATOR)) | ||
| 2448 | return 1; | ||
| 2449 | |||
| 2450 | dmsg->reason = *(data++); | ||
| 2451 | dmsg->byteorder = *(data++); | ||
| 2452 | dmsg->side_effects = *(uint16_t *) data; | ||
| 2453 | dmsg->timestamp = *(uint32_t *) (data + 2); | ||
| 2454 | dmsg->x = *(uint16_t *) (data + 6); | ||
| 2455 | dmsg->y = *(uint16_t *) (data + 8); | ||
| 2456 | |||
| 2457 | if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST) | ||
| 2458 | { | ||
| 2459 | SWAPCARD16 (dmsg->side_effects); | ||
| 2460 | SWAPCARD32 (dmsg->timestamp); | ||
| 2461 | SWAPCARD16 (dmsg->x); | ||
| 2462 | SWAPCARD16 (dmsg->y); | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST; | ||
| 2466 | |||
| 2467 | return 0; | ||
| 2468 | } | ||
| 2469 | |||
| 1982 | static void | 2470 | static void |
| 1983 | x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, | 2471 | x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, |
| 1984 | struct frame *f, Window wdesc, | 2472 | struct frame *f, Window wdesc, |
| @@ -1999,23 +2487,57 @@ x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, | |||
| 1999 | } | 2487 | } |
| 2000 | 2488 | ||
| 2001 | static void | 2489 | static void |
| 2002 | x_dnd_free_toplevels (void) | 2490 | x_dnd_free_toplevels (bool display_alive) |
| 2003 | { | 2491 | { |
| 2004 | struct x_client_list_window *last; | 2492 | struct x_client_list_window *last; |
| 2005 | struct x_client_list_window *tem = x_dnd_toplevels; | 2493 | struct x_client_list_window *tem = x_dnd_toplevels; |
| 2494 | ptrdiff_t n_windows, i, buffer_size; | ||
| 2495 | Window *destroy_windows; | ||
| 2496 | unsigned long *prev_masks; | ||
| 2497 | specpdl_ref count; | ||
| 2498 | Display *dpy; | ||
| 2499 | |||
| 2500 | if (!x_dnd_toplevels) | ||
| 2501 | /* Probably called inside an IO error handler. */ | ||
| 2502 | return; | ||
| 2503 | |||
| 2504 | /* Pacify GCC. */ | ||
| 2505 | prev_masks = NULL; | ||
| 2506 | destroy_windows = NULL; | ||
| 2006 | 2507 | ||
| 2508 | if (display_alive) | ||
| 2509 | { | ||
| 2510 | buffer_size = 1024; | ||
| 2511 | destroy_windows = xmalloc (sizeof *destroy_windows | ||
| 2512 | * buffer_size); | ||
| 2513 | prev_masks = xmalloc (sizeof *prev_masks * | ||
| 2514 | buffer_size); | ||
| 2515 | n_windows = 0; | ||
| 2516 | } | ||
| 2517 | |||
| 2518 | block_input (); | ||
| 2007 | while (tem) | 2519 | while (tem) |
| 2008 | { | 2520 | { |
| 2009 | last = tem; | 2521 | last = tem; |
| 2010 | tem = tem->next; | 2522 | tem = tem->next; |
| 2011 | 2523 | ||
| 2012 | x_catch_errors (last->dpy); | 2524 | if (display_alive) |
| 2013 | XSelectInput (last->dpy, last->window, | 2525 | { |
| 2014 | last->previous_event_mask); | 2526 | if (++n_windows >= buffer_size) |
| 2015 | #ifdef HAVE_XSHAPE | 2527 | { |
| 2016 | XShapeSelectInput (last->dpy, last->window, None); | 2528 | buffer_size += 1024; |
| 2017 | #endif | 2529 | destroy_windows |
| 2018 | x_uncatch_errors (); | 2530 | = xrealloc (destroy_windows, (sizeof *destroy_windows |
| 2531 | * buffer_size)); | ||
| 2532 | prev_masks | ||
| 2533 | = xrealloc (prev_masks, (sizeof *prev_masks | ||
| 2534 | * buffer_size)); | ||
| 2535 | } | ||
| 2536 | |||
| 2537 | dpy = last->dpy; | ||
| 2538 | prev_masks[n_windows - 1] = last->previous_event_mask; | ||
| 2539 | destroy_windows[n_windows - 1] = last->window; | ||
| 2540 | } | ||
| 2019 | 2541 | ||
| 2020 | #ifdef HAVE_XSHAPE | 2542 | #ifdef HAVE_XSHAPE |
| 2021 | if (last->n_input_rects != -1) | 2543 | if (last->n_input_rects != -1) |
| @@ -2028,6 +2550,34 @@ x_dnd_free_toplevels (void) | |||
| 2028 | } | 2550 | } |
| 2029 | 2551 | ||
| 2030 | x_dnd_toplevels = NULL; | 2552 | x_dnd_toplevels = NULL; |
| 2553 | |||
| 2554 | if (!display_alive) | ||
| 2555 | { | ||
| 2556 | unblock_input (); | ||
| 2557 | return; | ||
| 2558 | } | ||
| 2559 | |||
| 2560 | count = SPECPDL_INDEX (); | ||
| 2561 | record_unwind_protect_ptr (xfree, destroy_windows); | ||
| 2562 | record_unwind_protect_ptr (xfree, prev_masks); | ||
| 2563 | |||
| 2564 | if (display_alive) | ||
| 2565 | { | ||
| 2566 | x_catch_errors (dpy); | ||
| 2567 | |||
| 2568 | for (i = 0; i < n_windows; ++i) | ||
| 2569 | { | ||
| 2570 | XSelectInput (dpy, destroy_windows[i], prev_masks[i]); | ||
| 2571 | #ifdef HAVE_XSHAPE | ||
| 2572 | XShapeSelectInput (dpy, destroy_windows[i], None); | ||
| 2573 | #endif | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | x_uncatch_errors (); | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | unbind_to (count, Qnil); | ||
| 2580 | unblock_input (); | ||
| 2031 | } | 2581 | } |
| 2032 | 2582 | ||
| 2033 | static int | 2583 | static int |
| @@ -2102,27 +2652,29 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 2102 | toplevels = (Window *) data; | 2652 | toplevels = (Window *) data; |
| 2103 | 2653 | ||
| 2104 | #ifdef USE_XCB | 2654 | #ifdef USE_XCB |
| 2655 | USE_SAFE_ALLOCA; | ||
| 2656 | |||
| 2105 | window_attribute_cookies | 2657 | window_attribute_cookies |
| 2106 | = alloca (sizeof *window_attribute_cookies * nitems); | 2658 | = SAFE_ALLOCA (sizeof *window_attribute_cookies * nitems); |
| 2107 | translate_coordinate_cookies | 2659 | translate_coordinate_cookies |
| 2108 | = alloca (sizeof *translate_coordinate_cookies * nitems); | 2660 | = SAFE_ALLOCA (sizeof *translate_coordinate_cookies * nitems); |
| 2109 | get_property_cookies | 2661 | get_property_cookies |
| 2110 | = alloca (sizeof *get_property_cookies * nitems); | 2662 | = SAFE_ALLOCA (sizeof *get_property_cookies * nitems); |
| 2111 | xm_property_cookies | 2663 | xm_property_cookies |
| 2112 | = alloca (sizeof *xm_property_cookies * nitems); | 2664 | = SAFE_ALLOCA (sizeof *xm_property_cookies * nitems); |
| 2113 | extent_property_cookies | 2665 | extent_property_cookies |
| 2114 | = alloca (sizeof *extent_property_cookies * nitems); | 2666 | = SAFE_ALLOCA (sizeof *extent_property_cookies * nitems); |
| 2115 | get_geometry_cookies | 2667 | get_geometry_cookies |
| 2116 | = alloca (sizeof *get_geometry_cookies * nitems); | 2668 | = SAFE_ALLOCA (sizeof *get_geometry_cookies * nitems); |
| 2117 | 2669 | ||
| 2118 | #ifdef HAVE_XCB_SHAPE | 2670 | #ifdef HAVE_XCB_SHAPE |
| 2119 | bounding_rect_cookies | 2671 | bounding_rect_cookies |
| 2120 | = alloca (sizeof *bounding_rect_cookies * nitems); | 2672 | = SAFE_ALLOCA (sizeof *bounding_rect_cookies * nitems); |
| 2121 | #endif | 2673 | #endif |
| 2122 | 2674 | ||
| 2123 | #ifdef HAVE_XCB_SHAPE_INPUT_RECTS | 2675 | #ifdef HAVE_XCB_SHAPE_INPUT_RECTS |
| 2124 | input_rect_cookies | 2676 | input_rect_cookies |
| 2125 | = alloca (sizeof *input_rect_cookies * nitems); | 2677 | = SAFE_ALLOCA (sizeof *input_rect_cookies * nitems); |
| 2126 | #endif | 2678 | #endif |
| 2127 | 2679 | ||
| 2128 | for (i = 0; i < nitems; ++i) | 2680 | for (i = 0; i < nitems; ++i) |
| @@ -2353,7 +2905,9 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 2353 | && xcb_get_property_value_length (xm_property_reply) >= 4) | 2905 | && xcb_get_property_value_length (xm_property_reply) >= 4) |
| 2354 | { | 2906 | { |
| 2355 | xmdata = xcb_get_property_value (xm_property_reply); | 2907 | xmdata = xcb_get_property_value (xm_property_reply); |
| 2356 | tem->xm_protocol_style = xmdata[2]; | 2908 | |
| 2909 | if (xmdata[1] <= XM_DRAG_PROTOCOL_VERSION) | ||
| 2910 | tem->xm_protocol_style = xmdata[2]; | ||
| 2357 | } | 2911 | } |
| 2358 | #endif | 2912 | #endif |
| 2359 | 2913 | ||
| @@ -2509,7 +3063,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 2509 | } | 3063 | } |
| 2510 | 3064 | ||
| 2511 | /* And the common case where there is no input rect and the | 3065 | /* And the common case where there is no input rect and the |
| 2512 | bouding rect equals the window dimensions. */ | 3066 | bounding rect equals the window dimensions. */ |
| 2513 | 3067 | ||
| 2514 | if (tem->n_input_rects == -1 | 3068 | if (tem->n_input_rects == -1 |
| 2515 | && tem->n_bounding_rects == 1 | 3069 | && tem->n_bounding_rects == 1 |
| @@ -2602,6 +3156,13 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 2602 | #endif | 3156 | #endif |
| 2603 | } | 3157 | } |
| 2604 | 3158 | ||
| 3159 | #ifdef USE_XCB | ||
| 3160 | SAFE_FREE (); | ||
| 3161 | #endif | ||
| 3162 | |||
| 3163 | if (data) | ||
| 3164 | XFree (data); | ||
| 3165 | |||
| 2605 | return 0; | 3166 | return 0; |
| 2606 | } | 3167 | } |
| 2607 | 3168 | ||
| @@ -2611,7 +3172,7 @@ x_dnd_io_error_handler (Display *display) | |||
| 2611 | #ifdef USE_GTK | 3172 | #ifdef USE_GTK |
| 2612 | emacs_abort (); | 3173 | emacs_abort (); |
| 2613 | #else | 3174 | #else |
| 2614 | longjmp (x_dnd_disconnect_handler, 1); | 3175 | siglongjmp (x_dnd_disconnect_handler, 1); |
| 2615 | #endif | 3176 | #endif |
| 2616 | } | 3177 | } |
| 2617 | 3178 | ||
| @@ -2978,7 +3539,6 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, | |||
| 2978 | int dest_x, dest_y; | 3539 | int dest_x, dest_y; |
| 2979 | Window child_return, child; | 3540 | Window child_return, child; |
| 2980 | 3541 | ||
| 2981 | event.xbutton.type = ButtonPress; | ||
| 2982 | event.xbutton.serial = 0; | 3542 | event.xbutton.serial = 0; |
| 2983 | event.xbutton.send_event = True; | 3543 | event.xbutton.send_event = True; |
| 2984 | event.xbutton.display = dpyinfo->display; | 3544 | event.xbutton.display = dpyinfo->display; |
| @@ -2992,39 +3552,37 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, | |||
| 2992 | dest_x = root_x; | 3552 | dest_x = root_x; |
| 2993 | dest_y = root_y; | 3553 | dest_y = root_y; |
| 2994 | 3554 | ||
| 2995 | while (XTranslateCoordinates (dpyinfo->display, child, | 3555 | while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, |
| 2996 | child, root_x, root_y, &dest_x, | 3556 | child, root_x, root_y, &dest_x, &dest_y, |
| 2997 | &dest_y, &child_return) | 3557 | &child_return) |
| 2998 | && child_return != None | 3558 | && child_return != None) |
| 2999 | && XTranslateCoordinates (dpyinfo->display, child, | 3559 | child = child_return; |
| 3000 | child_return, root_x, root_y, | ||
| 3001 | &dest_x, &dest_y, &child)) | ||
| 3002 | { | ||
| 3003 | child = child_return; | ||
| 3004 | root_x = dest_x; | ||
| 3005 | root_y = dest_y; | ||
| 3006 | } | ||
| 3007 | 3560 | ||
| 3008 | if (CONSP (value)) | 3561 | if (CONSP (value)) |
| 3009 | x_own_selection (QPRIMARY, Fnth (make_fixnum (1), value), | 3562 | x_own_selection (QPRIMARY, Fnth (make_fixnum (1), value), |
| 3010 | frame); | 3563 | frame); |
| 3011 | else | 3564 | else |
| 3012 | x_own_selection (QPRIMARY, Qnil, frame); | 3565 | error ("Lost ownership of XdndSelection"); |
| 3013 | 3566 | ||
| 3014 | event.xbutton.window = child; | 3567 | event.xbutton.window = child; |
| 3568 | event.xbutton.subwindow = None; | ||
| 3015 | event.xbutton.x = dest_x; | 3569 | event.xbutton.x = dest_x; |
| 3016 | event.xbutton.y = dest_y; | 3570 | event.xbutton.y = dest_y; |
| 3017 | event.xbutton.state = 0; | 3571 | event.xbutton.state = 0; |
| 3018 | event.xbutton.button = 2; | 3572 | event.xbutton.button = 2; |
| 3019 | event.xbutton.same_screen = True; | 3573 | event.xbutton.same_screen = True; |
| 3020 | event.xbutton.time = before + 1; | ||
| 3021 | event.xbutton.time = before + 2; | ||
| 3022 | 3574 | ||
| 3023 | x_set_pending_dnd_time (before); | 3575 | x_set_pending_dnd_time (before); |
| 3024 | 3576 | ||
| 3577 | event.xbutton.type = ButtonPress; | ||
| 3578 | event.xbutton.time = before + 1; | ||
| 3579 | |||
| 3025 | XSendEvent (dpyinfo->display, child, | 3580 | XSendEvent (dpyinfo->display, child, |
| 3026 | True, ButtonPressMask, &event); | 3581 | True, ButtonPressMask, &event); |
| 3582 | |||
| 3027 | event.xbutton.type = ButtonRelease; | 3583 | event.xbutton.type = ButtonRelease; |
| 3584 | event.xbutton.time = before + 2; | ||
| 3585 | |||
| 3028 | XSendEvent (dpyinfo->display, child, | 3586 | XSendEvent (dpyinfo->display, child, |
| 3029 | True, ButtonReleaseMask, &event); | 3587 | True, ButtonReleaseMask, &event); |
| 3030 | 3588 | ||
| @@ -3057,19 +3615,20 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo | |||
| 3057 | XFree (atom_names[i - 1]); | 3615 | XFree (atom_names[i - 1]); |
| 3058 | } | 3616 | } |
| 3059 | 3617 | ||
| 3060 | name = XGetAtomName (dpyinfo->display, | 3618 | name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, |
| 3061 | x_dnd_wanted_action); | 3619 | NULL); |
| 3062 | 3620 | ||
| 3063 | if (name) | 3621 | if (name) |
| 3064 | { | 3622 | { |
| 3065 | arg = intern (name); | 3623 | arg = intern (name); |
| 3066 | XFree (name); | 3624 | xfree (name); |
| 3067 | } | 3625 | } |
| 3068 | else | 3626 | else |
| 3069 | arg = Qnil; | 3627 | arg = Qnil; |
| 3070 | 3628 | ||
| 3071 | ie.kind = UNSUPPORTED_DROP_EVENT; | 3629 | ie.kind = UNSUPPORTED_DROP_EVENT; |
| 3072 | ie.code = (unsigned) target_window; | 3630 | ie.code = (unsigned) target_window; |
| 3631 | ie.modifiers = x_dnd_unsupported_event_level; | ||
| 3073 | ie.arg = list3 (assq_no_quit (QXdndSelection, | 3632 | ie.arg = list3 (assq_no_quit (QXdndSelection, |
| 3074 | dpyinfo->terminal->Vselection_alist), | 3633 | dpyinfo->terminal->Vselection_alist), |
| 3075 | targets, arg); | 3634 | targets, arg); |
| @@ -3085,16 +3644,20 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo | |||
| 3085 | static Window | 3644 | static Window |
| 3086 | x_dnd_get_target_window (struct x_display_info *dpyinfo, | 3645 | x_dnd_get_target_window (struct x_display_info *dpyinfo, |
| 3087 | int root_x, int root_y, int *proto_out, | 3646 | int root_x, int root_y, int *proto_out, |
| 3088 | int *motif_out, Window *toplevel_out) | 3647 | int *motif_out, Window *toplevel_out, |
| 3648 | bool *was_frame) | ||
| 3089 | { | 3649 | { |
| 3090 | Window child_return, child, dummy, proxy; | 3650 | Window child_return, child, proxy; |
| 3091 | int dest_x_return, dest_y_return, rc, proto, motif; | 3651 | int dest_x_return, dest_y_return, rc, proto, motif; |
| 3652 | int parent_x, parent_y; | ||
| 3092 | bool extents_p; | 3653 | bool extents_p; |
| 3093 | #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) | 3654 | #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) |
| 3094 | Window overlay_window; | 3655 | Window overlay_window; |
| 3095 | XWindowAttributes attrs; | 3656 | XWindowAttributes attrs; |
| 3096 | #endif | 3657 | #endif |
| 3097 | int wmstate; | 3658 | int wmstate; |
| 3659 | struct frame *tooltip, *f; | ||
| 3660 | bool unrelated; | ||
| 3098 | 3661 | ||
| 3099 | child_return = dpyinfo->root_window; | 3662 | child_return = dpyinfo->root_window; |
| 3100 | dest_x_return = root_x; | 3663 | dest_x_return = root_x; |
| @@ -3103,6 +3666,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3103 | proto = -1; | 3666 | proto = -1; |
| 3104 | *motif_out = XM_DRAG_STYLE_NONE; | 3667 | *motif_out = XM_DRAG_STYLE_NONE; |
| 3105 | *toplevel_out = None; | 3668 | *toplevel_out = None; |
| 3669 | *was_frame = false; | ||
| 3106 | 3670 | ||
| 3107 | if (x_dnd_use_toplevels) | 3671 | if (x_dnd_use_toplevels) |
| 3108 | { | 3672 | { |
| @@ -3115,10 +3679,21 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3115 | && FRAME_X_WINDOW (x_dnd_frame) == child) | 3679 | && FRAME_X_WINDOW (x_dnd_frame) == child) |
| 3116 | *motif_out = XM_DRAG_STYLE_NONE; | 3680 | *motif_out = XM_DRAG_STYLE_NONE; |
| 3117 | 3681 | ||
| 3682 | f = x_top_window_to_frame (dpyinfo, child); | ||
| 3683 | |||
| 3118 | *toplevel_out = child; | 3684 | *toplevel_out = child; |
| 3119 | 3685 | ||
| 3120 | if (child != None) | 3686 | if (child != None) |
| 3121 | { | 3687 | { |
| 3688 | if (f) | ||
| 3689 | { | ||
| 3690 | *was_frame = true; | ||
| 3691 | *proto_out = -1; | ||
| 3692 | *motif_out = XM_DRAG_STYLE_NONE; | ||
| 3693 | |||
| 3694 | return child; | ||
| 3695 | } | ||
| 3696 | |||
| 3122 | #ifndef USE_XCB | 3697 | #ifndef USE_XCB |
| 3123 | proxy = x_dnd_get_window_proxy (dpyinfo, child); | 3698 | proxy = x_dnd_get_window_proxy (dpyinfo, child); |
| 3124 | #else | 3699 | #else |
| @@ -3161,10 +3736,13 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3161 | dpyinfo->Xatom_NET_WM_CM_Sn) != None) | 3736 | dpyinfo->Xatom_NET_WM_CM_Sn) != None) |
| 3162 | { | 3737 | { |
| 3163 | x_catch_errors (dpyinfo->display); | 3738 | x_catch_errors (dpyinfo->display); |
| 3739 | XGrabServer (dpyinfo->display); | ||
| 3164 | overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, | 3740 | overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, |
| 3165 | dpyinfo->root_window); | 3741 | dpyinfo->root_window); |
| 3166 | XCompositeReleaseOverlayWindow (dpyinfo->display, | 3742 | XCompositeReleaseOverlayWindow (dpyinfo->display, |
| 3167 | dpyinfo->root_window); | 3743 | dpyinfo->root_window); |
| 3744 | XUngrabServer (dpyinfo->display); | ||
| 3745 | |||
| 3168 | if (!x_had_errors_p (dpyinfo->display)) | 3746 | if (!x_had_errors_p (dpyinfo->display)) |
| 3169 | { | 3747 | { |
| 3170 | XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); | 3748 | XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); |
| @@ -3222,13 +3800,13 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3222 | while (child_return != None) | 3800 | while (child_return != None) |
| 3223 | { | 3801 | { |
| 3224 | child = child_return; | 3802 | child = child_return; |
| 3803 | parent_x = dest_x_return; | ||
| 3804 | parent_y = dest_y_return; | ||
| 3225 | 3805 | ||
| 3226 | x_catch_errors (dpyinfo->display); | 3806 | x_catch_errors (dpyinfo->display); |
| 3227 | rc = XTranslateCoordinates (dpyinfo->display, | 3807 | rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, |
| 3228 | child_return, child_return, | 3808 | child_return, root_x, root_y, &dest_x_return, |
| 3229 | dest_x_return, dest_y_return, | 3809 | &dest_y_return, &child_return); |
| 3230 | &dest_x_return, &dest_y_return, | ||
| 3231 | &child_return); | ||
| 3232 | 3810 | ||
| 3233 | if (x_had_errors_p (dpyinfo->display) || !rc) | 3811 | if (x_had_errors_p (dpyinfo->display) || !rc) |
| 3234 | { | 3812 | { |
| @@ -3238,6 +3816,35 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3238 | 3816 | ||
| 3239 | if (child_return) | 3817 | if (child_return) |
| 3240 | { | 3818 | { |
| 3819 | /* If child_return is a tooltip frame, look beneath it. We | ||
| 3820 | never want to drop anything onto a tooltip frame. */ | ||
| 3821 | |||
| 3822 | tooltip = x_tooltip_window_to_frame (dpyinfo, child_return, | ||
| 3823 | &unrelated); | ||
| 3824 | |||
| 3825 | if (tooltip || unrelated) | ||
| 3826 | child_return = x_get_window_below (dpyinfo->display, child_return, | ||
| 3827 | parent_x, parent_y, &dest_x_return, | ||
| 3828 | &dest_y_return); | ||
| 3829 | |||
| 3830 | if (!child_return) | ||
| 3831 | { | ||
| 3832 | x_uncatch_errors (); | ||
| 3833 | break; | ||
| 3834 | } | ||
| 3835 | |||
| 3836 | f = x_top_window_to_frame (dpyinfo, child_return); | ||
| 3837 | |||
| 3838 | if (f) | ||
| 3839 | { | ||
| 3840 | *proto_out = -1; | ||
| 3841 | *motif_out = XM_DRAG_STYLE_NONE; | ||
| 3842 | *toplevel_out = child_return; | ||
| 3843 | *was_frame = true; | ||
| 3844 | |||
| 3845 | return child_return; | ||
| 3846 | } | ||
| 3847 | |||
| 3241 | if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return, | 3848 | if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return, |
| 3242 | &wmstate, &proto, &motif, | 3849 | &wmstate, &proto, &motif, |
| 3243 | &proxy) | 3850 | &proxy) |
| @@ -3266,23 +3873,9 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3266 | return proxy; | 3873 | return proxy; |
| 3267 | } | 3874 | } |
| 3268 | } | 3875 | } |
| 3269 | |||
| 3270 | rc = XTranslateCoordinates (dpyinfo->display, | ||
| 3271 | child, child_return, | ||
| 3272 | dest_x_return, dest_y_return, | ||
| 3273 | &dest_x_return, &dest_y_return, | ||
| 3274 | &dummy); | ||
| 3275 | |||
| 3276 | if (x_had_errors_p (dpyinfo->display) || !rc) | ||
| 3277 | { | ||
| 3278 | x_uncatch_errors_after_check (); | ||
| 3279 | *proto_out = -1; | ||
| 3280 | *toplevel_out = dpyinfo->root_window; | ||
| 3281 | return None; | ||
| 3282 | } | ||
| 3283 | } | 3876 | } |
| 3284 | 3877 | ||
| 3285 | x_uncatch_errors_after_check (); | 3878 | x_uncatch_errors (); |
| 3286 | } | 3879 | } |
| 3287 | 3880 | ||
| 3288 | #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) | 3881 | #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) |
| @@ -3319,10 +3912,13 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, | |||
| 3319 | dpyinfo->Xatom_NET_WM_CM_Sn) != None) | 3912 | dpyinfo->Xatom_NET_WM_CM_Sn) != None) |
| 3320 | { | 3913 | { |
| 3321 | x_catch_errors (dpyinfo->display); | 3914 | x_catch_errors (dpyinfo->display); |
| 3915 | XGrabServer (dpyinfo->display); | ||
| 3322 | overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, | 3916 | overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, |
| 3323 | dpyinfo->root_window); | 3917 | dpyinfo->root_window); |
| 3324 | XCompositeReleaseOverlayWindow (dpyinfo->display, | 3918 | XCompositeReleaseOverlayWindow (dpyinfo->display, |
| 3325 | dpyinfo->root_window); | 3919 | dpyinfo->root_window); |
| 3920 | XUngrabServer (dpyinfo->display); | ||
| 3921 | |||
| 3326 | if (!x_had_errors_p (dpyinfo->display)) | 3922 | if (!x_had_errors_p (dpyinfo->display)) |
| 3327 | { | 3923 | { |
| 3328 | XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); | 3924 | XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); |
| @@ -3456,9 +4052,6 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) | |||
| 3456 | int i; | 4052 | int i; |
| 3457 | XEvent msg; | 4053 | XEvent msg; |
| 3458 | 4054 | ||
| 3459 | if (x_top_window_to_frame (dpyinfo, target)) | ||
| 3460 | return; | ||
| 3461 | |||
| 3462 | msg.xclient.type = ClientMessage; | 4055 | msg.xclient.type = ClientMessage; |
| 3463 | msg.xclient.message_type = dpyinfo->Xatom_XdndEnter; | 4056 | msg.xclient.message_type = dpyinfo->Xatom_XdndEnter; |
| 3464 | msg.xclient.format = 32; | 4057 | msg.xclient.format = 32; |
| @@ -3474,12 +4067,16 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) | |||
| 3474 | for (i = 0; i < min (3, x_dnd_n_targets); ++i) | 4067 | for (i = 0; i < min (3, x_dnd_n_targets); ++i) |
| 3475 | msg.xclient.data.l[i + 2] = x_dnd_targets[i]; | 4068 | msg.xclient.data.l[i + 2] = x_dnd_targets[i]; |
| 3476 | 4069 | ||
| 3477 | if (x_dnd_n_targets > 3) | 4070 | if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists) |
| 3478 | XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 4071 | XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 3479 | dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32, | 4072 | dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32, |
| 3480 | PropModeReplace, (unsigned char *) x_dnd_targets, | 4073 | PropModeReplace, (unsigned char *) x_dnd_targets, |
| 3481 | x_dnd_n_targets); | 4074 | x_dnd_n_targets); |
| 3482 | 4075 | ||
| 4076 | /* Now record that the type list has already been set (if required), | ||
| 4077 | so we don't have to set it again. */ | ||
| 4078 | x_dnd_init_type_lists = true; | ||
| 4079 | |||
| 3483 | x_catch_errors (dpyinfo->display); | 4080 | x_catch_errors (dpyinfo->display); |
| 3484 | XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); | 4081 | XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); |
| 3485 | x_uncatch_errors (); | 4082 | x_uncatch_errors (); |
| @@ -3493,23 +4090,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported, | |||
| 3493 | { | 4090 | { |
| 3494 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 4091 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 3495 | XEvent msg; | 4092 | XEvent msg; |
| 3496 | struct frame *target_frame; | ||
| 3497 | int dest_x, dest_y; | ||
| 3498 | Window child_return; | ||
| 3499 | |||
| 3500 | target_frame = x_top_window_to_frame (dpyinfo, target); | ||
| 3501 | |||
| 3502 | if (target_frame && XTranslateCoordinates (dpyinfo->display, | ||
| 3503 | dpyinfo->root_window, | ||
| 3504 | FRAME_X_WINDOW (target_frame), | ||
| 3505 | root_x, root_y, &dest_x, | ||
| 3506 | &dest_y, &child_return)) | ||
| 3507 | { | ||
| 3508 | x_dnd_movement_frame = target_frame; | ||
| 3509 | x_dnd_movement_x = dest_x; | ||
| 3510 | x_dnd_movement_y = dest_y; | ||
| 3511 | return; | ||
| 3512 | } | ||
| 3513 | 4093 | ||
| 3514 | if (target == x_dnd_mouse_rect_target | 4094 | if (target == x_dnd_mouse_rect_target |
| 3515 | && x_dnd_mouse_rect.width | 4095 | && x_dnd_mouse_rect.width |
| @@ -3533,7 +4113,7 @@ x_dnd_send_position (struct frame *f, Window target, int supported, | |||
| 3533 | 4113 | ||
| 3534 | if (supported >= 5) | 4114 | if (supported >= 5) |
| 3535 | { | 4115 | { |
| 3536 | if (button >= 4 && button <= 8) | 4116 | if (button >= 4 && button <= 7) |
| 3537 | { | 4117 | { |
| 3538 | msg.xclient.data.l[1] |= (1 << 9); | 4118 | msg.xclient.data.l[1] |= (1 << 9); |
| 3539 | msg.xclient.data.l[1] |= (button - 4) << 7; | 4119 | msg.xclient.data.l[1] |= (button - 4) << 7; |
| @@ -3567,9 +4147,6 @@ x_dnd_send_leave (struct frame *f, Window target) | |||
| 3567 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 4147 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 3568 | XEvent msg; | 4148 | XEvent msg; |
| 3569 | 4149 | ||
| 3570 | if (x_top_window_to_frame (dpyinfo, target)) | ||
| 3571 | return; | ||
| 3572 | |||
| 3573 | msg.xclient.type = ClientMessage; | 4150 | msg.xclient.type = ClientMessage; |
| 3574 | msg.xclient.message_type = dpyinfo->Xatom_XdndLeave; | 4151 | msg.xclient.message_type = dpyinfo->Xatom_XdndLeave; |
| 3575 | msg.xclient.format = 32; | 4152 | msg.xclient.format = 32; |
| @@ -3589,74 +4166,17 @@ static bool | |||
| 3589 | x_dnd_send_drop (struct frame *f, Window target, Time timestamp, | 4166 | x_dnd_send_drop (struct frame *f, Window target, Time timestamp, |
| 3590 | int supported) | 4167 | int supported) |
| 3591 | { | 4168 | { |
| 3592 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 4169 | struct x_display_info *dpyinfo; |
| 3593 | XEvent msg; | 4170 | XEvent msg; |
| 3594 | struct input_event ie; | ||
| 3595 | struct frame *self_frame; | ||
| 3596 | int root_x, root_y, win_x, win_y, i; | ||
| 3597 | unsigned int mask; | ||
| 3598 | Window root, child; | ||
| 3599 | Lisp_Object lval; | ||
| 3600 | char **atom_names; | ||
| 3601 | char *name; | ||
| 3602 | |||
| 3603 | self_frame = x_top_window_to_frame (dpyinfo, target); | ||
| 3604 | 4171 | ||
| 3605 | if (self_frame) | 4172 | if (x_dnd_action == None) |
| 3606 | { | ||
| 3607 | if (!x_dnd_allow_current_frame | ||
| 3608 | && self_frame == x_dnd_frame) | ||
| 3609 | return false; | ||
| 3610 | |||
| 3611 | /* Send a special drag-and-drop event when dropping on top of an | ||
| 3612 | Emacs frame to avoid all the overhead involved with sending | ||
| 3613 | client events. */ | ||
| 3614 | EVENT_INIT (ie); | ||
| 3615 | |||
| 3616 | if (XQueryPointer (dpyinfo->display, FRAME_X_WINDOW (self_frame), | ||
| 3617 | &root, &child, &root_x, &root_y, &win_x, &win_y, | ||
| 3618 | &mask)) | ||
| 3619 | { | ||
| 3620 | ie.kind = DRAG_N_DROP_EVENT; | ||
| 3621 | XSETFRAME (ie.frame_or_window, self_frame); | ||
| 3622 | |||
| 3623 | lval = Qnil; | ||
| 3624 | atom_names = alloca (x_dnd_n_targets * sizeof *atom_names); | ||
| 3625 | name = XGetAtomName (dpyinfo->display, x_dnd_wanted_action); | ||
| 3626 | |||
| 3627 | if (!XGetAtomNames (dpyinfo->display, x_dnd_targets, | ||
| 3628 | x_dnd_n_targets, atom_names)) | ||
| 3629 | { | ||
| 3630 | XFree (name); | ||
| 3631 | return false; | ||
| 3632 | } | ||
| 3633 | |||
| 3634 | for (i = x_dnd_n_targets; i != 0; --i) | ||
| 3635 | { | ||
| 3636 | lval = Fcons (intern (atom_names[i - 1]), lval); | ||
| 3637 | XFree (atom_names[i - 1]); | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | lval = Fcons (intern (name), lval); | ||
| 3641 | lval = Fcons (QXdndSelection, lval); | ||
| 3642 | ie.arg = lval; | ||
| 3643 | ie.timestamp = CurrentTime; | ||
| 3644 | |||
| 3645 | XSETINT (ie.x, win_x); | ||
| 3646 | XSETINT (ie.y, win_y); | ||
| 3647 | |||
| 3648 | XFree (name); | ||
| 3649 | kbd_buffer_store_event (&ie); | ||
| 3650 | |||
| 3651 | return false; | ||
| 3652 | } | ||
| 3653 | } | ||
| 3654 | else if (x_dnd_action == None) | ||
| 3655 | { | 4173 | { |
| 3656 | x_dnd_send_leave (f, target); | 4174 | x_dnd_send_leave (f, target); |
| 3657 | return false; | 4175 | return false; |
| 3658 | } | 4176 | } |
| 3659 | 4177 | ||
| 4178 | dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 4179 | |||
| 3660 | msg.xclient.type = ClientMessage; | 4180 | msg.xclient.type = ClientMessage; |
| 3661 | msg.xclient.message_type = dpyinfo->Xatom_XdndDrop; | 4181 | msg.xclient.message_type = dpyinfo->Xatom_XdndDrop; |
| 3662 | msg.xclient.format = 32; | 4182 | msg.xclient.format = 32; |
| @@ -3676,14 +4196,48 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, | |||
| 3676 | return true; | 4196 | return true; |
| 3677 | } | 4197 | } |
| 3678 | 4198 | ||
| 3679 | void | 4199 | static void |
| 3680 | x_set_dnd_targets (Atom *targets, int ntargets) | 4200 | x_set_dnd_targets (Atom *targets, int ntargets) |
| 3681 | { | 4201 | { |
| 3682 | if (x_dnd_targets) | 4202 | if (x_dnd_targets) |
| 3683 | xfree (x_dnd_targets); | 4203 | xfree (x_dnd_targets); |
| 3684 | 4204 | ||
| 3685 | x_dnd_targets = targets; | 4205 | block_input (); |
| 4206 | x_dnd_targets = xmalloc (sizeof *targets * ntargets); | ||
| 3686 | x_dnd_n_targets = ntargets; | 4207 | x_dnd_n_targets = ntargets; |
| 4208 | |||
| 4209 | memcpy (x_dnd_targets, targets, | ||
| 4210 | sizeof *targets * ntargets); | ||
| 4211 | unblock_input (); | ||
| 4212 | } | ||
| 4213 | |||
| 4214 | static void | ||
| 4215 | x_free_dnd_targets (void) | ||
| 4216 | { | ||
| 4217 | if (!x_dnd_targets) | ||
| 4218 | return; | ||
| 4219 | |||
| 4220 | xfree (x_dnd_targets); | ||
| 4221 | x_dnd_targets = NULL; | ||
| 4222 | x_dnd_n_targets = 0; | ||
| 4223 | } | ||
| 4224 | |||
| 4225 | static void | ||
| 4226 | x_clear_dnd_monitors (void) | ||
| 4227 | { | ||
| 4228 | x_dnd_monitors = Qnil; | ||
| 4229 | } | ||
| 4230 | |||
| 4231 | static void | ||
| 4232 | x_free_dnd_toplevels (void) | ||
| 4233 | { | ||
| 4234 | if (!x_dnd_use_toplevels || !x_dnd_toplevels) | ||
| 4235 | return; | ||
| 4236 | |||
| 4237 | /* If the display is deleted, x_dnd_toplevels will already be | ||
| 4238 | NULL, so we can always assume the display is alive here. */ | ||
| 4239 | |||
| 4240 | x_dnd_free_toplevels (true); | ||
| 3687 | } | 4241 | } |
| 3688 | 4242 | ||
| 3689 | static void | 4243 | static void |
| @@ -3716,9 +4270,7 @@ x_dnd_cleanup_drag_and_drop (void *frame) | |||
| 3716 | dmsg.side_effects | 4270 | dmsg.side_effects |
| 3717 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | 4271 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), |
| 3718 | x_dnd_wanted_action), | 4272 | x_dnd_wanted_action), |
| 3719 | XM_DROP_SITE_VALID, | 4273 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 3720 | xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | ||
| 3721 | x_dnd_wanted_action), | ||
| 3722 | XM_DROP_ACTION_DROP_CANCEL); | 4274 | XM_DROP_ACTION_DROP_CANCEL); |
| 3723 | dmsg.x = 0; | 4275 | dmsg.x = 0; |
| 3724 | dmsg.y = 0; | 4276 | dmsg.y = 0; |
| @@ -3739,12 +4291,8 @@ x_dnd_cleanup_drag_and_drop (void *frame) | |||
| 3739 | x_dnd_in_progress = false; | 4291 | x_dnd_in_progress = false; |
| 3740 | } | 4292 | } |
| 3741 | 4293 | ||
| 3742 | x_set_dnd_targets (NULL, 0); | ||
| 3743 | x_dnd_waiting_for_finish = false; | 4294 | x_dnd_waiting_for_finish = false; |
| 3744 | 4295 | ||
| 3745 | if (x_dnd_use_toplevels) | ||
| 3746 | x_dnd_free_toplevels (); | ||
| 3747 | |||
| 3748 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | 4296 | FRAME_DISPLAY_INFO (f)->grabbed = 0; |
| 3749 | #ifdef USE_GTK | 4297 | #ifdef USE_GTK |
| 3750 | current_hold_quit = NULL; | 4298 | current_hold_quit = NULL; |
| @@ -3768,11 +4316,123 @@ x_dnd_cleanup_drag_and_drop (void *frame) | |||
| 3768 | if (x_dnd_motif_setup_p) | 4316 | if (x_dnd_motif_setup_p) |
| 3769 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 4317 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 3770 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); | 4318 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); |
| 4319 | |||
| 4320 | /* Remove any type list set as well. */ | ||
| 4321 | if (x_dnd_init_type_lists && x_dnd_n_targets > 3) | ||
| 4322 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 4323 | FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); | ||
| 4324 | |||
| 3771 | unblock_input (); | 4325 | unblock_input (); |
| 3772 | 4326 | ||
| 3773 | x_dnd_frame = NULL; | 4327 | x_dnd_frame = NULL; |
| 3774 | } | 4328 | } |
| 3775 | 4329 | ||
| 4330 | static void | ||
| 4331 | x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target, | ||
| 4332 | unsigned short root_x, unsigned short root_y) | ||
| 4333 | { | ||
| 4334 | struct frame *f; | ||
| 4335 | int dest_x, dest_y; | ||
| 4336 | Window child_return; | ||
| 4337 | |||
| 4338 | f = x_top_window_to_frame (dpyinfo, target); | ||
| 4339 | |||
| 4340 | if (f && XTranslateCoordinates (dpyinfo->display, | ||
| 4341 | dpyinfo->root_window, | ||
| 4342 | FRAME_X_WINDOW (f), | ||
| 4343 | root_x, root_y, &dest_x, | ||
| 4344 | &dest_y, &child_return)) | ||
| 4345 | { | ||
| 4346 | x_dnd_movement_frame = f; | ||
| 4347 | x_dnd_movement_x = dest_x; | ||
| 4348 | x_dnd_movement_y = dest_y; | ||
| 4349 | |||
| 4350 | return; | ||
| 4351 | } | ||
| 4352 | } | ||
| 4353 | |||
| 4354 | static void | ||
| 4355 | x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, | ||
| 4356 | unsigned short root_x, unsigned short root_y, | ||
| 4357 | Time timestamp) | ||
| 4358 | { | ||
| 4359 | struct input_event ie; | ||
| 4360 | struct frame *f; | ||
| 4361 | Lisp_Object lval; | ||
| 4362 | char **atom_names; | ||
| 4363 | char *name; | ||
| 4364 | int win_x, win_y, i; | ||
| 4365 | Window dummy; | ||
| 4366 | |||
| 4367 | if (!x_dnd_allow_current_frame | ||
| 4368 | && (FRAME_OUTER_WINDOW (x_dnd_frame) | ||
| 4369 | == target)) | ||
| 4370 | return; | ||
| 4371 | |||
| 4372 | f = x_top_window_to_frame (dpyinfo, target); | ||
| 4373 | |||
| 4374 | if (!f) | ||
| 4375 | return; | ||
| 4376 | |||
| 4377 | if (NILP (Vx_dnd_native_test_function)) | ||
| 4378 | return; | ||
| 4379 | |||
| 4380 | if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, | ||
| 4381 | FRAME_X_WINDOW (f), root_x, root_y, | ||
| 4382 | &win_x, &win_y, &dummy)) | ||
| 4383 | return; | ||
| 4384 | |||
| 4385 | /* Emacs can't respond to DND events inside the nested event loop, | ||
| 4386 | so when dragging items to itself, call the test function | ||
| 4387 | manually. */ | ||
| 4388 | |||
| 4389 | XSETFRAME (lval, f); | ||
| 4390 | x_dnd_action = None; | ||
| 4391 | x_dnd_action_symbol | ||
| 4392 | = safe_call2 (Vx_dnd_native_test_function, | ||
| 4393 | Fposn_at_x_y (make_fixnum (win_x), | ||
| 4394 | make_fixnum (win_y), | ||
| 4395 | lval, Qnil), | ||
| 4396 | x_atom_to_symbol (dpyinfo, | ||
| 4397 | x_dnd_wanted_action)); | ||
| 4398 | |||
| 4399 | if (!SYMBOLP (x_dnd_action_symbol)) | ||
| 4400 | return; | ||
| 4401 | |||
| 4402 | EVENT_INIT (ie); | ||
| 4403 | |||
| 4404 | ie.kind = DRAG_N_DROP_EVENT; | ||
| 4405 | XSETFRAME (ie.frame_or_window, f); | ||
| 4406 | |||
| 4407 | lval = Qnil; | ||
| 4408 | atom_names = alloca (x_dnd_n_targets * sizeof *atom_names); | ||
| 4409 | name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL); | ||
| 4410 | |||
| 4411 | if (!XGetAtomNames (dpyinfo->display, x_dnd_targets, | ||
| 4412 | x_dnd_n_targets, atom_names)) | ||
| 4413 | { | ||
| 4414 | xfree (name); | ||
| 4415 | return; | ||
| 4416 | } | ||
| 4417 | |||
| 4418 | for (i = x_dnd_n_targets; i != 0; --i) | ||
| 4419 | { | ||
| 4420 | lval = Fcons (intern (atom_names[i - 1]), lval); | ||
| 4421 | XFree (atom_names[i - 1]); | ||
| 4422 | } | ||
| 4423 | |||
| 4424 | lval = Fcons (intern (name), lval); | ||
| 4425 | lval = Fcons (QXdndSelection, lval); | ||
| 4426 | ie.arg = lval; | ||
| 4427 | ie.timestamp = timestamp; | ||
| 4428 | |||
| 4429 | XSETINT (ie.x, win_x); | ||
| 4430 | XSETINT (ie.y, win_y); | ||
| 4431 | |||
| 4432 | xfree (name); | ||
| 4433 | kbd_buffer_store_event (&ie); | ||
| 4434 | } | ||
| 4435 | |||
| 3776 | /* Flush display of frame F. */ | 4436 | /* Flush display of frame F. */ |
| 3777 | 4437 | ||
| 3778 | static void | 4438 | static void |
| @@ -3967,11 +4627,16 @@ x_update_opaque_region (struct frame *f, XEvent *configure) | |||
| 3967 | (unsigned char *) &opaque_region, 4); | 4627 | (unsigned char *) &opaque_region, 4); |
| 3968 | else | 4628 | else |
| 3969 | { | 4629 | { |
| 3970 | object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f)); | 4630 | /* This causes child frames to not update correctly for an |
| 3971 | class = GTK_WIDGET_CLASS (object_class); | 4631 | unknown reason. (bug#55779) */ |
| 4632 | if (!FRAME_PARENT_FRAME (f)) | ||
| 4633 | { | ||
| 4634 | object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f)); | ||
| 4635 | class = GTK_WIDGET_CLASS (object_class); | ||
| 3972 | 4636 | ||
| 3973 | if (class->style_updated) | 4637 | if (class->style_updated) |
| 3974 | class->style_updated (FRAME_GTK_OUTER_WIDGET (f)); | 4638 | class->style_updated (FRAME_GTK_OUTER_WIDGET (f)); |
| 4639 | } | ||
| 3975 | } | 4640 | } |
| 3976 | #endif | 4641 | #endif |
| 3977 | unblock_input (); | 4642 | unblock_input (); |
| @@ -4062,27 +4727,48 @@ x_free_xi_devices (struct x_display_info *dpyinfo) | |||
| 4062 | unblock_input (); | 4727 | unblock_input (); |
| 4063 | } | 4728 | } |
| 4064 | 4729 | ||
| 4730 | #ifdef HAVE_XINPUT2_1 | ||
| 4731 | struct xi_known_valuator | ||
| 4732 | { | ||
| 4733 | /* The current value of this valuator. */ | ||
| 4734 | double current_value; | ||
| 4735 | |||
| 4736 | /* The number of the valuator. */ | ||
| 4737 | int number; | ||
| 4738 | |||
| 4739 | /* The next valuator whose value we already know. */ | ||
| 4740 | struct xi_known_valuator *next; | ||
| 4741 | }; | ||
| 4742 | #endif | ||
| 4743 | |||
| 4065 | static void | 4744 | static void |
| 4066 | xi_populate_device_from_info (struct xi_device_t *xi_device, | 4745 | xi_populate_device_from_info (struct xi_device_t *xi_device, |
| 4067 | XIDeviceInfo *device) | 4746 | XIDeviceInfo *device) |
| 4068 | { | 4747 | { |
| 4069 | #ifdef HAVE_XINPUT2_1 | 4748 | #ifdef HAVE_XINPUT2_1 |
| 4070 | struct xi_scroll_valuator_t *valuator; | 4749 | struct xi_scroll_valuator_t *valuator; |
| 4750 | struct xi_known_valuator *values, *tem; | ||
| 4071 | int actual_valuator_count; | 4751 | int actual_valuator_count; |
| 4072 | XIScrollClassInfo *info; | 4752 | XIScrollClassInfo *info; |
| 4753 | XIValuatorClassInfo *val_info; | ||
| 4073 | #endif | 4754 | #endif |
| 4755 | int c; | ||
| 4074 | #ifdef HAVE_XINPUT2_2 | 4756 | #ifdef HAVE_XINPUT2_2 |
| 4075 | XITouchClassInfo *touch_info; | 4757 | XITouchClassInfo *touch_info; |
| 4076 | #endif | 4758 | #endif |
| 4077 | int c; | 4759 | |
| 4760 | #ifdef HAVE_XINPUT2_1 | ||
| 4761 | USE_SAFE_ALLOCA; | ||
| 4762 | #endif | ||
| 4078 | 4763 | ||
| 4079 | xi_device->device_id = device->deviceid; | 4764 | xi_device->device_id = device->deviceid; |
| 4080 | xi_device->grab = 0; | 4765 | xi_device->grab = 0; |
| 4081 | 4766 | ||
| 4082 | #ifdef HAVE_XINPUT2_1 | 4767 | #ifdef HAVE_XINPUT2_1 |
| 4083 | actual_valuator_count = 0; | 4768 | actual_valuator_count = 0; |
| 4084 | xi_device->valuators = | 4769 | xi_device->valuators = xmalloc (sizeof *xi_device->valuators |
| 4085 | xmalloc (sizeof *xi_device->valuators * device->num_classes); | 4770 | * device->num_classes); |
| 4771 | values = NULL; | ||
| 4086 | #endif | 4772 | #endif |
| 4087 | #ifdef HAVE_XINPUT2_2 | 4773 | #ifdef HAVE_XINPUT2_2 |
| 4088 | xi_device->touchpoints = NULL; | 4774 | xi_device->touchpoints = NULL; |
| @@ -4114,7 +4800,21 @@ xi_populate_device_from_info (struct xi_device_t *xi_device, | |||
| 4114 | 4800 | ||
| 4115 | break; | 4801 | break; |
| 4116 | } | 4802 | } |
| 4803 | |||
| 4804 | case XIValuatorClass: | ||
| 4805 | { | ||
| 4806 | val_info = (XIValuatorClassInfo *) device->classes[c]; | ||
| 4807 | tem = SAFE_ALLOCA (sizeof *tem); | ||
| 4808 | |||
| 4809 | tem->next = values; | ||
| 4810 | tem->number = val_info->number; | ||
| 4811 | tem->current_value = val_info->value; | ||
| 4812 | |||
| 4813 | values = tem; | ||
| 4814 | break; | ||
| 4815 | } | ||
| 4117 | #endif | 4816 | #endif |
| 4817 | |||
| 4118 | #ifdef HAVE_XINPUT2_2 | 4818 | #ifdef HAVE_XINPUT2_2 |
| 4119 | case XITouchClass: | 4819 | case XITouchClass: |
| 4120 | { | 4820 | { |
| @@ -4129,6 +4829,25 @@ xi_populate_device_from_info (struct xi_device_t *xi_device, | |||
| 4129 | 4829 | ||
| 4130 | #ifdef HAVE_XINPUT2_1 | 4830 | #ifdef HAVE_XINPUT2_1 |
| 4131 | xi_device->scroll_valuator_count = actual_valuator_count; | 4831 | xi_device->scroll_valuator_count = actual_valuator_count; |
| 4832 | |||
| 4833 | /* Now look through all the valuators whose values are already known | ||
| 4834 | and populate our client-side records with their current | ||
| 4835 | values. */ | ||
| 4836 | |||
| 4837 | for (tem = values; values; values = values->next) | ||
| 4838 | { | ||
| 4839 | for (c = 0; c < xi_device->scroll_valuator_count; ++c) | ||
| 4840 | { | ||
| 4841 | if (xi_device->valuators[c].number == tem->number) | ||
| 4842 | { | ||
| 4843 | xi_device->valuators[c].invalid_p = false; | ||
| 4844 | xi_device->valuators[c].current_value = tem->current_value; | ||
| 4845 | xi_device->valuators[c].pending_enter_reset = true; | ||
| 4846 | } | ||
| 4847 | } | ||
| 4848 | } | ||
| 4849 | |||
| 4850 | SAFE_FREE (); | ||
| 4132 | #endif | 4851 | #endif |
| 4133 | } | 4852 | } |
| 4134 | 4853 | ||
| @@ -4242,6 +4961,7 @@ x_get_scroll_valuator_delta (struct x_display_info *dpyinfo, | |||
| 4242 | } | 4961 | } |
| 4243 | } | 4962 | } |
| 4244 | 4963 | ||
| 4964 | *valuator_return = NULL; | ||
| 4245 | return DBL_MAX; | 4965 | return DBL_MAX; |
| 4246 | } | 4966 | } |
| 4247 | 4967 | ||
| @@ -5305,6 +6025,20 @@ x_set_frame_alpha (struct frame *f) | |||
| 5305 | unsigned long opac; | 6025 | unsigned long opac; |
| 5306 | Window parent; | 6026 | Window parent; |
| 5307 | 6027 | ||
| 6028 | #ifndef USE_XCB | ||
| 6029 | unsigned char *data = NULL; | ||
| 6030 | Atom actual; | ||
| 6031 | int rc, format; | ||
| 6032 | unsigned long n, left; | ||
| 6033 | unsigned long value; | ||
| 6034 | #else | ||
| 6035 | xcb_get_property_cookie_t opacity_cookie; | ||
| 6036 | xcb_get_property_reply_t *opacity_reply; | ||
| 6037 | xcb_generic_error_t *error; | ||
| 6038 | bool rc; | ||
| 6039 | uint32_t value; | ||
| 6040 | #endif | ||
| 6041 | |||
| 5308 | if (dpyinfo->highlight_frame == f) | 6042 | if (dpyinfo->highlight_frame == f) |
| 5309 | alpha = f->alpha[0]; | 6043 | alpha = f->alpha[0]; |
| 5310 | else | 6044 | else |
| @@ -5343,19 +6077,22 @@ x_set_frame_alpha (struct frame *f) | |||
| 5343 | 6077 | ||
| 5344 | /* return unless necessary */ | 6078 | /* return unless necessary */ |
| 5345 | { | 6079 | { |
| 5346 | unsigned char *data = NULL; | 6080 | #ifndef USE_XCB |
| 5347 | Atom actual; | ||
| 5348 | int rc, format; | ||
| 5349 | unsigned long n, left; | ||
| 5350 | |||
| 5351 | rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, | 6081 | rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, |
| 5352 | 0, 1, False, XA_CARDINAL, | 6082 | 0, 1, False, XA_CARDINAL, |
| 5353 | &actual, &format, &n, &left, | 6083 | &actual, &format, &n, &left, |
| 5354 | &data); | 6084 | &data); |
| 5355 | 6085 | ||
| 5356 | if (rc == Success && actual != None && data) | 6086 | if (rc == Success && actual != None |
| 6087 | && n && format == XA_CARDINAL && data) | ||
| 5357 | { | 6088 | { |
| 5358 | unsigned long value = *(unsigned long *) data; | 6089 | value = *(unsigned long *) data; |
| 6090 | |||
| 6091 | /* Xlib sign-extends values greater than 0x7fffffff on 64-bit | ||
| 6092 | machines. Get the low bits by ourself. */ | ||
| 6093 | |||
| 6094 | value &= 0xffffffff; | ||
| 6095 | |||
| 5359 | if (value == opac) | 6096 | if (value == opac) |
| 5360 | { | 6097 | { |
| 5361 | x_uncatch_errors (); | 6098 | x_uncatch_errors (); |
| @@ -5366,6 +6103,37 @@ x_set_frame_alpha (struct frame *f) | |||
| 5366 | 6103 | ||
| 5367 | if (data) | 6104 | if (data) |
| 5368 | XFree (data); | 6105 | XFree (data); |
| 6106 | #else | ||
| 6107 | /* Avoid the confusing Xlib sign-extension mess by using XCB | ||
| 6108 | instead. */ | ||
| 6109 | opacity_cookie | ||
| 6110 | = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) win, | ||
| 6111 | (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity, | ||
| 6112 | XCB_ATOM_CARDINAL, 0, 1); | ||
| 6113 | opacity_reply | ||
| 6114 | = xcb_get_property_reply (dpyinfo->xcb_connection, | ||
| 6115 | opacity_cookie, &error); | ||
| 6116 | |||
| 6117 | rc = opacity_reply; | ||
| 6118 | |||
| 6119 | if (!opacity_reply) | ||
| 6120 | free (error); | ||
| 6121 | else | ||
| 6122 | { | ||
| 6123 | rc = (opacity_reply->format == 32 | ||
| 6124 | && opacity_reply->type == XCB_ATOM_CARDINAL | ||
| 6125 | && (xcb_get_property_value_length (opacity_reply) >= 4)); | ||
| 6126 | |||
| 6127 | if (rc) | ||
| 6128 | value = *(uint32_t *) xcb_get_property_value (opacity_reply); | ||
| 6129 | } | ||
| 6130 | |||
| 6131 | if (opacity_reply) | ||
| 6132 | free (opacity_reply); | ||
| 6133 | |||
| 6134 | if (rc && value == opac) | ||
| 6135 | return; | ||
| 6136 | #endif | ||
| 5369 | } | 6137 | } |
| 5370 | 6138 | ||
| 5371 | XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, | 6139 | XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, |
| @@ -5504,6 +6272,15 @@ show_back_buffer (struct frame *f) | |||
| 5504 | static void | 6272 | static void |
| 5505 | x_flip_and_flush (struct frame *f) | 6273 | x_flip_and_flush (struct frame *f) |
| 5506 | { | 6274 | { |
| 6275 | /* Flipping buffers requires a working connection to the X server, | ||
| 6276 | which isn't always present if `inhibit-redisplay' is t, since | ||
| 6277 | this can be called from the IO error handler. */ | ||
| 6278 | if (!NILP (Vinhibit_redisplay) | ||
| 6279 | /* This has to work for tooltip frames, however, and redisplay | ||
| 6280 | cannot happen when they are being flushed anyway. (bug#55519) */ | ||
| 6281 | && !FRAME_TOOLTIP_P (f)) | ||
| 6282 | return; | ||
| 6283 | |||
| 5507 | block_input (); | 6284 | block_input (); |
| 5508 | #ifdef HAVE_XDBE | 6285 | #ifdef HAVE_XDBE |
| 5509 | if (FRAME_X_NEED_BUFFER_FLIP (f)) | 6286 | if (FRAME_X_NEED_BUFFER_FLIP (f)) |
| @@ -5745,7 +6522,8 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) | |||
| 5745 | } | 6522 | } |
| 5746 | 6523 | ||
| 5747 | static void | 6524 | static void |
| 5748 | x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p) | 6525 | x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, |
| 6526 | struct draw_fringe_bitmap_params *p) | ||
| 5749 | { | 6527 | { |
| 5750 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 6528 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 5751 | Display *display = FRAME_X_DISPLAY (f); | 6529 | Display *display = FRAME_X_DISPLAY (f); |
| @@ -5762,15 +6540,21 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring | |||
| 5762 | mono-displays, the fill style may have been changed to | 6540 | mono-displays, the fill style may have been changed to |
| 5763 | FillSolid in x_draw_glyph_string_background. */ | 6541 | FillSolid in x_draw_glyph_string_background. */ |
| 5764 | if (face->stipple) | 6542 | if (face->stipple) |
| 5765 | XSetFillStyle (display, face->gc, FillOpaqueStippled); | 6543 | { |
| 5766 | else | 6544 | XSetFillStyle (display, face->gc, FillOpaqueStippled); |
| 5767 | XSetBackground (display, face->gc, face->background); | 6545 | x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny, |
| 5768 | 6546 | true); | |
| 5769 | x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny, | 6547 | XSetFillStyle (display, face->gc, FillSolid); |
| 5770 | true); | ||
| 5771 | 6548 | ||
| 5772 | if (!face->stipple) | 6549 | row->stipple_p = true; |
| 5773 | XSetForeground (display, face->gc, face->foreground); | 6550 | } |
| 6551 | else | ||
| 6552 | { | ||
| 6553 | XSetBackground (display, face->gc, face->background); | ||
| 6554 | x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny, | ||
| 6555 | true); | ||
| 6556 | XSetForeground (display, face->gc, face->foreground); | ||
| 6557 | } | ||
| 5774 | } | 6558 | } |
| 5775 | 6559 | ||
| 5776 | #ifdef USE_CAIRO | 6560 | #ifdef USE_CAIRO |
| @@ -6231,6 +7015,31 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) | |||
| 6231 | x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR); | 7015 | x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR); |
| 6232 | } | 7016 | } |
| 6233 | 7017 | ||
| 7018 | #ifndef USE_CAIRO | ||
| 7019 | |||
| 7020 | static void | ||
| 7021 | x_clear_point (struct frame *f, GC gc, int x, int y, | ||
| 7022 | bool respect_alpha_background) | ||
| 7023 | { | ||
| 7024 | XGCValues xgcv; | ||
| 7025 | Display *dpy; | ||
| 7026 | |||
| 7027 | dpy = FRAME_X_DISPLAY (f); | ||
| 7028 | |||
| 7029 | if (f->alpha_background != 1.0 | ||
| 7030 | && respect_alpha_background) | ||
| 7031 | { | ||
| 7032 | x_clear_rectangle (f, gc, x, y, 1, 1, true); | ||
| 7033 | return; | ||
| 7034 | } | ||
| 7035 | |||
| 7036 | XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv); | ||
| 7037 | XSetForeground (dpy, gc, xgcv.background); | ||
| 7038 | XDrawPoint (dpy, FRAME_X_DRAWABLE (f), gc, x, y); | ||
| 7039 | XSetForeground (dpy, gc, xgcv.foreground); | ||
| 7040 | } | ||
| 7041 | |||
| 7042 | #endif | ||
| 6234 | 7043 | ||
| 6235 | /* Draw the background of glyph_string S. If S->background_filled_p | 7044 | /* Draw the background of glyph_string S. If S->background_filled_p |
| 6236 | is non-zero don't draw it. FORCE_P non-zero means draw the | 7045 | is non-zero don't draw it. FORCE_P non-zero means draw the |
| @@ -6561,6 +7370,10 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) | |||
| 6561 | glyph->ascent + glyph->descent - 1); | 7370 | glyph->ascent + glyph->descent - 1); |
| 6562 | x += glyph->pixel_width; | 7371 | x += glyph->pixel_width; |
| 6563 | } | 7372 | } |
| 7373 | |||
| 7374 | /* Defend against hypothetical bad code elsewhere that uses | ||
| 7375 | s->char2b after this function returns. */ | ||
| 7376 | s->char2b = NULL; | ||
| 6564 | } | 7377 | } |
| 6565 | 7378 | ||
| 6566 | #ifdef USE_X_TOOLKIT | 7379 | #ifdef USE_X_TOOLKIT |
| @@ -6923,21 +7736,21 @@ x_hash_string_ignore_case (const char *string) | |||
| 6923 | /* On frame F, translate the color name to RGB values. Use cached | 7736 | /* On frame F, translate the color name to RGB values. Use cached |
| 6924 | information, if possible. | 7737 | information, if possible. |
| 6925 | 7738 | ||
| 6926 | Note that there is currently no way to clean old entries out of the | 7739 | If too many entries are placed in the cache, the least recently |
| 6927 | cache. However, it is limited to names in the server's database, | 7740 | used entries are removed. */ |
| 6928 | and names we've actually looked up; list-colors-display is probably | ||
| 6929 | the most color-intensive case we're likely to hit. */ | ||
| 6930 | 7741 | ||
| 6931 | Status | 7742 | Status |
| 6932 | x_parse_color (struct frame *f, const char *color_name, | 7743 | x_parse_color (struct frame *f, const char *color_name, |
| 6933 | XColor *color) | 7744 | XColor *color) |
| 6934 | { | 7745 | { |
| 6935 | unsigned short r, g, b; | 7746 | unsigned short r, g, b; |
| 6936 | Display *dpy = FRAME_X_DISPLAY (f); | 7747 | Display *dpy; |
| 6937 | Colormap cmap = FRAME_X_COLORMAP (f); | 7748 | Colormap cmap; |
| 6938 | struct x_display_info *dpyinfo; | 7749 | struct x_display_info *dpyinfo; |
| 6939 | struct color_name_cache_entry *cache_entry; | 7750 | struct color_name_cache_entry *cache_entry, *last; |
| 7751 | struct color_name_cache_entry *next, *color_entry; | ||
| 6940 | unsigned int hash, idx; | 7752 | unsigned int hash, idx; |
| 7753 | int rc, i; | ||
| 6941 | 7754 | ||
| 6942 | /* Don't pass #RGB strings directly to XParseColor, because that | 7755 | /* Don't pass #RGB strings directly to XParseColor, because that |
| 6943 | follows the X convention of zero-extending each channel | 7756 | follows the X convention of zero-extending each channel |
| @@ -6949,37 +7762,94 @@ x_parse_color (struct frame *f, const char *color_name, | |||
| 6949 | color->red = r; | 7762 | color->red = r; |
| 6950 | color->green = g; | 7763 | color->green = g; |
| 6951 | color->blue = b; | 7764 | color->blue = b; |
| 7765 | |||
| 6952 | return 1; | 7766 | return 1; |
| 6953 | } | 7767 | } |
| 6954 | 7768 | ||
| 7769 | /* Some X servers send BadValue on empty color names. */ | ||
| 7770 | if (!strlen (color_name)) | ||
| 7771 | return 0; | ||
| 7772 | |||
| 7773 | cmap = FRAME_X_COLORMAP (f); | ||
| 7774 | dpy = FRAME_X_DISPLAY (f); | ||
| 6955 | dpyinfo = FRAME_DISPLAY_INFO (f); | 7775 | dpyinfo = FRAME_DISPLAY_INFO (f); |
| 7776 | |||
| 6956 | hash = x_hash_string_ignore_case (color_name); | 7777 | hash = x_hash_string_ignore_case (color_name); |
| 6957 | idx = hash % dpyinfo->color_names_size; | 7778 | idx = hash % dpyinfo->color_names_size; |
| 6958 | 7779 | ||
| 6959 | for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names[idx]; | 7780 | last = NULL; |
| 7781 | |||
| 7782 | for (cache_entry = dpyinfo->color_names[idx]; | ||
| 6960 | cache_entry; cache_entry = cache_entry->next) | 7783 | cache_entry; cache_entry = cache_entry->next) |
| 6961 | { | 7784 | { |
| 6962 | if (!xstrcasecmp (cache_entry->name, color_name)) | 7785 | if (!xstrcasecmp (cache_entry->name, color_name)) |
| 6963 | { | 7786 | { |
| 6964 | *color = cache_entry->rgb; | 7787 | /* Move recently used entries to the start of the color |
| 6965 | return 1; | 7788 | cache. */ |
| 7789 | |||
| 7790 | if (last) | ||
| 7791 | { | ||
| 7792 | last->next = cache_entry->next; | ||
| 7793 | cache_entry->next = dpyinfo->color_names[idx]; | ||
| 7794 | |||
| 7795 | dpyinfo->color_names[idx] = cache_entry; | ||
| 7796 | } | ||
| 7797 | |||
| 7798 | if (cache_entry->valid) | ||
| 7799 | *color = cache_entry->rgb; | ||
| 7800 | |||
| 7801 | return cache_entry->valid; | ||
| 6966 | } | 7802 | } |
| 6967 | } | ||
| 6968 | 7803 | ||
| 6969 | /* Some X servers send BadValue on empty color names. */ | 7804 | last = cache_entry; |
| 6970 | if (!strlen (color_name)) | 7805 | } |
| 6971 | return 0; | ||
| 6972 | 7806 | ||
| 6973 | if (XParseColor (dpy, cmap, color_name, color) == 0) | 7807 | block_input (); |
| 6974 | /* No caching of negative results, currently. */ | 7808 | rc = XParseColor (dpy, cmap, color_name, color); |
| 6975 | return 0; | 7809 | unblock_input (); |
| 6976 | 7810 | ||
| 6977 | cache_entry = xzalloc (sizeof *cache_entry); | 7811 | cache_entry = xzalloc (sizeof *cache_entry); |
| 6978 | cache_entry->rgb = *color; | 7812 | dpyinfo->color_names_length[idx] += 1; |
| 7813 | |||
| 7814 | if (rc) | ||
| 7815 | cache_entry->rgb = *color; | ||
| 7816 | |||
| 7817 | cache_entry->valid = rc; | ||
| 6979 | cache_entry->name = xstrdup (color_name); | 7818 | cache_entry->name = xstrdup (color_name); |
| 6980 | cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names[idx]; | 7819 | cache_entry->next = dpyinfo->color_names[idx]; |
| 6981 | FRAME_DISPLAY_INFO (f)->color_names[idx] = cache_entry; | 7820 | |
| 6982 | return 1; | 7821 | dpyinfo->color_names[idx] = cache_entry; |
| 7822 | |||
| 7823 | /* Don't let the color cache become too big. */ | ||
| 7824 | if (dpyinfo->color_names_length[idx] > (x_color_cache_bucket_size > 0 | ||
| 7825 | ? x_color_cache_bucket_size : 128)) | ||
| 7826 | { | ||
| 7827 | i = 0; | ||
| 7828 | |||
| 7829 | for (last = dpyinfo->color_names[idx]; last; last = last->next) | ||
| 7830 | { | ||
| 7831 | if (++i == (x_color_cache_bucket_size > 0 | ||
| 7832 | ? x_color_cache_bucket_size : 128)) | ||
| 7833 | { | ||
| 7834 | next = last->next; | ||
| 7835 | last->next = NULL; | ||
| 7836 | |||
| 7837 | for (color_entry = next; color_entry; color_entry = last) | ||
| 7838 | { | ||
| 7839 | last = color_entry->next; | ||
| 7840 | |||
| 7841 | xfree (color_entry->name); | ||
| 7842 | xfree (color_entry); | ||
| 7843 | |||
| 7844 | dpyinfo->color_names_length[idx] -= 1; | ||
| 7845 | } | ||
| 7846 | |||
| 7847 | return rc; | ||
| 7848 | } | ||
| 7849 | } | ||
| 7850 | } | ||
| 7851 | |||
| 7852 | return rc; | ||
| 6983 | } | 7853 | } |
| 6984 | 7854 | ||
| 6985 | 7855 | ||
| @@ -7358,20 +8228,62 @@ x_setup_relief_colors (struct glyph_string *s) | |||
| 7358 | } | 8228 | } |
| 7359 | } | 8229 | } |
| 7360 | 8230 | ||
| 8231 | #ifndef USE_CAIRO | ||
| 8232 | static void | ||
| 8233 | x_fill_triangle (struct frame *f, GC gc, XPoint point1, | ||
| 8234 | XPoint point2, XPoint point3) | ||
| 8235 | { | ||
| 8236 | XPoint abc[3]; | ||
| 8237 | |||
| 8238 | abc[0] = point1; | ||
| 8239 | abc[1] = point2; | ||
| 8240 | abc[2] = point3; | ||
| 8241 | |||
| 8242 | XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), | ||
| 8243 | gc, abc, 3, Convex, CoordModeOrigin); | ||
| 8244 | } | ||
| 8245 | |||
| 8246 | static XPoint | ||
| 8247 | x_make_point (int x, int y) | ||
| 8248 | { | ||
| 8249 | XPoint pt; | ||
| 8250 | |||
| 8251 | pt.x = x; | ||
| 8252 | pt.y = y; | ||
| 8253 | |||
| 8254 | return pt; | ||
| 8255 | } | ||
| 8256 | |||
| 8257 | static bool | ||
| 8258 | x_inside_rect_p (XRectangle *rects, int nrects, int x, int y) | ||
| 8259 | { | ||
| 8260 | int i; | ||
| 8261 | |||
| 8262 | for (i = 0; i < nrects; ++i) | ||
| 8263 | { | ||
| 8264 | if (x >= rects[i].x && y >= rects[i].y | ||
| 8265 | && x < rects[i].x + rects[i].width | ||
| 8266 | && y < rects[i].y + rects[i].height) | ||
| 8267 | return true; | ||
| 8268 | } | ||
| 8269 | |||
| 8270 | return false; | ||
| 8271 | } | ||
| 8272 | #endif | ||
| 7361 | 8273 | ||
| 7362 | /* Draw a relief on frame F inside the rectangle given by LEFT_X, | 8274 | /* Draw a relief on frame F inside the rectangle given by LEFT_X, |
| 7363 | TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief | 8275 | TOP_Y, RIGHT_X, and BOTTOM_Y. VWIDTH and HWIDTH are respectively |
| 7364 | to draw, it must be >= 0. RAISED_P means draw a raised | 8276 | the thickness of the vertical relief (left and right) and |
| 7365 | relief. LEFT_P means draw a relief on the left side of | 8277 | horizontal relief (top and bottom) to draw, it must be >= 0. |
| 7366 | the rectangle. RIGHT_P means draw a relief on the right | 8278 | RAISED_P means draw a raised relief. LEFT_P means draw a relief on |
| 7367 | side of the rectangle. CLIP_RECT is the clipping rectangle to use | 8279 | the left side of the rectangle. RIGHT_P means draw a relief on the |
| 7368 | when drawing. */ | 8280 | right side of the rectangle. CLIP_RECT is the clipping rectangle |
| 8281 | to use when drawing. */ | ||
| 7369 | 8282 | ||
| 7370 | static void | 8283 | static void |
| 7371 | x_draw_relief_rect (struct frame *f, | 8284 | x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x, |
| 7372 | int left_x, int top_y, int right_x, int bottom_y, | 8285 | int bottom_y, int hwidth, int vwidth, bool raised_p, |
| 7373 | int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p, | 8286 | bool top_p, bool bot_p, bool left_p, bool right_p, |
| 7374 | bool left_p, bool right_p, | ||
| 7375 | XRectangle *clip_rect) | 8287 | XRectangle *clip_rect) |
| 7376 | { | 8288 | { |
| 7377 | #ifdef USE_CAIRO | 8289 | #ifdef USE_CAIRO |
| @@ -7447,90 +8359,118 @@ x_draw_relief_rect (struct frame *f, | |||
| 7447 | x_reset_clip_rectangles (f, top_left_gc); | 8359 | x_reset_clip_rectangles (f, top_left_gc); |
| 7448 | x_reset_clip_rectangles (f, bottom_right_gc); | 8360 | x_reset_clip_rectangles (f, bottom_right_gc); |
| 7449 | #else | 8361 | #else |
| 7450 | Display *dpy = FRAME_X_DISPLAY (f); | 8362 | GC gc, white_gc, black_gc, normal_gc; |
| 7451 | Drawable drawable = FRAME_X_DRAWABLE (f); | 8363 | Drawable drawable; |
| 7452 | int i; | 8364 | Display *dpy; |
| 7453 | GC gc; | ||
| 7454 | |||
| 7455 | if (raised_p) | ||
| 7456 | gc = f->output_data.x->white_relief.gc; | ||
| 7457 | else | ||
| 7458 | gc = f->output_data.x->black_relief.gc; | ||
| 7459 | XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); | ||
| 7460 | 8365 | ||
| 7461 | /* This code is more complicated than it has to be, because of two | 8366 | /* This code is more complicated than it has to be, because of two |
| 7462 | minor hacks to make the boxes look nicer: (i) if width > 1, draw | 8367 | minor hacks to make the boxes look nicer: (i) if width > 1, draw |
| 7463 | the outermost line using the black relief. (ii) Omit the four | 8368 | the outermost line using the black relief. (ii) Omit the four |
| 7464 | corner pixels. */ | 8369 | corner pixels. */ |
| 7465 | 8370 | ||
| 7466 | /* Top. */ | 8371 | white_gc = f->output_data.x->white_relief.gc; |
| 7467 | if (top_p) | 8372 | black_gc = f->output_data.x->black_relief.gc; |
| 7468 | { | 8373 | normal_gc = f->output_data.x->normal_gc; |
| 7469 | if (hwidth == 1) | ||
| 7470 | XDrawLine (dpy, drawable, gc, | ||
| 7471 | left_x + left_p, top_y, | ||
| 7472 | right_x + !right_p, top_y); | ||
| 7473 | 8374 | ||
| 7474 | for (i = 1; i < hwidth; ++i) | 8375 | drawable = FRAME_X_DRAWABLE (f); |
| 7475 | XDrawLine (dpy, drawable, gc, | 8376 | dpy = FRAME_X_DISPLAY (f); |
| 7476 | left_x + i * left_p, top_y + i, | ||
| 7477 | right_x + 1 - i * right_p, top_y + i); | ||
| 7478 | } | ||
| 7479 | 8377 | ||
| 7480 | /* Left. */ | 8378 | x_set_clip_rectangles (f, white_gc, clip_rect, 1); |
| 7481 | if (left_p) | 8379 | x_set_clip_rectangles (f, black_gc, clip_rect, 1); |
| 7482 | { | ||
| 7483 | if (vwidth == 1) | ||
| 7484 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); | ||
| 7485 | 8380 | ||
| 7486 | for (i = 1; i < vwidth; ++i) | ||
| 7487 | XDrawLine (dpy, drawable, gc, | ||
| 7488 | left_x + i, top_y + (i + 1) * top_p, | ||
| 7489 | left_x + i, bottom_y + 1 - (i + 1) * bot_p); | ||
| 7490 | } | ||
| 7491 | |||
| 7492 | XSetClipMask (dpy, gc, None); | ||
| 7493 | if (raised_p) | 8381 | if (raised_p) |
| 7494 | gc = f->output_data.x->black_relief.gc; | 8382 | gc = white_gc; |
| 7495 | else | 8383 | else |
| 7496 | gc = f->output_data.x->white_relief.gc; | 8384 | gc = black_gc; |
| 7497 | XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); | ||
| 7498 | 8385 | ||
| 7499 | /* Outermost top line. */ | 8386 | /* Draw lines. */ |
| 7500 | if (top_p && hwidth > 1) | ||
| 7501 | XDrawLine (dpy, drawable, gc, | ||
| 7502 | left_x + left_p, top_y, | ||
| 7503 | right_x + !right_p, top_y); | ||
| 7504 | 8387 | ||
| 7505 | /* Outermost left line. */ | 8388 | if (top_p) |
| 7506 | if (left_p && vwidth > 1) | 8389 | x_fill_rectangle (f, gc, left_x, top_y, |
| 7507 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); | 8390 | right_x - left_x + 1, hwidth, |
| 8391 | false); | ||
| 8392 | |||
| 8393 | if (left_p) | ||
| 8394 | x_fill_rectangle (f, gc, left_x, top_y, vwidth, | ||
| 8395 | bottom_y - top_y + 1, false); | ||
| 8396 | |||
| 8397 | if (raised_p) | ||
| 8398 | gc = black_gc; | ||
| 8399 | else | ||
| 8400 | gc = white_gc; | ||
| 7508 | 8401 | ||
| 7509 | /* Bottom. */ | ||
| 7510 | if (bot_p) | 8402 | if (bot_p) |
| 8403 | x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1, | ||
| 8404 | right_x - left_x + 1, hwidth, false); | ||
| 8405 | |||
| 8406 | if (right_p) | ||
| 8407 | x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y, | ||
| 8408 | vwidth, bottom_y - top_y + 1, false); | ||
| 8409 | |||
| 8410 | /* Draw corners. */ | ||
| 8411 | |||
| 8412 | if (bot_p && left_p) | ||
| 8413 | x_fill_triangle (f, raised_p ? white_gc : black_gc, | ||
| 8414 | x_make_point (left_x, bottom_y - hwidth), | ||
| 8415 | x_make_point (left_x + vwidth, bottom_y - hwidth), | ||
| 8416 | x_make_point (left_x, bottom_y)); | ||
| 8417 | |||
| 8418 | if (top_p && right_p) | ||
| 8419 | x_fill_triangle (f, raised_p ? white_gc : black_gc, | ||
| 8420 | x_make_point (right_x - vwidth, top_y), | ||
| 8421 | x_make_point (right_x, top_y), | ||
| 8422 | x_make_point (right_x - vwidth, top_y + hwidth)); | ||
| 8423 | |||
| 8424 | /* Draw outer line. */ | ||
| 8425 | |||
| 8426 | if (top_p && left_p && bot_p && right_p | ||
| 8427 | && hwidth > 1 && vwidth > 1) | ||
| 8428 | x_draw_rectangle (f, black_gc, left_x, top_y, | ||
| 8429 | right_x - left_x, bottom_y - top_y); | ||
| 8430 | else | ||
| 7511 | { | 8431 | { |
| 7512 | if (hwidth >= 1) | 8432 | if (top_p && hwidth > 1) |
| 7513 | XDrawLine (dpy, drawable, gc, | 8433 | XDrawLine (dpy, drawable, black_gc, left_x, top_y, |
| 7514 | left_x + left_p, bottom_y, | 8434 | right_x + 1, top_y); |
| 7515 | right_x + !right_p, bottom_y); | ||
| 7516 | 8435 | ||
| 7517 | for (i = 1; i < hwidth; ++i) | 8436 | if (bot_p && hwidth > 1) |
| 7518 | XDrawLine (dpy, drawable, gc, | 8437 | XDrawLine (dpy, drawable, black_gc, left_x, bottom_y, |
| 7519 | left_x + i * left_p, bottom_y - i, | 8438 | right_x + 1, bottom_y); |
| 7520 | right_x + 1 - i * right_p, bottom_y - i); | 8439 | |
| 8440 | if (left_p && vwidth > 1) | ||
| 8441 | XDrawLine (dpy, drawable, black_gc, left_x, top_y, | ||
| 8442 | left_x, bottom_y + 1); | ||
| 8443 | |||
| 8444 | if (right_p && vwidth > 1) | ||
| 8445 | XDrawLine (dpy, drawable, black_gc, right_x, top_y, | ||
| 8446 | right_x, bottom_y + 1); | ||
| 7521 | } | 8447 | } |
| 7522 | 8448 | ||
| 7523 | /* Right. */ | 8449 | /* Erase corners. */ |
| 7524 | if (right_p) | 8450 | |
| 8451 | if (hwidth > 1 && vwidth > 1) | ||
| 7525 | { | 8452 | { |
| 7526 | for (i = 0; i < vwidth; ++i) | 8453 | if (left_p && top_p && x_inside_rect_p (clip_rect, 1, |
| 7527 | XDrawLine (dpy, drawable, gc, | 8454 | left_x, top_y)) |
| 7528 | right_x - i, top_y + (i + 1) * top_p, | 8455 | /* This should respect `alpha-background' since it's being |
| 7529 | right_x - i, bottom_y + 1 - (i + 1) * bot_p); | 8456 | cleared with the background color of the frame. */ |
| 7530 | } | 8457 | x_clear_point (f, normal_gc, left_x, top_y, true); |
| 7531 | 8458 | ||
| 7532 | x_reset_clip_rectangles (f, gc); | 8459 | if (left_p && bot_p && x_inside_rect_p (clip_rect, 1, |
| 8460 | left_x, bottom_y)) | ||
| 8461 | x_clear_point (f, normal_gc, left_x, bottom_y, true); | ||
| 8462 | |||
| 8463 | if (right_p && top_p && x_inside_rect_p (clip_rect, 1, | ||
| 8464 | right_x, top_y)) | ||
| 8465 | x_clear_point (f, normal_gc, right_x, top_y, true); | ||
| 7533 | 8466 | ||
| 8467 | if (right_p && bot_p && x_inside_rect_p (clip_rect, 1, | ||
| 8468 | right_x, bottom_y)) | ||
| 8469 | x_clear_point (f, normal_gc, right_x, bottom_y, true); | ||
| 8470 | } | ||
| 8471 | |||
| 8472 | x_reset_clip_rectangles (f, white_gc); | ||
| 8473 | x_reset_clip_rectangles (f, black_gc); | ||
| 7534 | #endif | 8474 | #endif |
| 7535 | } | 8475 | } |
| 7536 | 8476 | ||
| @@ -8039,6 +8979,9 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 8039 | || s->img->pixmap == 0 | 8979 | || s->img->pixmap == 0 |
| 8040 | || s->width != s->background_width) | 8980 | || s->width != s->background_width) |
| 8041 | { | 8981 | { |
| 8982 | if (s->stippled_p) | ||
| 8983 | s->row->stipple_p = true; | ||
| 8984 | |||
| 8042 | #ifndef USE_CAIRO | 8985 | #ifndef USE_CAIRO |
| 8043 | if (s->img->mask) | 8986 | if (s->img->mask) |
| 8044 | { | 8987 | { |
| @@ -8219,6 +9162,8 @@ x_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 8219 | XSetFillStyle (display, gc, FillOpaqueStippled); | 9162 | XSetFillStyle (display, gc, FillOpaqueStippled); |
| 8220 | x_fill_rectangle (s->f, gc, x, y, w, h, true); | 9163 | x_fill_rectangle (s->f, gc, x, y, w, h, true); |
| 8221 | XSetFillStyle (display, gc, FillSolid); | 9164 | XSetFillStyle (display, gc, FillSolid); |
| 9165 | |||
| 9166 | s->row->stipple_p = true; | ||
| 8222 | } | 9167 | } |
| 8223 | else | 9168 | else |
| 8224 | { | 9169 | { |
| @@ -8245,8 +9190,13 @@ x_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 8245 | background_width -= text_left_x - x; | 9190 | background_width -= text_left_x - x; |
| 8246 | x = text_left_x; | 9191 | x = text_left_x; |
| 8247 | } | 9192 | } |
| 9193 | |||
| 9194 | if (!s->row->stipple_p) | ||
| 9195 | s->row->stipple_p = s->stippled_p; | ||
| 9196 | |||
| 8248 | if (background_width > 0) | 9197 | if (background_width > 0) |
| 8249 | x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); | 9198 | x_draw_glyph_string_bg_rect (s, x, s->y, |
| 9199 | background_width, s->height); | ||
| 8250 | } | 9200 | } |
| 8251 | 9201 | ||
| 8252 | s->background_filled_p = true; | 9202 | s->background_filled_p = true; |
| @@ -8522,13 +9472,13 @@ x_draw_glyph_string (struct glyph_string *s) | |||
| 8522 | val = (WINDOW_BUFFER_LOCAL_VALUE | 9472 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 8523 | (Qx_underline_at_descent_line, s->w)); | 9473 | (Qx_underline_at_descent_line, s->w)); |
| 8524 | underline_at_descent_line | 9474 | underline_at_descent_line |
| 8525 | = (!(NILP (val) || EQ (val, Qunbound)) | 9475 | = (!(NILP (val) || BASE_EQ (val, Qunbound)) |
| 8526 | || s->face->underline_at_descent_line_p); | 9476 | || s->face->underline_at_descent_line_p); |
| 8527 | 9477 | ||
| 8528 | val = (WINDOW_BUFFER_LOCAL_VALUE | 9478 | val = (WINDOW_BUFFER_LOCAL_VALUE |
| 8529 | (Qx_use_underline_position_properties, s->w)); | 9479 | (Qx_use_underline_position_properties, s->w)); |
| 8530 | use_underline_position_properties | 9480 | use_underline_position_properties |
| 8531 | = !(NILP (val) || EQ (val, Qunbound)); | 9481 | = !(NILP (val) || BASE_EQ (val, Qunbound)); |
| 8532 | 9482 | ||
| 8533 | /* Get the underline thickness. Default is 1 pixel. */ | 9483 | /* Get the underline thickness. Default is 1 pixel. */ |
| 8534 | if (font && font->underline_thickness > 0) | 9484 | if (font && font->underline_thickness > 0) |
| @@ -8560,7 +9510,7 @@ x_draw_glyph_string (struct glyph_string *s) | |||
| 8560 | } | 9510 | } |
| 8561 | 9511 | ||
| 8562 | /* Ignore minimum_offset if the amount of pixels was | 9512 | /* Ignore minimum_offset if the amount of pixels was |
| 8563 | explictly specified. */ | 9513 | explicitly specified. */ |
| 8564 | if (!s->face->underline_pixels_above_descent_line) | 9514 | if (!s->face->underline_pixels_above_descent_line) |
| 8565 | position = max (position, minimum_offset); | 9515 | position = max (position, minimum_offset); |
| 8566 | } | 9516 | } |
| @@ -8695,6 +9645,14 @@ x_draw_glyph_string (struct glyph_string *s) | |||
| 8695 | /* Reset clipping. */ | 9645 | /* Reset clipping. */ |
| 8696 | x_reset_clip_rectangles (s->f, s->gc); | 9646 | x_reset_clip_rectangles (s->f, s->gc); |
| 8697 | s->num_clips = 0; | 9647 | s->num_clips = 0; |
| 9648 | |||
| 9649 | /* Set the stippled flag that tells redisplay whether or not a | ||
| 9650 | stipple was actually draw. */ | ||
| 9651 | |||
| 9652 | if (s->first_glyph->type != STRETCH_GLYPH | ||
| 9653 | && s->first_glyph->type != IMAGE_GLYPH | ||
| 9654 | && !s->row->stipple_p) | ||
| 9655 | s->row->stipple_p = s->stippled_p; | ||
| 8698 | } | 9656 | } |
| 8699 | 9657 | ||
| 8700 | /* Shift display to make room for inserted glyphs. */ | 9658 | /* Shift display to make room for inserted glyphs. */ |
| @@ -8724,13 +9682,15 @@ x_delete_glyphs (struct frame *f, int n) | |||
| 8724 | /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable. | 9682 | /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable. |
| 8725 | If they are <= 0, this is probably an error. */ | 9683 | If they are <= 0, this is probably an error. */ |
| 8726 | 9684 | ||
| 8727 | MAYBE_UNUSED static void | 9685 | #if defined USE_GTK || !defined USE_CAIRO |
| 9686 | static void | ||
| 8728 | x_clear_area1 (Display *dpy, Window window, | 9687 | x_clear_area1 (Display *dpy, Window window, |
| 8729 | int x, int y, int width, int height, int exposures) | 9688 | int x, int y, int width, int height, int exposures) |
| 8730 | { | 9689 | { |
| 8731 | eassert (width > 0 && height > 0); | 9690 | eassert (width > 0 && height > 0); |
| 8732 | XClearArea (dpy, window, x, y, width, height, exposures); | 9691 | XClearArea (dpy, window, x, y, width, height, exposures); |
| 8733 | } | 9692 | } |
| 9693 | #endif | ||
| 8734 | 9694 | ||
| 8735 | void | 9695 | void |
| 8736 | x_clear_area (struct frame *f, int x, int y, int width, int height) | 9696 | x_clear_area (struct frame *f, int x, int y, int width, int height) |
| @@ -9439,8 +10399,24 @@ x_toggle_visible_pointer (struct frame *f, bool invisible) | |||
| 9439 | if (dpyinfo->invisible_cursor == None) | 10399 | if (dpyinfo->invisible_cursor == None) |
| 9440 | dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); | 10400 | dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); |
| 9441 | 10401 | ||
| 10402 | #ifndef HAVE_XFIXES | ||
| 9442 | if (dpyinfo->invisible_cursor == None) | 10403 | if (dpyinfo->invisible_cursor == None) |
| 9443 | invisible = false; | 10404 | invisible = false; |
| 10405 | #else | ||
| 10406 | /* But if Xfixes is available, try using it instead. */ | ||
| 10407 | if (dpyinfo->invisible_cursor == None) | ||
| 10408 | { | ||
| 10409 | if (x_probe_xfixes_extension (dpyinfo)) | ||
| 10410 | { | ||
| 10411 | dpyinfo->fixes_pointer_blanking = true; | ||
| 10412 | xfixes_toggle_visible_pointer (f, invisible); | ||
| 10413 | |||
| 10414 | return; | ||
| 10415 | } | ||
| 10416 | else | ||
| 10417 | invisible = false; | ||
| 10418 | } | ||
| 10419 | #endif | ||
| 9444 | 10420 | ||
| 9445 | if (invisible) | 10421 | if (invisible) |
| 9446 | XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f), | 10422 | XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f), |
| @@ -9588,6 +10564,67 @@ x_window_to_frame (struct x_display_info *dpyinfo, int wdesc) | |||
| 9588 | return 0; | 10564 | return 0; |
| 9589 | } | 10565 | } |
| 9590 | 10566 | ||
| 10567 | /* Like x_any_window_to_frame but only try to find tooltip frames. | ||
| 10568 | |||
| 10569 | If wdesc is a toolkit tooltip without an associated frame, set | ||
| 10570 | UNRELATED_TOOLTIP_P to true. Otherwise, set it to false. */ | ||
| 10571 | static struct frame * | ||
| 10572 | x_tooltip_window_to_frame (struct x_display_info *dpyinfo, | ||
| 10573 | Window wdesc, bool *unrelated_tooltip_p) | ||
| 10574 | { | ||
| 10575 | Lisp_Object tail, frame; | ||
| 10576 | struct frame *f; | ||
| 10577 | #ifdef USE_GTK | ||
| 10578 | GtkWidget *widget; | ||
| 10579 | GdkWindow *tooltip_window; | ||
| 10580 | #endif | ||
| 10581 | |||
| 10582 | *unrelated_tooltip_p = false; | ||
| 10583 | |||
| 10584 | FOR_EACH_FRAME (tail, frame) | ||
| 10585 | { | ||
| 10586 | f = XFRAME (frame); | ||
| 10587 | |||
| 10588 | if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f) | ||
| 10589 | && FRAME_DISPLAY_INFO (f) == dpyinfo | ||
| 10590 | && FRAME_X_WINDOW (f) == wdesc) | ||
| 10591 | return f; | ||
| 10592 | |||
| 10593 | #ifdef USE_GTK | ||
| 10594 | if (!FRAME_X_P (f)) | ||
| 10595 | continue; | ||
| 10596 | |||
| 10597 | if (FRAME_X_OUTPUT (f)->ttip_window) | ||
| 10598 | widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window); | ||
| 10599 | else | ||
| 10600 | widget = NULL; | ||
| 10601 | |||
| 10602 | if (widget) | ||
| 10603 | tooltip_window = gtk_widget_get_window (widget); | ||
| 10604 | else | ||
| 10605 | tooltip_window = NULL; | ||
| 10606 | |||
| 10607 | #ifdef HAVE_GTK3 | ||
| 10608 | if (tooltip_window | ||
| 10609 | && (gdk_x11_window_get_xid (tooltip_window) == wdesc)) | ||
| 10610 | { | ||
| 10611 | *unrelated_tooltip_p = true; | ||
| 10612 | break; | ||
| 10613 | } | ||
| 10614 | #else | ||
| 10615 | if (tooltip_window | ||
| 10616 | && (GDK_WINDOW_XID (tooltip_window) == wdesc)) | ||
| 10617 | { | ||
| 10618 | *unrelated_tooltip_p = true; | ||
| 10619 | break; | ||
| 10620 | } | ||
| 10621 | #endif | ||
| 10622 | #endif | ||
| 10623 | } | ||
| 10624 | |||
| 10625 | return NULL; | ||
| 10626 | } | ||
| 10627 | |||
| 9591 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | 10628 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
| 9592 | 10629 | ||
| 9593 | /* Like x_window_to_frame but also compares the window with the widget's | 10630 | /* Like x_window_to_frame but also compares the window with the widget's |
| @@ -9742,8 +10779,11 @@ static void | |||
| 9742 | x_next_event_from_any_display (XEvent *event) | 10779 | x_next_event_from_any_display (XEvent *event) |
| 9743 | { | 10780 | { |
| 9744 | struct x_display_info *dpyinfo; | 10781 | struct x_display_info *dpyinfo; |
| 9745 | fd_set fds; | 10782 | fd_set fds, rfds; |
| 9746 | int fd, maxfd; | 10783 | int fd, maxfd, rc; |
| 10784 | |||
| 10785 | rc = -1; | ||
| 10786 | FD_ZERO (&rfds); | ||
| 9747 | 10787 | ||
| 9748 | while (true) | 10788 | while (true) |
| 9749 | { | 10789 | { |
| @@ -9753,47 +10793,113 @@ x_next_event_from_any_display (XEvent *event) | |||
| 9753 | for (dpyinfo = x_display_list; dpyinfo; | 10793 | for (dpyinfo = x_display_list; dpyinfo; |
| 9754 | dpyinfo = dpyinfo->next) | 10794 | dpyinfo = dpyinfo->next) |
| 9755 | { | 10795 | { |
| 9756 | if (XPending (dpyinfo->display)) | 10796 | fd = ConnectionNumber (dpyinfo->display); |
| 10797 | |||
| 10798 | if ((rc < 0 || FD_ISSET (fd, &rfds)) | ||
| 10799 | && XPending (dpyinfo->display)) | ||
| 9757 | { | 10800 | { |
| 9758 | XNextEvent (dpyinfo->display, event); | 10801 | XNextEvent (dpyinfo->display, event); |
| 9759 | return; | 10802 | return; |
| 9760 | } | 10803 | } |
| 9761 | 10804 | ||
| 9762 | fd = XConnectionNumber (dpyinfo->display); | ||
| 9763 | |||
| 9764 | if (fd > maxfd) | 10805 | if (fd > maxfd) |
| 9765 | maxfd = fd; | 10806 | maxfd = fd; |
| 9766 | 10807 | ||
| 9767 | eassert (fd < FD_SETSIZE); | 10808 | eassert (fd < FD_SETSIZE); |
| 9768 | FD_SET (XConnectionNumber (dpyinfo->display), &fds); | 10809 | FD_SET (fd, &fds); |
| 9769 | } | 10810 | } |
| 9770 | 10811 | ||
| 9771 | eassert (maxfd >= 0); | 10812 | eassert (maxfd >= 0); |
| 9772 | 10813 | ||
| 9773 | /* We don't have to check the return of pselect, because if an | 10814 | /* Continue to read input even if pselect fails, because if an |
| 9774 | error occurs XPending will call the IO error handler, which | 10815 | error occurs XPending will call the IO error handler, which |
| 9775 | then brings us out of this loop. */ | 10816 | then brings us out of this loop. */ |
| 9776 | pselect (maxfd, &fds, NULL, NULL, NULL, NULL); | 10817 | rc = pselect (maxfd + 1, &fds, NULL, NULL, NULL, NULL); |
| 10818 | |||
| 10819 | if (rc >= 0) | ||
| 10820 | rfds = fds; | ||
| 9777 | } | 10821 | } |
| 9778 | } | 10822 | } |
| 9779 | 10823 | ||
| 9780 | #endif /* USE_X_TOOLKIT || USE_GTK */ | 10824 | #endif /* USE_X_TOOLKIT || USE_GTK */ |
| 9781 | 10825 | ||
| 9782 | static void | 10826 | static void |
| 9783 | x_clear_dnd_targets (void) | 10827 | x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem) |
| 9784 | { | 10828 | { |
| 9785 | if (x_dnd_unwind_flag) | 10829 | specpdl_ref count; |
| 9786 | x_set_dnd_targets (NULL, 0); | 10830 | struct selection_input_event se; |
| 10831 | |||
| 10832 | count = SPECPDL_INDEX (); | ||
| 10833 | se = tem->se; | ||
| 10834 | |||
| 10835 | record_unwind_protect_ptr (xfree, tem); | ||
| 10836 | x_handle_selection_event (&se); | ||
| 10837 | unbind_to (count, Qnil); | ||
| 10838 | } | ||
| 10839 | |||
| 10840 | /* Handle all pending selection request events from modal event | ||
| 10841 | loops. */ | ||
| 10842 | void | ||
| 10843 | x_handle_pending_selection_requests (void) | ||
| 10844 | { | ||
| 10845 | struct x_selection_request_event *tem; | ||
| 10846 | |||
| 10847 | while (pending_selection_requests) | ||
| 10848 | { | ||
| 10849 | tem = pending_selection_requests; | ||
| 10850 | pending_selection_requests = tem->next; | ||
| 10851 | |||
| 10852 | x_handle_pending_selection_requests_1 (tem); | ||
| 10853 | } | ||
| 10854 | } | ||
| 10855 | |||
| 10856 | static void | ||
| 10857 | x_push_selection_request (struct selection_input_event *se) | ||
| 10858 | { | ||
| 10859 | struct x_selection_request_event *tem; | ||
| 10860 | |||
| 10861 | tem = xmalloc (sizeof *tem); | ||
| 10862 | tem->next = pending_selection_requests; | ||
| 10863 | tem->se = *se; | ||
| 10864 | pending_selection_requests = tem; | ||
| 10865 | } | ||
| 10866 | |||
| 10867 | bool | ||
| 10868 | x_detect_pending_selection_requests (void) | ||
| 10869 | { | ||
| 10870 | return pending_selection_requests; | ||
| 10871 | } | ||
| 10872 | |||
| 10873 | static void | ||
| 10874 | x_clear_dnd_action (void) | ||
| 10875 | { | ||
| 10876 | x_dnd_action_symbol = Qnil; | ||
| 9787 | } | 10877 | } |
| 9788 | 10878 | ||
| 9789 | /* This function is defined far away from the rest of the XDND code so | 10879 | /* This function is defined far away from the rest of the XDND code so |
| 9790 | it can utilize `x_any_window_to_frame'. */ | 10880 | it can utilize `x_any_window_to_frame'. */ |
| 9791 | 10881 | ||
| 10882 | /* Implementors beware! On most other platforms (where drag-and-drop | ||
| 10883 | data is not provided via selections, but some kind of serialization | ||
| 10884 | mechanism), it is usually much easier to implement a suitable | ||
| 10885 | primitive instead of copying the C code here, and then to build | ||
| 10886 | `x-begin-drag' on top of that, by making it a wrapper function in | ||
| 10887 | Lisp that converts the list of targets and value of `XdndSelection' | ||
| 10888 | to serialized data. Also be sure to update the data types used in | ||
| 10889 | dnd.el. | ||
| 10890 | |||
| 10891 | For examples of how to do this, see `haiku-drag-message' and | ||
| 10892 | `x-begin-drag' in haikuselect.c and lisp/term/haiku-win.el, and | ||
| 10893 | `ns-begin-drag' and `x-begin-drag' in nsselect.m and | ||
| 10894 | lisp/term/ns-win.el. */ | ||
| 10895 | |||
| 9792 | Lisp_Object | 10896 | Lisp_Object |
| 9793 | x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | 10897 | x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, |
| 9794 | Lisp_Object return_frame, Atom *ask_action_list, | 10898 | Lisp_Object return_frame, Atom *ask_action_list, |
| 9795 | const char **ask_action_names, size_t n_ask_actions, | 10899 | const char **ask_action_names, size_t n_ask_actions, |
| 9796 | bool allow_current_frame) | 10900 | bool allow_current_frame, Atom *target_atoms, |
| 10901 | int ntargets, Lisp_Object selection_target_list, | ||
| 10902 | bool follow_tooltip) | ||
| 9797 | { | 10903 | { |
| 9798 | #ifndef USE_GTK | 10904 | #ifndef USE_GTK |
| 9799 | XEvent next_event; | 10905 | XEvent next_event; |
| @@ -9801,60 +10907,119 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9801 | #endif | 10907 | #endif |
| 9802 | XWindowAttributes root_window_attrs; | 10908 | XWindowAttributes root_window_attrs; |
| 9803 | struct input_event hold_quit; | 10909 | struct input_event hold_quit; |
| 9804 | struct frame *any; | ||
| 9805 | char *atom_name, *ask_actions; | 10910 | char *atom_name, *ask_actions; |
| 9806 | Lisp_Object action, ltimestamp; | 10911 | Lisp_Object action, ltimestamp; |
| 9807 | specpdl_ref ref; | 10912 | specpdl_ref ref, count, base; |
| 9808 | ptrdiff_t i, end, fill; | 10913 | ptrdiff_t i, end, fill; |
| 9809 | XTextProperty prop; | 10914 | XTextProperty prop; |
| 9810 | xm_drop_start_message dmsg; | 10915 | xm_drop_start_message dmsg; |
| 9811 | Lisp_Object frame_object, x, y, frame, local_value; | 10916 | Lisp_Object frame_object, x, y, frame, local_value; |
| 9812 | bool signals_were_pending; | 10917 | bool signals_were_pending, need_sync; |
| 9813 | #ifdef HAVE_XKB | 10918 | #ifdef HAVE_XKB |
| 9814 | XkbStateRec keyboard_state; | 10919 | XkbStateRec keyboard_state; |
| 9815 | #endif | 10920 | #endif |
| 9816 | #ifndef USE_GTK | 10921 | #ifndef USE_GTK |
| 9817 | struct x_display_info *event_display; | 10922 | struct x_display_info *event_display; |
| 9818 | #endif | 10923 | #endif |
| 10924 | union buffered_input_event *events, *event; | ||
| 10925 | int n_events; | ||
| 10926 | struct frame *event_frame; | ||
| 9819 | 10927 | ||
| 9820 | if (!FRAME_VISIBLE_P (f)) | 10928 | base = SPECPDL_INDEX (); |
| 10929 | |||
| 10930 | /* Bind this here to avoid juggling bindings and SAFE_FREE in | ||
| 10931 | Fx_begin_drag. */ | ||
| 10932 | specbind (Qx_dnd_targets_list, selection_target_list); | ||
| 10933 | |||
| 10934 | /* Before starting drag-and-drop, walk through the keyboard buffer | ||
| 10935 | to see if there are any UNSUPPORTED_DROP_EVENTs, and run them now | ||
| 10936 | if they exist, to prevent race conditions from happening due to | ||
| 10937 | multiple unsupported drops running at once. */ | ||
| 10938 | |||
| 10939 | block_input (); | ||
| 10940 | events = alloca (sizeof *events * KBD_BUFFER_SIZE); | ||
| 10941 | n_events = 0; | ||
| 10942 | event = kbd_fetch_ptr; | ||
| 10943 | |||
| 10944 | while (event != kbd_store_ptr) | ||
| 9821 | { | 10945 | { |
| 9822 | x_set_dnd_targets (NULL, 0); | 10946 | if (event->ie.kind == UNSUPPORTED_DROP_EVENT |
| 9823 | error ("Frame is invisible"); | 10947 | && event->ie.modifiers < x_dnd_unsupported_event_level) |
| 10948 | events[n_events++] = *event; | ||
| 10949 | |||
| 10950 | event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 10951 | ? kbd_buffer : event + 1); | ||
| 9824 | } | 10952 | } |
| 9825 | 10953 | ||
| 10954 | x_dnd_unsupported_event_level += 1; | ||
| 10955 | unblock_input (); | ||
| 10956 | |||
| 10957 | for (i = 0; i < n_events; ++i) | ||
| 10958 | { | ||
| 10959 | maybe_quit (); | ||
| 10960 | |||
| 10961 | event = &events[i]; | ||
| 10962 | event_frame = XFRAME (event->ie.frame_or_window); | ||
| 10963 | |||
| 10964 | if (!FRAME_LIVE_P (event_frame)) | ||
| 10965 | continue; | ||
| 10966 | |||
| 10967 | if (!NILP (Vx_dnd_unsupported_drop_function)) | ||
| 10968 | { | ||
| 10969 | if (!NILP (call7 (Vx_dnd_unsupported_drop_function, | ||
| 10970 | XCAR (XCDR (event->ie.arg)), event->ie.x, | ||
| 10971 | event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), | ||
| 10972 | make_uint (event->ie.code), | ||
| 10973 | event->ie.frame_or_window, | ||
| 10974 | make_int (event->ie.timestamp)))) | ||
| 10975 | continue; | ||
| 10976 | } | ||
| 10977 | |||
| 10978 | /* `x-dnd-unsupported-drop-function' could have deleted the | ||
| 10979 | event frame. */ | ||
| 10980 | if (!FRAME_LIVE_P (event_frame)) | ||
| 10981 | continue; | ||
| 10982 | |||
| 10983 | x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (event_frame), | ||
| 10984 | event->ie.frame_or_window, | ||
| 10985 | XCAR (event->ie.arg), | ||
| 10986 | XCAR (XCDR (event->ie.arg)), | ||
| 10987 | (Window) event->ie.code, | ||
| 10988 | XFIXNUM (event->ie.x), | ||
| 10989 | XFIXNUM (event->ie.y), | ||
| 10990 | event->ie.timestamp); | ||
| 10991 | break; | ||
| 10992 | } | ||
| 10993 | |||
| 10994 | if (!FRAME_VISIBLE_P (f)) | ||
| 10995 | error ("Frame must be visible"); | ||
| 10996 | |||
| 9826 | XSETFRAME (frame, f); | 10997 | XSETFRAME (frame, f); |
| 9827 | local_value = assq_no_quit (QXdndSelection, | 10998 | local_value = assq_no_quit (QXdndSelection, |
| 9828 | FRAME_TERMINAL (f)->Vselection_alist); | 10999 | FRAME_TERMINAL (f)->Vselection_alist); |
| 9829 | 11000 | ||
| 9830 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) | 11001 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) |
| 9831 | { | 11002 | error ("A drag-and-drop session is already in progress"); |
| 9832 | x_set_dnd_targets (NULL, 0); | ||
| 9833 | error ("A drag-and-drop session is already in progress"); | ||
| 9834 | } | ||
| 9835 | 11003 | ||
| 9836 | if (CONSP (local_value)) | 11004 | DEFER_SELECTIONS; |
| 9837 | { | ||
| 9838 | ref = SPECPDL_INDEX (); | ||
| 9839 | 11005 | ||
| 9840 | record_unwind_protect_void (x_clear_dnd_targets); | 11006 | /* If local_value is nil, then we lost ownership of XdndSelection. |
| 9841 | x_dnd_unwind_flag = true; | 11007 | Signal a more informative error than args-out-of-range. */ |
| 9842 | x_own_selection (QXdndSelection, | 11008 | if (NILP (local_value)) |
| 9843 | Fnth (make_fixnum (1), local_value), frame); | 11009 | error ("Lost ownership of XdndSelection"); |
| 9844 | x_dnd_unwind_flag = false; | 11010 | |
| 9845 | unbind_to (ref, Qnil); | 11011 | if (CONSP (local_value)) |
| 9846 | } | 11012 | x_own_selection (QXdndSelection, |
| 11013 | Fnth (make_fixnum (1), local_value), frame); | ||
| 9847 | else | 11014 | else |
| 9848 | { | 11015 | error ("No local value for XdndSelection"); |
| 9849 | x_set_dnd_targets (NULL, 0); | ||
| 9850 | error ("No local value for XdndSelection"); | ||
| 9851 | } | ||
| 9852 | 11016 | ||
| 9853 | if (popup_activated ()) | 11017 | if (popup_activated ()) |
| 9854 | { | 11018 | error ("Trying to drag-and-drop from within a menu-entry"); |
| 9855 | x_set_dnd_targets (NULL, 0); | 11019 | |
| 9856 | error ("Trying to drag-and-drop from within a menu-entry"); | 11020 | x_set_dnd_targets (target_atoms, ntargets); |
| 9857 | } | 11021 | record_unwind_protect_void (x_free_dnd_targets); |
| 11022 | record_unwind_protect_void (x_clear_dnd_action); | ||
| 9858 | 11023 | ||
| 9859 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), | 11024 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), |
| 9860 | QXdndSelection); | 11025 | QXdndSelection); |
| @@ -9864,10 +11029,24 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9864 | else | 11029 | else |
| 9865 | x_dnd_selection_timestamp = XFIXNUM (ltimestamp); | 11030 | x_dnd_selection_timestamp = XFIXNUM (ltimestamp); |
| 9866 | 11031 | ||
| 11032 | x_dnd_motif_operations | ||
| 11033 | = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction); | ||
| 11034 | |||
| 11035 | x_dnd_first_motif_operation = XM_DRAG_NOOP; | ||
| 11036 | |||
| 9867 | if (n_ask_actions) | 11037 | if (n_ask_actions) |
| 9868 | { | 11038 | { |
| 11039 | x_dnd_motif_operations | ||
| 11040 | = xm_operations_from_actions (FRAME_DISPLAY_INFO (f), | ||
| 11041 | ask_action_list, | ||
| 11042 | n_ask_actions); | ||
| 11043 | x_dnd_first_motif_operation | ||
| 11044 | = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | ||
| 11045 | ask_action_list[0]); | ||
| 11046 | |||
| 9869 | ask_actions = NULL; | 11047 | ask_actions = NULL; |
| 9870 | end = 0; | 11048 | end = 0; |
| 11049 | count = SPECPDL_INDEX (); | ||
| 9871 | 11050 | ||
| 9872 | for (i = 0; i < n_ask_actions; ++i) | 11051 | for (i = 0; i < n_ask_actions; ++i) |
| 9873 | { | 11052 | { |
| @@ -9889,16 +11068,25 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9889 | prop.format = 8; | 11068 | prop.format = 8; |
| 9890 | prop.nitems = end; | 11069 | prop.nitems = end; |
| 9891 | 11070 | ||
| 11071 | record_unwind_protect_ptr (xfree, ask_actions); | ||
| 11072 | |||
| 11073 | /* This can potentially store a lot of data in window | ||
| 11074 | properties, so check for allocation errors. */ | ||
| 9892 | block_input (); | 11075 | block_input (); |
| 11076 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 9893 | XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 11077 | XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 9894 | &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription); | 11078 | &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription); |
| 9895 | xfree (ask_actions); | ||
| 9896 | 11079 | ||
| 9897 | XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 11080 | XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 9898 | FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32, | 11081 | FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32, |
| 9899 | PropModeReplace, (unsigned char *) ask_action_list, | 11082 | PropModeReplace, (unsigned char *) ask_action_list, |
| 9900 | n_ask_actions); | 11083 | n_ask_actions); |
| 11084 | x_check_errors (FRAME_X_DISPLAY (f), | ||
| 11085 | "Can't set action descriptions: %s"); | ||
| 11086 | x_uncatch_errors_after_check (); | ||
| 9901 | unblock_input (); | 11087 | unblock_input (); |
| 11088 | |||
| 11089 | unbind_to (count, Qnil); | ||
| 9902 | } | 11090 | } |
| 9903 | else | 11091 | else |
| 9904 | { | 11092 | { |
| @@ -9914,14 +11102,45 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9914 | unblock_input (); | 11102 | unblock_input (); |
| 9915 | } | 11103 | } |
| 9916 | 11104 | ||
| 11105 | if (follow_tooltip) | ||
| 11106 | { | ||
| 11107 | #if defined HAVE_XRANDR || defined USE_GTK | ||
| 11108 | x_dnd_monitors | ||
| 11109 | = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list; | ||
| 11110 | |||
| 11111 | if (NILP (x_dnd_monitors)) | ||
| 11112 | #endif | ||
| 11113 | x_dnd_monitors | ||
| 11114 | = Fx_display_monitor_attributes_list (frame); | ||
| 11115 | |||
| 11116 | record_unwind_protect_void (x_clear_dnd_monitors); | ||
| 11117 | } | ||
| 11118 | |||
| 11119 | x_dnd_update_tooltip = follow_tooltip; | ||
| 11120 | |||
| 11121 | /* This shouldn't happen. */ | ||
| 11122 | if (x_dnd_toplevels) | ||
| 11123 | x_dnd_free_toplevels (true); | ||
| 11124 | |||
| 11125 | #ifdef USE_GTK | ||
| 11126 | /* Prevent GTK+ timeouts from being run, since they can call | ||
| 11127 | handle_one_xevent behind our back. */ | ||
| 11128 | suppress_xg_select (); | ||
| 11129 | record_unwind_protect_void (release_xg_select); | ||
| 11130 | #endif | ||
| 11131 | |||
| 11132 | /* Initialize most of the state for the drag-and-drop operation. */ | ||
| 9917 | x_dnd_in_progress = true; | 11133 | x_dnd_in_progress = true; |
| 11134 | x_dnd_recursion_depth = command_loop_level + minibuf_level; | ||
| 9918 | x_dnd_frame = f; | 11135 | x_dnd_frame = f; |
| 9919 | x_dnd_last_seen_window = None; | 11136 | x_dnd_last_seen_window = None; |
| 9920 | x_dnd_last_seen_toplevel = None; | 11137 | x_dnd_last_seen_toplevel = None; |
| 9921 | x_dnd_last_protocol_version = -1; | 11138 | x_dnd_last_protocol_version = -1; |
| 11139 | x_dnd_last_window_is_frame = false; | ||
| 9922 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; | 11140 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; |
| 9923 | x_dnd_mouse_rect_target = None; | 11141 | x_dnd_mouse_rect_target = None; |
| 9924 | x_dnd_action = None; | 11142 | x_dnd_action = None; |
| 11143 | x_dnd_action_symbol = Qnil; | ||
| 9925 | x_dnd_wanted_action = xaction; | 11144 | x_dnd_wanted_action = xaction; |
| 9926 | x_dnd_return_frame = 0; | 11145 | x_dnd_return_frame = 0; |
| 9927 | x_dnd_waiting_for_finish = false; | 11146 | x_dnd_waiting_for_finish = false; |
| @@ -9934,6 +11153,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9934 | x_dnd_toplevels = NULL; | 11153 | x_dnd_toplevels = NULL; |
| 9935 | x_dnd_allow_current_frame = allow_current_frame; | 11154 | x_dnd_allow_current_frame = allow_current_frame; |
| 9936 | x_dnd_movement_frame = NULL; | 11155 | x_dnd_movement_frame = NULL; |
| 11156 | x_dnd_init_type_lists = false; | ||
| 9937 | #ifdef HAVE_XKB | 11157 | #ifdef HAVE_XKB |
| 9938 | x_dnd_keyboard_state = 0; | 11158 | x_dnd_keyboard_state = 0; |
| 9939 | 11159 | ||
| @@ -9953,9 +11173,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9953 | { | 11173 | { |
| 9954 | if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f))) | 11174 | if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f))) |
| 9955 | { | 11175 | { |
| 9956 | x_dnd_free_toplevels (); | 11176 | x_dnd_free_toplevels (true); |
| 9957 | x_dnd_use_toplevels = false; | 11177 | x_dnd_use_toplevels = false; |
| 9958 | } | 11178 | } |
| 11179 | else | ||
| 11180 | record_unwind_protect_void (x_free_dnd_toplevels); | ||
| 9959 | } | 11181 | } |
| 9960 | 11182 | ||
| 9961 | if (!NILP (return_frame)) | 11183 | if (!NILP (return_frame)) |
| @@ -9983,14 +11205,17 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 9983 | 11205 | ||
| 9984 | while (x_dnd_in_progress || x_dnd_waiting_for_finish) | 11206 | while (x_dnd_in_progress || x_dnd_waiting_for_finish) |
| 9985 | { | 11207 | { |
| 9986 | hold_quit.kind = NO_EVENT; | 11208 | EVENT_INIT (hold_quit); |
| 11209 | |||
| 9987 | #ifdef USE_GTK | 11210 | #ifdef USE_GTK |
| 9988 | current_finish = X_EVENT_NORMAL; | 11211 | current_finish = X_EVENT_NORMAL; |
| 9989 | current_hold_quit = &hold_quit; | 11212 | current_hold_quit = &hold_quit; |
| 9990 | current_count = 0; | 11213 | current_count = 0; |
| 11214 | xg_pending_quit_event.kind = NO_EVENT; | ||
| 9991 | #endif | 11215 | #endif |
| 9992 | 11216 | ||
| 9993 | block_input (); | 11217 | block_input (); |
| 11218 | x_dnd_inside_handle_one_xevent = true; | ||
| 9994 | #ifdef USE_GTK | 11219 | #ifdef USE_GTK |
| 9995 | gtk_main_iteration (); | 11220 | gtk_main_iteration (); |
| 9996 | #elif defined USE_X_TOOLKIT | 11221 | #elif defined USE_X_TOOLKIT |
| @@ -10027,7 +11252,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10027 | &next_event, &finish, &hold_quit); | 11252 | &next_event, &finish, &hold_quit); |
| 10028 | #endif | 11253 | #endif |
| 10029 | } | 11254 | } |
| 11255 | #else | ||
| 11256 | /* Clear these before the read_socket_hook can be called. */ | ||
| 11257 | current_count = -1; | ||
| 11258 | current_hold_quit = NULL; | ||
| 10030 | #endif | 11259 | #endif |
| 11260 | x_dnd_inside_handle_one_xevent = false; | ||
| 10031 | 11261 | ||
| 10032 | /* The unblock_input below might try to read input, but | 11262 | /* The unblock_input below might try to read input, but |
| 10033 | XTread_socket does nothing inside a drag-and-drop event | 11263 | XTread_socket does nothing inside a drag-and-drop event |
| @@ -10042,7 +11272,16 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10042 | if (event_display == FRAME_DISPLAY_INFO (f)) | 11272 | if (event_display == FRAME_DISPLAY_INFO (f)) |
| 10043 | { | 11273 | { |
| 10044 | #endif | 11274 | #endif |
| 10045 | if (x_dnd_movement_frame) | 11275 | if (x_dnd_movement_frame |
| 11276 | /* FIXME: how come this can end up with movement frames | ||
| 11277 | from other displays on GTK builds? */ | ||
| 11278 | && (FRAME_X_DISPLAY (x_dnd_movement_frame) | ||
| 11279 | == FRAME_X_DISPLAY (f)) | ||
| 11280 | /* If both those variables are false, then F is no | ||
| 11281 | longer protected from deletion by Lisp code. This | ||
| 11282 | can only happen during the final iteration of the DND | ||
| 11283 | event loop. */ | ||
| 11284 | && (x_dnd_in_progress || x_dnd_waiting_for_finish)) | ||
| 10046 | { | 11285 | { |
| 10047 | XSETFRAME (frame_object, x_dnd_movement_frame); | 11286 | XSETFRAME (frame_object, x_dnd_movement_frame); |
| 10048 | XSETINT (x, x_dnd_movement_x); | 11287 | XSETINT (x, x_dnd_movement_x); |
| @@ -10050,6 +11289,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10050 | x_dnd_movement_frame = NULL; | 11289 | x_dnd_movement_frame = NULL; |
| 10051 | 11290 | ||
| 10052 | if (!NILP (Vx_dnd_movement_function) | 11291 | if (!NILP (Vx_dnd_movement_function) |
| 11292 | && FRAME_LIVE_P (XFRAME (frame_object)) | ||
| 10053 | && !FRAME_TOOLTIP_P (XFRAME (frame_object)) | 11293 | && !FRAME_TOOLTIP_P (XFRAME (frame_object)) |
| 10054 | && x_dnd_movement_x >= 0 | 11294 | && x_dnd_movement_x >= 0 |
| 10055 | && x_dnd_movement_y >= 0 | 11295 | && x_dnd_movement_y >= 0 |
| @@ -10071,19 +11311,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10071 | 11311 | ||
| 10072 | if (hold_quit.kind != NO_EVENT) | 11312 | if (hold_quit.kind != NO_EVENT) |
| 10073 | { | 11313 | { |
| 10074 | if (hold_quit.kind == SELECTION_REQUEST_EVENT) | ||
| 10075 | { | ||
| 10076 | x_dnd_old_window_attrs = root_window_attrs; | ||
| 10077 | x_dnd_unwind_flag = true; | ||
| 10078 | |||
| 10079 | ref = SPECPDL_INDEX (); | ||
| 10080 | record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); | ||
| 10081 | x_handle_selection_event ((struct selection_input_event *) &hold_quit); | ||
| 10082 | x_dnd_unwind_flag = false; | ||
| 10083 | unbind_to (ref, Qnil); | ||
| 10084 | continue; | ||
| 10085 | } | ||
| 10086 | |||
| 10087 | if (x_dnd_in_progress) | 11314 | if (x_dnd_in_progress) |
| 10088 | { | 11315 | { |
| 10089 | if (x_dnd_last_seen_window != None | 11316 | if (x_dnd_last_seen_window != None |
| @@ -10101,9 +11328,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10101 | dmsg.side_effects | 11328 | dmsg.side_effects |
| 10102 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | 11329 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), |
| 10103 | x_dnd_wanted_action), | 11330 | x_dnd_wanted_action), |
| 10104 | XM_DROP_SITE_VALID, | 11331 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 10105 | xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | ||
| 10106 | x_dnd_wanted_action), | ||
| 10107 | XM_DROP_ACTION_DROP_CANCEL); | 11332 | XM_DROP_ACTION_DROP_CANCEL); |
| 10108 | dmsg.x = 0; | 11333 | dmsg.x = 0; |
| 10109 | dmsg.y = 0; | 11334 | dmsg.y = 0; |
| @@ -10124,19 +11349,107 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10124 | x_dnd_frame = NULL; | 11349 | x_dnd_frame = NULL; |
| 10125 | } | 11350 | } |
| 10126 | 11351 | ||
| 10127 | x_set_dnd_targets (NULL, 0); | ||
| 10128 | x_dnd_waiting_for_finish = false; | 11352 | x_dnd_waiting_for_finish = false; |
| 11353 | x_dnd_return_frame_object = NULL; | ||
| 11354 | x_dnd_movement_frame = NULL; | ||
| 11355 | |||
| 11356 | /* Don't clear dpyinfo->grabbed if we're quitting. */ | ||
| 11357 | |||
| 11358 | #ifdef USE_GTK | ||
| 11359 | current_hold_quit = NULL; | ||
| 11360 | #endif | ||
| 11361 | /* Restore the old event mask. */ | ||
| 11362 | XSelectInput (FRAME_X_DISPLAY (f), | ||
| 11363 | FRAME_DISPLAY_INFO (f)->root_window, | ||
| 11364 | root_window_attrs.your_event_mask); | ||
| 11365 | #ifdef HAVE_XKB | ||
| 11366 | if (FRAME_DISPLAY_INFO (f)->supports_xkb) | ||
| 11367 | XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd, | ||
| 11368 | XkbStateNotifyMask, 0); | ||
| 11369 | #endif | ||
| 11370 | /* Delete the Motif drag initiator info if it was set up. */ | ||
| 11371 | if (x_dnd_motif_setup_p) | ||
| 11372 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 11373 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); | ||
| 11374 | |||
| 11375 | |||
| 11376 | /* Remove any type list set as well. */ | ||
| 11377 | if (x_dnd_init_type_lists && x_dnd_n_targets > 3) | ||
| 11378 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 11379 | FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); | ||
| 11380 | |||
| 11381 | /* Call kbd_buffer_store event, which calls | ||
| 11382 | handle_interrupt and sets `last-event-frame' along | ||
| 11383 | with various other things. */ | ||
| 11384 | kbd_buffer_store_event (&hold_quit); | ||
| 11385 | /* Now quit anyway. */ | ||
| 11386 | quit (); | ||
| 11387 | } | ||
| 11388 | |||
| 11389 | if (pending_selection_requests | ||
| 11390 | && (x_dnd_in_progress || x_dnd_waiting_for_finish)) | ||
| 11391 | { | ||
| 11392 | x_dnd_old_window_attrs = root_window_attrs; | ||
| 11393 | x_dnd_unwind_flag = true; | ||
| 11394 | |||
| 11395 | ref = SPECPDL_INDEX (); | ||
| 11396 | record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); | ||
| 11397 | x_handle_pending_selection_requests (); | ||
| 11398 | x_dnd_unwind_flag = false; | ||
| 11399 | unbind_to (ref, Qnil); | ||
| 11400 | } | ||
| 10129 | 11401 | ||
| 10130 | if (x_dnd_use_toplevels) | 11402 | #ifdef USE_GTK |
| 10131 | x_dnd_free_toplevels (); | 11403 | if (xg_pending_quit_event.kind != NO_EVENT) |
| 11404 | { | ||
| 11405 | xg_pending_quit_event.kind = NO_EVENT; | ||
| 10132 | 11406 | ||
| 11407 | if (x_dnd_in_progress) | ||
| 11408 | { | ||
| 11409 | if (x_dnd_last_seen_window != None | ||
| 11410 | && x_dnd_last_protocol_version != -1) | ||
| 11411 | x_dnd_send_leave (f, x_dnd_last_seen_window); | ||
| 11412 | else if (x_dnd_last_seen_window != None | ||
| 11413 | && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) | ||
| 11414 | && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE | ||
| 11415 | && x_dnd_motif_setup_p) | ||
| 11416 | { | ||
| 11417 | dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, | ||
| 11418 | XM_DRAG_REASON_DROP_START); | ||
| 11419 | dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; | ||
| 11420 | dmsg.timestamp = xg_pending_quit_event.timestamp; | ||
| 11421 | dmsg.side_effects | ||
| 11422 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | ||
| 11423 | x_dnd_wanted_action), | ||
| 11424 | XM_DROP_SITE_VALID, x_dnd_motif_operations, | ||
| 11425 | XM_DROP_ACTION_DROP_CANCEL); | ||
| 11426 | dmsg.x = 0; | ||
| 11427 | dmsg.y = 0; | ||
| 11428 | dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; | ||
| 11429 | dmsg.source_window = FRAME_X_WINDOW (f); | ||
| 11430 | |||
| 11431 | x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, | ||
| 11432 | x_dnd_last_seen_window, | ||
| 11433 | xg_pending_quit_event.timestamp); | ||
| 11434 | xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), | ||
| 11435 | x_dnd_last_seen_window, &dmsg); | ||
| 11436 | } | ||
| 11437 | |||
| 11438 | x_dnd_end_window = x_dnd_last_seen_window; | ||
| 11439 | x_dnd_last_seen_window = None; | ||
| 11440 | x_dnd_last_seen_toplevel = None; | ||
| 11441 | x_dnd_in_progress = false; | ||
| 11442 | x_dnd_frame = NULL; | ||
| 11443 | } | ||
| 11444 | |||
| 11445 | x_dnd_waiting_for_finish = false; | ||
| 10133 | x_dnd_return_frame_object = NULL; | 11446 | x_dnd_return_frame_object = NULL; |
| 10134 | x_dnd_movement_frame = NULL; | 11447 | x_dnd_movement_frame = NULL; |
| 10135 | 11448 | ||
| 10136 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | 11449 | FRAME_DISPLAY_INFO (f)->grabbed = 0; |
| 10137 | #ifdef USE_GTK | ||
| 10138 | current_hold_quit = NULL; | 11450 | current_hold_quit = NULL; |
| 10139 | #endif | 11451 | |
| 11452 | block_input (); | ||
| 10140 | /* Restore the old event mask. */ | 11453 | /* Restore the old event mask. */ |
| 10141 | XSelectInput (FRAME_X_DISPLAY (f), | 11454 | XSelectInput (FRAME_X_DISPLAY (f), |
| 10142 | FRAME_DISPLAY_INFO (f)->root_window, | 11455 | FRAME_DISPLAY_INFO (f)->root_window, |
| @@ -10150,9 +11463,17 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10150 | if (x_dnd_motif_setup_p) | 11463 | if (x_dnd_motif_setup_p) |
| 10151 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 11464 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 10152 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); | 11465 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); |
| 11466 | |||
| 11467 | |||
| 11468 | /* Remove any type list set as well. */ | ||
| 11469 | if (x_dnd_init_type_lists && x_dnd_n_targets > 3) | ||
| 11470 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 11471 | FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); | ||
| 11472 | unblock_input (); | ||
| 11473 | |||
| 10153 | quit (); | 11474 | quit (); |
| 10154 | } | 11475 | } |
| 10155 | #ifndef USE_GTK | 11476 | #else |
| 10156 | } | 11477 | } |
| 10157 | else | 11478 | else |
| 10158 | { | 11479 | { |
| @@ -10165,7 +11486,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10165 | #endif | 11486 | #endif |
| 10166 | } | 11487 | } |
| 10167 | 11488 | ||
| 10168 | x_set_dnd_targets (NULL, 0); | ||
| 10169 | x_dnd_waiting_for_finish = false; | 11489 | x_dnd_waiting_for_finish = false; |
| 10170 | 11490 | ||
| 10171 | #ifdef USE_GTK | 11491 | #ifdef USE_GTK |
| @@ -10187,6 +11507,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10187 | if (x_dnd_motif_setup_p) | 11507 | if (x_dnd_motif_setup_p) |
| 10188 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 11508 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 10189 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); | 11509 | FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); |
| 11510 | |||
| 11511 | /* Remove any type list set as well. */ | ||
| 11512 | if (x_dnd_init_type_lists && x_dnd_n_targets > 3) | ||
| 11513 | XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 11514 | FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); | ||
| 10190 | unblock_input (); | 11515 | unblock_input (); |
| 10191 | 11516 | ||
| 10192 | if (x_dnd_return_frame == 3 | 11517 | if (x_dnd_return_frame == 3 |
| @@ -10202,45 +11527,43 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10202 | 11527 | ||
| 10203 | XSETFRAME (action, x_dnd_return_frame_object); | 11528 | XSETFRAME (action, x_dnd_return_frame_object); |
| 10204 | x_dnd_return_frame_object = NULL; | 11529 | x_dnd_return_frame_object = NULL; |
| 10205 | return action; | 11530 | |
| 11531 | return unbind_to (base, action); | ||
| 10206 | } | 11532 | } |
| 10207 | 11533 | ||
| 10208 | x_dnd_return_frame_object = NULL; | 11534 | x_dnd_return_frame_object = NULL; |
| 10209 | |||
| 10210 | if (x_dnd_use_toplevels) | ||
| 10211 | x_dnd_free_toplevels (); | ||
| 10212 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | 11535 | FRAME_DISPLAY_INFO (f)->grabbed = 0; |
| 10213 | 11536 | ||
| 10214 | /* Emacs can't respond to DND events inside the nested event | 11537 | if (!NILP (x_dnd_action_symbol)) |
| 10215 | loop, so when dragging items to itself, always return | 11538 | return unbind_to (base, x_dnd_action_symbol); |
| 10216 | XdndActionPrivate. */ | ||
| 10217 | if (x_dnd_end_window != None | ||
| 10218 | && (any = x_any_window_to_frame (FRAME_DISPLAY_INFO (f), | ||
| 10219 | x_dnd_end_window)) | ||
| 10220 | && (allow_current_frame || any != f)) | ||
| 10221 | return QXdndActionPrivate; | ||
| 10222 | 11539 | ||
| 10223 | if (x_dnd_action != None) | 11540 | if (x_dnd_action != None) |
| 10224 | { | 11541 | { |
| 10225 | block_input (); | 11542 | block_input (); |
| 10226 | x_catch_errors (FRAME_X_DISPLAY (f)); | 11543 | x_catch_errors (FRAME_X_DISPLAY (f)); |
| 10227 | atom_name = XGetAtomName (FRAME_X_DISPLAY (f), | 11544 | atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f), |
| 10228 | x_dnd_action); | 11545 | x_dnd_action, &need_sync); |
| 10229 | x_uncatch_errors (); | 11546 | |
| 11547 | if (need_sync) | ||
| 11548 | x_uncatch_errors (); | ||
| 11549 | else | ||
| 11550 | /* No protocol request actually happened, so avoid the extra | ||
| 11551 | sync by calling x_uncatch_errors_after_check instead. */ | ||
| 11552 | x_uncatch_errors_after_check (); | ||
| 10230 | 11553 | ||
| 10231 | if (atom_name) | 11554 | if (atom_name) |
| 10232 | { | 11555 | { |
| 10233 | action = intern (atom_name); | 11556 | action = intern (atom_name); |
| 10234 | XFree (atom_name); | 11557 | xfree (atom_name); |
| 10235 | } | 11558 | } |
| 10236 | else | 11559 | else |
| 10237 | action = Qnil; | 11560 | action = Qnil; |
| 10238 | unblock_input (); | 11561 | unblock_input (); |
| 10239 | 11562 | ||
| 10240 | return action; | 11563 | return unbind_to (base, action); |
| 10241 | } | 11564 | } |
| 10242 | 11565 | ||
| 10243 | return Qnil; | 11566 | return unbind_to (base, Qnil); |
| 10244 | } | 11567 | } |
| 10245 | 11568 | ||
| 10246 | /* The focus may have changed. Figure out if it is a real focus change, | 11569 | /* The focus may have changed. Figure out if it is a real focus change, |
| @@ -10780,6 +12103,80 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event, | |||
| 10780 | return false; | 12103 | return false; |
| 10781 | } | 12104 | } |
| 10782 | 12105 | ||
| 12106 | /* Get a sibling below WINDOW on DPY at PARENT_X and PARENT_Y. */ | ||
| 12107 | static Window | ||
| 12108 | x_get_window_below (Display *dpy, Window window, | ||
| 12109 | int parent_x, int parent_y, | ||
| 12110 | int *inner_x, int *inner_y) | ||
| 12111 | { | ||
| 12112 | int rc, i, cx, cy; | ||
| 12113 | XWindowAttributes attrs; | ||
| 12114 | unsigned int nchildren; | ||
| 12115 | Window root, parent, *children, value; | ||
| 12116 | bool window_seen; | ||
| 12117 | |||
| 12118 | /* TODO: rewrite to have less dependencies. */ | ||
| 12119 | |||
| 12120 | children = NULL; | ||
| 12121 | window_seen = false; | ||
| 12122 | value = None; | ||
| 12123 | |||
| 12124 | rc = XQueryTree (dpy, window, &root, &parent, | ||
| 12125 | &children, &nchildren); | ||
| 12126 | |||
| 12127 | if (rc) | ||
| 12128 | { | ||
| 12129 | if (children) | ||
| 12130 | XFree (children); | ||
| 12131 | |||
| 12132 | rc = XQueryTree (dpy, parent, &root, | ||
| 12133 | &parent, &children, &nchildren); | ||
| 12134 | } | ||
| 12135 | |||
| 12136 | if (rc) | ||
| 12137 | { | ||
| 12138 | for (i = nchildren - 1; i >= 0; --i) | ||
| 12139 | { | ||
| 12140 | if (children[i] == window) | ||
| 12141 | { | ||
| 12142 | window_seen = true; | ||
| 12143 | continue; | ||
| 12144 | } | ||
| 12145 | |||
| 12146 | if (!window_seen) | ||
| 12147 | continue; | ||
| 12148 | |||
| 12149 | rc = XGetWindowAttributes (dpy, children[i], &attrs); | ||
| 12150 | |||
| 12151 | if (rc && attrs.map_state != IsViewable) | ||
| 12152 | continue; | ||
| 12153 | |||
| 12154 | if (rc && parent_x >= attrs.x | ||
| 12155 | && parent_y >= attrs.y | ||
| 12156 | && parent_x < attrs.x + attrs.width | ||
| 12157 | && parent_y < attrs.y + attrs.height) | ||
| 12158 | { | ||
| 12159 | value = children[i]; | ||
| 12160 | cx = parent_x - attrs.x; | ||
| 12161 | cy = parent_y - attrs.y; | ||
| 12162 | |||
| 12163 | break; | ||
| 12164 | } | ||
| 12165 | } | ||
| 12166 | } | ||
| 12167 | |||
| 12168 | if (children) | ||
| 12169 | XFree (children); | ||
| 12170 | |||
| 12171 | if (value) | ||
| 12172 | { | ||
| 12173 | *inner_x = cx; | ||
| 12174 | *inner_y = cy; | ||
| 12175 | } | ||
| 12176 | |||
| 12177 | return value; | ||
| 12178 | } | ||
| 12179 | |||
| 10783 | /* Return the current position of the mouse. | 12180 | /* Return the current position of the mouse. |
| 10784 | *FP should be a frame which indicates which display to ask about. | 12181 | *FP should be a frame which indicates which display to ask about. |
| 10785 | 12182 | ||
| @@ -10805,8 +12202,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 10805 | enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, | 12202 | enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, |
| 10806 | Time *timestamp) | 12203 | Time *timestamp) |
| 10807 | { | 12204 | { |
| 10808 | struct frame *f1; | 12205 | struct frame *f1, *maybe_tooltip; |
| 10809 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); | 12206 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); |
| 12207 | bool unrelated_tooltip; | ||
| 10810 | 12208 | ||
| 10811 | block_input (); | 12209 | block_input (); |
| 10812 | 12210 | ||
| @@ -10861,9 +12259,11 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 10861 | Window first_win = 0; | 12259 | Window first_win = 0; |
| 10862 | #endif | 12260 | #endif |
| 10863 | int win_x, win_y; | 12261 | int win_x, win_y; |
| 10864 | int parent_x = 0, parent_y = 0; | 12262 | int parent_x, parent_y; |
| 10865 | 12263 | ||
| 10866 | win = root; | 12264 | win = root; |
| 12265 | parent_x = root_x; | ||
| 12266 | parent_y = root_y; | ||
| 10867 | 12267 | ||
| 10868 | /* XTranslateCoordinates can get errors if the window | 12268 | /* XTranslateCoordinates can get errors if the window |
| 10869 | structure is changing at the same time this function | 12269 | structure is changing at the same time this function |
| @@ -10898,6 +12298,22 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 10898 | root_x, root_y, &win_x, &win_y, | 12298 | root_x, root_y, &win_x, &win_y, |
| 10899 | /* Child of win. */ | 12299 | /* Child of win. */ |
| 10900 | &child); | 12300 | &child); |
| 12301 | |||
| 12302 | /* If CHILD is a tooltip frame, look below it if | ||
| 12303 | track-mouse is drag-source. */ | ||
| 12304 | if (child != None | ||
| 12305 | && (EQ (track_mouse, Qdrag_source) | ||
| 12306 | || EQ (track_mouse, Qdropping))) | ||
| 12307 | { | ||
| 12308 | maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child, | ||
| 12309 | &unrelated_tooltip); | ||
| 12310 | |||
| 12311 | if (maybe_tooltip || unrelated_tooltip) | ||
| 12312 | child = x_get_window_below (dpyinfo->display, child, | ||
| 12313 | parent_x, parent_y, &win_x, | ||
| 12314 | &win_y); | ||
| 12315 | } | ||
| 12316 | |||
| 10901 | if (child == None || child == win) | 12317 | if (child == None || child == win) |
| 10902 | { | 12318 | { |
| 10903 | #ifdef USE_GTK | 12319 | #ifdef USE_GTK |
| @@ -13695,6 +15111,13 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) | |||
| 13695 | result = xg_filter_key (f1, event); | 15111 | result = xg_filter_key (f1, event); |
| 13696 | unblock_input (); | 15112 | unblock_input (); |
| 13697 | 15113 | ||
| 15114 | /* Clear `xg_pending_quit_event' so we don't end up reacting to quit | ||
| 15115 | events sent outside the main event loop (i.e. those sent from | ||
| 15116 | inside a popup menu event loop). */ | ||
| 15117 | |||
| 15118 | if (popup_activated ()) | ||
| 15119 | xg_pending_quit_event.kind = NO_EVENT; | ||
| 15120 | |||
| 13698 | if (result && f1) | 15121 | if (result && f1) |
| 13699 | /* There will probably be a GDK event generated soon, so | 15122 | /* There will probably be a GDK event generated soon, so |
| 13700 | exercise the wire to make pselect return. */ | 15123 | exercise the wire to make pselect return. */ |
| @@ -13900,6 +15323,132 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc) | |||
| 13900 | } | 15323 | } |
| 13901 | } | 15324 | } |
| 13902 | 15325 | ||
| 15326 | static void | ||
| 15327 | x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes) | ||
| 15328 | { | ||
| 15329 | Lisp_Object monitor, geometry; | ||
| 15330 | int min_x, min_y, max_x, max_y; | ||
| 15331 | int width, height; | ||
| 15332 | |||
| 15333 | width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame)); | ||
| 15334 | height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame)); | ||
| 15335 | |||
| 15336 | max_y = -1; | ||
| 15337 | |||
| 15338 | /* Try to determine the monitor where the mouse pointer is and | ||
| 15339 | its geometry. See bug#22549. */ | ||
| 15340 | while (CONSP (attributes)) | ||
| 15341 | { | ||
| 15342 | monitor = XCAR (attributes); | ||
| 15343 | geometry = assq_no_quit (Qgeometry, monitor); | ||
| 15344 | |||
| 15345 | if (CONSP (geometry)) | ||
| 15346 | { | ||
| 15347 | min_x = XFIXNUM (Fnth (make_fixnum (1), geometry)); | ||
| 15348 | min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); | ||
| 15349 | max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); | ||
| 15350 | max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); | ||
| 15351 | |||
| 15352 | if (min_x <= *root_x && *root_x < max_x | ||
| 15353 | && min_y <= *root_y && *root_y < max_y) | ||
| 15354 | break; | ||
| 15355 | |||
| 15356 | max_y = -1; | ||
| 15357 | } | ||
| 15358 | |||
| 15359 | attributes = XCDR (attributes); | ||
| 15360 | } | ||
| 15361 | |||
| 15362 | /* It was not possible to determine the monitor's geometry, so we | ||
| 15363 | assign some sane defaults here: */ | ||
| 15364 | if (max_y < 0) | ||
| 15365 | { | ||
| 15366 | min_x = 0; | ||
| 15367 | min_y = 0; | ||
| 15368 | max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame)); | ||
| 15369 | max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame)); | ||
| 15370 | } | ||
| 15371 | |||
| 15372 | if (*root_y + XFIXNUM (tip_dy) <= min_y) | ||
| 15373 | *root_y = min_y; /* Can happen for negative dy */ | ||
| 15374 | else if (*root_y + XFIXNUM (tip_dy) + height <= max_y) | ||
| 15375 | /* It fits below the pointer */ | ||
| 15376 | *root_y += XFIXNUM (tip_dy); | ||
| 15377 | else if (height + XFIXNUM (tip_dy) + min_y <= *root_y) | ||
| 15378 | /* It fits above the pointer. */ | ||
| 15379 | *root_y -= height + XFIXNUM (tip_dy); | ||
| 15380 | else | ||
| 15381 | /* Put it on the top. */ | ||
| 15382 | *root_y = min_y; | ||
| 15383 | |||
| 15384 | if (*root_x + XFIXNUM (tip_dx) <= min_x) | ||
| 15385 | *root_x = 0; /* Can happen for negative dx */ | ||
| 15386 | else if (*root_x + XFIXNUM (tip_dx) + width <= max_x) | ||
| 15387 | /* It fits to the right of the pointer. */ | ||
| 15388 | *root_x += XFIXNUM (tip_dx); | ||
| 15389 | else if (width + XFIXNUM (tip_dx) + min_x <= *root_x) | ||
| 15390 | /* It fits to the left of the pointer. */ | ||
| 15391 | *root_x -= width + XFIXNUM (tip_dx); | ||
| 15392 | else | ||
| 15393 | /* Put it left justified on the screen -- it ought to fit that way. */ | ||
| 15394 | *root_x = min_x; | ||
| 15395 | } | ||
| 15396 | |||
| 15397 | static void | ||
| 15398 | x_dnd_update_tooltip_position (int root_x, int root_y) | ||
| 15399 | { | ||
| 15400 | struct frame *tip_f; | ||
| 15401 | |||
| 15402 | if (!x_dnd_in_progress || !x_dnd_update_tooltip) | ||
| 15403 | return; | ||
| 15404 | |||
| 15405 | if (!FRAMEP (tip_frame)) | ||
| 15406 | return; | ||
| 15407 | |||
| 15408 | tip_f = XFRAME (tip_frame); | ||
| 15409 | |||
| 15410 | if (!FRAME_LIVE_P (tip_f) | ||
| 15411 | || !FRAME_VISIBLE_P (tip_f) | ||
| 15412 | || (FRAME_X_DISPLAY (tip_f) | ||
| 15413 | != FRAME_X_DISPLAY (x_dnd_frame))) | ||
| 15414 | return; | ||
| 15415 | |||
| 15416 | if (tip_window != None | ||
| 15417 | && FIXNUMP (tip_dx) && FIXNUMP (tip_dy)) | ||
| 15418 | { | ||
| 15419 | x_dnd_compute_tip_xy (&root_x, &root_y, | ||
| 15420 | x_dnd_monitors); | ||
| 15421 | |||
| 15422 | XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame), | ||
| 15423 | tip_window, root_x, root_y); | ||
| 15424 | } | ||
| 15425 | } | ||
| 15426 | |||
| 15427 | static void | ||
| 15428 | x_dnd_update_tooltip_now (void) | ||
| 15429 | { | ||
| 15430 | int root_x, root_y; | ||
| 15431 | Window root, child; | ||
| 15432 | int win_x, win_y; | ||
| 15433 | unsigned int mask; | ||
| 15434 | Bool rc; | ||
| 15435 | struct x_display_info *dpyinfo; | ||
| 15436 | |||
| 15437 | if (!x_dnd_in_progress || !x_dnd_update_tooltip) | ||
| 15438 | return; | ||
| 15439 | |||
| 15440 | dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame); | ||
| 15441 | |||
| 15442 | rc = XQueryPointer (dpyinfo->display, | ||
| 15443 | dpyinfo->root_window, | ||
| 15444 | &root, &child, &root_x, | ||
| 15445 | &root_y, &win_x, &win_y, | ||
| 15446 | &mask); | ||
| 15447 | |||
| 15448 | if (rc) | ||
| 15449 | x_dnd_update_tooltip_position (root_x, root_y); | ||
| 15450 | } | ||
| 15451 | |||
| 13903 | /* Get the window underneath the pointer, see if it moved, and update | 15452 | /* Get the window underneath the pointer, see if it moved, and update |
| 13904 | the DND state accordingly. */ | 15453 | the DND state accordingly. */ |
| 13905 | static void | 15454 | static void |
| @@ -13912,6 +15461,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 13912 | xm_top_level_enter_message emsg; | 15461 | xm_top_level_enter_message emsg; |
| 13913 | xm_drag_motion_message dmsg; | 15462 | xm_drag_motion_message dmsg; |
| 13914 | xm_drop_start_message dsmsg; | 15463 | xm_drop_start_message dsmsg; |
| 15464 | bool was_frame; | ||
| 13915 | 15465 | ||
| 13916 | if (XQueryPointer (dpyinfo->display, | 15466 | if (XQueryPointer (dpyinfo->display, |
| 13917 | dpyinfo->root_window, | 15467 | dpyinfo->root_window, |
| @@ -13922,7 +15472,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 13922 | { | 15472 | { |
| 13923 | target = x_dnd_get_target_window (dpyinfo, root_x, | 15473 | target = x_dnd_get_target_window (dpyinfo, root_x, |
| 13924 | root_y, &target_proto, | 15474 | root_y, &target_proto, |
| 13925 | &motif_style, &toplevel); | 15475 | &motif_style, &toplevel, |
| 15476 | &was_frame); | ||
| 13926 | 15477 | ||
| 13927 | if (toplevel != x_dnd_last_seen_toplevel) | 15478 | if (toplevel != x_dnd_last_seen_toplevel) |
| 13928 | { | 15479 | { |
| @@ -13939,6 +15490,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 13939 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 15490 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 13940 | else if (x_dnd_last_seen_window != None | 15491 | else if (x_dnd_last_seen_window != None |
| 13941 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 15492 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 15493 | && !x_dnd_disable_motif_drag | ||
| 13942 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 15494 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 13943 | { | 15495 | { |
| 13944 | if (!x_dnd_motif_setup_p) | 15496 | if (!x_dnd_motif_setup_p) |
| @@ -13978,6 +15530,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 13978 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 15530 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 13979 | else if (x_dnd_last_seen_window != None | 15531 | else if (x_dnd_last_seen_window != None |
| 13980 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 15532 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 15533 | && !x_dnd_disable_motif_drag | ||
| 13981 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 15534 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 13982 | { | 15535 | { |
| 13983 | if (!x_dnd_motif_setup_p) | 15536 | if (!x_dnd_motif_setup_p) |
| @@ -13999,11 +15552,13 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 13999 | x_dnd_last_seen_window = target; | 15552 | x_dnd_last_seen_window = target; |
| 14000 | x_dnd_last_protocol_version = target_proto; | 15553 | x_dnd_last_protocol_version = target_proto; |
| 14001 | x_dnd_last_motif_style = motif_style; | 15554 | x_dnd_last_motif_style = motif_style; |
| 15555 | x_dnd_last_window_is_frame = was_frame; | ||
| 14002 | 15556 | ||
| 14003 | if (target != None && x_dnd_last_protocol_version != -1) | 15557 | if (target != None && x_dnd_last_protocol_version != -1) |
| 14004 | x_dnd_send_enter (x_dnd_frame, target, | 15558 | x_dnd_send_enter (x_dnd_frame, target, |
| 14005 | x_dnd_last_protocol_version); | 15559 | x_dnd_last_protocol_version); |
| 14006 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)) | 15560 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 15561 | && !x_dnd_disable_motif_drag) | ||
| 14007 | { | 15562 | { |
| 14008 | if (!x_dnd_motif_setup_p) | 15563 | if (!x_dnd_motif_setup_p) |
| 14009 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 15564 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -14022,7 +15577,9 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14022 | } | 15577 | } |
| 14023 | } | 15578 | } |
| 14024 | 15579 | ||
| 14025 | if (x_dnd_last_protocol_version != -1 && target != None) | 15580 | if (x_dnd_last_window_is_frame && target != None) |
| 15581 | x_dnd_note_self_position (dpyinfo, target, root_x, root_y); | ||
| 15582 | else if (x_dnd_last_protocol_version != -1 && target != None) | ||
| 14026 | x_dnd_send_position (x_dnd_frame, target, | 15583 | x_dnd_send_position (x_dnd_frame, target, |
| 14027 | x_dnd_last_protocol_version, | 15584 | x_dnd_last_protocol_version, |
| 14028 | root_x, root_y, | 15585 | root_x, root_y, |
| @@ -14034,7 +15591,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14034 | 0 | 15591 | 0 |
| 14035 | #endif | 15592 | #endif |
| 14036 | ); | 15593 | ); |
| 14037 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None) | 15594 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None |
| 15595 | && !x_dnd_disable_motif_drag) | ||
| 14038 | { | 15596 | { |
| 14039 | if (!x_dnd_motif_setup_p) | 15597 | if (!x_dnd_motif_setup_p) |
| 14040 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 15598 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -14045,9 +15603,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14045 | dmsg.side_effects | 15603 | dmsg.side_effects |
| 14046 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 15604 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 14047 | x_dnd_wanted_action), | 15605 | x_dnd_wanted_action), |
| 14048 | XM_DROP_SITE_VALID, | 15606 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 14049 | xm_side_effect_from_action (dpyinfo, | ||
| 14050 | x_dnd_wanted_action), | ||
| 14051 | (!x_dnd_xm_use_help | 15607 | (!x_dnd_xm_use_help |
| 14052 | ? XM_DROP_ACTION_DROP | 15608 | ? XM_DROP_ACTION_DROP |
| 14053 | : XM_DROP_ACTION_DROP_HELP)); | 15609 | : XM_DROP_ACTION_DROP_HELP)); |
| @@ -14059,6 +15615,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14059 | xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), | 15615 | xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), |
| 14060 | target, &dmsg); | 15616 | target, &dmsg); |
| 14061 | } | 15617 | } |
| 15618 | |||
| 15619 | x_dnd_update_tooltip_position (root_x, root_y); | ||
| 14062 | } | 15620 | } |
| 14063 | /* The pointer moved out of the screen. */ | 15621 | /* The pointer moved out of the screen. */ |
| 14064 | else if (x_dnd_last_protocol_version != -1) | 15622 | else if (x_dnd_last_protocol_version != -1) |
| @@ -14079,9 +15637,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14079 | dsmsg.side_effects | 15637 | dsmsg.side_effects |
| 14080 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 15638 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 14081 | x_dnd_wanted_action), | 15639 | x_dnd_wanted_action), |
| 14082 | XM_DROP_SITE_VALID, | 15640 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 14083 | xm_side_effect_from_action (dpyinfo, | ||
| 14084 | x_dnd_wanted_action), | ||
| 14085 | XM_DROP_ACTION_DROP_CANCEL); | 15641 | XM_DROP_ACTION_DROP_CANCEL); |
| 14086 | dsmsg.x = 0; | 15642 | dsmsg.x = 0; |
| 14087 | dsmsg.y = 0; | 15643 | dsmsg.y = 0; |
| @@ -14104,6 +15660,236 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) | |||
| 14104 | } | 15660 | } |
| 14105 | } | 15661 | } |
| 14106 | 15662 | ||
| 15663 | int | ||
| 15664 | x_display_pixel_height (struct x_display_info *dpyinfo) | ||
| 15665 | { | ||
| 15666 | if (dpyinfo->screen_height) | ||
| 15667 | return dpyinfo->screen_height; | ||
| 15668 | |||
| 15669 | return HeightOfScreen (dpyinfo->screen); | ||
| 15670 | } | ||
| 15671 | |||
| 15672 | int | ||
| 15673 | x_display_pixel_width (struct x_display_info *dpyinfo) | ||
| 15674 | { | ||
| 15675 | if (dpyinfo->screen_width) | ||
| 15676 | return dpyinfo->screen_width; | ||
| 15677 | |||
| 15678 | return WidthOfScreen (dpyinfo->screen); | ||
| 15679 | } | ||
| 15680 | |||
| 15681 | /* Handle events from each display until CELL's car becomes non-nil, | ||
| 15682 | or TIMEOUT elapses. */ | ||
| 15683 | void | ||
| 15684 | x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout) | ||
| 15685 | { | ||
| 15686 | struct x_display_info *dpyinfo; | ||
| 15687 | fd_set fds; | ||
| 15688 | int fd, maxfd; | ||
| 15689 | #ifndef USE_GTK | ||
| 15690 | int finish, rc; | ||
| 15691 | XEvent event; | ||
| 15692 | fd_set rfds; | ||
| 15693 | #endif | ||
| 15694 | struct input_event hold_quit; | ||
| 15695 | struct timespec current, at; | ||
| 15696 | |||
| 15697 | at = timespec_add (current_timespec (), timeout); | ||
| 15698 | |||
| 15699 | #ifndef USE_GTK | ||
| 15700 | FD_ZERO (&rfds); | ||
| 15701 | rc = -1; | ||
| 15702 | #endif | ||
| 15703 | |||
| 15704 | while (true) | ||
| 15705 | { | ||
| 15706 | FD_ZERO (&fds); | ||
| 15707 | maxfd = -1; | ||
| 15708 | |||
| 15709 | for (dpyinfo = x_display_list; dpyinfo; | ||
| 15710 | dpyinfo = dpyinfo->next) | ||
| 15711 | { | ||
| 15712 | fd = ConnectionNumber (dpyinfo->display); | ||
| 15713 | |||
| 15714 | #ifndef USE_GTK | ||
| 15715 | if ((rc < 0 || FD_ISSET (fd, &rfds)) | ||
| 15716 | /* If pselect failed, the erroring display's IO error | ||
| 15717 | handler will eventually be called. */ | ||
| 15718 | && XPending (dpyinfo->display)) | ||
| 15719 | { | ||
| 15720 | while (XPending (dpyinfo->display)) | ||
| 15721 | { | ||
| 15722 | EVENT_INIT (hold_quit); | ||
| 15723 | |||
| 15724 | XNextEvent (dpyinfo->display, &event); | ||
| 15725 | handle_one_xevent (dpyinfo, &event, | ||
| 15726 | &finish, &hold_quit); | ||
| 15727 | |||
| 15728 | if (!NILP (XCAR (cell))) | ||
| 15729 | return; | ||
| 15730 | |||
| 15731 | if (finish == X_EVENT_GOTO_OUT) | ||
| 15732 | break; | ||
| 15733 | |||
| 15734 | /* Make us quit now. */ | ||
| 15735 | if (hold_quit.kind != NO_EVENT) | ||
| 15736 | kbd_buffer_store_event (&hold_quit); | ||
| 15737 | } | ||
| 15738 | } | ||
| 15739 | #endif | ||
| 15740 | |||
| 15741 | if (fd > maxfd) | ||
| 15742 | maxfd = fd; | ||
| 15743 | |||
| 15744 | eassert (fd < FD_SETSIZE); | ||
| 15745 | FD_SET (fd, &fds); | ||
| 15746 | } | ||
| 15747 | |||
| 15748 | /* Prevent events from being lost (from GTK's point of view) by | ||
| 15749 | using GDK to run the event loop. */ | ||
| 15750 | #ifdef USE_GTK | ||
| 15751 | while (gtk_events_pending ()) | ||
| 15752 | { | ||
| 15753 | EVENT_INIT (hold_quit); | ||
| 15754 | current_count = 0; | ||
| 15755 | current_hold_quit = &hold_quit; | ||
| 15756 | current_finish = X_EVENT_NORMAL; | ||
| 15757 | |||
| 15758 | gtk_main_iteration (); | ||
| 15759 | |||
| 15760 | current_count = -1; | ||
| 15761 | current_hold_quit = NULL; | ||
| 15762 | |||
| 15763 | /* Make us quit now. */ | ||
| 15764 | if (hold_quit.kind != NO_EVENT) | ||
| 15765 | kbd_buffer_store_event (&hold_quit); | ||
| 15766 | |||
| 15767 | if (!NILP (XCAR (cell))) | ||
| 15768 | return; | ||
| 15769 | |||
| 15770 | if (current_finish == X_EVENT_GOTO_OUT) | ||
| 15771 | break; | ||
| 15772 | } | ||
| 15773 | #endif | ||
| 15774 | |||
| 15775 | eassert (maxfd >= 0); | ||
| 15776 | |||
| 15777 | current = current_timespec (); | ||
| 15778 | |||
| 15779 | if (timespec_cmp (at, current) < 0 | ||
| 15780 | || !NILP (XCAR (cell))) | ||
| 15781 | return; | ||
| 15782 | |||
| 15783 | timeout = timespec_sub (at, current); | ||
| 15784 | |||
| 15785 | #ifndef USE_GTK | ||
| 15786 | rc = pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL); | ||
| 15787 | |||
| 15788 | if (rc >= 0) | ||
| 15789 | rfds = fds; | ||
| 15790 | #else | ||
| 15791 | pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL); | ||
| 15792 | #endif | ||
| 15793 | } | ||
| 15794 | } | ||
| 15795 | |||
| 15796 | #ifdef USE_GTK | ||
| 15797 | static void | ||
| 15798 | x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) | ||
| 15799 | { | ||
| 15800 | struct x_display_info *dpyinfo; | ||
| 15801 | struct input_event ie; | ||
| 15802 | Lisp_Object current_monitors, terminal; | ||
| 15803 | GdkDisplay *gdpy; | ||
| 15804 | Display *dpy; | ||
| 15805 | |||
| 15806 | gdpy = gdk_screen_get_display (gscr); | ||
| 15807 | dpy = gdk_x11_display_get_xdisplay (gdpy); | ||
| 15808 | dpyinfo = x_display_info_for_display (dpy); | ||
| 15809 | |||
| 15810 | if (!dpyinfo) | ||
| 15811 | return; | ||
| 15812 | |||
| 15813 | XSETTERMINAL (terminal, dpyinfo->terminal); | ||
| 15814 | |||
| 15815 | current_monitors | ||
| 15816 | = Fx_display_monitor_attributes_list (terminal); | ||
| 15817 | |||
| 15818 | if (NILP (Fequal (current_monitors, | ||
| 15819 | dpyinfo->last_monitor_attributes_list))) | ||
| 15820 | { | ||
| 15821 | EVENT_INIT (ie); | ||
| 15822 | ie.kind = MONITORS_CHANGED_EVENT; | ||
| 15823 | ie.arg = terminal; | ||
| 15824 | |||
| 15825 | kbd_buffer_store_event (&ie); | ||
| 15826 | |||
| 15827 | if (x_dnd_in_progress && x_dnd_update_tooltip) | ||
| 15828 | x_dnd_monitors = current_monitors; | ||
| 15829 | |||
| 15830 | x_dnd_update_tooltip_now (); | ||
| 15831 | } | ||
| 15832 | |||
| 15833 | dpyinfo->last_monitor_attributes_list = current_monitors; | ||
| 15834 | } | ||
| 15835 | #endif | ||
| 15836 | |||
| 15837 | /* Extract the root window coordinates from the client message EVENT | ||
| 15838 | if it is a message that we already understand. Return false if the | ||
| 15839 | event was not understood. */ | ||
| 15840 | static bool | ||
| 15841 | x_coords_from_dnd_message (struct x_display_info *dpyinfo, | ||
| 15842 | XEvent *event, int *x_out, int *y_out) | ||
| 15843 | { | ||
| 15844 | xm_drag_motion_message dmsg; | ||
| 15845 | xm_drop_start_message smsg; | ||
| 15846 | xm_drop_start_reply reply; | ||
| 15847 | |||
| 15848 | if (event->type != ClientMessage) | ||
| 15849 | return false; | ||
| 15850 | |||
| 15851 | if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition) | ||
| 15852 | { | ||
| 15853 | if (event->xclient.format != 32) | ||
| 15854 | return false; | ||
| 15855 | |||
| 15856 | *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16 | ||
| 15857 | & 0xffff); | ||
| 15858 | *y_out = (event->xclient.data.l[2] & 0xffff); | ||
| 15859 | |||
| 15860 | return true; | ||
| 15861 | } | ||
| 15862 | |||
| 15863 | if ((event->xclient.message_type | ||
| 15864 | == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE) | ||
| 15865 | && event->xclient.format == 8) | ||
| 15866 | { | ||
| 15867 | if (!xm_read_drag_motion_message (event, &dmsg)) | ||
| 15868 | { | ||
| 15869 | *x_out = dmsg.x; | ||
| 15870 | *y_out = dmsg.y; | ||
| 15871 | |||
| 15872 | return true; | ||
| 15873 | } | ||
| 15874 | else if (!xm_read_drop_start_message (event, &smsg)) | ||
| 15875 | { | ||
| 15876 | *x_out = smsg.x; | ||
| 15877 | *y_out = smsg.y; | ||
| 15878 | |||
| 15879 | return true; | ||
| 15880 | } | ||
| 15881 | else if (!xm_read_drop_start_reply (event, &reply)) | ||
| 15882 | { | ||
| 15883 | *x_out = reply.better_x; | ||
| 15884 | *y_out = reply.better_y; | ||
| 15885 | |||
| 15886 | return true; | ||
| 15887 | } | ||
| 15888 | } | ||
| 15889 | |||
| 15890 | return false; | ||
| 15891 | } | ||
| 15892 | |||
| 14107 | /* Handles the XEvent EVENT on display DPYINFO. | 15893 | /* Handles the XEvent EVENT on display DPYINFO. |
| 14108 | 15894 | ||
| 14109 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. | 15895 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. |
| @@ -14146,6 +15932,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14146 | GdkEvent *copy = NULL; | 15932 | GdkEvent *copy = NULL; |
| 14147 | GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); | 15933 | GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); |
| 14148 | #endif | 15934 | #endif |
| 15935 | int dx, dy; | ||
| 15936 | USE_SAFE_ALLOCA; | ||
| 14149 | 15937 | ||
| 14150 | *finish = X_EVENT_NORMAL; | 15938 | *finish = X_EVENT_NORMAL; |
| 14151 | 15939 | ||
| @@ -14176,11 +15964,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14176 | { | 15964 | { |
| 14177 | case ClientMessage: | 15965 | case ClientMessage: |
| 14178 | { | 15966 | { |
| 15967 | int rc; | ||
| 15968 | |||
| 14179 | if (x_dnd_in_progress | 15969 | if (x_dnd_in_progress |
| 14180 | && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo | 15970 | && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo |
| 14181 | && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) | 15971 | && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) |
| 14182 | { | 15972 | { |
| 14183 | Window target; | 15973 | Window target; |
| 15974 | unsigned long r1, r2; | ||
| 14184 | 15975 | ||
| 14185 | target = event->xclient.data.l[0]; | 15976 | target = event->xclient.data.l[0]; |
| 14186 | 15977 | ||
| @@ -14188,11 +15979,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14188 | && target == x_dnd_last_seen_window | 15979 | && target == x_dnd_last_seen_window |
| 14189 | && event->xclient.data.l[1] & 2) | 15980 | && event->xclient.data.l[1] & 2) |
| 14190 | { | 15981 | { |
| 15982 | r1 = event->xclient.data.l[2]; | ||
| 15983 | r2 = event->xclient.data.l[2]; | ||
| 15984 | |||
| 14191 | x_dnd_mouse_rect_target = target; | 15985 | x_dnd_mouse_rect_target = target; |
| 14192 | x_dnd_mouse_rect.x = (event->xclient.data.l[2] & 0xffff0000) >> 16; | 15986 | x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16; |
| 14193 | x_dnd_mouse_rect.y = (event->xclient.data.l[2] & 0xffff); | 15987 | x_dnd_mouse_rect.y = (r1 & 0xffff); |
| 14194 | x_dnd_mouse_rect.width = (event->xclient.data.l[3] & 0xffff0000) >> 16; | 15988 | x_dnd_mouse_rect.width = (r2 & 0xffff0000) >> 16; |
| 14195 | x_dnd_mouse_rect.height = (event->xclient.data.l[3] & 0xffff); | 15989 | x_dnd_mouse_rect.height = (r2 & 0xffff); |
| 14196 | } | 15990 | } |
| 14197 | else | 15991 | else |
| 14198 | x_dnd_mouse_rect_target = None; | 15992 | x_dnd_mouse_rect_target = None; |
| @@ -14377,25 +16171,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14377 | 16171 | ||
| 14378 | 16172 | ||
| 14379 | if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping | 16173 | if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping |
| 16174 | /* Handling window stacking changes during | ||
| 16175 | drag-and-drop requires Emacs to select for | ||
| 16176 | SubstructureNotifyMask, which in turn causes the | ||
| 16177 | message to be sent to Emacs itself using the event | ||
| 16178 | mask specified by the EWMH. To avoid an infinite | ||
| 16179 | loop, make sure the client message's window is not | ||
| 16180 | the root window if DND is in progress. */ | ||
| 16181 | && (!(x_dnd_in_progress | ||
| 16182 | || x_dnd_waiting_for_finish) | ||
| 16183 | || event->xclient.window != dpyinfo->root_window) | ||
| 14380 | && event->xclient.format == 32) | 16184 | && event->xclient.format == 32) |
| 14381 | { | 16185 | { |
| 14382 | XEvent send_event = *event; | 16186 | XEvent send_event = *event; |
| 14383 | 16187 | ||
| 14384 | send_event.xclient.window = dpyinfo->root_window; | 16188 | send_event.xclient.window = dpyinfo->root_window; |
| 14385 | XSendEvent (dpyinfo->display, dpyinfo->root_window, False, | 16189 | XSendEvent (dpyinfo->display, dpyinfo->root_window, False, |
| 14386 | /* FIXME: handling window stacking changes | 16190 | SubstructureRedirectMask | SubstructureNotifyMask, |
| 14387 | during drag-and-drop requires Emacs to | ||
| 14388 | select for SubstructureNotifyMask, | ||
| 14389 | which in turn causes the message to be | ||
| 14390 | sent to Emacs itself using the event | ||
| 14391 | mask specified by the EWMH. To avoid | ||
| 14392 | an infinite loop, just use | ||
| 14393 | SubstructureRedirectMask when a | ||
| 14394 | drag-and-drop operation is in | ||
| 14395 | progress. */ | ||
| 14396 | ((x_dnd_in_progress || x_dnd_waiting_for_finish) | ||
| 14397 | ? SubstructureRedirectMask | ||
| 14398 | : SubstructureRedirectMask | SubstructureNotifyMask), | ||
| 14399 | &send_event); | 16191 | &send_event); |
| 14400 | 16192 | ||
| 14401 | *finish = X_EVENT_DROP; | 16193 | *finish = X_EVENT_DROP; |
| @@ -14435,17 +16227,21 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14435 | *finish = X_EVENT_DROP; | 16227 | *finish = X_EVENT_DROP; |
| 14436 | #else | 16228 | #else |
| 14437 | widget = FRAME_GTK_OUTER_WIDGET (f); | 16229 | widget = FRAME_GTK_OUTER_WIDGET (f); |
| 16230 | window = gtk_widget_get_window (widget); | ||
| 16231 | eassert (window); | ||
| 16232 | |||
| 16233 | /* This could be a (former) child frame for which | ||
| 16234 | frame synchronization was disabled. Enable it | ||
| 16235 | now. */ | ||
| 16236 | gdk_x11_window_set_frame_sync_enabled (window, TRUE); | ||
| 14438 | 16237 | ||
| 14439 | if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p) | 16238 | if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p) |
| 14440 | { | 16239 | { |
| 14441 | window = gtk_widget_get_window (widget); | ||
| 14442 | eassert (window); | ||
| 14443 | frame_clock = gdk_window_get_frame_clock (window); | 16240 | frame_clock = gdk_window_get_frame_clock (window); |
| 14444 | eassert (frame_clock); | 16241 | eassert (frame_clock); |
| 14445 | 16242 | ||
| 14446 | gdk_frame_clock_request_phase (frame_clock, | 16243 | gdk_frame_clock_request_phase (frame_clock, |
| 14447 | GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT); | 16244 | GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT); |
| 14448 | |||
| 14449 | FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true; | 16245 | FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true; |
| 14450 | } | 16246 | } |
| 14451 | #endif | 16247 | #endif |
| @@ -14503,7 +16299,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14503 | goto OTHER; | 16299 | goto OTHER; |
| 14504 | #ifndef USE_CAIRO | 16300 | #ifndef USE_CAIRO |
| 14505 | Pixmap pixmap = (Pixmap) event->xclient.data.l[1]; | 16301 | Pixmap pixmap = (Pixmap) event->xclient.data.l[1]; |
| 16302 | /* FIXME: why does this sometimes generate a BadMatch | ||
| 16303 | error? */ | ||
| 16304 | x_catch_errors (dpyinfo->display); | ||
| 14506 | x_kill_gs_process (pixmap, f); | 16305 | x_kill_gs_process (pixmap, f); |
| 16306 | x_uncatch_errors (); | ||
| 14507 | expose_frame (f, 0, 0, 0, 0); | 16307 | expose_frame (f, 0, 0, 0, 0); |
| 14508 | #endif /* !USE_CAIRO */ | 16308 | #endif /* !USE_CAIRO */ |
| 14509 | goto done; | 16309 | goto done; |
| @@ -14542,24 +16342,34 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14542 | f = any; | 16342 | f = any; |
| 14543 | if (!f) | 16343 | if (!f) |
| 14544 | goto OTHER; | 16344 | goto OTHER; |
| 14545 | if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie)) | 16345 | |
| 16346 | /* These values are always used initialized, but GCC doesn't | ||
| 16347 | know that. */ | ||
| 16348 | dx = 0; | ||
| 16349 | dy = 0; | ||
| 16350 | |||
| 16351 | rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event, | ||
| 16352 | &dx, &dy); | ||
| 16353 | |||
| 16354 | if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie, | ||
| 16355 | rc, dx, dy)) | ||
| 14546 | *finish = X_EVENT_DROP; | 16356 | *finish = X_EVENT_DROP; |
| 14547 | } | 16357 | } |
| 14548 | break; | 16358 | break; |
| 14549 | 16359 | ||
| 14550 | case SelectionNotify: | 16360 | case SelectionNotify: |
| 14551 | #ifdef USE_X_TOOLKIT | 16361 | #if defined USE_X_TOOLKIT || defined USE_GTK |
| 14552 | if (! x_window_to_frame (dpyinfo, event->xselection.requestor)) | 16362 | if (!x_window_to_frame (dpyinfo, event->xselection.requestor)) |
| 14553 | goto OTHER; | 16363 | goto OTHER; |
| 14554 | #endif /* not USE_X_TOOLKIT */ | 16364 | #endif /* not USE_X_TOOLKIT and not USE_GTK */ |
| 14555 | x_handle_selection_notify (&event->xselection); | 16365 | x_handle_selection_notify (&event->xselection); |
| 14556 | break; | 16366 | break; |
| 14557 | 16367 | ||
| 14558 | case SelectionClear: /* Someone has grabbed ownership. */ | 16368 | case SelectionClear: /* Someone has grabbed ownership. */ |
| 14559 | #ifdef USE_X_TOOLKIT | 16369 | #if defined USE_X_TOOLKIT || defined USE_GTK |
| 14560 | if (! x_window_to_frame (dpyinfo, event->xselectionclear.window)) | 16370 | if (!x_window_to_frame (dpyinfo, event->xselectionclear.window)) |
| 14561 | goto OTHER; | 16371 | goto OTHER; |
| 14562 | #endif /* USE_X_TOOLKIT */ | 16372 | #endif /* not USE_X_TOOLKIT and not USE_GTK */ |
| 14563 | { | 16373 | { |
| 14564 | const XSelectionClearEvent *eventp = &event->xselectionclear; | 16374 | const XSelectionClearEvent *eventp = &event->xselectionclear; |
| 14565 | 16375 | ||
| @@ -14567,6 +16377,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14567 | SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; | 16377 | SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; |
| 14568 | SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; | 16378 | SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; |
| 14569 | SELECTION_EVENT_TIME (&inev.sie) = eventp->time; | 16379 | SELECTION_EVENT_TIME (&inev.sie) = eventp->time; |
| 16380 | |||
| 16381 | if (x_use_pending_selection_requests) | ||
| 16382 | { | ||
| 16383 | x_push_selection_request (&inev.sie); | ||
| 16384 | EVENT_INIT (inev.ie); | ||
| 16385 | } | ||
| 14570 | } | 16386 | } |
| 14571 | break; | 16387 | break; |
| 14572 | 16388 | ||
| @@ -14590,11 +16406,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14590 | events immediately, by setting hold_quit to the input | 16406 | events immediately, by setting hold_quit to the input |
| 14591 | event. */ | 16407 | event. */ |
| 14592 | 16408 | ||
| 14593 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) | 16409 | if (x_use_pending_selection_requests) |
| 14594 | { | 16410 | { |
| 14595 | eassume (hold_quit); | 16411 | x_push_selection_request (&inev.sie); |
| 14596 | |||
| 14597 | *hold_quit = inev.ie; | ||
| 14598 | EVENT_INIT (inev.ie); | 16412 | EVENT_INIT (inev.ie); |
| 14599 | } | 16413 | } |
| 14600 | 16414 | ||
| @@ -14604,7 +16418,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14604 | && eventp->selection == dpyinfo->Xatom_XdndSelection | 16418 | && eventp->selection == dpyinfo->Xatom_XdndSelection |
| 14605 | && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS | 16419 | && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS |
| 14606 | || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)) | 16420 | || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)) |
| 14607 | x_dnd_waiting_for_finish = false; | 16421 | { |
| 16422 | x_dnd_waiting_for_finish = false; | ||
| 16423 | |||
| 16424 | /* If the transfer failed, then return nil from | ||
| 16425 | `x-begin-drag'. */ | ||
| 16426 | if (eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE) | ||
| 16427 | x_dnd_action = None; | ||
| 16428 | } | ||
| 14608 | } | 16429 | } |
| 14609 | break; | 16430 | break; |
| 14610 | 16431 | ||
| @@ -14625,7 +16446,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14625 | unsigned long nitems, bytesafter; | 16446 | unsigned long nitems, bytesafter; |
| 14626 | unsigned char *data = NULL; | 16447 | unsigned char *data = NULL; |
| 14627 | 16448 | ||
| 14628 | |||
| 14629 | if (event->xproperty.state == PropertyDelete) | 16449 | if (event->xproperty.state == PropertyDelete) |
| 14630 | { | 16450 | { |
| 14631 | if (!last) | 16451 | if (!last) |
| @@ -14714,6 +16534,107 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14714 | } | 16534 | } |
| 14715 | } | 16535 | } |
| 14716 | 16536 | ||
| 16537 | if (f && FRAME_X_OUTPUT (f)->alpha_identical_p | ||
| 16538 | && (event->xproperty.atom | ||
| 16539 | == dpyinfo->Xatom_net_wm_window_opacity)) | ||
| 16540 | { | ||
| 16541 | #ifndef USE_XCB | ||
| 16542 | int rc, actual_format; | ||
| 16543 | Atom actual; | ||
| 16544 | unsigned char *tmp_data; | ||
| 16545 | unsigned long n, left, opacity; | ||
| 16546 | |||
| 16547 | tmp_data = NULL; | ||
| 16548 | #else | ||
| 16549 | xcb_get_property_cookie_t opacity_cookie; | ||
| 16550 | xcb_get_property_reply_t *opacity_reply; | ||
| 16551 | xcb_generic_error_t *error; | ||
| 16552 | bool rc; | ||
| 16553 | uint32_t value; | ||
| 16554 | #endif | ||
| 16555 | |||
| 16556 | if (event->xproperty.state == PropertyDelete) | ||
| 16557 | { | ||
| 16558 | f->alpha[0] = 1.0; | ||
| 16559 | f->alpha[1] = 1.0; | ||
| 16560 | |||
| 16561 | store_frame_param (f, Qalpha, Qnil); | ||
| 16562 | } | ||
| 16563 | else | ||
| 16564 | { | ||
| 16565 | #ifndef USE_XCB | ||
| 16566 | rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f), | ||
| 16567 | dpyinfo->Xatom_net_wm_window_opacity, | ||
| 16568 | 0, 1, False, AnyPropertyType, &actual, | ||
| 16569 | &actual_format, &n, &left, &tmp_data); | ||
| 16570 | |||
| 16571 | if (rc == Success && actual_format == 32 | ||
| 16572 | && (actual == XA_CARDINAL | ||
| 16573 | /* Some broken programs set the opacity property | ||
| 16574 | to those types, but window managers accept | ||
| 16575 | them anyway. */ | ||
| 16576 | || actual == XA_ATOM | ||
| 16577 | || actual == XA_WINDOW) && n) | ||
| 16578 | { | ||
| 16579 | opacity = *(unsigned long *) tmp_data & OPAQUE; | ||
| 16580 | f->alpha[0] = (double) opacity / (double) OPAQUE; | ||
| 16581 | f->alpha[1] = (double) opacity / (double) OPAQUE; | ||
| 16582 | |||
| 16583 | store_frame_param (f, Qalpha, make_float (f->alpha[0])); | ||
| 16584 | } | ||
| 16585 | else | ||
| 16586 | { | ||
| 16587 | f->alpha[0] = 1.0; | ||
| 16588 | f->alpha[1] = 1.0; | ||
| 16589 | |||
| 16590 | store_frame_param (f, Qalpha, Qnil); | ||
| 16591 | } | ||
| 16592 | #else | ||
| 16593 | opacity_cookie | ||
| 16594 | = xcb_get_property (dpyinfo->xcb_connection, 0, | ||
| 16595 | (xcb_window_t) FRAME_OUTER_WINDOW (f), | ||
| 16596 | (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity, | ||
| 16597 | XCB_ATOM_CARDINAL, 0, 1); | ||
| 16598 | opacity_reply | ||
| 16599 | = xcb_get_property_reply (dpyinfo->xcb_connection, | ||
| 16600 | opacity_cookie, &error); | ||
| 16601 | |||
| 16602 | if (!opacity_reply) | ||
| 16603 | free (error), rc = false; | ||
| 16604 | else | ||
| 16605 | rc = (opacity_reply->format == 32 | ||
| 16606 | && (opacity_reply->type == XCB_ATOM_CARDINAL | ||
| 16607 | || opacity_reply->type == XCB_ATOM_ATOM | ||
| 16608 | || opacity_reply->type == XCB_ATOM_WINDOW) | ||
| 16609 | && (xcb_get_property_value_length (opacity_reply) >= 4)); | ||
| 16610 | |||
| 16611 | if (rc) | ||
| 16612 | { | ||
| 16613 | value = *(uint32_t *) xcb_get_property_value (opacity_reply); | ||
| 16614 | |||
| 16615 | f->alpha[0] = (double) value / (double) OPAQUE; | ||
| 16616 | f->alpha[1] = (double) value / (double) OPAQUE; | ||
| 16617 | store_frame_param (f, Qalpha, make_float (f->alpha[0])); | ||
| 16618 | } | ||
| 16619 | else | ||
| 16620 | { | ||
| 16621 | f->alpha[0] = 1.0; | ||
| 16622 | f->alpha[1] = 1.0; | ||
| 16623 | |||
| 16624 | store_frame_param (f, Qalpha, Qnil); | ||
| 16625 | } | ||
| 16626 | |||
| 16627 | if (opacity_reply) | ||
| 16628 | free (opacity_reply); | ||
| 16629 | #endif | ||
| 16630 | } | ||
| 16631 | |||
| 16632 | #ifndef USE_XCB | ||
| 16633 | if (tmp_data) | ||
| 16634 | XFree (tmp_data); | ||
| 16635 | #endif | ||
| 16636 | } | ||
| 16637 | |||
| 14717 | if (event->xproperty.window == dpyinfo->root_window | 16638 | if (event->xproperty.window == dpyinfo->root_window |
| 14718 | && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking | 16639 | && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking |
| 14719 | || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop) | 16640 | || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop) |
| @@ -14722,11 +16643,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 14722 | { | 16643 | { |
| 14723 | if (x_dnd_use_toplevels) | 16644 | if (x_dnd_use_toplevels) |
| 14724 | { | 16645 | { |
| 14725 | x_dnd_free_toplevels (); | 16646 | x_dnd_free_toplevels (true); |
| 14726 | 16647 | ||
| 14727 | if (x_dnd_compute_toplevels (dpyinfo)) | 16648 | if (x_dnd_compute_toplevels (dpyinfo)) |
| 14728 | { | 16649 | { |
| 14729 | x_dnd_free_toplevels (); | 16650 | x_dnd_free_toplevels (true); |
| 14730 | x_dnd_use_toplevels = false; | 16651 | x_dnd_use_toplevels = false; |
| 14731 | } | 16652 | } |
| 14732 | } | 16653 | } |
| @@ -15223,9 +17144,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15223 | memset (&compose_status, 0, sizeof (compose_status)); | 17144 | memset (&compose_status, 0, sizeof (compose_status)); |
| 15224 | 17145 | ||
| 15225 | #ifdef HAVE_XKB | 17146 | #ifdef HAVE_XKB |
| 15226 | if (FRAME_DISPLAY_INFO (f)->xkb_desc) | 17147 | if (dpyinfo->xkb_desc) |
| 15227 | { | 17148 | { |
| 15228 | XkbDescRec *rec = FRAME_DISPLAY_INFO (f)->xkb_desc; | 17149 | XkbDescRec *rec = dpyinfo->xkb_desc; |
| 15229 | 17150 | ||
| 15230 | if (rec->map->modmap && rec->map->modmap[xkey.keycode]) | 17151 | if (rec->map->modmap && rec->map->modmap[xkey.keycode]) |
| 15231 | goto done_keysym; | 17152 | goto done_keysym; |
| @@ -15256,7 +17177,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15256 | if (status_return == XBufferOverflow) | 17177 | if (status_return == XBufferOverflow) |
| 15257 | { | 17178 | { |
| 15258 | copy_bufsiz = nbytes + 1; | 17179 | copy_bufsiz = nbytes + 1; |
| 15259 | copy_bufptr = alloca (copy_bufsiz); | 17180 | copy_bufptr = SAFE_ALLOCA (copy_bufsiz); |
| 15260 | nbytes = XmbLookupString (FRAME_XIC (f), | 17181 | nbytes = XmbLookupString (FRAME_XIC (f), |
| 15261 | &xkey, (char *) copy_bufptr, | 17182 | &xkey, (char *) copy_bufptr, |
| 15262 | copy_bufsiz, &keysym, | 17183 | copy_bufsiz, &keysym, |
| @@ -15594,7 +17515,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15594 | 17515 | ||
| 15595 | if (f && x_mouse_click_focus_ignore_position) | 17516 | if (f && x_mouse_click_focus_ignore_position) |
| 15596 | { | 17517 | { |
| 15597 | ignore_next_mouse_click_timeout = event->xmotion.time + 200; | 17518 | ignore_next_mouse_click_timeout = (event->xmotion.time |
| 17519 | + x_mouse_click_focus_ignore_time); | ||
| 15598 | mouse_click_timeout_display = dpyinfo; | 17520 | mouse_click_timeout_display = dpyinfo; |
| 15599 | } | 17521 | } |
| 15600 | 17522 | ||
| @@ -15693,7 +17615,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15693 | Do it only if there's something to cancel. | 17615 | Do it only if there's something to cancel. |
| 15694 | Otherwise, the startup message is cleared when | 17616 | Otherwise, the startup message is cleared when |
| 15695 | the mouse leaves the frame. */ | 17617 | the mouse leaves the frame. */ |
| 15696 | if (any_help_event_p) | 17618 | if (any_help_event_p |
| 17619 | /* But never if `mouse-drag-and-drop-region' is in | ||
| 17620 | progress, since that results in the tooltip being | ||
| 17621 | dismissed when the mouse moves on top. */ | ||
| 17622 | && !((EQ (track_mouse, Qdrag_source) | ||
| 17623 | || EQ (track_mouse, Qdropping)) | ||
| 17624 | && gui_mouse_grabbed (dpyinfo))) | ||
| 15697 | do_help = -1; | 17625 | do_help = -1; |
| 15698 | } | 17626 | } |
| 15699 | #ifdef USE_GTK | 17627 | #ifdef USE_GTK |
| @@ -15724,6 +17652,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15724 | f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window); | 17652 | f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window); |
| 15725 | 17653 | ||
| 15726 | if (x_dnd_in_progress | 17654 | if (x_dnd_in_progress |
| 17655 | /* Handle these events normally if the recursion | ||
| 17656 | level is higher than when the drag-and-drop | ||
| 17657 | operation was initiated. This is so that mouse | ||
| 17658 | input works while we're in the debugger for, say, | ||
| 17659 | `x-dnd-movement-function`. */ | ||
| 17660 | && (command_loop_level + minibuf_level | ||
| 17661 | <= x_dnd_recursion_depth) | ||
| 15727 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) | 17662 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) |
| 15728 | { | 17663 | { |
| 15729 | Window target, toplevel; | 17664 | Window target, toplevel; |
| @@ -15731,6 +17666,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15731 | xm_top_level_leave_message lmsg; | 17666 | xm_top_level_leave_message lmsg; |
| 15732 | xm_top_level_enter_message emsg; | 17667 | xm_top_level_enter_message emsg; |
| 15733 | xm_drag_motion_message dmsg; | 17668 | xm_drag_motion_message dmsg; |
| 17669 | XRectangle *r; | ||
| 17670 | bool was_frame; | ||
| 17671 | |||
| 17672 | /* Always clear mouse face. */ | ||
| 17673 | clear_mouse_face (hlinfo); | ||
| 17674 | hlinfo->mouse_face_hidden = true; | ||
| 15734 | 17675 | ||
| 15735 | /* Sometimes the drag-and-drop operation starts with the | 17676 | /* Sometimes the drag-and-drop operation starts with the |
| 15736 | pointer of a frame invisible due to input. Since | 17677 | pointer of a frame invisible due to input. Since |
| @@ -15738,13 +17679,35 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15738 | visible manually. */ | 17679 | visible manually. */ |
| 15739 | 17680 | ||
| 15740 | if (f) | 17681 | if (f) |
| 15741 | XTtoggle_invisible_pointer (f, false); | 17682 | { |
| 17683 | XTtoggle_invisible_pointer (f, false); | ||
| 17684 | |||
| 17685 | r = &dpyinfo->last_mouse_glyph; | ||
| 17686 | |||
| 17687 | /* Also remember the mouse glyph and set | ||
| 17688 | mouse_moved. */ | ||
| 17689 | if (f != dpyinfo->last_mouse_glyph_frame | ||
| 17690 | || event->xmotion.x < r->x | ||
| 17691 | || event->xmotion.x >= r->x + r->width | ||
| 17692 | || event->xmotion.y < r->y | ||
| 17693 | || event->xmotion.y >= r->y + r->height) | ||
| 17694 | { | ||
| 17695 | f->mouse_moved = true; | ||
| 17696 | f->last_mouse_device = Qnil; | ||
| 17697 | dpyinfo->last_mouse_scroll_bar = NULL; | ||
| 17698 | |||
| 17699 | remember_mouse_glyph (f, event->xmotion.x, | ||
| 17700 | event->xmotion.y, r); | ||
| 17701 | dpyinfo->last_mouse_glyph_frame = f; | ||
| 17702 | } | ||
| 17703 | } | ||
| 15742 | 17704 | ||
| 15743 | target = x_dnd_get_target_window (dpyinfo, | 17705 | target = x_dnd_get_target_window (dpyinfo, |
| 15744 | event->xmotion.x_root, | 17706 | event->xmotion.x_root, |
| 15745 | event->xmotion.y_root, | 17707 | event->xmotion.y_root, |
| 15746 | &target_proto, | 17708 | &target_proto, |
| 15747 | &motif_style, &toplevel); | 17709 | &motif_style, &toplevel, |
| 17710 | &was_frame); | ||
| 15748 | 17711 | ||
| 15749 | if (toplevel != x_dnd_last_seen_toplevel) | 17712 | if (toplevel != x_dnd_last_seen_toplevel) |
| 15750 | { | 17713 | { |
| @@ -15761,6 +17724,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15761 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 17724 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 15762 | else if (x_dnd_last_seen_window != None | 17725 | else if (x_dnd_last_seen_window != None |
| 15763 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 17726 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 17727 | && !x_dnd_disable_motif_drag | ||
| 15764 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 17728 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 15765 | { | 17729 | { |
| 15766 | if (!x_dnd_motif_setup_p) | 17730 | if (!x_dnd_motif_setup_p) |
| @@ -15800,6 +17764,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15800 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 17764 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 15801 | else if (x_dnd_last_seen_window != None | 17765 | else if (x_dnd_last_seen_window != None |
| 15802 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 17766 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 17767 | && x_dnd_disable_motif_drag | ||
| 15803 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 17768 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 15804 | { | 17769 | { |
| 15805 | if (!x_dnd_motif_setup_p) | 17770 | if (!x_dnd_motif_setup_p) |
| @@ -15816,7 +17781,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15816 | dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; | 17781 | dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; |
| 15817 | dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 17782 | dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 15818 | x_dnd_wanted_action), | 17783 | x_dnd_wanted_action), |
| 15819 | XM_DROP_SITE_NONE, XM_DRAG_NOOP, | 17784 | XM_DROP_SITE_NONE, x_dnd_motif_operations, |
| 15820 | XM_DROP_ACTION_DROP_CANCEL); | 17785 | XM_DROP_ACTION_DROP_CANCEL); |
| 15821 | dmsg.timestamp = event->xmotion.time; | 17786 | dmsg.timestamp = event->xmotion.time; |
| 15822 | dmsg.x = event->xmotion.x_root; | 17787 | dmsg.x = event->xmotion.x_root; |
| @@ -15842,11 +17807,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15842 | x_dnd_last_seen_window = target; | 17807 | x_dnd_last_seen_window = target; |
| 15843 | x_dnd_last_protocol_version = target_proto; | 17808 | x_dnd_last_protocol_version = target_proto; |
| 15844 | x_dnd_last_motif_style = motif_style; | 17809 | x_dnd_last_motif_style = motif_style; |
| 17810 | x_dnd_last_window_is_frame = was_frame; | ||
| 15845 | 17811 | ||
| 15846 | if (target != None && x_dnd_last_protocol_version != -1) | 17812 | if (target != None && x_dnd_last_protocol_version != -1) |
| 15847 | x_dnd_send_enter (x_dnd_frame, target, | 17813 | x_dnd_send_enter (x_dnd_frame, target, |
| 15848 | x_dnd_last_protocol_version); | 17814 | x_dnd_last_protocol_version); |
| 15849 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)) | 17815 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 17816 | && !x_dnd_disable_motif_drag) | ||
| 15850 | { | 17817 | { |
| 15851 | if (!x_dnd_motif_setup_p) | 17818 | if (!x_dnd_motif_setup_p) |
| 15852 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 17819 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -15865,7 +17832,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15865 | } | 17832 | } |
| 15866 | } | 17833 | } |
| 15867 | 17834 | ||
| 15868 | if (x_dnd_last_protocol_version != -1 && target != None) | 17835 | if (x_dnd_last_window_is_frame && target != None) |
| 17836 | x_dnd_note_self_position (dpyinfo, target, | ||
| 17837 | event->xbutton.x_root, | ||
| 17838 | event->xbutton.y_root); | ||
| 17839 | else if (x_dnd_last_protocol_version != -1 && target != None) | ||
| 15869 | x_dnd_send_position (x_dnd_frame, target, | 17840 | x_dnd_send_position (x_dnd_frame, target, |
| 15870 | x_dnd_last_protocol_version, | 17841 | x_dnd_last_protocol_version, |
| 15871 | event->xmotion.x_root, | 17842 | event->xmotion.x_root, |
| @@ -15873,7 +17844,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15873 | x_dnd_selection_timestamp, | 17844 | x_dnd_selection_timestamp, |
| 15874 | x_dnd_wanted_action, 0, | 17845 | x_dnd_wanted_action, 0, |
| 15875 | event->xmotion.state); | 17846 | event->xmotion.state); |
| 15876 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None) | 17847 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None |
| 17848 | && !x_dnd_disable_motif_drag) | ||
| 15877 | { | 17849 | { |
| 15878 | if (!x_dnd_motif_setup_p) | 17850 | if (!x_dnd_motif_setup_p) |
| 15879 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 17851 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -15883,9 +17855,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15883 | dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; | 17855 | dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; |
| 15884 | dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 17856 | dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 15885 | x_dnd_wanted_action), | 17857 | x_dnd_wanted_action), |
| 15886 | XM_DROP_SITE_VALID, | 17858 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 15887 | xm_side_effect_from_action (dpyinfo, | ||
| 15888 | x_dnd_wanted_action), | ||
| 15889 | (!x_dnd_xm_use_help | 17859 | (!x_dnd_xm_use_help |
| 15890 | ? XM_DROP_ACTION_DROP | 17860 | ? XM_DROP_ACTION_DROP |
| 15891 | : XM_DROP_ACTION_DROP_HELP)); | 17861 | : XM_DROP_ACTION_DROP_HELP)); |
| @@ -15898,6 +17868,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 15898 | target, &dmsg); | 17868 | target, &dmsg); |
| 15899 | } | 17869 | } |
| 15900 | 17870 | ||
| 17871 | x_dnd_update_tooltip_position (event->xmotion.x_root, | ||
| 17872 | event->xmotion.y_root); | ||
| 17873 | |||
| 15901 | goto OTHER; | 17874 | goto OTHER; |
| 15902 | } | 17875 | } |
| 15903 | 17876 | ||
| @@ -16000,6 +17973,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16000 | So if this ConfigureNotify is immediately followed by another | 17973 | So if this ConfigureNotify is immediately followed by another |
| 16001 | for the same window, use the info from the latest update, and | 17974 | for the same window, use the info from the latest update, and |
| 16002 | consider the events all handled. */ | 17975 | consider the events all handled. */ |
| 17976 | |||
| 16003 | /* Opaque resize may be trickier; ConfigureNotify events are | 17977 | /* Opaque resize may be trickier; ConfigureNotify events are |
| 16004 | mixed with Expose events for multiple windows. */ | 17978 | mixed with Expose events for multiple windows. */ |
| 16005 | configureEvent = *event; | 17979 | configureEvent = *event; |
| @@ -16021,6 +17995,36 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16021 | configureEvent = next_event; | 17995 | configureEvent = next_event; |
| 16022 | } | 17996 | } |
| 16023 | 17997 | ||
| 17998 | /* If we get a ConfigureNotify for the root window, this means | ||
| 17999 | the dimensions of the screen it's on changed. */ | ||
| 18000 | |||
| 18001 | if (configureEvent.xconfigure.window == dpyinfo->root_window) | ||
| 18002 | { | ||
| 18003 | #ifdef HAVE_XRANDR | ||
| 18004 | /* This function is OK to call even if the X server doesn't | ||
| 18005 | support RandR. */ | ||
| 18006 | XRRUpdateConfiguration (&configureEvent); | ||
| 18007 | #elif !defined USE_GTK | ||
| 18008 | /* Catch screen size changes even if RandR is not available | ||
| 18009 | on the client. GTK does this internally. */ | ||
| 18010 | |||
| 18011 | if (configureEvent.xconfigure.width != dpyinfo->screen_width | ||
| 18012 | || configureEvent.xconfigure.height != dpyinfo->screen_height) | ||
| 18013 | { | ||
| 18014 | inev.ie.kind = MONITORS_CHANGED_EVENT; | ||
| 18015 | XSETTERMINAL (inev.ie.arg, dpyinfo->terminal); | ||
| 18016 | |||
| 18017 | /* Store this event now since inev.ie.type could be set to | ||
| 18018 | MOVE_FRAME_EVENT later. */ | ||
| 18019 | kbd_buffer_store_event (&inev.ie); | ||
| 18020 | inev.ie.kind = NO_EVENT; | ||
| 18021 | } | ||
| 18022 | #endif | ||
| 18023 | |||
| 18024 | dpyinfo->screen_width = configureEvent.xconfigure.width; | ||
| 18025 | dpyinfo->screen_height = configureEvent.xconfigure.height; | ||
| 18026 | } | ||
| 18027 | |||
| 16024 | if (x_dnd_in_progress && x_dnd_use_toplevels | 18028 | if (x_dnd_in_progress && x_dnd_use_toplevels |
| 16025 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) | 18029 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) |
| 16026 | { | 18030 | { |
| @@ -16182,15 +18186,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16182 | #endif | 18186 | #endif |
| 16183 | x_net_wm_state (f, configureEvent.xconfigure.window); | 18187 | x_net_wm_state (f, configureEvent.xconfigure.window); |
| 16184 | 18188 | ||
| 16185 | #ifdef USE_X_TOOLKIT | 18189 | #if defined USE_X_TOOLKIT || defined USE_GTK |
| 16186 | /* Tip frames are pure X window, set size for them. */ | 18190 | /* Tip frames are pure X window, set size for them. */ |
| 16187 | if (FRAME_TOOLTIP_P (f)) | 18191 | if (FRAME_TOOLTIP_P (f)) |
| 16188 | { | 18192 | { |
| 16189 | if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height | 18193 | if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height |
| 16190 | || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) | 18194 | || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) |
| 16191 | { | 18195 | SET_FRAME_GARBAGED (f); |
| 16192 | SET_FRAME_GARBAGED (f); | 18196 | |
| 16193 | } | ||
| 16194 | FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; | 18197 | FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; |
| 16195 | FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; | 18198 | FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; |
| 16196 | } | 18199 | } |
| @@ -16317,8 +18320,31 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16317 | bool dnd_grab = false; | 18320 | bool dnd_grab = false; |
| 16318 | 18321 | ||
| 16319 | if (x_dnd_in_progress | 18322 | if (x_dnd_in_progress |
| 18323 | /* Handle these events normally if the recursion | ||
| 18324 | level is higher than when the drag-and-drop | ||
| 18325 | operation was initiated. This is so that mouse | ||
| 18326 | input works while we're in the debugger for, say, | ||
| 18327 | `x-dnd-movement-function`. */ | ||
| 18328 | && (command_loop_level + minibuf_level | ||
| 18329 | <= x_dnd_recursion_depth) | ||
| 16320 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) | 18330 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) |
| 16321 | { | 18331 | { |
| 18332 | f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window); | ||
| 18333 | |||
| 18334 | if (event->type == ButtonPress) | ||
| 18335 | { | ||
| 18336 | dpyinfo->grabbed |= (1 << event->xbutton.button); | ||
| 18337 | dpyinfo->last_mouse_frame = f; | ||
| 18338 | if (f && !tab_bar_p) | ||
| 18339 | f->last_tab_bar_item = -1; | ||
| 18340 | #if ! defined (USE_GTK) | ||
| 18341 | if (f && !tool_bar_p) | ||
| 18342 | f->last_tool_bar_item = -1; | ||
| 18343 | #endif /* not USE_GTK */ | ||
| 18344 | } | ||
| 18345 | else | ||
| 18346 | dpyinfo->grabbed &= ~(1 << event->xbutton.button); | ||
| 18347 | |||
| 16322 | if (event->xbutton.type == ButtonPress | 18348 | if (event->xbutton.type == ButtonPress |
| 16323 | && x_dnd_last_seen_window != None | 18349 | && x_dnd_last_seen_window != None |
| 16324 | && x_dnd_last_protocol_version != -1) | 18350 | && x_dnd_last_protocol_version != -1) |
| @@ -16350,7 +18376,26 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16350 | x_dnd_end_window = x_dnd_last_seen_window; | 18376 | x_dnd_end_window = x_dnd_last_seen_window; |
| 16351 | x_dnd_in_progress = false; | 18377 | x_dnd_in_progress = false; |
| 16352 | 18378 | ||
| 18379 | if (x_dnd_update_tooltip | ||
| 18380 | && FRAMEP (tip_frame) | ||
| 18381 | && FRAME_LIVE_P (XFRAME (tip_frame)) | ||
| 18382 | && (FRAME_X_DISPLAY (XFRAME (tip_frame)) | ||
| 18383 | == FRAME_X_DISPLAY (x_dnd_frame))) | ||
| 18384 | Fx_hide_tip (); | ||
| 18385 | |||
| 18386 | x_dnd_finish_frame = x_dnd_frame; | ||
| 18387 | |||
| 16353 | if (x_dnd_last_seen_window != None | 18388 | if (x_dnd_last_seen_window != None |
| 18389 | && x_dnd_last_window_is_frame) | ||
| 18390 | { | ||
| 18391 | x_dnd_waiting_for_finish = false; | ||
| 18392 | x_dnd_note_self_drop (dpyinfo, | ||
| 18393 | x_dnd_last_seen_window, | ||
| 18394 | event->xbutton.x_root, | ||
| 18395 | event->xbutton.y_root, | ||
| 18396 | event->xbutton.time); | ||
| 18397 | } | ||
| 18398 | else if (x_dnd_last_seen_window != None | ||
| 16354 | && x_dnd_last_protocol_version != -1) | 18399 | && x_dnd_last_protocol_version != -1) |
| 16355 | { | 18400 | { |
| 16356 | x_dnd_pending_finish_target = x_dnd_last_seen_window; | 18401 | x_dnd_pending_finish_target = x_dnd_last_seen_window; |
| @@ -16386,9 +18431,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16386 | dmsg.side_effects | 18431 | dmsg.side_effects |
| 16387 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 18432 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 16388 | x_dnd_wanted_action), | 18433 | x_dnd_wanted_action), |
| 16389 | XM_DROP_SITE_VALID, | 18434 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 16390 | xm_side_effect_from_action (dpyinfo, | ||
| 16391 | x_dnd_wanted_action), | ||
| 16392 | (!x_dnd_xm_use_help | 18435 | (!x_dnd_xm_use_help |
| 16393 | ? XM_DROP_ACTION_DROP | 18436 | ? XM_DROP_ACTION_DROP |
| 16394 | : XM_DROP_ACTION_DROP_HELP)); | 18437 | : XM_DROP_ACTION_DROP_HELP)); |
| @@ -16436,15 +18479,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16436 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; | 18479 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; |
| 16437 | x_dnd_last_seen_window = None; | 18480 | x_dnd_last_seen_window = None; |
| 16438 | x_dnd_last_seen_toplevel = None; | 18481 | x_dnd_last_seen_toplevel = None; |
| 18482 | x_dnd_last_window_is_frame = false; | ||
| 16439 | x_dnd_frame = NULL; | 18483 | x_dnd_frame = NULL; |
| 16440 | x_set_dnd_targets (NULL, 0); | ||
| 16441 | } | 18484 | } |
| 16442 | } | 18485 | } |
| 16443 | 18486 | ||
| 16444 | goto OTHER; | 18487 | goto OTHER; |
| 16445 | } | 18488 | } |
| 16446 | 18489 | ||
| 16447 | if (x_dnd_in_progress) | 18490 | if (x_dnd_in_progress |
| 18491 | && (command_loop_level + minibuf_level | ||
| 18492 | <= x_dnd_recursion_depth)) | ||
| 16448 | goto OTHER; | 18493 | goto OTHER; |
| 16449 | 18494 | ||
| 16450 | memset (&compose_status, 0, sizeof (compose_status)); | 18495 | memset (&compose_status, 0, sizeof (compose_status)); |
| @@ -16480,7 +18525,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16480 | f = x_any_window_to_frame (dpyinfo, event->xbutton.window); | 18525 | f = x_any_window_to_frame (dpyinfo, event->xbutton.window); |
| 16481 | 18526 | ||
| 16482 | if (event->xbutton.button > 3 | 18527 | if (event->xbutton.button > 3 |
| 16483 | && event->xbutton.button < 9 | 18528 | && event->xbutton.button < 8 |
| 16484 | && f) | 18529 | && f) |
| 16485 | { | 18530 | { |
| 16486 | if (ignore_next_mouse_click_timeout | 18531 | if (ignore_next_mouse_click_timeout |
| @@ -16794,7 +18839,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16794 | ev.window = enter->event; | 18839 | ev.window = enter->event; |
| 16795 | ev.time = enter->time; | 18840 | ev.time = enter->time; |
| 16796 | 18841 | ||
| 16797 | x_display_set_last_user_time (dpyinfo, xi_event->time); | 18842 | x_display_set_last_user_time (dpyinfo, enter->time); |
| 16798 | 18843 | ||
| 16799 | #ifdef USE_MOTIF | 18844 | #ifdef USE_MOTIF |
| 16800 | use_copy = true; | 18845 | use_copy = true; |
| @@ -16852,7 +18897,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16852 | 18897 | ||
| 16853 | if (f && x_mouse_click_focus_ignore_position) | 18898 | if (f && x_mouse_click_focus_ignore_position) |
| 16854 | { | 18899 | { |
| 16855 | ignore_next_mouse_click_timeout = xev->time + 200; | 18900 | ignore_next_mouse_click_timeout = (enter->time |
| 18901 | + x_mouse_click_focus_ignore_time); | ||
| 16856 | mouse_click_timeout_display = dpyinfo; | 18902 | mouse_click_timeout_display = dpyinfo; |
| 16857 | } | 18903 | } |
| 16858 | 18904 | ||
| @@ -16896,7 +18942,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16896 | 18942 | ||
| 16897 | #ifdef USE_X_TOOLKIT | 18943 | #ifdef USE_X_TOOLKIT |
| 16898 | if (popup_activated () | 18944 | if (popup_activated () |
| 16899 | && leave->mode == XINotifyPassiveUngrab) | 18945 | && (leave->mode == XINotifyPassiveUngrab |
| 18946 | || leave->mode == XINotifyUngrab)) | ||
| 16900 | any = x_any_window_to_frame (dpyinfo, leave->event); | 18947 | any = x_any_window_to_frame (dpyinfo, leave->event); |
| 16901 | #endif | 18948 | #endif |
| 16902 | 18949 | ||
| @@ -16941,7 +18988,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16941 | leave->deviceid, false); | 18988 | leave->deviceid, false); |
| 16942 | #endif | 18989 | #endif |
| 16943 | 18990 | ||
| 16944 | x_display_set_last_user_time (dpyinfo, xi_event->time); | 18991 | x_display_set_last_user_time (dpyinfo, leave->time); |
| 16945 | 18992 | ||
| 16946 | #ifdef HAVE_XWIDGETS | 18993 | #ifdef HAVE_XWIDGETS |
| 16947 | { | 18994 | { |
| @@ -16968,6 +19015,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16968 | masks are set on the frame widget's window. */ | 19015 | masks are set on the frame widget's window. */ |
| 16969 | f = x_window_to_frame (dpyinfo, leave->event); | 19016 | f = x_window_to_frame (dpyinfo, leave->event); |
| 16970 | 19017 | ||
| 19018 | /* Also do this again here, since the test for `any' | ||
| 19019 | above may not have found a frame, as that usually | ||
| 19020 | just looks up a top window on Xt builds. */ | ||
| 19021 | |||
| 19022 | #ifdef HAVE_XINPUT2_1 | ||
| 19023 | if (leave->detail != XINotifyInferior && f) | ||
| 19024 | xi_reset_scroll_valuators_for_device_id (dpyinfo, | ||
| 19025 | leave->deviceid, false); | ||
| 19026 | #endif | ||
| 19027 | |||
| 16971 | if (!f) | 19028 | if (!f) |
| 16972 | f = x_top_window_to_frame (dpyinfo, leave->event); | 19029 | f = x_top_window_to_frame (dpyinfo, leave->event); |
| 16973 | #endif | 19030 | #endif |
| @@ -16985,7 +19042,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16985 | Do it only if there's something to cancel. | 19042 | Do it only if there's something to cancel. |
| 16986 | Otherwise, the startup message is cleared when | 19043 | Otherwise, the startup message is cleared when |
| 16987 | the mouse leaves the frame. */ | 19044 | the mouse leaves the frame. */ |
| 16988 | if (any_help_event_p) | 19045 | if (any_help_event_p |
| 19046 | /* But never if `mouse-drag-and-drop-region' is | ||
| 19047 | in progress, since that results in the | ||
| 19048 | tooltip being dismissed when the mouse moves | ||
| 19049 | on top. */ | ||
| 19050 | && !((EQ (track_mouse, Qdrag_source) | ||
| 19051 | || EQ (track_mouse, Qdropping)) | ||
| 19052 | && gui_mouse_grabbed (dpyinfo))) | ||
| 16989 | do_help = -1; | 19053 | do_help = -1; |
| 16990 | } | 19054 | } |
| 16991 | #ifdef USE_GTK | 19055 | #ifdef USE_GTK |
| @@ -17004,6 +19068,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17004 | XIValuatorState *states; | 19068 | XIValuatorState *states; |
| 17005 | double *values; | 19069 | double *values; |
| 17006 | bool found_valuator = false; | 19070 | bool found_valuator = false; |
| 19071 | bool other_valuators_found = false; | ||
| 17007 | #endif | 19072 | #endif |
| 17008 | /* A fake XMotionEvent for x_note_mouse_movement. */ | 19073 | /* A fake XMotionEvent for x_note_mouse_movement. */ |
| 17009 | XMotionEvent ev; | 19074 | XMotionEvent ev; |
| @@ -17061,6 +19126,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17061 | i, *values, &val); | 19126 | i, *values, &val); |
| 17062 | values++; | 19127 | values++; |
| 17063 | 19128 | ||
| 19129 | if (!val) | ||
| 19130 | { | ||
| 19131 | other_valuators_found = true; | ||
| 19132 | continue; | ||
| 19133 | } | ||
| 19134 | |||
| 17064 | if (delta != DBL_MAX) | 19135 | if (delta != DBL_MAX) |
| 17065 | { | 19136 | { |
| 17066 | if (!f) | 19137 | if (!f) |
| @@ -17208,12 +19279,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17208 | So instead of that, just ignore XI wheel | 19279 | So instead of that, just ignore XI wheel |
| 17209 | events which land on a scroll bar. | 19280 | events which land on a scroll bar. |
| 17210 | 19281 | ||
| 17211 | Here we assume anything which isn't the edit | 19282 | Here we assume anything which isn't the edit |
| 17212 | widget window is a scroll bar. */ | 19283 | widget window is a scroll bar. */ |
| 17213 | 19284 | ||
| 17214 | if (xev->child != None | 19285 | if (xev->child != None |
| 17215 | && xev->child != FRAME_X_WINDOW (f)) | 19286 | && xev->child != FRAME_X_WINDOW (f)) |
| 17216 | goto OTHER; | 19287 | goto XI_OTHER; |
| 17217 | #endif | 19288 | #endif |
| 17218 | 19289 | ||
| 17219 | if (fabs (total_x) > 0 || fabs (total_y) > 0) | 19290 | if (fabs (total_x) > 0 || fabs (total_y) > 0) |
| @@ -17249,7 +19320,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17249 | if (source && !NILP (source->name)) | 19320 | if (source && !NILP (source->name)) |
| 17250 | inev.ie.device = source->name; | 19321 | inev.ie.device = source->name; |
| 17251 | 19322 | ||
| 17252 | goto XI_OTHER; | 19323 | if (!other_valuators_found) |
| 19324 | goto XI_OTHER; | ||
| 17253 | } | 19325 | } |
| 17254 | #ifdef HAVE_XWIDGETS | 19326 | #ifdef HAVE_XWIDGETS |
| 17255 | } | 19327 | } |
| @@ -17304,10 +19376,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17304 | f = mouse_or_wdesc_frame (dpyinfo, xev->event); | 19376 | f = mouse_or_wdesc_frame (dpyinfo, xev->event); |
| 17305 | 19377 | ||
| 17306 | if (x_dnd_in_progress | 19378 | if (x_dnd_in_progress |
| 19379 | /* Handle these events normally if the recursion | ||
| 19380 | level is higher than when the drag-and-drop | ||
| 19381 | operation was initiated. This is so that mouse | ||
| 19382 | input works while we're in the debugger for, say, | ||
| 19383 | `x-dnd-movement-function`. */ | ||
| 19384 | && (command_loop_level + minibuf_level | ||
| 19385 | <= x_dnd_recursion_depth) | ||
| 17307 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) | 19386 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) |
| 17308 | { | 19387 | { |
| 17309 | Window target, toplevel; | 19388 | Window target, toplevel; |
| 17310 | int target_proto, motif_style; | 19389 | int target_proto, motif_style; |
| 19390 | XRectangle *r; | ||
| 19391 | bool was_frame; | ||
| 19392 | |||
| 19393 | /* Always clear mouse face. */ | ||
| 19394 | clear_mouse_face (hlinfo); | ||
| 19395 | hlinfo->mouse_face_hidden = true; | ||
| 17311 | 19396 | ||
| 17312 | /* Sometimes the drag-and-drop operation starts with the | 19397 | /* Sometimes the drag-and-drop operation starts with the |
| 17313 | pointer of a frame invisible due to input. Since | 19398 | pointer of a frame invisible due to input. Since |
| @@ -17315,14 +19400,37 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17315 | visible manually. */ | 19400 | visible manually. */ |
| 17316 | 19401 | ||
| 17317 | if (f) | 19402 | if (f) |
| 17318 | XTtoggle_invisible_pointer (f, false); | 19403 | { |
| 19404 | XTtoggle_invisible_pointer (f, false); | ||
| 19405 | |||
| 19406 | r = &dpyinfo->last_mouse_glyph; | ||
| 19407 | |||
| 19408 | /* Also remember the mouse glyph and set | ||
| 19409 | mouse_moved. */ | ||
| 19410 | if (f != dpyinfo->last_mouse_glyph_frame | ||
| 19411 | || xev->event_x < r->x | ||
| 19412 | || xev->event_x >= r->x + r->width | ||
| 19413 | || xev->event_y < r->y | ||
| 19414 | || xev->event_y >= r->y + r->height) | ||
| 19415 | { | ||
| 19416 | f->mouse_moved = true; | ||
| 19417 | f->last_mouse_device = (source ? source->name | ||
| 19418 | : Qnil); | ||
| 19419 | dpyinfo->last_mouse_scroll_bar = NULL; | ||
| 19420 | |||
| 19421 | remember_mouse_glyph (f, xev->event_x, | ||
| 19422 | xev->event_y, r); | ||
| 19423 | dpyinfo->last_mouse_glyph_frame = f; | ||
| 19424 | } | ||
| 19425 | } | ||
| 17319 | 19426 | ||
| 17320 | target = x_dnd_get_target_window (dpyinfo, | 19427 | target = x_dnd_get_target_window (dpyinfo, |
| 17321 | xev->root_x, | 19428 | xev->root_x, |
| 17322 | xev->root_y, | 19429 | xev->root_y, |
| 17323 | &target_proto, | 19430 | &target_proto, |
| 17324 | &motif_style, | 19431 | &motif_style, |
| 17325 | &toplevel); | 19432 | &toplevel, |
| 19433 | &was_frame); | ||
| 17326 | 19434 | ||
| 17327 | if (toplevel != x_dnd_last_seen_toplevel) | 19435 | if (toplevel != x_dnd_last_seen_toplevel) |
| 17328 | { | 19436 | { |
| @@ -17339,6 +19447,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17339 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 19447 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 17340 | else if (x_dnd_last_seen_window != None | 19448 | else if (x_dnd_last_seen_window != None |
| 17341 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 19449 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 19450 | && !x_dnd_disable_motif_drag | ||
| 17342 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 19451 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 17343 | { | 19452 | { |
| 17344 | if (!x_dnd_motif_setup_p) | 19453 | if (!x_dnd_motif_setup_p) |
| @@ -17378,6 +19487,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17378 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 19487 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 17379 | else if (x_dnd_last_seen_window != None | 19488 | else if (x_dnd_last_seen_window != None |
| 17380 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) | 19489 | && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 19490 | && !x_dnd_disable_motif_drag | ||
| 17381 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) | 19491 | && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)) |
| 17382 | { | 19492 | { |
| 17383 | if (!x_dnd_motif_setup_p) | 19493 | if (!x_dnd_motif_setup_p) |
| @@ -17396,7 +19506,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17396 | dmsg.side_effects | 19506 | dmsg.side_effects |
| 17397 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 19507 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 17398 | x_dnd_wanted_action), | 19508 | x_dnd_wanted_action), |
| 17399 | XM_DROP_SITE_NONE, XM_DRAG_NOOP, | 19509 | XM_DROP_SITE_NONE, x_dnd_motif_operations, |
| 17400 | XM_DROP_ACTION_DROP_CANCEL); | 19510 | XM_DROP_ACTION_DROP_CANCEL); |
| 17401 | dmsg.timestamp = xev->time; | 19511 | dmsg.timestamp = xev->time; |
| 17402 | dmsg.x = lrint (xev->root_x); | 19512 | dmsg.x = lrint (xev->root_x); |
| @@ -17422,11 +19532,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17422 | x_dnd_last_seen_window = target; | 19532 | x_dnd_last_seen_window = target; |
| 17423 | x_dnd_last_protocol_version = target_proto; | 19533 | x_dnd_last_protocol_version = target_proto; |
| 17424 | x_dnd_last_motif_style = motif_style; | 19534 | x_dnd_last_motif_style = motif_style; |
| 19535 | x_dnd_last_window_is_frame = was_frame; | ||
| 17425 | 19536 | ||
| 17426 | if (target != None && x_dnd_last_protocol_version != -1) | 19537 | if (target != None && x_dnd_last_protocol_version != -1) |
| 17427 | x_dnd_send_enter (x_dnd_frame, target, | 19538 | x_dnd_send_enter (x_dnd_frame, target, |
| 17428 | x_dnd_last_protocol_version); | 19539 | x_dnd_last_protocol_version); |
| 17429 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)) | 19540 | else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) |
| 19541 | && !x_dnd_disable_motif_drag) | ||
| 17430 | { | 19542 | { |
| 17431 | if (!x_dnd_motif_setup_p) | 19543 | if (!x_dnd_motif_setup_p) |
| 17432 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 19544 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -17445,7 +19557,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17445 | } | 19557 | } |
| 17446 | } | 19558 | } |
| 17447 | 19559 | ||
| 17448 | if (x_dnd_last_protocol_version != -1 && target != None) | 19560 | if (x_dnd_last_window_is_frame && target != None) |
| 19561 | x_dnd_note_self_position (dpyinfo, target, | ||
| 19562 | xev->root_x, xev->root_y); | ||
| 19563 | else if (x_dnd_last_protocol_version != -1 && target != None) | ||
| 17449 | { | 19564 | { |
| 17450 | dnd_state = xev->mods.effective; | 19565 | dnd_state = xev->mods.effective; |
| 17451 | 19566 | ||
| @@ -17466,7 +19581,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17466 | x_dnd_wanted_action, 0, | 19581 | x_dnd_wanted_action, 0, |
| 17467 | dnd_state); | 19582 | dnd_state); |
| 17468 | } | 19583 | } |
| 17469 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None) | 19584 | else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None |
| 19585 | && !x_dnd_disable_motif_drag) | ||
| 17470 | { | 19586 | { |
| 17471 | if (!x_dnd_motif_setup_p) | 19587 | if (!x_dnd_motif_setup_p) |
| 17472 | xm_setup_drag_info (dpyinfo, x_dnd_frame); | 19588 | xm_setup_drag_info (dpyinfo, x_dnd_frame); |
| @@ -17477,9 +19593,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17477 | dmsg.side_effects | 19593 | dmsg.side_effects |
| 17478 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 19594 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 17479 | x_dnd_wanted_action), | 19595 | x_dnd_wanted_action), |
| 17480 | XM_DROP_SITE_VALID, | 19596 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 17481 | xm_side_effect_from_action (dpyinfo, | ||
| 17482 | x_dnd_wanted_action), | ||
| 17483 | (!x_dnd_xm_use_help | 19597 | (!x_dnd_xm_use_help |
| 17484 | ? XM_DROP_ACTION_DROP | 19598 | ? XM_DROP_ACTION_DROP |
| 17485 | : XM_DROP_ACTION_DROP_HELP)); | 19599 | : XM_DROP_ACTION_DROP_HELP)); |
| @@ -17492,6 +19606,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17492 | target, &dmsg); | 19606 | target, &dmsg); |
| 17493 | } | 19607 | } |
| 17494 | 19608 | ||
| 19609 | x_dnd_update_tooltip_position (xev->root_x, xev->root_y); | ||
| 19610 | |||
| 17495 | goto XI_OTHER; | 19611 | goto XI_OTHER; |
| 17496 | } | 19612 | } |
| 17497 | 19613 | ||
| @@ -17558,7 +19674,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17558 | { | 19674 | { |
| 17559 | #ifndef USE_TOOLKIT_SCROLL_BARS | 19675 | #ifndef USE_TOOLKIT_SCROLL_BARS |
| 17560 | struct scroll_bar *bar | 19676 | struct scroll_bar *bar |
| 17561 | = x_window_to_scroll_bar (xi_event->display, xev->event, 2); | 19677 | = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2); |
| 17562 | 19678 | ||
| 17563 | if (bar) | 19679 | if (bar) |
| 17564 | x_scroll_bar_note_movement (bar, &ev); | 19680 | x_scroll_bar_note_movement (bar, &ev); |
| @@ -17595,8 +19711,26 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17595 | int dnd_state; | 19711 | int dnd_state; |
| 17596 | 19712 | ||
| 17597 | if (x_dnd_in_progress | 19713 | if (x_dnd_in_progress |
| 19714 | && (command_loop_level + minibuf_level | ||
| 19715 | <= x_dnd_recursion_depth) | ||
| 17598 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) | 19716 | && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) |
| 17599 | { | 19717 | { |
| 19718 | f = mouse_or_wdesc_frame (dpyinfo, xev->event); | ||
| 19719 | |||
| 19720 | if (xev->evtype == XI_ButtonPress) | ||
| 19721 | { | ||
| 19722 | dpyinfo->grabbed |= (1 << xev->detail); | ||
| 19723 | dpyinfo->last_mouse_frame = f; | ||
| 19724 | if (f && !tab_bar_p) | ||
| 19725 | f->last_tab_bar_item = -1; | ||
| 19726 | #if ! defined (USE_GTK) | ||
| 19727 | if (f && !tool_bar_p) | ||
| 19728 | f->last_tool_bar_item = -1; | ||
| 19729 | #endif /* not USE_GTK */ | ||
| 19730 | } | ||
| 19731 | else | ||
| 19732 | dpyinfo->grabbed &= ~(1 << xev->detail); | ||
| 19733 | |||
| 17600 | if (xev->evtype == XI_ButtonPress | 19734 | if (xev->evtype == XI_ButtonPress |
| 17601 | && x_dnd_last_seen_window != None | 19735 | && x_dnd_last_seen_window != None |
| 17602 | && x_dnd_last_protocol_version != -1) | 19736 | && x_dnd_last_protocol_version != -1) |
| @@ -17634,8 +19768,33 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17634 | x_dnd_end_window = x_dnd_last_seen_window; | 19768 | x_dnd_end_window = x_dnd_last_seen_window; |
| 17635 | x_dnd_in_progress = false; | 19769 | x_dnd_in_progress = false; |
| 17636 | 19770 | ||
| 19771 | /* If a tooltip that we're following is | ||
| 19772 | displayed, hide it now. */ | ||
| 19773 | |||
| 19774 | if (x_dnd_update_tooltip | ||
| 19775 | && FRAMEP (tip_frame) | ||
| 19776 | && FRAME_LIVE_P (XFRAME (tip_frame)) | ||
| 19777 | && (FRAME_X_DISPLAY (XFRAME (tip_frame)) | ||
| 19778 | == FRAME_X_DISPLAY (x_dnd_frame))) | ||
| 19779 | Fx_hide_tip (); | ||
| 19780 | |||
| 19781 | /* This doesn't have to be marked since it | ||
| 19782 | is only accessed if | ||
| 19783 | x_dnd_waiting_for_finish is true, which | ||
| 19784 | is only possible inside the DND event | ||
| 19785 | loop where that frame is on the | ||
| 19786 | stack. */ | ||
| 19787 | x_dnd_finish_frame = x_dnd_frame; | ||
| 19788 | |||
| 17637 | if (x_dnd_last_seen_window != None | 19789 | if (x_dnd_last_seen_window != None |
| 17638 | && x_dnd_last_protocol_version != -1) | 19790 | && x_dnd_last_window_is_frame) |
| 19791 | { | ||
| 19792 | x_dnd_waiting_for_finish = false; | ||
| 19793 | x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window, | ||
| 19794 | xev->root_x, xev->root_y, xev->time); | ||
| 19795 | } | ||
| 19796 | else if (x_dnd_last_seen_window != None | ||
| 19797 | && x_dnd_last_protocol_version != -1) | ||
| 17639 | { | 19798 | { |
| 17640 | x_dnd_pending_finish_target = x_dnd_last_seen_window; | 19799 | x_dnd_pending_finish_target = x_dnd_last_seen_window; |
| 17641 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; | 19800 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; |
| @@ -17670,9 +19829,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17670 | dmsg.side_effects | 19829 | dmsg.side_effects |
| 17671 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, | 19830 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo, |
| 17672 | x_dnd_wanted_action), | 19831 | x_dnd_wanted_action), |
| 17673 | XM_DROP_SITE_VALID, | 19832 | XM_DROP_SITE_VALID, x_dnd_motif_operations, |
| 17674 | xm_side_effect_from_action (dpyinfo, | ||
| 17675 | x_dnd_wanted_action), | ||
| 17676 | (!x_dnd_xm_use_help | 19833 | (!x_dnd_xm_use_help |
| 17677 | ? XM_DROP_ACTION_DROP | 19834 | ? XM_DROP_ACTION_DROP |
| 17678 | : XM_DROP_ACTION_DROP_HELP)); | 19835 | : XM_DROP_ACTION_DROP_HELP)); |
| @@ -17727,15 +19884,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17727 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; | 19884 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; |
| 17728 | x_dnd_last_seen_window = None; | 19885 | x_dnd_last_seen_window = None; |
| 17729 | x_dnd_last_seen_toplevel = None; | 19886 | x_dnd_last_seen_toplevel = None; |
| 19887 | x_dnd_last_window_is_frame = false; | ||
| 17730 | x_dnd_frame = NULL; | 19888 | x_dnd_frame = NULL; |
| 17731 | x_set_dnd_targets (NULL, 0); | ||
| 17732 | 19889 | ||
| 17733 | goto XI_OTHER; | 19890 | goto XI_OTHER; |
| 17734 | } | 19891 | } |
| 17735 | } | 19892 | } |
| 17736 | } | 19893 | } |
| 17737 | 19894 | ||
| 17738 | if (x_dnd_in_progress) | 19895 | if (x_dnd_in_progress |
| 19896 | && (command_loop_level + minibuf_level | ||
| 19897 | <= x_dnd_recursion_depth)) | ||
| 17739 | goto XI_OTHER; | 19898 | goto XI_OTHER; |
| 17740 | 19899 | ||
| 17741 | #ifdef USE_MOTIF | 19900 | #ifdef USE_MOTIF |
| @@ -17801,9 +19960,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17801 | 19960 | ||
| 17802 | g_object_ref (copy->button.window); | 19961 | g_object_ref (copy->button.window); |
| 17803 | 19962 | ||
| 17804 | if (popup_activated () | 19963 | if (popup_activated ()) |
| 17805 | && xev->evtype == XI_ButtonRelease) | 19964 | { |
| 17806 | goto XI_OTHER; | 19965 | /* GTK+ popup menus don't respond to core buttons |
| 19966 | after Button3, so don't dismiss popup menus upon | ||
| 19967 | wheel movement here either. */ | ||
| 19968 | if (xev->detail > 3) | ||
| 19969 | *finish = X_EVENT_DROP; | ||
| 19970 | |||
| 19971 | if (xev->evtype == XI_ButtonRelease) | ||
| 19972 | goto XI_OTHER; | ||
| 19973 | } | ||
| 17807 | #endif | 19974 | #endif |
| 17808 | 19975 | ||
| 17809 | #ifdef HAVE_XINPUT2_1 | 19976 | #ifdef HAVE_XINPUT2_1 |
| @@ -17896,7 +20063,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17896 | 20063 | ||
| 17897 | f = x_any_window_to_frame (dpyinfo, xev->event); | 20064 | f = x_any_window_to_frame (dpyinfo, xev->event); |
| 17898 | 20065 | ||
| 17899 | if (xev->detail > 3 && xev->detail < 9 && f) | 20066 | if (xev->detail > 3 && xev->detail < 8 && f) |
| 17900 | { | 20067 | { |
| 17901 | if (xev->evtype == XI_ButtonRelease) | 20068 | if (xev->evtype == XI_ButtonRelease) |
| 17902 | { | 20069 | { |
| @@ -17939,7 +20106,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 17939 | 20106 | ||
| 17940 | if (f) | 20107 | if (f) |
| 17941 | { | 20108 | { |
| 17942 | if (xev->detail >= 4 && xev->detail <= 8) | 20109 | if (xev->detail >= 4 && xev->detail < 8) |
| 17943 | { | 20110 | { |
| 17944 | if (xev->evtype == XI_ButtonRelease) | 20111 | if (xev->evtype == XI_ButtonRelease) |
| 17945 | { | 20112 | { |
| @@ -18260,9 +20427,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18260 | state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers); | 20427 | state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers); |
| 18261 | 20428 | ||
| 18262 | #ifdef HAVE_XKB | 20429 | #ifdef HAVE_XKB |
| 18263 | if (FRAME_DISPLAY_INFO (f)->xkb_desc) | 20430 | if (dpyinfo->xkb_desc) |
| 18264 | { | 20431 | { |
| 18265 | XkbDescRec *rec = FRAME_DISPLAY_INFO (f)->xkb_desc; | 20432 | XkbDescRec *rec = dpyinfo->xkb_desc; |
| 18266 | 20433 | ||
| 18267 | if (rec->map->modmap && rec->map->modmap[xev->detail]) | 20434 | if (rec->map->modmap && rec->map->modmap[xev->detail]) |
| 18268 | goto xi_done_keysym; | 20435 | goto xi_done_keysym; |
| @@ -18352,7 +20519,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18352 | if (status_return == XBufferOverflow) | 20519 | if (status_return == XBufferOverflow) |
| 18353 | { | 20520 | { |
| 18354 | copy_bufsiz = nbytes + 1; | 20521 | copy_bufsiz = nbytes + 1; |
| 18355 | copy_bufptr = alloca (copy_bufsiz); | 20522 | copy_bufptr = SAFE_ALLOCA (copy_bufsiz); |
| 18356 | nbytes = XmbLookupString (FRAME_XIC (f), | 20523 | nbytes = XmbLookupString (FRAME_XIC (f), |
| 18357 | &xkey, (char *) copy_bufptr, | 20524 | &xkey, (char *) copy_bufptr, |
| 18358 | copy_bufsiz, &keysym, | 20525 | copy_bufsiz, &keysym, |
| @@ -18384,8 +20551,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18384 | copy_bufsiz, &overflow); | 20551 | copy_bufsiz, &overflow); |
| 18385 | if (overflow) | 20552 | if (overflow) |
| 18386 | { | 20553 | { |
| 18387 | copy_bufptr = alloca ((copy_bufsiz += overflow) | 20554 | copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow) |
| 18388 | * sizeof *copy_bufptr); | 20555 | * sizeof *copy_bufptr); |
| 18389 | overflow = 0; | 20556 | overflow = 0; |
| 18390 | nbytes = XkbTranslateKeySym (dpyinfo->display, &sym, | 20557 | nbytes = XkbTranslateKeySym (dpyinfo->display, &sym, |
| 18391 | state & ~mods_rtrn, copy_bufptr, | 20558 | state & ~mods_rtrn, copy_bufptr, |
| @@ -18696,7 +20863,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18696 | struct xi_touch_point_t *tem, *last; | 20863 | struct xi_touch_point_t *tem, *last; |
| 18697 | #endif | 20864 | #endif |
| 18698 | 20865 | ||
| 18699 | disabled = alloca (sizeof *disabled * hev->num_info); | 20866 | disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info); |
| 18700 | n_disabled = 0; | 20867 | n_disabled = 0; |
| 18701 | 20868 | ||
| 18702 | for (i = 0; i < hev->num_info; ++i) | 20869 | for (i = 0; i < hev->num_info; ++i) |
| @@ -18995,6 +21162,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18995 | 21162 | ||
| 18996 | if (!menu_bar_p && !tool_bar_p) | 21163 | if (!menu_bar_p && !tool_bar_p) |
| 18997 | { | 21164 | { |
| 21165 | x_catch_errors (dpyinfo->display); | ||
| 21166 | |||
| 18998 | if (f && device->direct_p) | 21167 | if (f && device->direct_p) |
| 18999 | { | 21168 | { |
| 19000 | *finish = X_EVENT_DROP; | 21169 | *finish = X_EVENT_DROP; |
| @@ -19023,6 +21192,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 19023 | XIAllowTouchEvents (dpyinfo->display, xev->deviceid, | 21192 | XIAllowTouchEvents (dpyinfo->display, xev->deviceid, |
| 19024 | xev->detail, xev->event, XIRejectTouch); | 21193 | xev->detail, xev->event, XIRejectTouch); |
| 19025 | #endif | 21194 | #endif |
| 21195 | x_uncatch_errors (); | ||
| 19026 | } | 21196 | } |
| 19027 | else | 21197 | else |
| 19028 | { | 21198 | { |
| @@ -19135,7 +21305,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 19135 | 21305 | ||
| 19136 | device = xi_device_from_id (dpyinfo, pev->deviceid); | 21306 | device = xi_device_from_id (dpyinfo, pev->deviceid); |
| 19137 | source = xi_device_from_id (dpyinfo, pev->sourceid); | 21307 | source = xi_device_from_id (dpyinfo, pev->sourceid); |
| 19138 | x_display_set_last_user_time (dpyinfo, xi_event->time); | 21308 | x_display_set_last_user_time (dpyinfo, pev->time); |
| 19139 | 21309 | ||
| 19140 | if (!device) | 21310 | if (!device) |
| 19141 | goto XI_OTHER; | 21311 | goto XI_OTHER; |
| @@ -19466,7 +21636,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 19466 | } | 21636 | } |
| 19467 | 21637 | ||
| 19468 | /* And the common case where there is no input rect and the | 21638 | /* And the common case where there is no input rect and the |
| 19469 | bouding rect equals the window dimensions. */ | 21639 | bounding rect equals the window dimensions. */ |
| 19470 | 21640 | ||
| 19471 | if (tem->n_input_rects == -1 | 21641 | if (tem->n_input_rects == -1 |
| 19472 | && tem->n_bounding_rects == 1 | 21642 | && tem->n_bounding_rects == 1 |
| @@ -19484,6 +21654,75 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 19484 | } | 21654 | } |
| 19485 | } | 21655 | } |
| 19486 | #endif | 21656 | #endif |
| 21657 | #if defined HAVE_XRANDR && !defined USE_GTK | ||
| 21658 | if (dpyinfo->xrandr_supported_p | ||
| 21659 | && (event->type == (dpyinfo->xrandr_event_base | ||
| 21660 | + RRScreenChangeNotify) | ||
| 21661 | || event->type == (dpyinfo->xrandr_event_base | ||
| 21662 | + RRNotify))) | ||
| 21663 | { | ||
| 21664 | union buffered_input_event *ev; | ||
| 21665 | Time timestamp; | ||
| 21666 | Lisp_Object current_monitors; | ||
| 21667 | XRRScreenChangeNotifyEvent *notify; | ||
| 21668 | |||
| 21669 | if (event->type == (dpyinfo->xrandr_event_base | ||
| 21670 | + RRScreenChangeNotify)) | ||
| 21671 | XRRUpdateConfiguration (event); | ||
| 21672 | |||
| 21673 | if (event->type == (dpyinfo->xrandr_event_base | ||
| 21674 | + RRScreenChangeNotify)) | ||
| 21675 | { | ||
| 21676 | notify = ((XRRScreenChangeNotifyEvent *) event); | ||
| 21677 | timestamp = notify->timestamp; | ||
| 21678 | |||
| 21679 | /* Don't set screen dimensions if the notification is | ||
| 21680 | for a different screen. */ | ||
| 21681 | if (notify->root == dpyinfo->root_window) | ||
| 21682 | { | ||
| 21683 | dpyinfo->screen_width = notify->width; | ||
| 21684 | dpyinfo->screen_height = notify->height; | ||
| 21685 | dpyinfo->screen_mm_width = notify->mwidth; | ||
| 21686 | dpyinfo->screen_mm_height = notify->mheight; | ||
| 21687 | } | ||
| 21688 | } | ||
| 21689 | else | ||
| 21690 | timestamp = 0; | ||
| 21691 | |||
| 21692 | ev = (kbd_store_ptr == kbd_buffer | ||
| 21693 | ? kbd_buffer + KBD_BUFFER_SIZE - 1 | ||
| 21694 | : kbd_store_ptr - 1); | ||
| 21695 | |||
| 21696 | if (kbd_store_ptr != kbd_fetch_ptr | ||
| 21697 | && ev->ie.kind == MONITORS_CHANGED_EVENT | ||
| 21698 | && XTERMINAL (ev->ie.arg) == dpyinfo->terminal) | ||
| 21699 | /* Don't store a MONITORS_CHANGED_EVENT if there is | ||
| 21700 | already an undelivered event on the queue. */ | ||
| 21701 | goto OTHER; | ||
| 21702 | |||
| 21703 | inev.ie.kind = MONITORS_CHANGED_EVENT; | ||
| 21704 | inev.ie.timestamp = timestamp; | ||
| 21705 | XSETTERMINAL (inev.ie.arg, dpyinfo->terminal); | ||
| 21706 | |||
| 21707 | /* Also don't do anything if the monitor configuration | ||
| 21708 | didn't really change. */ | ||
| 21709 | |||
| 21710 | current_monitors | ||
| 21711 | = Fx_display_monitor_attributes_list (inev.ie.arg); | ||
| 21712 | |||
| 21713 | if (!NILP (Fequal (current_monitors, | ||
| 21714 | dpyinfo->last_monitor_attributes_list))) | ||
| 21715 | inev.ie.kind = NO_EVENT; | ||
| 21716 | |||
| 21717 | dpyinfo->last_monitor_attributes_list = current_monitors; | ||
| 21718 | |||
| 21719 | if (x_dnd_in_progress && x_dnd_update_tooltip) | ||
| 21720 | x_dnd_monitors = current_monitors; | ||
| 21721 | |||
| 21722 | if (inev.ie.kind != NO_EVENT) | ||
| 21723 | x_dnd_update_tooltip_now (); | ||
| 21724 | } | ||
| 21725 | #endif | ||
| 19487 | OTHER: | 21726 | OTHER: |
| 19488 | #ifdef USE_X_TOOLKIT | 21727 | #ifdef USE_X_TOOLKIT |
| 19489 | block_input (); | 21728 | block_input (); |
| @@ -19566,6 +21805,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 19566 | if (any && any != f) | 21805 | if (any && any != f) |
| 19567 | flush_dirty_back_buffer_on (any); | 21806 | flush_dirty_back_buffer_on (any); |
| 19568 | #endif | 21807 | #endif |
| 21808 | |||
| 21809 | SAFE_FREE (); | ||
| 19569 | return count; | 21810 | return count; |
| 19570 | } | 21811 | } |
| 19571 | 21812 | ||
| @@ -19611,8 +21852,18 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 19611 | /* Don't allow XTread_socket to do anything if drag-and-drop is in | 21852 | /* Don't allow XTread_socket to do anything if drag-and-drop is in |
| 19612 | progress. If unblock_input causes XTread_socket to be called and | 21853 | progress. If unblock_input causes XTread_socket to be called and |
| 19613 | read X events while the drag-and-drop event loop is in progress, | 21854 | read X events while the drag-and-drop event loop is in progress, |
| 19614 | things can go wrong very quick. */ | 21855 | things can go wrong very quick. |
| 19615 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) | 21856 | |
| 21857 | When x_dnd_unwind_flag is true, the above doesn't apply, since | ||
| 21858 | the surrounding code takes special precautions to keep it safe. | ||
| 21859 | |||
| 21860 | That doesn't matter for events from displays other than the | ||
| 21861 | display of the drag-and-drop operation, though. */ | ||
| 21862 | if (!x_dnd_unwind_flag | ||
| 21863 | && ((x_dnd_in_progress | ||
| 21864 | && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame)) | ||
| 21865 | || (x_dnd_waiting_for_finish | ||
| 21866 | && dpyinfo->display == x_dnd_finish_display))) | ||
| 19616 | return 0; | 21867 | return 0; |
| 19617 | 21868 | ||
| 19618 | block_input (); | 21869 | block_input (); |
| @@ -20129,70 +22380,131 @@ x_text_icon (struct frame *f, const char *icon_name) | |||
| 20129 | return false; | 22380 | return false; |
| 20130 | } | 22381 | } |
| 20131 | 22382 | ||
| 20132 | #define X_ERROR_MESSAGE_SIZE 200 | ||
| 20133 | |||
| 20134 | /* If non-nil, this should be a string. | ||
| 20135 | It means catch X errors and store the error message in this string. | ||
| 20136 | 22383 | ||
| 20137 | The reason we use a stack is that x_catch_error/x_uncatch_error can | 22384 | struct x_error_message_stack |
| 20138 | be called from a signal handler. | 22385 | { |
| 20139 | */ | 22386 | /* Pointer to the error message of any error that was generated, or |
| 22387 | NULL. */ | ||
| 22388 | char *string; | ||
| 20140 | 22389 | ||
| 20141 | struct x_error_message_stack { | 22390 | /* The display this error handler applies to. */ |
| 20142 | char string[X_ERROR_MESSAGE_SIZE]; | ||
| 20143 | Display *dpy; | 22391 | Display *dpy; |
| 22392 | |||
| 22393 | /* A function to call upon an error if non-NULL. */ | ||
| 20144 | x_special_error_handler handler; | 22394 | x_special_error_handler handler; |
| 22395 | |||
| 22396 | /* Some data to pass to that handler function. */ | ||
| 20145 | void *handler_data; | 22397 | void *handler_data; |
| 22398 | |||
| 22399 | /* The previous handler in this stack. */ | ||
| 20146 | struct x_error_message_stack *prev; | 22400 | struct x_error_message_stack *prev; |
| 22401 | |||
| 22402 | /* The first request that this error handler applies to. Keeping | ||
| 22403 | track of this allows us to avoid an XSync yet still have errors | ||
| 22404 | for previously made requests be handled correctly. */ | ||
| 22405 | unsigned long first_request; | ||
| 20147 | }; | 22406 | }; |
| 22407 | |||
| 22408 | /* Stack of X error message handlers. Whenever an error is generated | ||
| 22409 | on a display, look in this stack for an appropriate error handler, | ||
| 22410 | set its `string' to the error message and call its `handler' with | ||
| 22411 | `handler_data'. If no handler applies to the error, don't catch | ||
| 22412 | it, and let it crash Emacs instead. | ||
| 22413 | |||
| 22414 | This used to be a pointer to a string in which any error would be | ||
| 22415 | placed before 2006. */ | ||
| 20148 | static struct x_error_message_stack *x_error_message; | 22416 | static struct x_error_message_stack *x_error_message; |
| 20149 | 22417 | ||
| 20150 | /* An X error handler which stores the error message in | 22418 | /* The amount of items (depth) in that stack. */ |
| 20151 | *x_error_message. This is called from x_error_handler if | 22419 | int x_error_message_count; |
| 20152 | x_catch_errors is in effect. */ | 22420 | |
| 22421 | static struct x_error_message_stack * | ||
| 22422 | x_find_error_handler (Display *dpy, XErrorEvent *event) | ||
| 22423 | { | ||
| 22424 | struct x_error_message_stack *stack; | ||
| 22425 | |||
| 22426 | stack = x_error_message; | ||
| 22427 | |||
| 22428 | while (stack) | ||
| 22429 | { | ||
| 22430 | if (X_COMPARE_SERIALS (event->serial, >=, | ||
| 22431 | stack->first_request) | ||
| 22432 | && dpy == stack->dpy) | ||
| 22433 | return stack; | ||
| 22434 | |||
| 22435 | stack = stack->prev; | ||
| 22436 | } | ||
| 22437 | |||
| 22438 | return NULL; | ||
| 22439 | } | ||
| 22440 | |||
| 22441 | void | ||
| 22442 | x_unwind_errors_to (int depth) | ||
| 22443 | { | ||
| 22444 | while (x_error_message_count > depth) | ||
| 22445 | /* This is safe to call because we check whether or not | ||
| 22446 | x_error_message->dpy is still alive before calling XSync. */ | ||
| 22447 | x_uncatch_errors (); | ||
| 22448 | } | ||
| 22449 | |||
| 22450 | #define X_ERROR_MESSAGE_SIZE 200 | ||
| 22451 | |||
| 22452 | /* An X error handler which stores the error message in the first | ||
| 22453 | applicable handler in the x_error_message stack. This is called | ||
| 22454 | from *x_error_handler if an x_catch_errors for DISPLAY is in | ||
| 22455 | effect. */ | ||
| 20153 | 22456 | ||
| 20154 | static void | 22457 | static void |
| 20155 | x_error_catcher (Display *display, XErrorEvent *event) | 22458 | x_error_catcher (Display *display, XErrorEvent *event, |
| 22459 | struct x_error_message_stack *stack) | ||
| 20156 | { | 22460 | { |
| 22461 | char buf[X_ERROR_MESSAGE_SIZE]; | ||
| 22462 | |||
| 20157 | XGetErrorText (display, event->error_code, | 22463 | XGetErrorText (display, event->error_code, |
| 20158 | x_error_message->string, | 22464 | buf, X_ERROR_MESSAGE_SIZE); |
| 20159 | X_ERROR_MESSAGE_SIZE); | 22465 | |
| 20160 | if (x_error_message->handler) | 22466 | if (stack->string) |
| 20161 | x_error_message->handler (display, event, x_error_message->string, | 22467 | xfree (stack->string); |
| 20162 | x_error_message->handler_data); | 22468 | |
| 22469 | stack->string = xstrdup (buf); | ||
| 22470 | |||
| 22471 | if (stack->handler) | ||
| 22472 | stack->handler (display, event, stack->string, | ||
| 22473 | stack->handler_data); | ||
| 20163 | } | 22474 | } |
| 20164 | 22475 | ||
| 20165 | /* Begin trapping X errors for display DPY. Actually we trap X errors | 22476 | /* Begin trapping X errors for display DPY. |
| 20166 | for all displays, but DPY should be the display you are actually | ||
| 20167 | operating on. | ||
| 20168 | 22477 | ||
| 20169 | After calling this function, X protocol errors no longer cause | 22478 | After calling this function, X protocol errors generated on DPY no |
| 20170 | Emacs to exit; instead, they are recorded in the string | 22479 | longer cause Emacs to exit; instead, they are recorded in an error |
| 20171 | stored in *x_error_message. | 22480 | handler pushed onto the stack `x_error_message'. |
| 20172 | 22481 | ||
| 20173 | Calling x_check_errors signals an Emacs error if an X error has | 22482 | Calling x_check_errors signals an Emacs error if an X error has |
| 20174 | occurred since the last call to x_catch_errors or x_check_errors. | 22483 | occurred since the last call to x_catch_errors or x_check_errors. |
| 20175 | 22484 | ||
| 20176 | Calling x_uncatch_errors resumes the normal error handling. | 22485 | Calling x_uncatch_errors resumes the normal error handling, |
| 20177 | Calling x_uncatch_errors_after_check is similar, but skips an XSync | 22486 | skipping an XSync if the last request made is known to have been |
| 20178 | to the server, and should be used only immediately after | 22487 | processed. Calling x_uncatch_errors_after_check is similar, but |
| 20179 | x_had_errors_p or x_check_errors. */ | 22488 | always skips an XSync to the server, and should be used only |
| 22489 | immediately after x_had_errors_p or x_check_errors, or when it is | ||
| 22490 | known that no requests have been made since the last x_catch_errors | ||
| 22491 | call for DPY. */ | ||
| 20180 | 22492 | ||
| 20181 | void | 22493 | void |
| 20182 | x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, | 22494 | x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, |
| 20183 | void *handler_data) | 22495 | void *handler_data) |
| 20184 | { | 22496 | { |
| 20185 | struct x_error_message_stack *data = xmalloc (sizeof *data); | 22497 | struct x_error_message_stack *data; |
| 20186 | |||
| 20187 | /* Make sure any errors from previous requests have been dealt with. */ | ||
| 20188 | XSync (dpy, False); | ||
| 20189 | 22498 | ||
| 22499 | data = xzalloc (sizeof *data); | ||
| 20190 | data->dpy = dpy; | 22500 | data->dpy = dpy; |
| 20191 | data->string[0] = 0; | ||
| 20192 | data->handler = handler; | 22501 | data->handler = handler; |
| 20193 | data->handler_data = handler_data; | 22502 | data->handler_data = handler_data; |
| 20194 | data->prev = x_error_message; | 22503 | data->prev = x_error_message; |
| 22504 | data->first_request = NextRequest (dpy); | ||
| 20195 | x_error_message = data; | 22505 | x_error_message = data; |
| 22506 | |||
| 22507 | ++x_error_message_count; | ||
| 20196 | } | 22508 | } |
| 20197 | 22509 | ||
| 20198 | void | 22510 | void |
| @@ -20216,12 +22528,14 @@ x_uncatch_errors_after_check (void) | |||
| 20216 | block_input (); | 22528 | block_input (); |
| 20217 | tmp = x_error_message; | 22529 | tmp = x_error_message; |
| 20218 | x_error_message = x_error_message->prev; | 22530 | x_error_message = x_error_message->prev; |
| 22531 | --x_error_message_count; | ||
| 22532 | if (tmp->string) | ||
| 22533 | xfree (tmp->string); | ||
| 20219 | xfree (tmp); | 22534 | xfree (tmp); |
| 20220 | unblock_input (); | 22535 | unblock_input (); |
| 20221 | } | 22536 | } |
| 20222 | 22537 | ||
| 20223 | /* Undo the last x_catch_errors call. | 22538 | /* Undo the last x_catch_errors call. */ |
| 20224 | DPY should be the display that was passed to x_catch_errors. */ | ||
| 20225 | 22539 | ||
| 20226 | void | 22540 | void |
| 20227 | x_uncatch_errors (void) | 22541 | x_uncatch_errors (void) |
| @@ -20239,11 +22553,22 @@ x_uncatch_errors (void) | |||
| 20239 | 22553 | ||
| 20240 | /* The display may have been closed before this function is called. | 22554 | /* The display may have been closed before this function is called. |
| 20241 | Check if it is still open before calling XSync. */ | 22555 | Check if it is still open before calling XSync. */ |
| 20242 | if (x_display_info_for_display (x_error_message->dpy) != 0) | 22556 | if (x_display_info_for_display (x_error_message->dpy) != 0 |
| 22557 | /* There is no point in making this extra sync if all requests | ||
| 22558 | are known to have been fully processed. */ | ||
| 22559 | && (LastKnownRequestProcessed (x_error_message->dpy) | ||
| 22560 | != NextRequest (x_error_message->dpy) - 1) | ||
| 22561 | /* Likewise if no request was made since the trap was | ||
| 22562 | installed. */ | ||
| 22563 | && (NextRequest (x_error_message->dpy) | ||
| 22564 | > x_error_message->first_request)) | ||
| 20243 | XSync (x_error_message->dpy, False); | 22565 | XSync (x_error_message->dpy, False); |
| 20244 | 22566 | ||
| 20245 | tmp = x_error_message; | 22567 | tmp = x_error_message; |
| 20246 | x_error_message = x_error_message->prev; | 22568 | x_error_message = x_error_message->prev; |
| 22569 | --x_error_message_count; | ||
| 22570 | if (tmp->string) | ||
| 22571 | xfree (tmp->string); | ||
| 20247 | xfree (tmp); | 22572 | xfree (tmp); |
| 20248 | unblock_input (); | 22573 | unblock_input (); |
| 20249 | } | 22574 | } |
| @@ -20255,36 +22580,64 @@ x_uncatch_errors (void) | |||
| 20255 | void | 22580 | void |
| 20256 | x_check_errors (Display *dpy, const char *format) | 22581 | x_check_errors (Display *dpy, const char *format) |
| 20257 | { | 22582 | { |
| 20258 | /* Make sure to catch any errors incurred so far. */ | 22583 | char *string; |
| 20259 | XSync (dpy, False); | 22584 | |
| 22585 | /* This shouldn't happen, since x_check_errors should be called | ||
| 22586 | immediately inside an x_catch_errors block. */ | ||
| 22587 | if (dpy != x_error_message->dpy) | ||
| 22588 | emacs_abort (); | ||
| 20260 | 22589 | ||
| 20261 | if (x_error_message->string[0]) | 22590 | /* There is no point in making this extra sync if all requests |
| 22591 | are known to have been fully processed. */ | ||
| 22592 | if ((LastKnownRequestProcessed (dpy) | ||
| 22593 | != NextRequest (dpy) - 1) | ||
| 22594 | && (NextRequest (dpy) | ||
| 22595 | > x_error_message->first_request)) | ||
| 22596 | XSync (dpy, False); | ||
| 22597 | |||
| 22598 | if (x_error_message->string) | ||
| 20262 | { | 22599 | { |
| 20263 | char string[X_ERROR_MESSAGE_SIZE]; | 22600 | string = alloca (strlen (x_error_message->string) + 1); |
| 20264 | memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE); | 22601 | strcpy (string, x_error_message->string); |
| 20265 | x_uncatch_errors (); | 22602 | |
| 20266 | error (format, string); | 22603 | error (format, string); |
| 20267 | } | 22604 | } |
| 20268 | } | 22605 | } |
| 20269 | 22606 | ||
| 20270 | /* Nonzero if we had any X protocol errors | 22607 | /* Nonzero if any X protocol errors were generated since the last call |
| 20271 | since we did x_catch_errors on DPY. */ | 22608 | to x_catch_errors on DPY. */ |
| 20272 | 22609 | ||
| 20273 | bool | 22610 | bool |
| 20274 | x_had_errors_p (Display *dpy) | 22611 | x_had_errors_p (Display *dpy) |
| 20275 | { | 22612 | { |
| 22613 | /* This shouldn't happen, since x_check_errors should be called | ||
| 22614 | immediately inside an x_catch_errors block. */ | ||
| 22615 | if (dpy != x_error_message->dpy) | ||
| 22616 | emacs_abort (); | ||
| 22617 | |||
| 20276 | /* Make sure to catch any errors incurred so far. */ | 22618 | /* Make sure to catch any errors incurred so far. */ |
| 20277 | XSync (dpy, False); | 22619 | if ((LastKnownRequestProcessed (dpy) |
| 22620 | != NextRequest (dpy) - 1) | ||
| 22621 | && (NextRequest (dpy) | ||
| 22622 | > x_error_message->first_request)) | ||
| 22623 | XSync (dpy, False); | ||
| 20278 | 22624 | ||
| 20279 | return x_error_message->string[0] != 0; | 22625 | return x_error_message->string; |
| 20280 | } | 22626 | } |
| 20281 | 22627 | ||
| 20282 | /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ | 22628 | /* Forget about any errors we have had, since we did x_catch_errors on |
| 22629 | DPY. */ | ||
| 20283 | 22630 | ||
| 20284 | void | 22631 | void |
| 20285 | x_clear_errors (Display *dpy) | 22632 | x_clear_errors (Display *dpy) |
| 20286 | { | 22633 | { |
| 20287 | x_error_message->string[0] = 0; | 22634 | /* This shouldn't happen, since x_check_errors should be called |
| 22635 | immediately inside an x_catch_errors block. */ | ||
| 22636 | if (dpy != x_error_message->dpy) | ||
| 22637 | emacs_abort (); | ||
| 22638 | |||
| 22639 | xfree (x_error_message->string); | ||
| 22640 | x_error_message->string = NULL; | ||
| 20288 | } | 22641 | } |
| 20289 | 22642 | ||
| 20290 | #if false | 22643 | #if false |
| @@ -20302,9 +22655,12 @@ x_fully_uncatch_errors (void) | |||
| 20302 | 22655 | ||
| 20303 | #if false | 22656 | #if false |
| 20304 | static unsigned int x_wire_count; | 22657 | static unsigned int x_wire_count; |
| 20305 | x_trace_wire (void) | 22658 | |
| 22659 | static int | ||
| 22660 | x_trace_wire (Display *dpy) | ||
| 20306 | { | 22661 | { |
| 20307 | fprintf (stderr, "Lib call: %d\n", ++x_wire_count); | 22662 | fprintf (stderr, "Lib call: %u\n", ++x_wire_count); |
| 22663 | return 0; | ||
| 20308 | } | 22664 | } |
| 20309 | #endif | 22665 | #endif |
| 20310 | 22666 | ||
| @@ -20344,63 +22700,64 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) | |||
| 20344 | 22700 | ||
| 20345 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) | 22701 | if (x_dnd_in_progress || x_dnd_waiting_for_finish) |
| 20346 | { | 22702 | { |
| 20347 | /* Handle display disconnect errors here because this function | 22703 | if (!ioerror) |
| 20348 | is not reentrant at this particular spot. */ | ||
| 20349 | io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler); | ||
| 20350 | |||
| 20351 | if (!sigsetjmp (x_dnd_disconnect_handler, 1) | ||
| 20352 | && x_dnd_in_progress | ||
| 20353 | && dpy != (x_dnd_waiting_for_finish | ||
| 20354 | ? x_dnd_finish_display | ||
| 20355 | : FRAME_X_DISPLAY (x_dnd_frame))) | ||
| 20356 | { | 22704 | { |
| 20357 | /* Clean up drag and drop if the drag frame's display isn't | 22705 | /* Handle display disconnect errors here because this function |
| 20358 | the one being disconnected. */ | 22706 | is not reentrant at this particular spot. */ |
| 20359 | f = x_dnd_frame; | 22707 | io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler); |
| 20360 | 22708 | ||
| 20361 | if (x_dnd_last_seen_window != None | 22709 | if (!!sigsetjmp (x_dnd_disconnect_handler, 1) |
| 20362 | && x_dnd_last_protocol_version != -1) | 22710 | && x_dnd_in_progress |
| 20363 | x_dnd_send_leave (x_dnd_frame, | 22711 | && dpy == (x_dnd_waiting_for_finish |
| 20364 | x_dnd_last_seen_window); | 22712 | ? x_dnd_finish_display |
| 20365 | else if (x_dnd_last_seen_window != None | 22713 | : FRAME_X_DISPLAY (x_dnd_frame))) |
| 20366 | && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) | ||
| 20367 | && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE | ||
| 20368 | && x_dnd_motif_setup_p) | ||
| 20369 | { | 22714 | { |
| 20370 | dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, | 22715 | /* Clean up drag and drop if the drag frame's display isn't |
| 20371 | XM_DRAG_REASON_DROP_START); | 22716 | the one being disconnected. */ |
| 20372 | dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; | 22717 | f = x_dnd_frame; |
| 20373 | dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time; | 22718 | |
| 20374 | dmsg.side_effects | 22719 | if (x_dnd_last_seen_window != None |
| 20375 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | 22720 | && x_dnd_last_protocol_version != -1) |
| 20376 | x_dnd_wanted_action), | 22721 | x_dnd_send_leave (x_dnd_frame, |
| 20377 | XM_DROP_SITE_VALID, | 22722 | x_dnd_last_seen_window); |
| 20378 | xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), | 22723 | else if (x_dnd_last_seen_window != None |
| 20379 | x_dnd_wanted_action), | 22724 | && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) |
| 20380 | XM_DROP_ACTION_DROP_CANCEL); | 22725 | && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE |
| 20381 | dmsg.x = 0; | 22726 | && x_dnd_motif_setup_p) |
| 20382 | dmsg.y = 0; | 22727 | { |
| 20383 | dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; | 22728 | dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, |
| 20384 | dmsg.source_window = FRAME_X_WINDOW (f); | 22729 | XM_DRAG_REASON_DROP_START); |
| 20385 | 22730 | dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; | |
| 20386 | x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, | 22731 | dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time; |
| 20387 | x_dnd_last_seen_window, 0); | 22732 | dmsg.side_effects |
| 20388 | xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), | 22733 | = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), |
| 20389 | x_dnd_last_seen_window, &dmsg); | 22734 | x_dnd_wanted_action), |
| 22735 | XM_DROP_SITE_VALID, x_dnd_motif_operations, | ||
| 22736 | XM_DROP_ACTION_DROP_CANCEL); | ||
| 22737 | dmsg.x = 0; | ||
| 22738 | dmsg.y = 0; | ||
| 22739 | dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; | ||
| 22740 | dmsg.source_window = FRAME_X_WINDOW (f); | ||
| 22741 | |||
| 22742 | x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, | ||
| 22743 | x_dnd_last_seen_window, 0); | ||
| 22744 | xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), | ||
| 22745 | x_dnd_last_seen_window, &dmsg); | ||
| 22746 | } | ||
| 20390 | } | 22747 | } |
| 22748 | |||
| 22749 | XSetIOErrorHandler (io_error_handler); | ||
| 20391 | } | 22750 | } |
| 20392 | 22751 | ||
| 20393 | XSetIOErrorHandler (io_error_handler); | ||
| 20394 | dpyinfo = x_display_info_for_display (dpy); | 22752 | dpyinfo = x_display_info_for_display (dpy); |
| 20395 | 22753 | ||
| 20396 | x_dnd_last_seen_window = None; | 22754 | x_dnd_last_seen_window = None; |
| 20397 | x_dnd_last_seen_toplevel = None; | 22755 | x_dnd_last_seen_toplevel = None; |
| 20398 | x_dnd_in_progress = false; | 22756 | x_dnd_in_progress = false; |
| 20399 | x_set_dnd_targets (NULL, 0); | ||
| 20400 | x_dnd_waiting_for_finish = false; | 22757 | x_dnd_waiting_for_finish = false; |
| 20401 | 22758 | ||
| 20402 | if (x_dnd_use_toplevels) | 22759 | if (x_dnd_use_toplevels) |
| 20403 | x_dnd_free_toplevels (); | 22760 | x_dnd_free_toplevels (!ioerror); |
| 20404 | 22761 | ||
| 20405 | x_dnd_return_frame_object = NULL; | 22762 | x_dnd_return_frame_object = NULL; |
| 20406 | x_dnd_movement_frame = NULL; | 22763 | x_dnd_movement_frame = NULL; |
| @@ -20417,6 +22774,12 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) | |||
| 20417 | dpyinfo->display = 0; | 22774 | dpyinfo->display = 0; |
| 20418 | } | 22775 | } |
| 20419 | 22776 | ||
| 22777 | /* delete_frame can still try to read async input (even though we | ||
| 22778 | tell pass `noelisp'), because looking up the `delete-before' | ||
| 22779 | parameter calls Fassq which then calls maybe_quit. So block | ||
| 22780 | input while deleting frames. */ | ||
| 22781 | block_input (); | ||
| 22782 | |||
| 20420 | /* First delete frames whose mini-buffers are on frames | 22783 | /* First delete frames whose mini-buffers are on frames |
| 20421 | that are on the dead display. */ | 22784 | that are on the dead display. */ |
| 20422 | FOR_EACH_FRAME (tail, frame) | 22785 | FOR_EACH_FRAME (tail, frame) |
| @@ -20481,6 +22844,8 @@ For details, see etc/PROBLEMS.\n", | |||
| 20481 | } | 22844 | } |
| 20482 | } | 22845 | } |
| 20483 | 22846 | ||
| 22847 | unblock_input (); | ||
| 22848 | |||
| 20484 | if (terminal_list == 0) | 22849 | if (terminal_list == 0) |
| 20485 | { | 22850 | { |
| 20486 | fprintf (stderr, "%s\n", error_msg); | 22851 | fprintf (stderr, "%s\n", error_msg); |
| @@ -20506,16 +22871,16 @@ static void x_error_quitter (Display *, XErrorEvent *); | |||
| 20506 | static int | 22871 | static int |
| 20507 | x_error_handler (Display *display, XErrorEvent *event) | 22872 | x_error_handler (Display *display, XErrorEvent *event) |
| 20508 | { | 22873 | { |
| 22874 | struct x_error_message_stack *stack; | ||
| 20509 | #ifdef HAVE_XINPUT2 | 22875 | #ifdef HAVE_XINPUT2 |
| 20510 | struct x_display_info *dpyinfo; | 22876 | struct x_display_info *dpyinfo; |
| 20511 | #endif | 22877 | #endif |
| 20512 | 22878 | ||
| 20513 | #if defined USE_GTK && defined HAVE_GTK3 | 22879 | #if defined USE_GTK && defined HAVE_GTK3 |
| 20514 | if ((event->error_code == BadMatch || event->error_code == BadWindow) | 22880 | if ((event->error_code == BadMatch |
| 22881 | || event->error_code == BadWindow) | ||
| 20515 | && event->request_code == X_SetInputFocus) | 22882 | && event->request_code == X_SetInputFocus) |
| 20516 | { | 22883 | return 0; |
| 20517 | return 0; | ||
| 20518 | } | ||
| 20519 | #endif | 22884 | #endif |
| 20520 | 22885 | ||
| 20521 | /* If we try to ungrab or grab a device that doesn't exist anymore | 22886 | /* If we try to ungrab or grab a device that doesn't exist anymore |
| @@ -20536,8 +22901,10 @@ x_error_handler (Display *display, XErrorEvent *event) | |||
| 20536 | return 0; | 22901 | return 0; |
| 20537 | #endif | 22902 | #endif |
| 20538 | 22903 | ||
| 20539 | if (x_error_message) | 22904 | stack = x_find_error_handler (display, event); |
| 20540 | x_error_catcher (display, event); | 22905 | |
| 22906 | if (stack) | ||
| 22907 | x_error_catcher (display, event, stack); | ||
| 20541 | else | 22908 | else |
| 20542 | x_error_quitter (display, event); | 22909 | x_error_quitter (display, event); |
| 20543 | return 0; | 22910 | return 0; |
| @@ -21043,17 +23410,16 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) | |||
| 21043 | https://freedesktop.org/wiki/Specifications/wm-spec/. */ | 23410 | https://freedesktop.org/wiki/Specifications/wm-spec/. */ |
| 21044 | 23411 | ||
| 21045 | bool | 23412 | bool |
| 21046 | x_wm_supports (struct frame *f, Atom want_atom) | 23413 | x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom) |
| 21047 | { | 23414 | { |
| 21048 | Atom actual_type; | 23415 | Atom actual_type; |
| 21049 | unsigned long actual_size, bytes_remaining; | 23416 | unsigned long actual_size, bytes_remaining; |
| 21050 | int i, rc, actual_format; | 23417 | int i, rc, actual_format; |
| 21051 | bool ret; | 23418 | bool ret; |
| 21052 | Window wmcheck_window; | 23419 | Window wmcheck_window; |
| 21053 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 21054 | Window target_window = dpyinfo->root_window; | 23420 | Window target_window = dpyinfo->root_window; |
| 21055 | int max_len = 65536; | 23421 | int max_len = 65536; |
| 21056 | Display *dpy = FRAME_X_DISPLAY (f); | 23422 | Display *dpy = dpyinfo->display; |
| 21057 | unsigned char *tmp_data = NULL; | 23423 | unsigned char *tmp_data = NULL; |
| 21058 | Atom target_type = XA_WINDOW; | 23424 | Atom target_type = XA_WINDOW; |
| 21059 | 23425 | ||
| @@ -21127,6 +23493,13 @@ x_wm_supports (struct frame *f, Atom want_atom) | |||
| 21127 | return ret; | 23493 | return ret; |
| 21128 | } | 23494 | } |
| 21129 | 23495 | ||
| 23496 | bool | ||
| 23497 | x_wm_supports (struct frame *f, Atom want_atom) | ||
| 23498 | { | ||
| 23499 | return x_wm_supports_1 (FRAME_DISPLAY_INFO (f), | ||
| 23500 | want_atom); | ||
| 23501 | } | ||
| 23502 | |||
| 21130 | static void | 23503 | static void |
| 21131 | set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value) | 23504 | set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value) |
| 21132 | { | 23505 | { |
| @@ -21289,15 +23662,20 @@ x_get_current_wm_state (struct frame *f, | |||
| 21289 | #ifdef USE_XCB | 23662 | #ifdef USE_XCB |
| 21290 | xcb_get_property_cookie_t prop_cookie; | 23663 | xcb_get_property_cookie_t prop_cookie; |
| 21291 | xcb_get_property_reply_t *prop; | 23664 | xcb_get_property_reply_t *prop; |
| 21292 | xcb_atom_t *reply_data UNINIT; | 23665 | typedef xcb_atom_t reply_data_object; |
| 21293 | #else | 23666 | #else |
| 21294 | Display *dpy = FRAME_X_DISPLAY (f); | 23667 | Display *dpy = FRAME_X_DISPLAY (f); |
| 21295 | unsigned long bytes_remaining; | 23668 | unsigned long bytes_remaining; |
| 21296 | int rc, actual_format; | 23669 | int rc, actual_format; |
| 21297 | Atom actual_type; | 23670 | Atom actual_type; |
| 21298 | unsigned char *tmp_data = NULL; | 23671 | unsigned char *tmp_data = NULL; |
| 21299 | Atom *reply_data UNINIT; | 23672 | typedef Atom reply_data_object; |
| 21300 | #endif | 23673 | #endif |
| 23674 | reply_data_object *reply_data; | ||
| 23675 | # if defined GCC_LINT || defined lint | ||
| 23676 | reply_data_object reply_data_dummy; | ||
| 23677 | reply_data = &reply_data_dummy; | ||
| 23678 | # endif | ||
| 21301 | 23679 | ||
| 21302 | *sticky = false; | 23680 | *sticky = false; |
| 21303 | *size_state = FULLSCREEN_NONE; | 23681 | *size_state = FULLSCREEN_NONE; |
| @@ -21648,7 +24026,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top) | |||
| 21648 | int adjusted_left; | 24026 | int adjusted_left; |
| 21649 | int adjusted_top; | 24027 | int adjusted_top; |
| 21650 | 24028 | ||
| 21651 | FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A; | 24029 | FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A; |
| 21652 | FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left; | 24030 | FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left; |
| 21653 | FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top; | 24031 | FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top; |
| 21654 | 24032 | ||
| @@ -21665,7 +24043,6 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top) | |||
| 21665 | else | 24043 | else |
| 21666 | /* It's a "Type B" window manager. We don't have to adjust the | 24044 | /* It's a "Type B" window manager. We don't have to adjust the |
| 21667 | frame's position. */ | 24045 | frame's position. */ |
| 21668 | |||
| 21669 | FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; | 24046 | FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; |
| 21670 | } | 24047 | } |
| 21671 | 24048 | ||
| @@ -21679,11 +24056,17 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top) | |||
| 21679 | static void | 24056 | static void |
| 21680 | x_sync_with_move (struct frame *f, int left, int top, bool fuzzy) | 24057 | x_sync_with_move (struct frame *f, int left, int top, bool fuzzy) |
| 21681 | { | 24058 | { |
| 21682 | int count = 0; | 24059 | sigset_t emptyset; |
| 24060 | int count, current_left, current_top; | ||
| 24061 | struct timespec fallback; | ||
| 24062 | |||
| 24063 | sigemptyset (&emptyset); | ||
| 24064 | count = 0; | ||
| 21683 | 24065 | ||
| 21684 | while (count++ < 50) | 24066 | while (count++ < 50) |
| 21685 | { | 24067 | { |
| 21686 | int current_left = 0, current_top = 0; | 24068 | current_left = 0; |
| 24069 | current_top = 0; | ||
| 21687 | 24070 | ||
| 21688 | /* In theory, this call to XSync only needs to happen once, but in | 24071 | /* In theory, this call to XSync only needs to happen once, but in |
| 21689 | practice, it doesn't seem to work, hence the need for the surrounding | 24072 | practice, it doesn't seem to work, hence the need for the surrounding |
| @@ -21708,7 +24091,14 @@ x_sync_with_move (struct frame *f, int left, int top, bool fuzzy) | |||
| 21708 | /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry | 24091 | /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry |
| 21709 | will then return up-to-date position info. */ | 24092 | will then return up-to-date position info. */ |
| 21710 | 24093 | ||
| 21711 | wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0); | 24094 | fallback = dtotimespec (0.5); |
| 24095 | |||
| 24096 | /* This will hang if input is blocked, so use pselect to wait | ||
| 24097 | instead. */ | ||
| 24098 | if (input_blocked_p ()) | ||
| 24099 | pselect (0, NULL, NULL, NULL, &fallback, &emptyset); | ||
| 24100 | else | ||
| 24101 | wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0); | ||
| 21712 | } | 24102 | } |
| 21713 | 24103 | ||
| 21714 | 24104 | ||
| @@ -22375,6 +24765,18 @@ x_make_frame_visible_invisible (struct frame *f, bool visible) | |||
| 22375 | x_make_frame_invisible (f); | 24765 | x_make_frame_invisible (f); |
| 22376 | } | 24766 | } |
| 22377 | 24767 | ||
| 24768 | Cursor | ||
| 24769 | x_create_font_cursor (struct x_display_info *dpyinfo, int glyph) | ||
| 24770 | { | ||
| 24771 | if (glyph <= 65535) | ||
| 24772 | return XCreateFontCursor (dpyinfo->display, glyph); | ||
| 24773 | |||
| 24774 | /* x-pointer-invisible cannot fit in CARD16, and thus cannot be any | ||
| 24775 | existing cursor. */ | ||
| 24776 | return make_invisible_cursor (dpyinfo); | ||
| 24777 | } | ||
| 24778 | |||
| 24779 | |||
| 22378 | /* Change window state from mapped to iconified. */ | 24780 | /* Change window state from mapped to iconified. */ |
| 22379 | 24781 | ||
| 22380 | void | 24782 | void |
| @@ -22462,6 +24864,10 @@ x_iconify_frame (struct frame *f) | |||
| 22462 | msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state; | 24864 | msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state; |
| 22463 | msg.xclient.format = 32; | 24865 | msg.xclient.format = 32; |
| 22464 | msg.xclient.data.l[0] = IconicState; | 24866 | msg.xclient.data.l[0] = IconicState; |
| 24867 | msg.xclient.data.l[1] = 0; | ||
| 24868 | msg.xclient.data.l[2] = 0; | ||
| 24869 | msg.xclient.data.l[3] = 0; | ||
| 24870 | msg.xclient.data.l[4] = 0; | ||
| 22465 | 24871 | ||
| 22466 | if (! XSendEvent (FRAME_X_DISPLAY (f), | 24872 | if (! XSendEvent (FRAME_X_DISPLAY (f), |
| 22467 | FRAME_DISPLAY_INFO (f)->root_window, | 24873 | FRAME_DISPLAY_INFO (f)->root_window, |
| @@ -22691,7 +25097,6 @@ x_destroy_window (struct frame *f) | |||
| 22691 | x_free_frame_resources (f); | 25097 | x_free_frame_resources (f); |
| 22692 | 25098 | ||
| 22693 | xfree (f->output_data.x->saved_menu_event); | 25099 | xfree (f->output_data.x->saved_menu_event); |
| 22694 | xfree (f->output_data.x); | ||
| 22695 | 25100 | ||
| 22696 | #ifdef HAVE_X_I18N | 25101 | #ifdef HAVE_X_I18N |
| 22697 | if (f->output_data.x->preedit_chars) | 25102 | if (f->output_data.x->preedit_chars) |
| @@ -22703,11 +25108,162 @@ x_destroy_window (struct frame *f) | |||
| 22703 | XFree (f->output_data.x->xi_masks); | 25108 | XFree (f->output_data.x->xi_masks); |
| 22704 | #endif | 25109 | #endif |
| 22705 | 25110 | ||
| 25111 | xfree (f->output_data.x); | ||
| 22706 | f->output_data.x = NULL; | 25112 | f->output_data.x = NULL; |
| 22707 | 25113 | ||
| 22708 | dpyinfo->reference_count--; | 25114 | dpyinfo->reference_count--; |
| 22709 | } | 25115 | } |
| 22710 | 25116 | ||
| 25117 | /* Intern NAME in DPYINFO, but check to see if the atom was already | ||
| 25118 | interned when the X connection was opened, and use that instead. | ||
| 25119 | |||
| 25120 | If PREDEFINED_ONLY, return None if the atom was not interned during | ||
| 25121 | connection setup or is predefined. */ | ||
| 25122 | Atom | ||
| 25123 | x_intern_cached_atom (struct x_display_info *dpyinfo, | ||
| 25124 | const char *name, bool predefined_only) | ||
| 25125 | { | ||
| 25126 | int i; | ||
| 25127 | char *ptr; | ||
| 25128 | Atom *atom; | ||
| 25129 | |||
| 25130 | /* Special atoms that depend on the screen number. */ | ||
| 25131 | char xsettings_atom_name[sizeof "_XSETTINGS_S%d" - 2 | ||
| 25132 | + INT_STRLEN_BOUND (int)]; | ||
| 25133 | char cm_atom_name[sizeof "_NET_WM_CM_S%d" - 2 | ||
| 25134 | + INT_STRLEN_BOUND (int)]; | ||
| 25135 | |||
| 25136 | sprintf (xsettings_atom_name, "_XSETTINGS_S%d", | ||
| 25137 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 25138 | sprintf (cm_atom_name, "_NET_WM_CM_S%d", | ||
| 25139 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 25140 | |||
| 25141 | if (!strcmp (name, xsettings_atom_name)) | ||
| 25142 | return dpyinfo->Xatom_xsettings_sel; | ||
| 25143 | |||
| 25144 | if (!strcmp (name, cm_atom_name)) | ||
| 25145 | return dpyinfo->Xatom_NET_WM_CM_Sn; | ||
| 25146 | |||
| 25147 | /* Now do some common predefined atoms. */ | ||
| 25148 | if (!strcmp (name, "PRIMARY")) | ||
| 25149 | return XA_PRIMARY; | ||
| 25150 | |||
| 25151 | if (!strcmp (name, "SECONDARY")) | ||
| 25152 | return XA_SECONDARY; | ||
| 25153 | |||
| 25154 | if (!strcmp (name, "STRING")) | ||
| 25155 | return XA_STRING; | ||
| 25156 | |||
| 25157 | if (!strcmp (name, "INTEGER")) | ||
| 25158 | return XA_INTEGER; | ||
| 25159 | |||
| 25160 | if (!strcmp (name, "ATOM")) | ||
| 25161 | return XA_ATOM; | ||
| 25162 | |||
| 25163 | if (!strcmp (name, "CARDINAL")) | ||
| 25164 | return XA_CARDINAL; | ||
| 25165 | |||
| 25166 | if (!strcmp (name, "WINDOW")) | ||
| 25167 | return XA_WINDOW; | ||
| 25168 | |||
| 25169 | for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) | ||
| 25170 | { | ||
| 25171 | ptr = (char *) dpyinfo; | ||
| 25172 | |||
| 25173 | if (!strcmp (x_atom_refs[i].name, name)) | ||
| 25174 | { | ||
| 25175 | atom = (Atom *) (ptr + x_atom_refs[i].offset); | ||
| 25176 | |||
| 25177 | return *atom; | ||
| 25178 | } | ||
| 25179 | } | ||
| 25180 | |||
| 25181 | if (predefined_only) | ||
| 25182 | return None; | ||
| 25183 | |||
| 25184 | return XInternAtom (dpyinfo->display, name, False); | ||
| 25185 | } | ||
| 25186 | |||
| 25187 | /* Get the name of ATOM, but try not to make a request to the X | ||
| 25188 | server. Whether or not a request to the X server happened is | ||
| 25189 | placed in NEED_SYNC. */ | ||
| 25190 | char * | ||
| 25191 | x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, | ||
| 25192 | bool *need_sync) | ||
| 25193 | { | ||
| 25194 | char *dpyinfo_pointer, *name, *value, *buffer; | ||
| 25195 | int i; | ||
| 25196 | Atom ref_atom; | ||
| 25197 | |||
| 25198 | dpyinfo_pointer = (char *) dpyinfo; | ||
| 25199 | value = NULL; | ||
| 25200 | |||
| 25201 | if (need_sync) | ||
| 25202 | *need_sync = false; | ||
| 25203 | |||
| 25204 | buffer = alloca (45 + INT_STRLEN_BOUND (int)); | ||
| 25205 | |||
| 25206 | switch (atom) | ||
| 25207 | { | ||
| 25208 | case XA_PRIMARY: | ||
| 25209 | return xstrdup ("PRIMARY"); | ||
| 25210 | |||
| 25211 | case XA_SECONDARY: | ||
| 25212 | return xstrdup ("SECONDARY"); | ||
| 25213 | |||
| 25214 | case XA_INTEGER: | ||
| 25215 | return xstrdup ("INTEGER"); | ||
| 25216 | |||
| 25217 | case XA_ATOM: | ||
| 25218 | return xstrdup ("ATOM"); | ||
| 25219 | |||
| 25220 | case XA_CARDINAL: | ||
| 25221 | return xstrdup ("CARDINAL"); | ||
| 25222 | |||
| 25223 | case XA_WINDOW: | ||
| 25224 | return xstrdup ("WINDOW"); | ||
| 25225 | |||
| 25226 | default: | ||
| 25227 | if (atom == dpyinfo->Xatom_xsettings_sel) | ||
| 25228 | { | ||
| 25229 | sprintf (buffer, "_XSETTINGS_S%d", | ||
| 25230 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 25231 | return xstrdup (buffer); | ||
| 25232 | } | ||
| 25233 | |||
| 25234 | if (atom == dpyinfo->Xatom_NET_WM_CM_Sn) | ||
| 25235 | { | ||
| 25236 | sprintf (buffer, "_NET_WM_CM_S%d", | ||
| 25237 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 25238 | return xstrdup (buffer); | ||
| 25239 | } | ||
| 25240 | |||
| 25241 | for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) | ||
| 25242 | { | ||
| 25243 | ref_atom = *(Atom *) (dpyinfo_pointer | ||
| 25244 | + x_atom_refs[i].offset); | ||
| 25245 | |||
| 25246 | if (atom == ref_atom) | ||
| 25247 | return xstrdup (x_atom_refs[i].name); | ||
| 25248 | } | ||
| 25249 | |||
| 25250 | name = XGetAtomName (dpyinfo->display, atom); | ||
| 25251 | |||
| 25252 | if (need_sync) | ||
| 25253 | *need_sync = true; | ||
| 25254 | |||
| 25255 | if (name) | ||
| 25256 | { | ||
| 25257 | value = xstrdup (name); | ||
| 25258 | XFree (name); | ||
| 25259 | } | ||
| 25260 | |||
| 25261 | break; | ||
| 25262 | } | ||
| 25263 | |||
| 25264 | return value; | ||
| 25265 | } | ||
| 25266 | |||
| 22711 | 25267 | ||
| 22712 | /* Setting window manager hints. */ | 25268 | /* Setting window manager hints. */ |
| 22713 | 25269 | ||
| @@ -23152,7 +25708,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23152 | #ifdef USE_XCB | 25708 | #ifdef USE_XCB |
| 23153 | xcb_connection_t *xcb_conn; | 25709 | xcb_connection_t *xcb_conn; |
| 23154 | #endif | 25710 | #endif |
| 23155 | char *cm_atom_sprintf; | 25711 | static char const cm_atom_fmt[] = "_NET_WM_CM_S%d"; |
| 25712 | char cm_atom_sprintf[sizeof cm_atom_fmt - 2 + INT_STRLEN_BOUND (int)]; | ||
| 25713 | #ifdef USE_GTK | ||
| 25714 | GdkDisplay *gdpy; | ||
| 25715 | GdkScreen *gscr; | ||
| 25716 | #endif | ||
| 23156 | 25717 | ||
| 23157 | block_input (); | 25718 | block_input (); |
| 23158 | 25719 | ||
| @@ -23314,6 +25875,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23314 | } | 25875 | } |
| 23315 | #endif | 25876 | #endif |
| 23316 | 25877 | ||
| 25878 | /* Select for structure events on the root window, since this allows | ||
| 25879 | us to record changes to the size of the screen. */ | ||
| 25880 | |||
| 25881 | XSelectInput (dpy, DefaultRootWindow (dpy), StructureNotifyMask); | ||
| 25882 | |||
| 23317 | /* We have definitely succeeded. Record the new connection. */ | 25883 | /* We have definitely succeeded. Record the new connection. */ |
| 23318 | 25884 | ||
| 23319 | dpyinfo = xzalloc (sizeof *dpyinfo); | 25885 | dpyinfo = xzalloc (sizeof *dpyinfo); |
| @@ -23332,7 +25898,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23332 | { | 25898 | { |
| 23333 | terminal->kboard = allocate_kboard (Qx); | 25899 | terminal->kboard = allocate_kboard (Qx); |
| 23334 | 25900 | ||
| 23335 | if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, Qunbound)) | 25901 | if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, |
| 25902 | Qunbound)) | ||
| 23336 | { | 25903 | { |
| 23337 | char *vendor = ServerVendor (dpy); | 25904 | char *vendor = ServerVendor (dpy); |
| 23338 | 25905 | ||
| @@ -23375,12 +25942,14 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23375 | dpyinfo->color_names_size = 256; | 25942 | dpyinfo->color_names_size = 256; |
| 23376 | dpyinfo->color_names = xzalloc (dpyinfo->color_names_size | 25943 | dpyinfo->color_names = xzalloc (dpyinfo->color_names_size |
| 23377 | * sizeof *dpyinfo->color_names); | 25944 | * sizeof *dpyinfo->color_names); |
| 25945 | dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size | ||
| 25946 | * sizeof *dpyinfo->color_names_length); | ||
| 23378 | 25947 | ||
| 23379 | /* Set the name of the terminal. */ | 25948 | /* Set the name of the terminal. */ |
| 23380 | terminal->name = xlispstrdup (display_name); | 25949 | terminal->name = xlispstrdup (display_name); |
| 23381 | 25950 | ||
| 23382 | #if false | 25951 | #if false |
| 23383 | XSetAfterFunction (x_current_display, x_trace_wire); | 25952 | XSetAfterFunction (dpyinfo->display, x_trace_wire); |
| 23384 | #endif | 25953 | #endif |
| 23385 | 25954 | ||
| 23386 | Lisp_Object system_name = Fsystem_name (); | 25955 | Lisp_Object system_name = Fsystem_name (); |
| @@ -23754,17 +26323,59 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23754 | ; | 26323 | ; |
| 23755 | #endif | 26324 | #endif |
| 23756 | 26325 | ||
| 26326 | #if defined HAVE_XRANDR || defined USE_GTK | ||
| 26327 | Lisp_Object term; | ||
| 26328 | |||
| 26329 | XSETTERMINAL (term, terminal); | ||
| 26330 | #endif | ||
| 26331 | |||
| 23757 | #ifdef HAVE_XRANDR | 26332 | #ifdef HAVE_XRANDR |
| 23758 | int xrr_event_base, xrr_error_base; | 26333 | dpyinfo->xrandr_supported_p |
| 23759 | bool xrr_ok = false; | 26334 | = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base, |
| 23760 | xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base); | 26335 | &dpyinfo->xrandr_error_base); |
| 23761 | if (xrr_ok) | 26336 | |
| 26337 | #ifndef USE_GTK | ||
| 26338 | dpyinfo->last_monitor_attributes_list = Qnil; | ||
| 26339 | #endif | ||
| 26340 | |||
| 26341 | if (dpyinfo->xrandr_supported_p) | ||
| 23762 | { | 26342 | { |
| 23763 | XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version, | 26343 | XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version, |
| 23764 | &dpyinfo->xrandr_minor_version); | 26344 | &dpyinfo->xrandr_minor_version); |
| 26345 | |||
| 26346 | #ifndef USE_GTK | ||
| 26347 | if (dpyinfo->xrandr_major_version == 1 | ||
| 26348 | && dpyinfo->xrandr_minor_version >= 2) | ||
| 26349 | { | ||
| 26350 | XRRSelectInput (dpyinfo->display, | ||
| 26351 | dpyinfo->root_window, | ||
| 26352 | (RRScreenChangeNotifyMask | ||
| 26353 | | RRCrtcChangeNotifyMask | ||
| 26354 | | RROutputChangeNotifyMask | ||
| 26355 | /* Emacs doesn't actually need this, but GTK | ||
| 26356 | selects for it when the display is | ||
| 26357 | initialized. */ | ||
| 26358 | | RROutputPropertyNotifyMask)); | ||
| 26359 | |||
| 26360 | dpyinfo->last_monitor_attributes_list | ||
| 26361 | = Fx_display_monitor_attributes_list (term); | ||
| 26362 | } | ||
| 26363 | #endif | ||
| 23765 | } | 26364 | } |
| 23766 | #endif | 26365 | #endif |
| 23767 | 26366 | ||
| 26367 | #ifdef USE_GTK | ||
| 26368 | dpyinfo->last_monitor_attributes_list | ||
| 26369 | = Fx_display_monitor_attributes_list (term); | ||
| 26370 | |||
| 26371 | gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); | ||
| 26372 | gscr = gdk_display_get_default_screen (gdpy); | ||
| 26373 | |||
| 26374 | g_signal_connect (G_OBJECT (gscr), "monitors-changed", | ||
| 26375 | G_CALLBACK (x_monitors_changed_cb), | ||
| 26376 | NULL); | ||
| 26377 | #endif | ||
| 26378 | |||
| 23768 | #ifdef HAVE_XKB | 26379 | #ifdef HAVE_XKB |
| 23769 | int xkb_major, xkb_minor, xkb_op, xkb_error_code; | 26380 | int xkb_major, xkb_minor, xkb_op, xkb_error_code; |
| 23770 | xkb_major = XkbMajorVersion; | 26381 | xkb_major = XkbMajorVersion; |
| @@ -23843,141 +26454,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23843 | dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm; | 26454 | dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm; |
| 23844 | } | 26455 | } |
| 23845 | 26456 | ||
| 23846 | { | 26457 | sprintf (cm_atom_sprintf, cm_atom_fmt, |
| 23847 | int n = snprintf (NULL, 0, "_NET_WM_CM_S%d", | 26458 | XScreenNumberOfScreen (dpyinfo->screen)); |
| 23848 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 23849 | cm_atom_sprintf = alloca (n + 1); | ||
| 23850 | |||
| 23851 | snprintf (cm_atom_sprintf, n + 1, "_NET_WM_CM_S%d", | ||
| 23852 | XScreenNumberOfScreen (dpyinfo->screen)); | ||
| 23853 | } | ||
| 23854 | 26459 | ||
| 23855 | { | 26460 | { |
| 23856 | static const struct | ||
| 23857 | { | ||
| 23858 | const char *name; | ||
| 23859 | int offset; | ||
| 23860 | } atom_refs[] = { | ||
| 23861 | #define ATOM_REFS_INIT(string, member) \ | ||
| 23862 | { string, offsetof (struct x_display_info, member) }, | ||
| 23863 | ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols) | ||
| 23864 | ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus) | ||
| 23865 | ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself) | ||
| 23866 | ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window) | ||
| 23867 | ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state) | ||
| 23868 | ATOM_REFS_INIT ("WM_STATE", Xatom_wm_state) | ||
| 23869 | ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied) | ||
| 23870 | ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved) | ||
| 23871 | ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader) | ||
| 23872 | ATOM_REFS_INIT ("WM_TRANSIENT_FOR", Xatom_wm_transient_for) | ||
| 23873 | ATOM_REFS_INIT ("Editres", Xatom_editres) | ||
| 23874 | ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD) | ||
| 23875 | ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP) | ||
| 23876 | ATOM_REFS_INIT ("TEXT", Xatom_TEXT) | ||
| 23877 | ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT) | ||
| 23878 | ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING) | ||
| 23879 | ATOM_REFS_INIT ("DELETE", Xatom_DELETE) | ||
| 23880 | ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE) | ||
| 23881 | ATOM_REFS_INIT ("INCR", Xatom_INCR) | ||
| 23882 | ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP) | ||
| 23883 | ATOM_REFS_INIT ("EMACS_SERVER_TIME_PROP", Xatom_EMACS_SERVER_TIME_PROP) | ||
| 23884 | ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS) | ||
| 23885 | ATOM_REFS_INIT ("NULL", Xatom_NULL) | ||
| 23886 | ATOM_REFS_INIT ("ATOM", Xatom_ATOM) | ||
| 23887 | ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR) | ||
| 23888 | ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) | ||
| 23889 | ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) | ||
| 23890 | ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS) | ||
| 23891 | /* For properties of font. */ | ||
| 23892 | ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE) | ||
| 23893 | ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH) | ||
| 23894 | ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET) | ||
| 23895 | ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE) | ||
| 23896 | ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT) | ||
| 23897 | /* Ghostscript support. */ | ||
| 23898 | ATOM_REFS_INIT ("DONE", Xatom_DONE) | ||
| 23899 | ATOM_REFS_INIT ("PAGE", Xatom_PAGE) | ||
| 23900 | ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) | ||
| 23901 | ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar) | ||
| 23902 | ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) | ||
| 23903 | /* EWMH */ | ||
| 23904 | ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) | ||
| 23905 | ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen) | ||
| 23906 | ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ", | ||
| 23907 | Xatom_net_wm_state_maximized_horz) | ||
| 23908 | ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT", | ||
| 23909 | Xatom_net_wm_state_maximized_vert) | ||
| 23910 | ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky) | ||
| 23911 | ATOM_REFS_INIT ("_NET_WM_STATE_SHADED", Xatom_net_wm_state_shaded) | ||
| 23912 | ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden) | ||
| 23913 | ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type) | ||
| 23914 | ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP", | ||
| 23915 | Xatom_net_window_type_tooltip) | ||
| 23916 | ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name) | ||
| 23917 | ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name) | ||
| 23918 | ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported) | ||
| 23919 | ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check) | ||
| 23920 | ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity) | ||
| 23921 | ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window) | ||
| 23922 | ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents) | ||
| 23923 | ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop) | ||
| 23924 | ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea) | ||
| 23925 | ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request) | ||
| 23926 | ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter) | ||
| 23927 | ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn) | ||
| 23928 | ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time) | ||
| 23929 | ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window) | ||
| 23930 | ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking) | ||
| 23931 | /* Session management */ | ||
| 23932 | ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) | ||
| 23933 | ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) | ||
| 23934 | ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) | ||
| 23935 | ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar) | ||
| 23936 | ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above) | ||
| 23937 | ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below) | ||
| 23938 | ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region) | ||
| 23939 | ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping) | ||
| 23940 | ATOM_REFS_INIT ("_NET_WM_PID", Xatom_net_wm_pid) | ||
| 23941 | #ifdef HAVE_XKB | ||
| 23942 | ATOM_REFS_INIT ("Meta", Xatom_Meta) | ||
| 23943 | ATOM_REFS_INIT ("Super", Xatom_Super) | ||
| 23944 | ATOM_REFS_INIT ("Hyper", Xatom_Hyper) | ||
| 23945 | ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock) | ||
| 23946 | ATOM_REFS_INIT ("Alt", Xatom_Alt) | ||
| 23947 | #endif | ||
| 23948 | /* DND source. */ | ||
| 23949 | ATOM_REFS_INIT ("XdndAware", Xatom_XdndAware) | ||
| 23950 | ATOM_REFS_INIT ("XdndSelection", Xatom_XdndSelection) | ||
| 23951 | ATOM_REFS_INIT ("XdndTypeList", Xatom_XdndTypeList) | ||
| 23952 | ATOM_REFS_INIT ("XdndActionCopy", Xatom_XdndActionCopy) | ||
| 23953 | ATOM_REFS_INIT ("XdndActionMove", Xatom_XdndActionMove) | ||
| 23954 | ATOM_REFS_INIT ("XdndActionLink", Xatom_XdndActionLink) | ||
| 23955 | ATOM_REFS_INIT ("XdndActionAsk", Xatom_XdndActionAsk) | ||
| 23956 | ATOM_REFS_INIT ("XdndActionPrivate", Xatom_XdndActionPrivate) | ||
| 23957 | ATOM_REFS_INIT ("XdndActionList", Xatom_XdndActionList) | ||
| 23958 | ATOM_REFS_INIT ("XdndActionDescription", Xatom_XdndActionDescription) | ||
| 23959 | ATOM_REFS_INIT ("XdndProxy", Xatom_XdndProxy) | ||
| 23960 | ATOM_REFS_INIT ("XdndEnter", Xatom_XdndEnter) | ||
| 23961 | ATOM_REFS_INIT ("XdndPosition", Xatom_XdndPosition) | ||
| 23962 | ATOM_REFS_INIT ("XdndStatus", Xatom_XdndStatus) | ||
| 23963 | ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave) | ||
| 23964 | ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop) | ||
| 23965 | ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished) | ||
| 23966 | /* Motif drop protocol support. */ | ||
| 23967 | ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW) | ||
| 23968 | ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS) | ||
| 23969 | ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE", | ||
| 23970 | Xatom_MOTIF_DRAG_AND_DROP_MESSAGE) | ||
| 23971 | ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO", | ||
| 23972 | Xatom_MOTIF_DRAG_INITIATOR_INFO) | ||
| 23973 | ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO", | ||
| 23974 | Xatom_MOTIF_DRAG_RECEIVER_INFO) | ||
| 23975 | ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS) | ||
| 23976 | ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE) | ||
| 23977 | }; | ||
| 23978 | |||
| 23979 | int i; | 26461 | int i; |
| 23980 | enum { atom_count = ARRAYELTS (atom_refs) }; | 26462 | enum { atom_count = ARRAYELTS (x_atom_refs) }; |
| 23981 | /* 1 for _XSETTINGS_SN. */ | 26463 | /* 1 for _XSETTINGS_SN. */ |
| 23982 | enum { total_atom_count = 2 + atom_count }; | 26464 | enum { total_atom_count = 2 + atom_count }; |
| 23983 | Atom atoms_return[total_atom_count]; | 26465 | Atom atoms_return[total_atom_count]; |
| @@ -23987,7 +26469,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23987 | + INT_STRLEN_BOUND (int)]; | 26469 | + INT_STRLEN_BOUND (int)]; |
| 23988 | 26470 | ||
| 23989 | for (i = 0; i < atom_count; i++) | 26471 | for (i = 0; i < atom_count; i++) |
| 23990 | atom_names[i] = (char *) atom_refs[i].name; | 26472 | atom_names[i] = (char *) x_atom_refs[i].name; |
| 23991 | 26473 | ||
| 23992 | /* Build _XSETTINGS_SN atom name. */ | 26474 | /* Build _XSETTINGS_SN atom name. */ |
| 23993 | sprintf (xsettings_atom_name, xsettings_fmt, | 26475 | sprintf (xsettings_atom_name, xsettings_fmt, |
| @@ -23999,7 +26481,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 23999 | False, atoms_return); | 26481 | False, atoms_return); |
| 24000 | 26482 | ||
| 24001 | for (i = 0; i < atom_count; i++) | 26483 | for (i = 0; i < atom_count; i++) |
| 24002 | *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i]; | 26484 | *(Atom *) ((char *) dpyinfo + x_atom_refs[i].offset) = atoms_return[i]; |
| 24003 | 26485 | ||
| 24004 | /* Manually copy last two atoms. */ | 26486 | /* Manually copy last two atoms. */ |
| 24005 | dpyinfo->Xatom_xsettings_sel = atoms_return[i]; | 26487 | dpyinfo->Xatom_xsettings_sel = atoms_return[i]; |
| @@ -24126,7 +26608,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 24126 | /* Only do this for the very first display in the Emacs session. | 26608 | /* Only do this for the very first display in the Emacs session. |
| 24127 | Ignore X session management when Emacs was first started on a | 26609 | Ignore X session management when Emacs was first started on a |
| 24128 | tty or started as a daemon. */ | 26610 | tty or started as a daemon. */ |
| 24129 | if (terminal->id == 1 && ! IS_DAEMON) | 26611 | if (!dpyinfo->next && ! IS_DAEMON) |
| 24130 | x_session_initialize (dpyinfo); | 26612 | x_session_initialize (dpyinfo); |
| 24131 | #endif | 26613 | #endif |
| 24132 | 26614 | ||
| @@ -24154,6 +26636,7 @@ x_delete_display (struct x_display_info *dpyinfo) | |||
| 24154 | struct terminal *t; | 26636 | struct terminal *t; |
| 24155 | struct color_name_cache_entry *color_entry, *next_color_entry; | 26637 | struct color_name_cache_entry *color_entry, *next_color_entry; |
| 24156 | int i; | 26638 | int i; |
| 26639 | struct x_selection_request_event *ie, *last, *temp; | ||
| 24157 | 26640 | ||
| 24158 | /* Close all frames and delete the generic struct terminal for this | 26641 | /* Close all frames and delete the generic struct terminal for this |
| 24159 | X display. */ | 26642 | X display. */ |
| @@ -24169,6 +26652,30 @@ x_delete_display (struct x_display_info *dpyinfo) | |||
| 24169 | break; | 26652 | break; |
| 24170 | } | 26653 | } |
| 24171 | 26654 | ||
| 26655 | /* Find any pending selection requests for this display and unchain | ||
| 26656 | them. */ | ||
| 26657 | |||
| 26658 | last = NULL; | ||
| 26659 | |||
| 26660 | for (ie = pending_selection_requests; ie; ie = ie->next) | ||
| 26661 | { | ||
| 26662 | again: | ||
| 26663 | |||
| 26664 | if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo) | ||
| 26665 | { | ||
| 26666 | if (last) | ||
| 26667 | last->next = ie->next; | ||
| 26668 | |||
| 26669 | temp = ie; | ||
| 26670 | ie = ie->next; | ||
| 26671 | xfree (temp); | ||
| 26672 | |||
| 26673 | goto again; | ||
| 26674 | } | ||
| 26675 | |||
| 26676 | last = ie; | ||
| 26677 | } | ||
| 26678 | |||
| 24172 | if (next_noop_dpyinfo == dpyinfo) | 26679 | if (next_noop_dpyinfo == dpyinfo) |
| 24173 | next_noop_dpyinfo = dpyinfo->next; | 26680 | next_noop_dpyinfo = dpyinfo->next; |
| 24174 | 26681 | ||
| @@ -24199,6 +26706,7 @@ x_delete_display (struct x_display_info *dpyinfo) | |||
| 24199 | } | 26706 | } |
| 24200 | 26707 | ||
| 24201 | xfree (dpyinfo->color_names); | 26708 | xfree (dpyinfo->color_names); |
| 26709 | xfree (dpyinfo->color_names_length); | ||
| 24202 | xfree (dpyinfo->x_id_name); | 26710 | xfree (dpyinfo->x_id_name); |
| 24203 | xfree (dpyinfo->x_dnd_atoms); | 26711 | xfree (dpyinfo->x_dnd_atoms); |
| 24204 | xfree (dpyinfo->color_cells); | 26712 | xfree (dpyinfo->color_cells); |
| @@ -24335,11 +26843,12 @@ x_delete_terminal (struct terminal *terminal) | |||
| 24335 | x_dnd_last_seen_window = None; | 26843 | x_dnd_last_seen_window = None; |
| 24336 | x_dnd_last_seen_toplevel = None; | 26844 | x_dnd_last_seen_toplevel = None; |
| 24337 | x_dnd_in_progress = false; | 26845 | x_dnd_in_progress = false; |
| 24338 | x_set_dnd_targets (NULL, 0); | ||
| 24339 | x_dnd_waiting_for_finish = false; | 26846 | x_dnd_waiting_for_finish = false; |
| 24340 | 26847 | ||
| 26848 | /* The display is going away, so there's no point in | ||
| 26849 | de-selecting for input on the DND toplevels. */ | ||
| 24341 | if (x_dnd_use_toplevels) | 26850 | if (x_dnd_use_toplevels) |
| 24342 | x_dnd_free_toplevels (); | 26851 | x_dnd_free_toplevels (false); |
| 24343 | 26852 | ||
| 24344 | x_dnd_return_frame_object = NULL; | 26853 | x_dnd_return_frame_object = NULL; |
| 24345 | x_dnd_movement_frame = NULL; | 26854 | x_dnd_movement_frame = NULL; |
| @@ -24576,7 +27085,8 @@ mark_xterm (void) | |||
| 24576 | mark_object (val); | 27085 | mark_object (val); |
| 24577 | } | 27086 | } |
| 24578 | 27087 | ||
| 24579 | #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS | 27088 | #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \ |
| 27089 | || defined HAVE_XRANDR || defined USE_GTK | ||
| 24580 | for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) | 27090 | for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) |
| 24581 | { | 27091 | { |
| 24582 | #ifdef HAVE_XINPUT2 | 27092 | #ifdef HAVE_XINPUT2 |
| @@ -24587,6 +27097,9 @@ mark_xterm (void) | |||
| 24587 | for (i = 0; i < dpyinfo->n_protected_windows; ++i) | 27097 | for (i = 0; i < dpyinfo->n_protected_windows; ++i) |
| 24588 | mark_object (dpyinfo->protected_windows[i]); | 27098 | mark_object (dpyinfo->protected_windows[i]); |
| 24589 | #endif | 27099 | #endif |
| 27100 | #if defined HAVE_XRANDR || defined USE_GTK | ||
| 27101 | mark_object (dpyinfo->last_monitor_attributes_list); | ||
| 27102 | #endif | ||
| 24590 | } | 27103 | } |
| 24591 | #endif | 27104 | #endif |
| 24592 | } | 27105 | } |
| @@ -24597,9 +27110,16 @@ syms_of_xterm (void) | |||
| 24597 | x_error_message = NULL; | 27110 | x_error_message = NULL; |
| 24598 | PDUMPER_IGNORE (x_error_message); | 27111 | PDUMPER_IGNORE (x_error_message); |
| 24599 | 27112 | ||
| 27113 | x_dnd_monitors = Qnil; | ||
| 27114 | staticpro (&x_dnd_monitors); | ||
| 27115 | |||
| 27116 | x_dnd_action_symbol = Qnil; | ||
| 27117 | staticpro (&x_dnd_action_symbol); | ||
| 27118 | |||
| 24600 | DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); | 27119 | DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); |
| 24601 | DEFSYM (Qlatin_1, "latin-1"); | 27120 | DEFSYM (Qlatin_1, "latin-1"); |
| 24602 | DEFSYM (Qnow, "now"); | 27121 | DEFSYM (Qnow, "now"); |
| 27122 | DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list"); | ||
| 24603 | 27123 | ||
| 24604 | #ifdef USE_GTK | 27124 | #ifdef USE_GTK |
| 24605 | xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); | 27125 | xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); |
| @@ -24637,9 +27157,21 @@ This variable is used only when the window manager requires that you | |||
| 24637 | click on a frame to select it (give it focus). In that case, a value | 27157 | click on a frame to select it (give it focus). In that case, a value |
| 24638 | of nil, means that the selected window and cursor position changes to | 27158 | of nil, means that the selected window and cursor position changes to |
| 24639 | reflect the mouse click position, while a non-nil value means that the | 27159 | reflect the mouse click position, while a non-nil value means that the |
| 24640 | selected window or cursor position is preserved. */); | 27160 | selected window or cursor position is preserved. |
| 27161 | |||
| 27162 | This option works by ignoring button press events for a given amount | ||
| 27163 | of time after a frame might've been focused. If it does not work for | ||
| 27164 | you, try increasing the value of | ||
| 27165 | `x-mouse-click-focus-ignore-time'. */); | ||
| 24641 | x_mouse_click_focus_ignore_position = false; | 27166 | x_mouse_click_focus_ignore_position = false; |
| 24642 | 27167 | ||
| 27168 | DEFVAR_INT ("x-mouse-click-focus-ignore-time", x_mouse_click_focus_ignore_time, | ||
| 27169 | doc: /* Number of miliseconds for which to ignore buttons after focus change. | ||
| 27170 | This variable only takes effect if | ||
| 27171 | `x-mouse-click-focus-ignore-position' is non-nil, and should be | ||
| 27172 | adjusted if the default value does not work for whatever reason. */); | ||
| 27173 | x_mouse_click_focus_ignore_time = 200; | ||
| 27174 | |||
| 24643 | DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, | 27175 | DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, |
| 24644 | doc: /* Which toolkit scroll bars Emacs uses, if any. | 27176 | doc: /* Which toolkit scroll bars Emacs uses, if any. |
| 24645 | A value of nil means Emacs doesn't use toolkit scroll bars. | 27177 | A value of nil means Emacs doesn't use toolkit scroll bars. |
| @@ -24791,6 +27323,13 @@ during a drag-and-drop session, to work around broken implementations | |||
| 24791 | of Motif. */); | 27323 | of Motif. */); |
| 24792 | x_dnd_fix_motif_leave = true; | 27324 | x_dnd_fix_motif_leave = true; |
| 24793 | 27325 | ||
| 27326 | DEFVAR_BOOL ("x-dnd-disable-motif-drag", x_dnd_disable_motif_drag, | ||
| 27327 | doc: /* Disable the Motif drag protocol during DND. | ||
| 27328 | This reduces network usage, but also means you can no longer scroll | ||
| 27329 | around inside the Motif window underneath the cursor during | ||
| 27330 | drag-and-drop. */); | ||
| 27331 | x_dnd_disable_motif_drag = false; | ||
| 27332 | |||
| 24794 | DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function, | 27333 | DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function, |
| 24795 | doc: /* Function called upon mouse movement on a frame during drag-and-drop. | 27334 | doc: /* Function called upon mouse movement on a frame during drag-and-drop. |
| 24796 | It should either be nil, or accept two arguments FRAME and POSITION, | 27335 | It should either be nil, or accept two arguments FRAME and POSITION, |
| @@ -24800,16 +27339,41 @@ mouse position list. */); | |||
| 24800 | 27339 | ||
| 24801 | DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, | 27340 | DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, |
| 24802 | doc: /* Function called when trying to drop on an unsupported window. | 27341 | doc: /* Function called when trying to drop on an unsupported window. |
| 24803 | This function is called whenever the user tries to drop | 27342 | This function is called whenever the user tries to drop something on a |
| 24804 | something on a window that does not support either the XDND or | 27343 | window that does not support either the XDND or Motif protocols for |
| 24805 | Motif protocols for drag-and-drop. It should return a non-nil | 27344 | drag-and-drop. It should return a non-nil value if the drop was |
| 24806 | value if the drop was handled by the function, and nil if it was | 27345 | handled by the function, and nil if it was not. It should accept |
| 24807 | not. It should accept several arguments TARGETS, X, Y, ACTION, | 27346 | several arguments TARGETS, X, Y, ACTION, WINDOW-ID, FRAME and TIME, |
| 24808 | WINDOW-ID and FRAME, where TARGETS is the list of targets that | 27347 | where TARGETS is the list of targets that was passed to |
| 24809 | was passed to `x-begin-drag', WINDOW-ID is the numeric XID of | 27348 | `x-begin-drag', WINDOW-ID is the numeric XID of the window that is |
| 24810 | the window that is being dropped on, X and Y are the root | 27349 | being dropped on, X and Y are the root window-relative coordinates |
| 24811 | window-relative coordinates where the drop happened, ACTION | 27350 | where the drop happened, ACTION is the action that was passed to |
| 24812 | is the action that was passed to `x-begin-drag', and FRAME is | 27351 | `x-begin-drag', FRAME is the frame which initiated the drag-and-drop |
| 24813 | the frame which initiated the drag-and-drop operation. */); | 27352 | operation, and TIME is the X server time when the drop happened. */); |
| 24814 | Vx_dnd_unsupported_drop_function = Qnil; | 27353 | Vx_dnd_unsupported_drop_function = Qnil; |
| 27354 | |||
| 27355 | DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size, | ||
| 27356 | doc: /* Max number of buckets allowed per display in the internal color cache. | ||
| 27357 | Values less than 1 mean 128. This option is for debugging only. */); | ||
| 27358 | x_color_cache_bucket_size = 128; | ||
| 27359 | |||
| 27360 | DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list, | ||
| 27361 | doc: /* List of drag-and-drop targets. | ||
| 27362 | This variable contains the list of drag-and-drop selection targets | ||
| 27363 | during a drag-and-drop operation, in the same format as the TARGET | ||
| 27364 | argument to `x-begin-drag'. */); | ||
| 27365 | Vx_dnd_targets_list = Qnil; | ||
| 27366 | |||
| 27367 | DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function, | ||
| 27368 | doc: /* Function that determines return value of drag-and-drop on Emacs frames. | ||
| 27369 | If the value is a function, `x-begin-drag' will call it with two | ||
| 27370 | arguments, POS and ACTION, where POS is a mouse position list | ||
| 27371 | that specifies the location of the drop, and ACTION is the | ||
| 27372 | action specified by the caller of `x-begin-drag'. The function | ||
| 27373 | should return a symbol describing what to return from | ||
| 27374 | `x-begin-drag' if the drop happens on an Emacs frame. | ||
| 27375 | |||
| 27376 | If the value is nil, or the function returns a value that is not | ||
| 27377 | a symbol, a drop on an Emacs frame will be canceled. */); | ||
| 27378 | Vx_dnd_native_test_function = Qnil; | ||
| 24815 | } | 27379 | } |
diff --git a/src/xterm.h b/src/xterm.h index 3e06564bee9..82b4308041a 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -196,8 +196,15 @@ extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap); | |||
| 196 | struct color_name_cache_entry | 196 | struct color_name_cache_entry |
| 197 | { | 197 | { |
| 198 | struct color_name_cache_entry *next; | 198 | struct color_name_cache_entry *next; |
| 199 | |||
| 200 | /* The color values of the cached color entry. */ | ||
| 199 | XColor rgb; | 201 | XColor rgb; |
| 202 | |||
| 203 | /* The name of the cached color. */ | ||
| 200 | char *name; | 204 | char *name; |
| 205 | |||
| 206 | /* Whether or not RGB is valid (i.e. the color actually exists). */ | ||
| 207 | bool_bf valid : 1; | ||
| 201 | }; | 208 | }; |
| 202 | 209 | ||
| 203 | #ifdef HAVE_XINPUT2 | 210 | #ifdef HAVE_XINPUT2 |
| @@ -513,6 +520,9 @@ struct x_display_info | |||
| 513 | /* A cache mapping color names to RGB values. */ | 520 | /* A cache mapping color names to RGB values. */ |
| 514 | struct color_name_cache_entry **color_names; | 521 | struct color_name_cache_entry **color_names; |
| 515 | 522 | ||
| 523 | /* The number of buckets for each hash in that hash table. */ | ||
| 524 | ptrdiff_t *color_names_length; | ||
| 525 | |||
| 516 | /* The size of that hash table. */ | 526 | /* The size of that hash table. */ |
| 517 | int color_names_size; | 527 | int color_names_size; |
| 518 | 528 | ||
| @@ -595,10 +605,19 @@ struct x_display_info | |||
| 595 | XModifierKeymap *modmap; | 605 | XModifierKeymap *modmap; |
| 596 | 606 | ||
| 597 | #ifdef HAVE_XRANDR | 607 | #ifdef HAVE_XRANDR |
| 608 | bool xrandr_supported_p; | ||
| 609 | int xrandr_event_base; | ||
| 610 | int xrandr_error_base; | ||
| 598 | int xrandr_major_version; | 611 | int xrandr_major_version; |
| 599 | int xrandr_minor_version; | 612 | int xrandr_minor_version; |
| 600 | #endif | 613 | #endif |
| 601 | 614 | ||
| 615 | #if defined HAVE_XRANDR || defined USE_GTK | ||
| 616 | /* This is used to determine if the monitor configuration really | ||
| 617 | changed upon receiving a monitor change event. */ | ||
| 618 | Lisp_Object last_monitor_attributes_list; | ||
| 619 | #endif | ||
| 620 | |||
| 602 | #if defined USE_CAIRO || defined HAVE_XRENDER | 621 | #if defined USE_CAIRO || defined HAVE_XRENDER |
| 603 | XExtCodes *ext_codes; | 622 | XExtCodes *ext_codes; |
| 604 | #endif | 623 | #endif |
| @@ -683,6 +702,17 @@ struct x_display_info | |||
| 683 | int n_protected_windows; | 702 | int n_protected_windows; |
| 684 | int protected_windows_max; | 703 | int protected_windows_max; |
| 685 | #endif | 704 | #endif |
| 705 | |||
| 706 | /* The current dimensions of the screen. This is updated when a | ||
| 707 | ConfigureNotify is received for the root window, and is zero if | ||
| 708 | that didn't happen. */ | ||
| 709 | int screen_width; | ||
| 710 | int screen_height; | ||
| 711 | |||
| 712 | /* The mm width and height of the screen. Updated on | ||
| 713 | RRScreenChangeNotify. */ | ||
| 714 | int screen_mm_width; | ||
| 715 | int screen_mm_height; | ||
| 686 | }; | 716 | }; |
| 687 | 717 | ||
| 688 | #ifdef HAVE_X_I18N | 718 | #ifdef HAVE_X_I18N |
| @@ -706,6 +736,9 @@ extern bool x_display_ok (const char *); | |||
| 706 | extern void select_visual (struct x_display_info *); | 736 | extern void select_visual (struct x_display_info *); |
| 707 | 737 | ||
| 708 | extern Window tip_window; | 738 | extern Window tip_window; |
| 739 | extern Lisp_Object tip_dx; | ||
| 740 | extern Lisp_Object tip_dy; | ||
| 741 | extern Lisp_Object tip_frame; | ||
| 709 | 742 | ||
| 710 | /* Each X frame object points to its own struct x_output object | 743 | /* Each X frame object points to its own struct x_output object |
| 711 | in the output_data.x field. The x_output structure contains | 744 | in the output_data.x field. The x_output structure contains |
| @@ -925,6 +958,10 @@ struct x_output | |||
| 925 | false, tell Xt not to wait. */ | 958 | false, tell Xt not to wait. */ |
| 926 | bool_bf wait_for_wm : 1; | 959 | bool_bf wait_for_wm : 1; |
| 927 | 960 | ||
| 961 | /* True if this frame's alpha value is the same for both the active | ||
| 962 | and inactive states. */ | ||
| 963 | bool_bf alpha_identical_p : 1; | ||
| 964 | |||
| 928 | #ifdef HAVE_X_I18N | 965 | #ifdef HAVE_X_I18N |
| 929 | /* Input context (currently, this means Compose key handler setup). */ | 966 | /* Input context (currently, this means Compose key handler setup). */ |
| 930 | XIC xic; | 967 | XIC xic; |
| @@ -1352,8 +1389,8 @@ extern const char *x_get_string_resource (void *, const char *, const char *); | |||
| 1352 | 1389 | ||
| 1353 | /* Defined in xterm.c */ | 1390 | /* Defined in xterm.c */ |
| 1354 | 1391 | ||
| 1355 | typedef void (*x_special_error_handler)(Display *, XErrorEvent *, char *, | 1392 | typedef void (*x_special_error_handler) (Display *, XErrorEvent *, char *, |
| 1356 | void *); | 1393 | void *); |
| 1357 | 1394 | ||
| 1358 | extern bool x_text_icon (struct frame *, const char *); | 1395 | extern bool x_text_icon (struct frame *, const char *); |
| 1359 | extern void x_catch_errors (Display *); | 1396 | extern void x_catch_errors (Display *); |
| @@ -1362,6 +1399,7 @@ extern void x_catch_errors_with_handler (Display *, x_special_error_handler, | |||
| 1362 | extern void x_check_errors (Display *, const char *) | 1399 | extern void x_check_errors (Display *, const char *) |
| 1363 | ATTRIBUTE_FORMAT_PRINTF (2, 0); | 1400 | ATTRIBUTE_FORMAT_PRINTF (2, 0); |
| 1364 | extern bool x_had_errors_p (Display *); | 1401 | extern bool x_had_errors_p (Display *); |
| 1402 | extern void x_unwind_errors_to (int); | ||
| 1365 | extern void x_uncatch_errors (void); | 1403 | extern void x_uncatch_errors (void); |
| 1366 | extern void x_uncatch_errors_after_check (void); | 1404 | extern void x_uncatch_errors_after_check (void); |
| 1367 | extern void x_clear_errors (Display *); | 1405 | extern void x_clear_errors (Display *); |
| @@ -1372,7 +1410,8 @@ extern void x_iconify_frame (struct frame *f); | |||
| 1372 | extern void x_free_frame_resources (struct frame *); | 1410 | extern void x_free_frame_resources (struct frame *); |
| 1373 | extern void x_wm_set_size_hint (struct frame *, long, bool); | 1411 | extern void x_wm_set_size_hint (struct frame *, long, bool); |
| 1374 | 1412 | ||
| 1375 | extern void x_delete_terminal (struct terminal *terminal); | 1413 | extern void x_delete_terminal (struct terminal *); |
| 1414 | extern Cursor x_create_font_cursor (struct x_display_info *, int); | ||
| 1376 | extern unsigned long x_copy_color (struct frame *, unsigned long); | 1415 | extern unsigned long x_copy_color (struct frame *, unsigned long); |
| 1377 | #ifdef USE_X_TOOLKIT | 1416 | #ifdef USE_X_TOOLKIT |
| 1378 | extern XtAppContext Xt_app_con; | 1417 | extern XtAppContext Xt_app_con; |
| @@ -1390,6 +1429,7 @@ extern void x_clear_area (struct frame *f, int, int, int, int); | |||
| 1390 | || (!defined USE_X_TOOLKIT && !defined USE_GTK) | 1429 | || (!defined USE_X_TOOLKIT && !defined USE_GTK) |
| 1391 | extern void x_mouse_leave (struct x_display_info *); | 1430 | extern void x_mouse_leave (struct x_display_info *); |
| 1392 | #endif | 1431 | #endif |
| 1432 | extern void x_wait_for_cell_change (Lisp_Object, struct timespec); | ||
| 1393 | 1433 | ||
| 1394 | #ifndef USE_GTK | 1434 | #ifndef USE_GTK |
| 1395 | extern int x_dispatch_event (XEvent *, Display *); | 1435 | extern int x_dispatch_event (XEvent *, Display *); |
| @@ -1419,25 +1459,24 @@ extern void x_xr_reset_ext_clip (struct frame *f); | |||
| 1419 | extern void x_scroll_bar_configure (GdkEvent *); | 1459 | extern void x_scroll_bar_configure (GdkEvent *); |
| 1420 | #endif | 1460 | #endif |
| 1421 | 1461 | ||
| 1462 | #define DEFER_SELECTIONS \ | ||
| 1463 | x_defer_selection_requests (); \ | ||
| 1464 | record_unwind_protect_void (x_release_selection_requests_and_flush) | ||
| 1465 | |||
| 1466 | extern void x_defer_selection_requests (void); | ||
| 1467 | extern void x_release_selection_requests_and_flush (void); | ||
| 1468 | extern void x_handle_pending_selection_requests (void); | ||
| 1469 | extern bool x_detect_pending_selection_requests (void); | ||
| 1422 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, | 1470 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, |
| 1423 | Lisp_Object, Atom *, const char **, | 1471 | Lisp_Object, Atom *, const char **, |
| 1424 | size_t, bool); | 1472 | size_t, bool, Atom *, int, |
| 1473 | Lisp_Object, bool); | ||
| 1425 | extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object, | 1474 | extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object, |
| 1426 | Lisp_Object, Lisp_Object, Window, int, | 1475 | Lisp_Object, Lisp_Object, Window, int, |
| 1427 | int, Time); | 1476 | int, Time); |
| 1428 | extern void x_set_dnd_targets (Atom *, int); | ||
| 1429 | |||
| 1430 | INLINE int | ||
| 1431 | x_display_pixel_height (struct x_display_info *dpyinfo) | ||
| 1432 | { | ||
| 1433 | return HeightOfScreen (dpyinfo->screen); | ||
| 1434 | } | ||
| 1435 | 1477 | ||
| 1436 | INLINE int | 1478 | extern int x_display_pixel_height (struct x_display_info *); |
| 1437 | x_display_pixel_width (struct x_display_info *dpyinfo) | 1479 | extern int x_display_pixel_width (struct x_display_info *); |
| 1438 | { | ||
| 1439 | return WidthOfScreen (dpyinfo->screen); | ||
| 1440 | } | ||
| 1441 | 1480 | ||
| 1442 | INLINE unsigned long | 1481 | INLINE unsigned long |
| 1443 | x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) | 1482 | x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) |
| @@ -1471,6 +1510,7 @@ extern void x_set_shaded (struct frame *, Lisp_Object, Lisp_Object); | |||
| 1471 | extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object); | 1510 | extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object); |
| 1472 | extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object); | 1511 | extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object); |
| 1473 | extern bool x_wm_supports (struct frame *, Atom); | 1512 | extern bool x_wm_supports (struct frame *, Atom); |
| 1513 | extern bool x_wm_supports_1 (struct x_display_info *, Atom); | ||
| 1474 | extern void x_wait_for_event (struct frame *, int); | 1514 | extern void x_wait_for_event (struct frame *, int); |
| 1475 | extern void x_clear_under_internal_border (struct frame *f); | 1515 | extern void x_clear_under_internal_border (struct frame *f); |
| 1476 | 1516 | ||
| @@ -1495,11 +1535,13 @@ extern void x_handle_property_notify (const XPropertyEvent *); | |||
| 1495 | extern void x_handle_selection_notify (const XSelectionEvent *); | 1535 | extern void x_handle_selection_notify (const XSelectionEvent *); |
| 1496 | extern void x_handle_selection_event (struct selection_input_event *); | 1536 | extern void x_handle_selection_event (struct selection_input_event *); |
| 1497 | extern void x_clear_frame_selections (struct frame *); | 1537 | extern void x_clear_frame_selections (struct frame *); |
| 1538 | extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); | ||
| 1498 | 1539 | ||
| 1499 | extern bool x_handle_dnd_message (struct frame *, | 1540 | extern bool x_handle_dnd_message (struct frame *, |
| 1500 | const XClientMessageEvent *, | 1541 | const XClientMessageEvent *, |
| 1501 | struct x_display_info *, | 1542 | struct x_display_info *, |
| 1502 | struct input_event *); | 1543 | struct input_event *, |
| 1544 | bool, int, int); | ||
| 1503 | extern int x_check_property_data (Lisp_Object); | 1545 | extern int x_check_property_data (Lisp_Object); |
| 1504 | extern void x_fill_property_data (Display *, | 1546 | extern void x_fill_property_data (Display *, |
| 1505 | Lisp_Object, | 1547 | Lisp_Object, |
| @@ -1518,6 +1560,10 @@ extern Lisp_Object x_timestamp_for_selection (struct x_display_info *, | |||
| 1518 | Lisp_Object); | 1560 | Lisp_Object); |
| 1519 | extern void x_set_pending_dnd_time (Time); | 1561 | extern void x_set_pending_dnd_time (Time); |
| 1520 | extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object); | 1562 | extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object); |
| 1563 | extern Atom x_intern_cached_atom (struct x_display_info *, const char *, | ||
| 1564 | bool); | ||
| 1565 | extern char *x_get_atom_name (struct x_display_info *, Atom, bool *) | ||
| 1566 | ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE; | ||
| 1521 | 1567 | ||
| 1522 | #ifdef USE_GTK | 1568 | #ifdef USE_GTK |
| 1523 | extern bool xg_set_icon (struct frame *, Lisp_Object); | 1569 | extern bool xg_set_icon (struct frame *, Lisp_Object); |
| @@ -1578,7 +1624,11 @@ extern struct input_event xg_pending_quit_event; | |||
| 1578 | #endif | 1624 | #endif |
| 1579 | 1625 | ||
| 1580 | extern bool x_dnd_in_progress; | 1626 | extern bool x_dnd_in_progress; |
| 1627 | extern bool x_dnd_waiting_for_finish; | ||
| 1581 | extern struct frame *x_dnd_frame; | 1628 | extern struct frame *x_dnd_frame; |
| 1629 | extern struct frame *x_dnd_finish_frame; | ||
| 1630 | extern unsigned x_dnd_unsupported_event_level; | ||
| 1631 | extern int x_error_message_count; | ||
| 1582 | 1632 | ||
| 1583 | #ifdef HAVE_XINPUT2 | 1633 | #ifdef HAVE_XINPUT2 |
| 1584 | extern struct xi_device_t *xi_device_from_id (struct x_display_info *, int); | 1634 | extern struct xi_device_t *xi_device_from_id (struct x_display_info *, int); |