commit fe3af8d4f2a4cd67958f76d1b708e8a78e68cd4f (HEAD, refs/remotes/origin/master) Author: Martin Rudalics Date: Thu Mar 23 07:51:19 2017 +0100 c:/Temp/gtk-window-move/ChangeLog.txt diff --git a/src/gtkutil.c b/src/gtkutil.c index 3a00e36222..63f0143641 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -783,33 +783,55 @@ xg_set_geometry (struct frame *f) { if (f->size_hint_flags & (USPosition | PPosition)) { - int left = f->left_pos; - int xneg = f->size_hint_flags & XNegative; - int top = f->top_pos; - int yneg = f->size_hint_flags & YNegative; - char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)]; - guint id; - - if (xneg) - left = -left; - if (yneg) - top = -top; - - sprintf (geom_str, "=%dx%d%c%d%c%d", - FRAME_PIXEL_WIDTH (f), - FRAME_PIXEL_HEIGHT (f), - (xneg ? '-' : '+'), left, - (yneg ? '-' : '+'), top); - - /* Silence warning about visible children. */ - id = g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL - | G_LOG_FLAG_RECURSION, my_log_handler, NULL); - - if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - geom_str)) - fprintf (stderr, "Failed to parse: '%s'\n", geom_str); - - g_log_remove_handler ("Gtk", id); + if (x_gtk_use_window_move) + { + /* Handle negative positions without consulting + gtk_window_parse_geometry (Bug#25851). The position will + be off by scrollbar width + window manager decorations. */ + if (f->size_hint_flags & XNegative) + f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) + - FRAME_PIXEL_WIDTH (f) + f->left_pos); + + if (f->size_hint_flags & YNegative) + f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) + - FRAME_PIXEL_HEIGHT (f) + f->top_pos); + + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + + /* Reset size hint flags. */ + f->size_hint_flags &= ~ (XNegative | YNegative); + } + else + { + int left = f->left_pos; + int xneg = f->size_hint_flags & XNegative; + int top = f->top_pos; + int yneg = f->size_hint_flags & YNegative; + char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)]; + guint id; + + if (xneg) + left = -left; + if (yneg) + top = -top; + + sprintf (geom_str, "=%dx%d%c%d%c%d", + FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f), + (xneg ? '-' : '+'), left, + (yneg ? '-' : '+'), top); + + /* Silence warning about visible children. */ + id = g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL + | G_LOG_FLAG_RECURSION, my_log_handler, NULL); + + if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + geom_str)) + fprintf (stderr, "Failed to parse: '%s'\n", geom_str); + + g_log_remove_handler ("Gtk", id); + } } } @@ -1406,6 +1428,13 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) else if (win_gravity == StaticGravity) size_hints.win_gravity = GDK_GRAVITY_STATIC; + if (x_gtk_use_window_move) + { + if (flags & PPosition) hint_flags |= GDK_HINT_POS; + if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS; + if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE; + } + if (user_position) { hint_flags &= ~GDK_HINT_POS; diff --git a/src/xterm.c b/src/xterm.c index 7856793f8d..4f9eff6c5e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10056,11 +10056,26 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ f->size_hint_flags |= YNegative; f->win_gravity = NorthWestGravity; } + x_calc_absolute_position (f); block_input (); x_wm_set_size_hint (f, 0, false); +#ifdef USE_GTK + if (x_gtk_use_window_move) + { + /* When a position change was requested and the outer GTK widget + has been realized already, leave it to gtk_window_move to DTRT + and return. Used for Bug#25851 and Bug#25943. */ + if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + unblock_input (); + return; + } +#endif /* USE_GTK */ + modified_left = f->left_pos; modified_top = f->top_pos; @@ -12905,4 +12920,11 @@ state. Set this variable only if your window manager cannot handle the transition between the various maximization states. */); x_frame_normalize_before_maximize = false; + + DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move, + doc: /* Non-nil means rely on gtk_window_move to set frame positions. +If this variable is t, the GTK build uses the function gtk_window_move +to set or store frame positions and disables some time consuming frame +position adjustments. */); + x_gtk_use_window_move = false; } commit 560d6f91246ee90ac6e630ae941097a4d4f8f730 Author: Michael Albinus Date: Wed Mar 22 19:33:03 2017 +0000 Fix filenotify.el issue for kqueue * lisp/filenotify.el (file-notify-add-watch): Use directory for remote file name handlers. * test/lisp/filenotify-tests.el (file-notify-test01-add-watch): Create/delete temporary file only for "kqueue". (file-notify-test02-rm-watch): Create/delete temporary files. diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 7eb6229976..80e9f898b2 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -347,13 +347,7 @@ FILE is the name of the file whose event is being reported." (if handler ;; A file name handler could exist even if there is no local ;; file notification support. - (setq desc (funcall - handler 'file-notify-add-watch - ;; kqueue does not report file changes in - ;; directory monitor. So we must watch the file - ;; itself. - (if (eq file-notify--library 'kqueue) file dir) - flags callback)) + (setq desc (funcall handler 'file-notify-add-watch dir flags callback)) ;; Check, whether Emacs has been compiled with file notification ;; support. @@ -391,6 +385,8 @@ FILE is the name of the file whose event is being reported." ;; Call low-level function. (setq desc (funcall + ;; kqueue does not report file changes in directory + ;; monitor. So we must watch the file itself. func (if (eq file-notify--library 'kqueue) file dir) l-flags 'file-notify-callback))) diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 654e1af112..329ea58d3b 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -294,13 +294,20 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (file-notify-add-watch temporary-file-directory '(change attribute-change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + + ;; File monitors like kqueue insist, that the watched file + ;; exists. Directory monitors are not bound to this + ;; restriction. + (when (string-equal (file-notify--test-library) "kqueue") + (write-region + "any text" nil file-notify--test-tmpfile nil 'no-message)) (should (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile '(change attribute-change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) - (delete-file file-notify--test-tmpfile) + (when (string-equal (file-notify--test-library) "kqueue") + (delete-file file-notify--test-tmpfile)) ;; Check error handling. (should-error (file-notify-add-watch 1 2 3 4) @@ -378,6 +385,8 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (progn (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) (should (setq file-notify--test-desc (file-notify-add-watch @@ -390,6 +399,8 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (file-notify-rm-watch file-notify--test-desc) (file-notify-rm-watch file-notify--test-desc) (file-notify-rm-watch file-notify--test-desc1) + (delete-file file-notify--test-tmpfile) + (delete-file file-notify--test-tmpfile1) ;; The environment shall be cleaned up. (file-notify--test-cleanup-p)) commit 716b46848989bc343797d98488a7a0cc33ed3179 Author: Michael Albinus Date: Wed Mar 22 14:15:45 2017 +0100 Extend `file-notify-test02-rm-watch' * test/lisp/filenotify-tests.el (file-notify-test02-rm-watch): Expect it failed for inotify. Divide tests into different `unwind-protect' clauses. Check, that removing watch descriptors out of order do not harm. (Bug#26126) diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 7208032237..654e1af112 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -340,20 +340,24 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (expand-file-name (make-temp-name "file-notify-test") temporary-file-directory)) -;; This test is inspired by Bug#26127. +;; This test is inspired by Bug#26126 and Bug#26127. (ert-deftest file-notify-test02-rm-watch () "Check `file-notify-rm-watch'." + ;; There is a problem with inotify removing watch descriptors out of + ;; order. Temporarily, we expect to fail this test until it is + ;; fixed. + :expected-result + (if (string-equal (file-notify--test-library) "inotify") :failed :passed) (skip-unless (file-notify--test-local-enabled)) (unwind-protect + ;; Check, that `file-notify-rm-watch' works. (progn - ;; Check, that `file-notify-rm-watch' works. (should (setq file-notify--test-desc (file-notify-add-watch temporary-file-directory '(change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) - ;; Check, that any parameter is accepted. (condition-case err (progn @@ -363,7 +367,15 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (file-notify-rm-watch 'foo)) (error (ert-fail err))) - ;; Check, that no error is returned removing a watch descriptor twice. + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + ;; Cleanup. + (file-notify--test-cleanup)) + + (unwind-protect + ;; Check, that no error is returned removing a watch descriptor twice. + (progn (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) (should @@ -374,6 +386,7 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (setq file-notify--test-desc1 (file-notify-add-watch file-notify--test-tmpfile1 '(change) #'ignore))) + ;; Remove `file-notify--test-desc' twice. (file-notify-rm-watch file-notify--test-desc) (file-notify-rm-watch file-notify--test-desc) (file-notify-rm-watch file-notify--test-desc1) @@ -382,6 +395,40 @@ This returns only for the local case and gfilenotify; otherwise it is nil. (file-notify--test-cleanup-p)) ;; Cleanup. + (file-notify--test-cleanup)) + + (unwind-protect + ;; Check, that removing watch descriptors out of order do not harm. + (let (results) + (cl-flet ((first-callback (event) + (when (eq (nth 1 event) 'deleted) (push 1 results))) + (second-callback (event) + (when (eq (nth 1 event) 'deleted) (push 2 results)))) + (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) + (write-region + "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile + '(change) #'first-callback))) + (should + (setq file-notify--test-desc1 + (file-notify-add-watch + file-notify--test-tmpfile + '(change) #'second-callback))) + ;; Remove first watch. + (file-notify-rm-watch file-notify--test-desc) + ;; Only the second callback shall run. + (delete-file file-notify--test-tmpfile) + (file-notify--wait-for-events + (file-notify--test-timeout) results) + (should (equal results (list 2))) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) + + ;; Cleanup. (file-notify--test-cleanup))) (file-notify--deftest-remote file-notify-test02-rm-watch