diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog.13 | 4 | ||||
-rw-r--r-- | src/dired.c | 5 | ||||
-rw-r--r-- | src/editfns.c | 13 | ||||
-rw-r--r-- | src/fileio.c | 5 | ||||
-rw-r--r-- | src/fns.c | 41 | ||||
-rw-r--r-- | src/frame.c | 28 | ||||
-rw-r--r-- | src/lisp.h | 15 | ||||
-rw-r--r-- | src/minibuf.c | 12 | ||||
-rw-r--r-- | src/nsterm.m | 23 | ||||
-rw-r--r-- | src/pdumper.c | 2 | ||||
-rw-r--r-- | src/sqlite.c | 173 | ||||
-rw-r--r-- | src/sysdep.c | 2 | ||||
-rw-r--r-- | src/widget.c | 42 | ||||
-rw-r--r-- | src/widget.h | 2 | ||||
-rw-r--r-- | src/widgetprv.h | 3 | ||||
-rw-r--r-- | src/window.c | 97 | ||||
-rw-r--r-- | src/xdisp.c | 15 | ||||
-rw-r--r-- | src/xfns.c | 14 | ||||
-rw-r--r-- | src/xterm.c | 226 |
19 files changed, 481 insertions, 241 deletions
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13 index abf2a9421a2..268a59219c4 100644 --- a/src/ChangeLog.13 +++ b/src/ChangeLog.13 @@ -11147,7 +11147,7 @@ 2013-11-01 Claudio Bley <claudio.bley@googlemail.com> * image.c (pbm_next_char): New function. - See http://netpbm.sourceforge.net/doc/pbm.html for the details. + See https://netpbm.sourceforge.net/doc/pbm.html for the details. (pbm_scan_number): Use it. (Qlibjpeg_version): New variable. (syms_of_image): DEFSYM and initialize it. @@ -14215,7 +14215,7 @@ * w32.c (PEXCEPTION_POINTERS, PEXCEPTION_RECORD, PCONTEXT): Define variables of these types so that GDB would know about them, as aid for debugging fatal exceptions. (Bug#15024) See also - http://sourceware.org/ml/gdb/2013-08/msg00010.html for related + https://sourceware.org/ml/gdb/2013-08/msg00010.html for related discussions. 2013-08-08 Jan Djärv <jan.h.d@swipnet.se> diff --git a/src/dired.c b/src/dired.c index c2c099f0a5f..ef729df5d2b 100644 --- a/src/dired.c +++ b/src/dired.c @@ -923,11 +923,12 @@ Elements of the attribute list are: 8. File modes, as a string of ten letters or dashes as in ls -l. 9. An unspecified value, present only for backward compatibility. 10. inode number, as a nonnegative integer. -11. Filesystem device number, as an integer. +11. Filesystem device identifier, as an integer or a cons cell of integers. Large integers are bignums, so `eq' might not work on them. On most filesystems, the combination of the inode and the device -number uniquely identifies the file. +identifier uniquely identifies the file. This unique file identification +is provided by the access function `file-attribute-file-identifier'. On MS-Windows, performance depends on `w32-get-true-file-attributes', which see. diff --git a/src/editfns.c b/src/editfns.c index c1414071c79..3f9618edb08 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3551,10 +3551,15 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) || float_conversion || conversion == 'i' || conversion == 'o' || conversion == 'x' || conversion == 'X')) - error ("Invalid format operation %%%c", - multibyte_format - ? STRING_CHAR ((unsigned char *) format - 1) - : *((unsigned char *) format - 1)); + { + unsigned char *p = (unsigned char *) format - 1; + if (multibyte_format) + error ("Invalid format operation %%%c", STRING_CHAR (p)); + else + error (*p <= 127 ? "Invalid format operation %%%c" + : "Invalid format operation char #o%03o", + *p); + } else if (! (FIXNUMP (arg) || ((BIGNUMP (arg) || FLOATP (arg)) && conversion != 'c'))) error ("Format specifier doesn't match argument type"); diff --git a/src/fileio.c b/src/fileio.c index dd7f85ec97f..8f96e973b25 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5000,9 +5000,10 @@ by calling `format-decode', which see. */) unbind_to (count1, Qnil); } - if (!NILP (visit) && current_buffer->modtime.tv_nsec < 0) + if (save_errno != 0) { /* Signal an error if visiting a file that could not be opened. */ + eassert (!NILP (visit) && NILP (handler)); report_file_errno ("Opening input file", orig_filename, save_errno); } @@ -6362,7 +6363,7 @@ init_fileio (void) For more on why fsync does not suffice even if it works properly, see: Roche X. Necessary step(s) to synchronize filename operations on disk. Austin Group Defect 672, 2013-03-19 - http://austingroupbugs.net/view.php?id=672 */ + https://austingroupbugs.net/view.php?id=672 */ write_region_inhibit_fsync = noninteractive; } diff --git a/src/fns.c b/src/fns.c index bc4915eb25b..40557923827 100644 --- a/src/fns.c +++ b/src/fns.c @@ -433,6 +433,22 @@ If string STR1 is greater, the value is a positive number N; return Qt; } +/* Check whether the platform allows access to unaligned addresses for + size_t integers without trapping or undue penalty (a few cycles is OK). + + This whitelist is incomplete but since it is only used to improve + performance, omitting cases is safe. */ +#if defined __x86_64__|| defined __amd64__ \ + || defined __i386__ || defined __i386 \ + || defined __arm64__ || defined __aarch64__ \ + || defined __powerpc__ || defined __powerpc \ + || defined __ppc__ || defined __ppc \ + || defined __s390__ || defined __s390x__ +#define HAVE_FAST_UNALIGNED_ACCESS 1 +#else +#define HAVE_FAST_UNALIGNED_ACCESS 0 +#endif + DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, doc: /* Return non-nil if STRING1 is less than STRING2 in lexicographic order. Case is significant. @@ -468,18 +484,23 @@ Symbols are also allowed; their print names are used instead. */) ptrdiff_t nb1 = SBYTES (string1); ptrdiff_t nb2 = SBYTES (string2); ptrdiff_t nb = min (nb1, nb2); - - /* First compare entire machine words. (String data is allocated - with word alignment.) */ - typedef size_t word_t; - int ws = sizeof (word_t); - const word_t *w1 = (const word_t *) SDATA (string1); - const word_t *w2 = (const word_t *) SDATA (string2); ptrdiff_t b = 0; - while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) - b += ws; - /* Scan forward to the differing byte (at most ws-1 bytes). */ + /* String data is normally allocated with word alignment, but + there are exceptions (notably pure strings) so we restrict the + wordwise skipping to safe architectures. */ + if (HAVE_FAST_UNALIGNED_ACCESS) + { + /* First compare entire machine words. */ + typedef size_t word_t; + int ws = sizeof (word_t); + const word_t *w1 = (const word_t *) SDATA (string1); + const word_t *w2 = (const word_t *) SDATA (string2); + while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) + b += ws; + } + + /* Scan forward to the differing byte. */ while (b < nb && SREF (string1, b) == SREF (string2, b)) b++; diff --git a/src/frame.c b/src/frame.c index 91b9bec82c3..f076a5ba54e 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1503,17 +1503,7 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); - selected_frame = frame; - - move_minibuffers_onto_frame (sf, for_deletion); - - if (f->select_mini_window_flag - && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) - f->selected_window = f->minibuffer_window; - f->select_mini_window_flag = false; - - if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) - last_nonminibuf_frame = XFRAME (selected_frame); + move_minibuffers_onto_frame (sf, frame, for_deletion); /* If the selected window in the target frame is its mini-window, we move to a different window, the most recently used one, unless there is a @@ -1528,6 +1518,20 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) Fset_frame_selected_window (frame, w, Qnil); } + /* After setting `selected_frame`, we're temporarily in an inconsistent + state where (selected-window) != (frame-selected-window). Until this + invariant is restored we should be very careful not to run ELisp code. + (bug#58343) */ + selected_frame = frame; + + if (f->select_mini_window_flag + && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) + f->selected_window = f->minibuffer_window; + f->select_mini_window_flag = false; + + if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) + last_nonminibuf_frame = XFRAME (selected_frame); + Fselect_window (f->selected_window, norecord); /* We want to make sure that the next event generates a frame-switch @@ -2110,7 +2114,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) else /* Ensure any minibuffers on FRAME are moved onto the selected frame. */ - move_minibuffers_onto_frame (f, true); + move_minibuffers_onto_frame (f, selected_frame, true); /* Don't let echo_area_window to remain on a deleted frame. */ if (EQ (f->minibuffer_window, echo_area_window)) diff --git a/src/lisp.h b/src/lisp.h index 9710dbef8d2..5f6721595c0 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1575,10 +1575,15 @@ struct Lisp_String { struct { - ptrdiff_t size; /* MSB is used as the markbit. */ - ptrdiff_t size_byte; /* Set to -1 for unibyte strings, - -2 for data in rodata, - -3 for immovable unibyte strings. */ + /* Number of characters in string; MSB is used as the mark bit. */ + ptrdiff_t size; + /* If nonnegative, number of bytes in the string (which is multibyte). + If negative, the string is unibyte: + -1 for data normally allocated + -2 for data in rodata (C string constants) + -3 for data that must be immovable (used for bytecode) */ + ptrdiff_t size_byte; + INTERVAL intervals; /* Text properties in this string. */ unsigned char *data; } s; @@ -4787,7 +4792,7 @@ extern void clear_regexp_cache (void); extern Lisp_Object Vminibuffer_list; extern Lisp_Object last_minibuf_string; -extern void move_minibuffers_onto_frame (struct frame *, bool); +extern void move_minibuffers_onto_frame (struct frame *, Lisp_Object, bool); extern bool is_minibuffer (EMACS_INT, Lisp_Object); extern EMACS_INT this_minibuffer_depth (Lisp_Object); extern EMACS_INT minibuf_level; diff --git a/src/minibuf.c b/src/minibuf.c index bedc5644807..3f34b1b0834 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -187,13 +187,15 @@ zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window) /* If `minibuffer_follows_selected_frame' is t, or we're about to delete a frame which potentially "contains" minibuffers, move them - from the old frame to the selected frame. This function is + from the old frame to the to-be-selected frame. This function is intended to be called from `do_switch_frame' in frame.c. OF is the - old frame, FOR_DELETION is true if OF is about to be deleted. */ + old frame, FRAME is the to-be-selected frame, and FOR_DELETION is true + if OF is about to be deleted. */ void -move_minibuffers_onto_frame (struct frame *of, bool for_deletion) +move_minibuffers_onto_frame (struct frame *of, Lisp_Object frame, + bool for_deletion) { - struct frame *f = XFRAME (selected_frame); + struct frame *f = XFRAME (frame); minibuf_window = f->minibuffer_window; if (!(minibuf_level @@ -206,7 +208,7 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion) { zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); if (for_deletion && XFRAME (MB_frame) != of) - MB_frame = selected_frame; + MB_frame = frame; } } diff --git a/src/nsterm.m b/src/nsterm.m index 82fe58e90ec..1fc72d83f66 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2479,7 +2479,7 @@ get_keysym_name (int keysym) { static char value[16]; NSTRACE ("get_keysym_name"); - sprintf (value, "%d", keysym); + snprintf (value, 16, "%d", keysym); return value; } @@ -4263,7 +4263,7 @@ ns_draw_glyphless_glyph_string_foreground (struct glyph_string *s) { unsigned int ch = glyph->u.glyphless.ch; eassume (ch <= MAX_CHAR); - sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch); + snprintf (buf, 7, "%0*X", ch < 0x10000 ? 4 : 6, ch); str = buf; } @@ -6116,17 +6116,20 @@ ns_term_shutdown (int sig) - (void) terminate: (id)sender { + struct input_event ie; + struct frame *f; + NSTRACE ("[EmacsApp terminate:]"); - struct frame *emacsframe = SELECTED_FRAME (); + f = SELECTED_FRAME (); + EVENT_INIT (ie); - if (!emacs_event) - return; + ie.kind = NS_NONKEY_EVENT; + ie.code = KEY_NS_POWER_OFF; + ie.arg = Qt; /* mark as non-key event */ + XSETFRAME (ie.frame_or_window, f); - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_POWER_OFF; - emacs_event->arg = Qt; /* mark as non-key event */ - EV_TRAILER ((id)nil); + kbd_buffer_store_event (&ie); } static bool @@ -8593,7 +8596,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) EmacsLayer *layer = (EmacsLayer *)[self layer]; [layer setContentsScale:[[notification object] backingScaleFactor]]; - [layer setColorSpace:[[[notification object] colorSpace] CGColorSpace]]; + [layer setColorSpace:[(id) [[notification object] colorSpace] CGColorSpace]]; ns_clear_frame (emacsframe); expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame)); diff --git a/src/pdumper.c b/src/pdumper.c index 903298f17d2..5e6ccd9bd88 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2067,7 +2067,7 @@ dump_interval_tree (struct dump_context *ctx, static dump_off dump_string (struct dump_context *ctx, const struct Lisp_String *string) { -#if CHECK_STRUCTS && !defined (HASH_Lisp_String_C2CAF90352) +#if CHECK_STRUCTS && !defined (HASH_Lisp_String_03B2DF1C8E) # error "Lisp_String changed. See CHECK_STRUCTS comment in config.h." #endif /* If we have text properties, write them _after_ the string so that diff --git a/src/sqlite.c b/src/sqlite.c index 54bfb7b6c61..1526e344e53 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -51,6 +51,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); +DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); @@ -88,6 +89,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # undef sqlite3_bind_null # undef sqlite3_bind_int # undef sqlite3_errmsg +# undef sqlite3_errstr # undef sqlite3_step # undef sqlite3_changes # undef sqlite3_column_count @@ -112,6 +114,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # define sqlite3_bind_null fn_sqlite3_bind_null # define sqlite3_bind_int fn_sqlite3_bind_int # define sqlite3_errmsg fn_sqlite3_errmsg +# define sqlite3_errstr fn_sqlite3_errstr # define sqlite3_step fn_sqlite3_step # define sqlite3_changes fn_sqlite3_changes # define sqlite3_column_count fn_sqlite3_column_count @@ -139,6 +142,7 @@ load_dll_functions (HMODULE library) LOAD_DLL_FN (library, sqlite3_bind_null); LOAD_DLL_FN (library, sqlite3_bind_int); LOAD_DLL_FN (library, sqlite3_errmsg); + LOAD_DLL_FN (library, sqlite3_errstr); LOAD_DLL_FN (library, sqlite3_step); LOAD_DLL_FN (library, sqlite3_changes); LOAD_DLL_FN (library, sqlite3_column_count); @@ -373,72 +377,6 @@ bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values) return NULL; } -DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, - doc: /* Execute a non-select SQL statement. -If VALUES is non-nil, it should be a vector or a list of values -to bind when executing a statement like - - insert into foo values (?, ?, ...) - -Value is the number of affected rows. */) - (Lisp_Object db, Lisp_Object query, Lisp_Object values) -{ - check_sqlite (db, false); - CHECK_STRING (query); - if (!(NILP (values) || CONSP (values) || VECTORP (values))) - xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); - - sqlite3 *sdb = XSQLITE (db)->db; - Lisp_Object retval = Qnil; - const char *errmsg = NULL; - Lisp_Object encoded = encode_string (query); - sqlite3_stmt *stmt = NULL; - - /* We only execute the first statement -- if there's several - (separated by a semicolon), the subsequent statements won't be - done. */ - int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - if (stmt != NULL) - { - sqlite3_finalize (stmt); - sqlite3_reset (stmt); - } - - errmsg = sqlite3_errmsg (sdb); - goto exit; - } - - /* Bind ? values. */ - if (!NILP (values)) { - const char *err = bind_values (sdb, stmt, values); - if (err != NULL) - { - errmsg = err; - goto exit; - } - } - - ret = sqlite3_step (stmt); - sqlite3_finalize (stmt); - if (ret != SQLITE_OK && ret != SQLITE_DONE) - { - errmsg = sqlite3_errmsg (sdb); - goto exit; - } - - retval = make_fixnum (sqlite3_changes (sdb)); - - exit: - if (errmsg != NULL) - xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? - Qsqlite_locked_error: Qerror, - build_string (errmsg)); - - return retval; -} - static Lisp_Object row_to_value (sqlite3_stmt *stmt) { @@ -484,6 +422,94 @@ row_to_value (sqlite3_stmt *stmt) } static Lisp_Object +sqlite_prepare_errmsg (int code, sqlite3 *sdb) +{ + Lisp_Object errmsg = build_string (sqlite3_errstr (code)); + /* More details about what went wrong. */ + const char *sql_error = sqlite3_errmsg (sdb); + if (sql_error) + return CALLN (Fformat, build_string ("%s (%s)"), + errmsg, build_string (sql_error)); + else + return errmsg; +} + +DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, + doc: /* Execute a non-select SQL statement. +If VALUES is non-nil, it should be a vector or a list of values +to bind when executing a statement like + + insert into foo values (?, ?, ...) + +Value is the number of affected rows. */) + (Lisp_Object db, Lisp_Object query, Lisp_Object values) +{ + check_sqlite (db, false); + CHECK_STRING (query); + if (!(NILP (values) || CONSP (values) || VECTORP (values))) + xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); + + sqlite3 *sdb = XSQLITE (db)->db; + Lisp_Object errmsg = Qnil, + encoded = encode_string (query); + sqlite3_stmt *stmt = NULL; + + /* We only execute the first statement -- if there's several + (separated by a semicolon), the subsequent statements won't be + done. */ + int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + if (stmt != NULL) + { + sqlite3_finalize (stmt); + sqlite3_reset (stmt); + } + + errmsg = sqlite_prepare_errmsg (ret, sdb); + goto exit; + } + + /* Bind ? values. */ + if (!NILP (values)) + { + const char *err = bind_values (sdb, stmt, values); + if (err != NULL) + { + errmsg = build_string (err); + goto exit; + } + } + + ret = sqlite3_step (stmt); + + if (ret == SQLITE_ROW) + { + Lisp_Object data = Qnil; + do + data = Fcons (row_to_value (stmt), data); + while (sqlite3_step (stmt) == SQLITE_ROW); + + sqlite3_finalize (stmt); + return Fnreverse (data); + } + else if (ret == SQLITE_OK || ret == SQLITE_DONE) + { + Lisp_Object rows = make_fixnum (sqlite3_changes (sdb)); + sqlite3_finalize (stmt); + return rows; + } + else + errmsg = build_string (sqlite3_errmsg (sdb)); + + exit: + sqlite3_finalize (stmt); + xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? + Qsqlite_locked_error: Qerror, + errmsg); +} + +static Lisp_Object column_names (sqlite3_stmt *stmt) { Lisp_Object columns = Qnil; @@ -517,9 +543,8 @@ which means that we return a set object that can be queried with xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); sqlite3 *sdb = XSQLITE (db)->db; - Lisp_Object retval = Qnil; - const char *errmsg = NULL; - Lisp_Object encoded = encode_string (query); + Lisp_Object retval = Qnil, errmsg = Qnil, + encoded = encode_string (query); sqlite3_stmt *stmt = NULL; int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), SBYTES (encoded), @@ -528,7 +553,7 @@ which means that we return a set object that can be queried with { if (stmt) sqlite3_finalize (stmt); - + errmsg = sqlite_prepare_errmsg (ret, sdb); goto exit; } @@ -539,7 +564,7 @@ which means that we return a set object that can be queried with if (err != NULL) { sqlite3_finalize (stmt); - errmsg = err; + errmsg = build_string (err); goto exit; } } @@ -553,7 +578,7 @@ which means that we return a set object that can be queried with /* Return the data directly. */ Lisp_Object data = Qnil; - while ((ret = sqlite3_step (stmt)) == SQLITE_ROW) + while (sqlite3_step (stmt) == SQLITE_ROW) data = Fcons (row_to_value (stmt), data); if (EQ (return_type, Qfull)) @@ -563,8 +588,8 @@ which means that we return a set object that can be queried with sqlite3_finalize (stmt); exit: - if (errmsg != NULL) - xsignal1 (Qerror, build_string (errmsg)); + if (! NILP (errmsg)) + xsignal1 (Qerror, errmsg); return retval; } diff --git a/src/sysdep.c b/src/sysdep.c index abb385d1388..736723bdf3d 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -2432,7 +2432,7 @@ emacs_pipe (int fd[2]) /* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs. For the background behind this mess, please see Austin Group defect 529 - <http://austingroupbugs.net/view.php?id=529>. */ + <https://austingroupbugs.net/view.php?id=529>. */ #ifndef POSIX_CLOSE_RESTART # define POSIX_CLOSE_RESTART 1 diff --git a/src/widget.c b/src/widget.c index 5a75cdaca8e..aaab33b6d8e 100644 --- a/src/widget.c +++ b/src/widget.c @@ -195,7 +195,7 @@ round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, out_width, out_height); } -static Widget +static WMShellWidget get_wm_shell (Widget w) { Widget wmshell; @@ -204,7 +204,7 @@ get_wm_shell (Widget w) wmshell && !XtIsWMShell (wmshell); wmshell = XtParent (wmshell)); - return wmshell; + return (WMShellWidget) wmshell; } #if 0 /* Currently not used. */ @@ -269,8 +269,8 @@ set_frame_size (EmacsFrame ew) (f, build_string ("set_frame_size")); } -static void -update_wm_hints (Widget wmshell, EmacsFrame ew) +static bool +update_wm_hints (WMShellWidget wmshell, EmacsFrame ew) { int cw; int ch; @@ -280,6 +280,12 @@ update_wm_hints (Widget wmshell, EmacsFrame ew) int char_height; int base_width; int base_height; + char buffer[sizeof wmshell->wm.size_hints]; + char *hints_ptr; + + /* Copy the old size hints to the buffer. */ + memcpy (buffer, &wmshell->wm.size_hints, + sizeof wmshell->wm.size_hints); pixel_to_char_size (ew, ew->core.width, ew->core.height, &char_width, &char_height); @@ -292,27 +298,29 @@ update_wm_hints (Widget wmshell, EmacsFrame ew) base_height = (wmshell->core.height - ew->core.height + (rounded_height - (char_height * ch))); - /* Ensure that Xt actually sets window manager hint flags specified - by the caller by making sure XtNminWidth (a relatively harmless - resource) always changes each time this function is invoked. */ - ew->emacs_frame.size_switch = !ew->emacs_frame.size_switch; - - XtVaSetValues (wmshell, + XtVaSetValues ((Widget) wmshell, XtNbaseWidth, (XtArgVal) base_width, XtNbaseHeight, (XtArgVal) base_height, XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw), XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch), - XtNminWidth, (XtArgVal) (base_width - + ew->emacs_frame.size_switch), - XtNminHeight, (XtArgVal) (base_height - + ew->emacs_frame.size_switch), + XtNminWidth, (XtArgVal) base_width, + XtNminHeight, (XtArgVal) base_height, NULL); + + /* Return if size hints really changed. If they did not, then Xt + probably didn't set them either (or take the flags into + account.) */ + hints_ptr = (char *) &wmshell->wm.size_hints; + + /* Skip flags, which is unsigned long. */ + return memcmp (hints_ptr + sizeof (long), buffer + sizeof (long), + sizeof wmshell->wm.wm_hints - sizeof (long)); } -void +bool widget_update_wm_size_hints (Widget widget, Widget frame) { - update_wm_hints (widget, (EmacsFrame) frame); + return update_wm_hints ((WMShellWidget) widget, (EmacsFrame) frame); } static void @@ -357,8 +365,6 @@ EmacsFrameInitialize (Widget request, Widget new, exit (1); } - ew->emacs_frame.size_switch = 1; - update_from_various_frame_slots (ew); set_frame_size (ew); } diff --git a/src/widget.h b/src/widget.h index 2906d5ff9ec..cf83cb10781 100644 --- a/src/widget.h +++ b/src/widget.h @@ -97,6 +97,6 @@ extern struct _DisplayContext *display_context; /* Special entry points */ void EmacsFrameSetCharSize (Widget, int, int); void widget_store_internal_border (Widget widget); -void widget_update_wm_size_hints (Widget widget, Widget frame); +bool widget_update_wm_size_hints (Widget widget, Widget frame); #endif /* _EmacsFrame_h */ diff --git a/src/widgetprv.h b/src/widgetprv.h index fe960326b03..3a4d9206ffe 100644 --- a/src/widgetprv.h +++ b/src/widgetprv.h @@ -49,9 +49,6 @@ typedef struct { Boolean visual_bell; /* flash instead of beep */ int bell_volume; /* how loud is beep */ - int size_switch; /* hack to make setting size - hints work correctly */ - /* private state */ } EmacsFramePart; diff --git a/src/window.c b/src/window.c index da80fabe33f..4e8b352e164 100644 --- a/src/window.c +++ b/src/window.c @@ -52,6 +52,7 @@ static ptrdiff_t get_leaf_windows (struct window *, struct window **, ptrdiff_t); static void window_scroll_pixel_based (Lisp_Object, int, bool, bool); static void window_scroll_line_based (Lisp_Object, int, bool, bool); +static void window_scroll_for_long_lines (struct window *, int, bool); static void foreach_window (struct frame *, bool (* fn) (struct window *, void *), void *); @@ -5536,19 +5537,40 @@ window_internal_height (struct window *w) static void window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror) { + struct window *w = XWINDOW (window); + struct buffer *b = XBUFFER (w->contents); + bool long_lines_truncated = + b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines)); specpdl_ref count = SPECPDL_INDEX (); n = clip_to_bounds (INT_MIN, n, INT_MAX); - wset_redisplay (XWINDOW (window)); + wset_redisplay (w); - if (whole && fast_but_imprecise_scrolling) + /* Does this window's buffer have very long and truncated lines? */ + if (b->long_line_optimizations_p + && !long_lines_truncated + && !NILP (Vtruncate_partial_width_windows) + && w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w)))) + { + if (FIXNUMP (Vtruncate_partial_width_windows)) + long_lines_truncated = + w->total_cols < XFIXNAT (Vtruncate_partial_width_windows); + else + long_lines_truncated = true; + } + + if (whole && (fast_but_imprecise_scrolling || long_lines_truncated)) specbind (Qfontification_functions, Qnil); - /* On GUI frames, use the pixel-based version which is much slower - than the line-based one but can handle varying line heights. */ - if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) + if (whole && long_lines_truncated) + window_scroll_for_long_lines (w, n, noerror); + else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) { + + /* On GUI frames, use the pixel-based version which is much + slower than the line-based one, but can handle varying + line heights. */ record_unwind_protect_void (unwind_display_working_on_window); display_working_on_window_p = true; window_scroll_pixel_based (window, n, whole, noerror); @@ -5598,6 +5620,71 @@ sanitize_next_screen_context_lines (void) return clip_to_bounds (0, next_screen_context_lines, 1000000); } +/* Implementation of window_scroll for very long and truncated lines. + This is a simplified version, it only handles WHOLE window scrolls, + and doesn't honor scroll-preserve-screen-position nor scroll-margin. */ +static void +window_scroll_for_long_lines (struct window *w, int n, bool noerror) +{ + ptrdiff_t startpos = marker_position (w->start); + ptrdiff_t startbyte = marker_byte_position (w->start); + int nscls = sanitize_next_screen_context_lines (); + register int ht = window_internal_height (w); + + n *= max (1, ht - nscls); + + /* If point is not visible in window, bring it inside window. */ + struct position pos; + int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y; + if (!(PT >= startpos + && PT <= ZV + && startpos <= ZV + && pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh, + &dummy_vpos) + && !rtop && !rbot)) + { + pos = *vmotion (PT, PT_BYTE, - (ht / 2), w); + startpos = pos.bufpos; + startbyte = pos.bytepos; + } + SET_PT_BOTH (startpos, startbyte); + + bool lose = n < 0 && PT == BEGV; + pos = *vmotion (PT, PT_BYTE, n, w); + if (lose) + { + if (noerror) + return; + else + xsignal0 (Qbeginning_of_buffer); + } + + bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n'; + if (pos.bufpos < ZV) + { + set_marker_restricted_both (w->start, w->contents, + pos.bufpos, pos.bytepos); + w->start_at_line_beg = bolp; + wset_update_mode_line (w); + /* Set force_start so that redisplay_window will run + the window-scroll-functions. */ + w->force_start = true; + SET_PT_BOTH (pos.bufpos, pos.bytepos); + if (n > 0) + pos = *vmotion (PT, PT_BYTE, ht / 2, w); + else if (n < 0) + pos = *vmotion (PT, PT_BYTE, - (ht / 2), w); + SET_PT_BOTH (pos.bufpos, pos.bytepos); + } + else + { + if (noerror) + return; + else + xsignal0 (Qend_of_buffer); + } +} + /* Implementation of window_scroll that works based on pixel line heights. See the comment of window_scroll for parameter descriptions. */ diff --git a/src/xdisp.c b/src/xdisp.c index 9534e27843e..e390de6a336 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -20165,7 +20165,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) from point. */ centering_position = window_box_height (w) / 2; } - move_it_vertically_backward (&it, centering_position); + if (current_buffer->long_line_optimizations_p + && it.line_wrap == TRUNCATE) + { + /* For very long and truncated lines, go back using a simplified + method, which ignored any inaccuracies due to line-height + differences, display properties/overlays, etc. */ + int nlines = centering_position / frame_line_height; + + while (nlines-- && IT_CHARPOS (it) > BEGV) + back_to_previous_visible_line_start (&it); + reseat_1 (&it, it.current.pos, true); + } + else + move_it_vertically_backward (&it, centering_position); eassert (IT_CHARPOS (it) >= BEGV); diff --git a/src/xfns.c b/src/xfns.c index 8cea93c6698..91124488994 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4179,11 +4179,15 @@ x_window (struct frame *f) { /* XIM server might require some X events. */ unsigned long fevent = NoEventMask; - XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); - attributes.event_mask |= fevent; - attribute_mask = CWEventMask; - XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - attribute_mask, &attributes); + + if (fevent) + { + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + attributes.event_mask |= fevent; + attribute_mask = CWEventMask; + XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + attribute_mask, &attributes); + } } } #endif /* HAVE_X_I18N */ diff --git a/src/xterm.c b/src/xterm.c index aaf2e7988be..d35af7a8de2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1425,9 +1425,6 @@ struct x_client_list_window /* The width and height of the window. */ int width, height; - /* Whether or not the window is mapped. */ - bool mapped_p; - /* A bitmask describing events Emacs was listening for from the window before some extra events were added in `x_dnd_compute_toplevels'. */ @@ -1439,9 +1436,6 @@ struct x_client_list_window /* The next window in this list. */ struct x_client_list_window *next; - /* The Motif protocol style of this window, if any. */ - uint8_t xm_protocol_style; - /* The extents of the frame window in each direction. */ int frame_extents_left; int frame_extents_right; @@ -1452,18 +1446,24 @@ struct x_client_list_window /* The border width of this window. */ int border_width; - /* The rectangles making up the input shape. */ - XRectangle *input_rects; - /* The number of rectangles composing the input shape. */ int n_input_rects; + /* The rectangles making up the input shape. */ + XRectangle *input_rects; + /* The rectangles making up the bounding shape. */ XRectangle *bounding_rects; /* The number of rectangles composing the bounding shape. */ int n_bounding_rects; #endif + + /* The Motif protocol style of this window, if any. */ + uint8_t xm_protocol_style; + + /* Whether or not the window is mapped. */ + bool mapped_p; }; /* List of all toplevels in stacking order, from top to bottom. */ @@ -5139,24 +5139,20 @@ x_update_opaque_region (struct frame *f, XEvent *configure) if (!FRAME_DISPLAY_INFO (f)->alpha_bits) return; - block_input (); if (f->alpha_background < 1.0) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, NULL, 0); #ifndef HAVE_GTK3 else - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); #else else if (FRAME_TOOLTIP_P (f)) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); @@ -5174,7 +5170,6 @@ x_update_opaque_region (struct frame *f, XEvent *configure) } } #endif - unblock_input (); } @@ -7144,8 +7139,6 @@ show_back_buffer (struct frame *f) cairo_t *cr; #endif - block_input (); - if (FRAME_X_DOUBLE_BUFFERED_P (f)) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME @@ -7174,8 +7167,6 @@ show_back_buffer (struct frame *f) } FRAME_X_NEED_BUFFER_FLIP (f) = false; - - unblock_input (); } #endif @@ -7283,8 +7274,12 @@ XTframe_up_to_date (struct frame *f) static void XTbuffer_flipping_unblocked_hook (struct frame *f) { + block_input (); + if (FRAME_X_NEED_BUFFER_FLIP (f)) show_back_buffer (f); + + unblock_input (); } #endif @@ -7313,8 +7308,6 @@ x_clear_under_internal_border (struct frame *f) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); - if (face) { unsigned long color = face->background; @@ -7335,8 +7328,6 @@ x_clear_under_internal_border (struct frame *f) x_clear_area (f, width - border, 0, border, height); x_clear_area (f, 0, height - border, width, border); } - - unblock_input (); } } @@ -7384,7 +7375,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); if (face) { unsigned long color = face->background; @@ -7402,7 +7392,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) x_clear_area (f, 0, y, width, height); x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height); } - unblock_input (); } } #endif @@ -7601,11 +7590,27 @@ static void x_check_font (struct frame *, struct font *); user time. We don't sanitize timestamps from events sent by the X server itself because some Lisp might have set the user time to a ridiculously large value, and this way a more reasonable timestamp - can be obtained upon the next event. */ + can be obtained upon the next event. + + Alternatively, the server time could've overflowed. + + SET_PROPERTY specifies whether or not to change the user time + property for the active frame. The important thing is to not set + the last user time upon leave events; on Metacity and GNOME Shell, + mapping a new frame on top of the old frame potentially causes + crossing events to be sent to the old frame if it contains the + pointer, as the new frame will initially stack above the old frame. + If _NET_WM_USER_TIME is changed at that point, then GNOME may get + notified about the user time change on the old frame before it + tries to focus the new frame, which will make it consider the new + frame (whose user time property will not have been updated at that + point, due to not being focused) as having been mapped + out-of-order, and lower the new frame, which is typically not what + users want. */ static void x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, - bool send_event) + bool send_event, bool set_property) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME uint_fast64_t monotonic_time; @@ -7678,7 +7683,8 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, #ifndef USE_GTK /* Don't waste bandwidth if the time hasn't actually changed. */ - if (focus_frame && old_time != dpyinfo->last_user_time) + if (focus_frame && old_time != dpyinfo->last_user_time + && set_property) { time = dpyinfo->last_user_time; @@ -7719,6 +7725,7 @@ x_set_gtk_user_time (struct frame *f, Time time) itself. */ #ifndef USE_GTK + static void x_update_frame_user_time_window (struct frame *f) { @@ -7782,13 +7789,14 @@ x_update_frame_user_time_window (struct frame *f) } } } + #endif void x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, Time time) { - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, true); } @@ -9595,31 +9603,49 @@ x_draw_glyph_string_box (struct glyph_string *s) #ifndef USE_CAIRO + static void x_composite_image (struct glyph_string *s, Pixmap dest, +#ifdef HAVE_XRENDER + Picture destination, +#endif int srcX, int srcY, int dstX, int dstY, int width, int height) { - Display *display = FRAME_X_DISPLAY (s->f); + Display *display; #ifdef HAVE_XRENDER - if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f)) - { - Picture destination; - XRenderPictFormat *default_format; - XRenderPictureAttributes attr UNINIT; + XRenderPictFormat *default_format; + XRenderPictureAttributes attr UNINIT; +#endif - default_format = FRAME_X_PICTURE_FORMAT (s->f); - destination = XRenderCreatePicture (display, dest, - default_format, 0, &attr); + display = FRAME_X_DISPLAY (s->f); - XRenderComposite (display, s->img->mask_picture ? PictOpOver : PictOpSrc, - s->img->picture, s->img->mask_picture, destination, - srcX, srcY, - srcX, srcY, - dstX, dstY, - width, height); +#ifdef HAVE_XRENDER + if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f)) + { + if (destination == None) + { + /* The destination picture was not specified. This means we + have to create a picture representing the */ + default_format = FRAME_X_PICTURE_FORMAT (s->f); + destination = XRenderCreatePicture (display, dest, + default_format, 0, &attr); + + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); + + XRenderFreePicture (display, destination); + } + else + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); - XRenderFreePicture (display, destination); return; } #endif @@ -9629,6 +9655,7 @@ x_composite_image (struct glyph_string *s, Pixmap dest, srcX, srcY, width, height, dstX, dstY); } + #endif /* !USE_CAIRO */ @@ -9707,6 +9734,9 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif s->slice.x + r.x - x, s->slice.y + r.y - y, r.x, r.y, r.width, r.height); } @@ -9720,7 +9750,12 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) - x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif + s->slice.x + r.x - x, + s->slice.y + r.y - y, r.x, r.y, r.width, r.height); /* When the image has a mask, we can expect that at @@ -9886,8 +9921,11 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) XChangeGC (display, s->gc, mask, &xgcv); x_composite_image (s, pixmap, - s->slice.x, s->slice.y, - x, y, s->slice.width, s->slice.height); +#ifdef HAVE_XRENDER + None, +#endif + s->slice.x, s->slice.y, x, y, + s->slice.width, s->slice.height); XSetClipMask (display, s->gc, None); } else @@ -12761,7 +12799,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, true); device->focus_frame = mentioned_frame; device->focus_frame_time = event->time; @@ -12771,7 +12809,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, false); device->focus_frame = NULL; @@ -14153,7 +14191,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, < dpyinfo->last_mouse_movement_time)) x_display_set_last_user_time (dpyinfo, dpyinfo->last_mouse_movement_time, - dpyinfo->last_mouse_movement_time_send_event); + dpyinfo->last_mouse_movement_time_send_event, + true); if ((!f1 || FRAME_TOOLTIP_P (f1)) && (EQ (track_mouse, Qdropping) @@ -14769,7 +14808,8 @@ xg_scroll_callback (GtkRange *range, GtkScrollType scroll, dpyinfo = FRAME_DISPLAY_INFO (f); if (time != GDK_CURRENT_TIME) - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, + true); switch (scroll) { @@ -18091,7 +18131,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, required for SetInputFocus to work correctly after taking the input focus. */ x_display_set_last_user_time (dpyinfo, event->xclient.data.l[1], - true); + true, true); goto done; } @@ -19079,7 +19119,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, case KeyPress: x_display_set_last_user_time (dpyinfo, event->xkey.time, - event->xkey.send_event); + event->xkey.send_event, + true); ignore_next_mouse_click_timeout = 0; coding = Qlatin_1; @@ -19558,7 +19599,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case EnterNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -19681,7 +19722,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case LeaveNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -20496,7 +20537,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { if (event->xbutton.type == ButtonPress) x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); #ifdef HAVE_XWIDGETS struct xwidget_view *xvw = xwidget_view_from_window (event->xbutton.window); @@ -20548,7 +20589,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == ButtonPress) { x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; @@ -21105,7 +21146,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.send_event = enter->send_event; x_display_set_last_user_time (dpyinfo, enter->time, - enter->send_event); + enter->send_event, false); #ifdef USE_MOTIF use_copy = true; @@ -21291,7 +21332,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, leave->time, - leave->send_event); + leave->send_event, false); #ifdef HAVE_XWIDGETS { @@ -21566,7 +21607,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, state = xi_convert_event_state (xev); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (found_valuator) xwidget_scroll (xv, xev->event_x, xev->event_y, @@ -21586,7 +21627,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (found_valuator) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #if defined USE_GTK && !defined HAVE_GTK3 @@ -22077,7 +22118,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); dpyinfo->grabbed |= (1 << xev->detail); dpyinfo->last_mouse_frame = f; @@ -22120,7 +22161,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->flags & XIPointerEmulated) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #endif x_dnd_note_self_wheel (dpyinfo, x_dnd_last_seen_window, @@ -22356,7 +22397,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); source = xi_device_from_id (dpyinfo, xev->sourceid); device = xi_device_from_id (dpyinfo, xev->deviceid); @@ -22735,7 +22776,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); ignore_next_mouse_click_timeout = 0; f = x_any_window_to_frame (dpyinfo, xev->event); @@ -23374,7 +23415,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23472,7 +23513,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23519,7 +23560,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23560,7 +23601,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, pev->deviceid); source = xi_device_from_id (dpyinfo, pev->sourceid); x_display_set_last_user_time (dpyinfo, pev->time, - pev->send_event); + pev->send_event, true); if (!device) goto XI_OTHER; @@ -27995,6 +28036,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) Window window = FRAME_OUTER_WINDOW (f); #ifdef USE_X_TOOLKIT WMShellWidget shell; + bool hints_changed; #endif if (!window) @@ -28021,8 +28063,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags |= USPosition; } - widget_update_wm_size_hints (f->output_data.x->widget, - f->output_data.x->edit_widget); + hints_changed + = widget_update_wm_size_hints (f->output_data.x->widget, + f->output_data.x->edit_widget); #ifdef USE_MOTIF /* Do this all over again for the benefit of Motif, which always @@ -28035,6 +28078,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags &= ~PPosition; shell->wm.size_hints.flags |= USPosition; } +#endif /* Drill hints into Motif, since it keeps setting its own. */ size_hints.flags = shell->wm.size_hints.flags; @@ -28052,15 +28096,23 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y; size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x; size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y; -#ifdef HAVE_X11XTR6 size_hints.base_width = shell->wm.base_width; size_hints.base_height = shell->wm.base_height; size_hints.win_gravity = shell->wm.win_gravity; -#endif +#ifdef USE_MOTIF XSetWMNormalHints (XtDisplay (f->output_data.x->widget), XtWindow (f->output_data.x->widget), &size_hints); +#else + /* In many cases, widget_update_wm_size_hints will not have + updated the size hints if only flags changed. When that + happens, set the WM hints manually. */ + + if (!hints_changed) + XSetWMNormalHints (XtDisplay (f->output_data.x->widget), + XtWindow (f->output_data.x->widget), + &size_hints); #endif return; @@ -28475,9 +28527,10 @@ xi_check_toolkit (Display *display) #endif -/* Open a connection to X display DISPLAY_NAME, and return - the structure that describes the open display. - If we cannot contact the display, return null. */ +/* Open a connection to X display DISPLAY_NAME, and return the + structure that describes the open display. If obtaining the XCB + connection or toolkit-specific display fails, return NULL. Signal + an error if opening the display itself failed. */ struct x_display_info * x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) @@ -28504,9 +28557,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) ++x_initialized; } - if (! x_display_ok (SSDATA (display_name))) +#if defined USE_X_TOOLKIT || defined USE_GTK + + if (!x_display_ok (SSDATA (display_name))) error ("Display %s can't be opened", SSDATA (display_name)); +#endif + #ifdef USE_GTK { #define NUM_ARGV 10 @@ -28633,6 +28690,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) /* Detect failure. */ if (dpy == 0) { +#if !defined USE_X_TOOLKIT && !defined USE_GTK + /* Avoid opening a display three times (once in dispextern.c + upon startup, once in x_display_ok, and once above) to + determine whether or not the display is alive on no toolkit + builds, where no toolkit initialization happens at all. */ + + error ("Display %s can't be opened", SSDATA (display_name)); +#endif + unblock_input (); return 0; } |