summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Kaludercic <philipk@posteo.net>2022-10-15 17:38:30 +0200
committerPhilip Kaludercic <philipk@posteo.net>2022-10-15 17:38:30 +0200
commit01e45efcd44e92dd259283df0e62653c7c20e9cc (patch)
tree552c1a6ce7d52b897cf5f089d6c589921efbe9bd /src
parent982c0e6c15535defcf6ac3c4d4169708c60efc18 (diff)
parent5933055a3e7387b0095f0df7876a208ab15f4f45 (diff)
downloademacs-01e45efcd44e92dd259283df0e62653c7c20e9cc.tar.gz
emacs-01e45efcd44e92dd259283df0e62653c7c20e9cc.tar.bz2
emacs-01e45efcd44e92dd259283df0e62653c7c20e9cc.zip
Merge branch 'master' into feature/package+vc
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog.134
-rw-r--r--src/dired.c5
-rw-r--r--src/editfns.c13
-rw-r--r--src/fileio.c5
-rw-r--r--src/fns.c41
-rw-r--r--src/frame.c28
-rw-r--r--src/lisp.h15
-rw-r--r--src/minibuf.c12
-rw-r--r--src/nsterm.m23
-rw-r--r--src/pdumper.c2
-rw-r--r--src/sqlite.c173
-rw-r--r--src/sysdep.c2
-rw-r--r--src/widget.c42
-rw-r--r--src/widget.h2
-rw-r--r--src/widgetprv.h3
-rw-r--r--src/window.c97
-rw-r--r--src/xdisp.c15
-rw-r--r--src/xfns.c14
-rw-r--r--src/xterm.c226
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;
}