commit b3dd0ce75ba9314eb7a682e5fcf8b4cfbc67655b (HEAD, refs/remotes/origin/master) Author: Martin Rudalics Date: Thu Jun 10 09:14:21 2021 +0200 Provide new option `delete-window-set-selected' (Bug#47300) When `delete-window' deletes its frame's selected window, this new option allows to choose another window as replacement. * lisp/window.el (get-lru-window, get-mru-window) (get-largest-window): New optional argument NO-OTHER. (window-at-pos): New function. (delete-window-set-selected): New option. (delete-window): Handle `delete-window-set-selected'. * src/window.c (Fdelete_window_internal): Set the selected window of WINDOW's frame to the first window on that frame and let `delete-window' choose a more suitable window instead. * doc/lispref/windows.texi (Deleting Windows): Describe new option `delete-window-set-selected'. (Cyclic Window Ordering): Describe new NO-OTHER argument for `get-lru-window', `get-mru-window' and `get-largest-window'. * etc/NEWS: Mention `delete-window-set-selected' and the NO-OTHER argument. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 44656c057a..bcb492d68f 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -1318,6 +1318,23 @@ lieu of the usual action of @code{delete-window}. @xref{Window Parameters}. @end deffn +When @code{delete-window} deletes the selected window of its frame, it +has to make another window the new selected window of that frame. The +following option allows to choose which window gets selected instead. + +@defopt delete-window-set-selected +This option allows to specify which window should become a frame's +selected window after @code{delete-window} has deleted the previously +selected one. + +Possible choices are @code{mru} (the default) to select the most +recently used window on that frame and @code{pos} to choose the window +at the position of point of the previously selected window. If this +option is @code{nil}, it means to choose the frame's first window +instead. Note that a window with a non-@code{nil} +@code{no-other-window} parameter is never chosen. +@end defopt + @deffn Command delete-other-windows &optional window This function makes @var{window} fill its frame, deleting other windows as necessary. If @var{window} is omitted or @code{nil}, it @@ -2007,7 +2024,7 @@ meaning as for @code{next-window}. criterion, without selecting it: @cindex least recently used window -@defun get-lru-window &optional all-frames dedicated not-selected +@defun get-lru-window &optional all-frames dedicated not-selected no-other This function returns a live window which is heuristically the least recently used. The optional argument @var{all-frames} has the same meaning as in @code{next-window}. @@ -2018,33 +2035,25 @@ window (@pxref{Dedicated Windows}) is never a candidate unless the optional argument @var{dedicated} is non-@code{nil}. The selected window is never returned, unless it is the only candidate. However, if the optional argument @var{not-selected} is non-@code{nil}, this -function returns @code{nil} in that case. +function returns @code{nil} in that case. The optional argument +@var{no-other}, if non-@code{nil}, means to never return a window whose +@code{no-other-window} parameter is non-@code{nil}. @end defun @cindex most recently used window -@defun get-mru-window &optional all-frames dedicated not-selected +@defun get-mru-window &optional all-frames dedicated not-selected no-other This function is like @code{get-lru-window}, but it returns the most recently used window instead. The meaning of the arguments is the -same as described for @code{get-lru-window}. +same as for @code{get-lru-window}. @end defun @cindex largest window -@defun get-largest-window &optional all-frames dedicated not-selected +@defun get-largest-window &optional all-frames dedicated not-selected no-other This function returns the window with the largest area (height times -width). The optional argument @var{all-frames} specifies the windows to -search, and has the same meaning as in @code{next-window}. - -A minibuffer window is never a candidate. A dedicated window -(@pxref{Dedicated Windows}) is never a candidate unless the optional -argument @var{dedicated} is non-@code{nil}. The selected window is not -a candidate if the optional argument @var{not-selected} is -non-@code{nil}. If the optional argument @var{not-selected} is -non-@code{nil} and the selected window is the only candidate, this -function returns @code{nil}. - -If there are two candidate windows of the same size, this function -prefers the one that comes first in the cyclic ordering of windows, -starting from the selected window. +width). If there are two candidate windows of the same size, it prefers +the one that comes first in the cyclic ordering of windows, starting +from the selected window. The meaning of the arguments is the same as +for @code{get-lru-window}. @end defun @cindex window that satisfies a predicate diff --git a/etc/NEWS b/etc/NEWS index 3075fa0cd4..06c6efd995 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -604,6 +604,17 @@ These options include 'windmove-default-keybindings', ** Windows ++++ +*** New option 'delete-window-set-selected'. +This allows to choose a frame's selected window after deleting the +previously selected one. + ++++ +*** New argument NO-OTHER for some window functions. +'get-lru-window', ‘get-mru-window’ and 'get-largest-window' now accept a +new optional argument NO-OTHER which if non-nil avoids returning a +window whose 'no-other-window' parameter is non-nil. + +++ *** New 'display-buffer' function 'display-buffer-use-least-recent-window'. This is like 'display-buffer-use-some-window', but won't reuse the diff --git a/lisp/window.el b/lisp/window.el index fd1c617d6b..e7551f30c3 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -2499,14 +2499,16 @@ and no others." (defalias 'some-window 'get-window-with-predicate) -(defun get-lru-window (&optional all-frames dedicated not-selected) +(defun get-lru-window (&optional all-frames dedicated not-selected no-other) "Return the least recently used window on frames specified by ALL-FRAMES. Return a full-width window if possible. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Avoid returning the selected window if possible. Optional argument NOT-SELECTED non-nil means never return the -selected window. +selected window. Optional argument NO-OTHER non-nil means to +never return a window whose 'no-other-window' parameter is +non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2526,7 +2528,9 @@ selected frame and no others." (let (best-window best-time second-best-window second-best-time time) (dolist (window (window-list-1 nil 'nomini all-frames)) (when (and (or dedicated (not (window-dedicated-p window))) - (or (not not-selected) (not (eq window (selected-window))))) + (or (not not-selected) (not (eq window (selected-window)))) + (or (not no-other) + (not (window-parameter window 'no-other-window)))) (setq time (window-use-time window)) (if (or (eq window (selected-window)) (not (window-full-width-p window))) @@ -2538,12 +2542,14 @@ selected frame and no others." (setq best-window window))))) (or best-window second-best-window))) -(defun get-mru-window (&optional all-frames dedicated not-selected) +(defun get-mru-window (&optional all-frames dedicated not-selected no-other) "Return the most recently used window on frames specified by ALL-FRAMES. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED -non-nil means never return the selected window. +non-nil means never return the selected window. Optional +argument NO-OTHER non-nil means to never return a window whose +'no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2565,17 +2571,21 @@ selected frame and no others." (setq time (window-use-time window)) (when (and (or dedicated (not (window-dedicated-p window))) (or (not not-selected) (not (eq window (selected-window)))) - (or (not best-time) (> time best-time))) + (or (not no-other) + (not (window-parameter window 'no-other-window))) + (or (not best-time) (> time best-time))) (setq best-time time) (setq best-window window))) best-window)) -(defun get-largest-window (&optional all-frames dedicated not-selected) +(defun get-largest-window (&optional all-frames dedicated not-selected no-other) "Return the largest window on frames specified by ALL-FRAMES. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED -non-nil means never return the selected window. +non-nil means never return the selected window. Optional +argument NO-OTHER non-nil means to never return a window whose +'no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2596,7 +2606,9 @@ selected frame and no others." best-window size) (dolist (window (window-list-1 nil 'nomini all-frames)) (when (and (or dedicated (not (window-dedicated-p window))) - (or (not not-selected) (not (eq window (selected-window))))) + (or (not not-selected) (not (eq window (selected-window)))) + (or (not no-other) + (not (window-parameter window 'no-other-window)))) (setq size (* (window-pixel-height window) (window-pixel-width window))) (when (> size best-size) @@ -4130,18 +4142,53 @@ frame can be safely deleted." ;; of its frame. t)))) -(defun window--in-subtree-p (window root) - "Return t if WINDOW is either ROOT or a member of ROOT's subtree." - (or (eq window root) - (let ((parent (window-parent window))) - (catch 'done - (while parent - (if (eq parent root) - (throw 'done t) - (setq parent (window-parent parent)))))))) +(defun window-at-pos (x y &optional frame no-other) + "Return live window at coordinates X, Y on specified FRAME. +X and Y are counted in pixels from an origin at 0, 0 of FRAME's +native frame. A coordinate on an edge shared by two windows is +attributed to the window on the right (or below). Return nil if +no such window can be found. + +Optional argument FRAME must specify a live frame and defaults to +the selected one. Optional argument NO-OTHER non-nil means to +not return a window with a non-nil 'no-other-window' parameter." + (setq frame (window-normalize-frame frame)) + (let* ((root-edges (window-edges (frame-root-window frame) nil nil t)) + (root-left (nth 2 root-edges)) + (root-bottom (nth 3 root-edges))) + (catch 'window + (walk-window-tree + (lambda (window) + (let ((edges (window-edges window nil nil t))) + (when (and (>= x (nth 0 edges)) + (or (< x (nth 2 edges)) (= x root-left)) + (>= y (nth 1 edges)) + (or (< y (nth 3 edges)) (= y root-bottom))) + (if (and no-other (window-parameter window 'no-other-window)) + (throw 'window nil) + (throw 'window window))))) + frame)))) + +(defcustom delete-window-set-selected 'mru + "How to choose a frame's selected window after window deletion. +When a frame's selected window gets deleted, Emacs has to choose +another live window on that frame to serve as its selected +window. This option allows to control which window gets selected +instead. + +The possible choices are 'mru' (the default) to select the most +recently used window on that frame and 'pos' to choose the window +at the position of point of the previously selected window. If +this is nil, choose the frame's first window instead. A window +with a non-nil 'no-other-window' parameter is never chosen." + :type '(choice (const :tag "Most recently used" mru) + (const :tag "At position of deleted" pos) + (const :tag "Frame's first " nil)) + :group 'windows + :version "28.1") (defun delete-window (&optional window) - "Delete WINDOW. + "Delete specified WINDOW. WINDOW must be a valid window and defaults to the selected one. Return nil. @@ -4156,7 +4203,11 @@ Otherwise, if WINDOW is part of an atomic window, call `delete-window' with the root of the atomic window as its argument. Signal an error if WINDOW is either the only window on its frame, the last non-side window, or part of an atomic window -that is its frame's root window." +that is its frame's root window. + +If WINDOW is the selected window on its frame, choose some other +window as that frame's selected window according to the value of +the option `delete-window-set-selected'." (interactive) (setq window (window-normalize-window window)) (let* ((frame (window-frame window)) @@ -4191,11 +4242,11 @@ that is its frame's root window." (window-combination-resize (or window-combination-resize (window-parameter parent 'window-side))) - (frame-selected - (window--in-subtree-p (frame-selected-window frame) window)) + (frame-selected-window (frame-selected-window frame)) ;; Emacs 23 preferably gives WINDOW's space to its left ;; sibling. - (sibling (or (window-left window) (window-right window)))) + (sibling (or (window-left window) (window-right window))) + frame-selected-window-edges frame-selected-window-pos) (window--resize-reset frame horizontal) (cond ((and (not (eq window-combination-resize t)) @@ -4211,15 +4262,63 @@ that is its frame's root window." (t ;; Can't do without resizing fixed-size windows. (window--resize-siblings window (- size) horizontal t))) + + (when (eq delete-window-set-selected 'pos) + ;; Remember edges and position of point of the selected window + ;; of WINDOW'S frame. + (setq frame-selected-window-edges + (window-edges frame-selected-window nil nil t)) + (setq frame-selected-window-pos + (nth 2 (posn-at-point nil frame-selected-window)))) + ;; Actually delete WINDOW. (delete-window-internal window) (window--pixel-to-total frame horizontal) - (when (and frame-selected - (window-parameter - (frame-selected-window frame) 'no-other-window)) - ;; `delete-window-internal' has selected a window that should - ;; not be selected, fix this here. - (other-window -1 frame)) + + ;; If we deleted the selected window of WINDOW's frame, choose + ;; another one based on `delete-window-set-selected'. Note + ;; that both `window-at-pos' and `get-mru-window' may fail to + ;; produce a suitable window in which case we will fall back on + ;; its frame's first window, chosen by `delete-window-internal'. + (cond + ((window-live-p frame-selected-window)) + ((and frame-selected-window-pos + ;; We have a recorded position of point of the previously + ;; selected window. Try to find the window that is now + ;; at that position. + (let ((new-frame-selected-window + (window-at-pos + (+ (nth 0 frame-selected-window-edges) + (car frame-selected-window-pos)) + (+ (nth 1 frame-selected-window-edges) + (cdr frame-selected-window-pos)) + frame t))) + (and new-frame-selected-window + ;; Select window at WINDOW's position at point. + (set-frame-selected-window + frame new-frame-selected-window))))) + ((and (eq delete-window-set-selected 'mru) + ;; Try to use the most recently used window. + (let ((mru-window (get-mru-window frame nil nil t))) + (and mru-window + (set-frame-selected-window frame mru-window))))) + ((and (window-parameter + (frame-selected-window frame) 'no-other-window) + ;; If `delete-window-internal' selected a window with a + ;; non-nil 'no-other-window' parameter as its frame's + ;; selected window, try to choose another one. + (catch 'found + (walk-window-tree + (lambda (other) + (unless (window-parameter other 'no-other-window) + (set-frame-selected-window frame other) + (throw 'found t))) + frame)))) + (t + ;; Record the window chosen by `delete-window-internal'. + (set-frame-selected-window + frame (frame-selected-window frame)))) + (window--check frame) ;; Always return nil. nil)))) diff --git a/src/window.c b/src/window.c index 2d98ae5f15..db324effcc 100644 --- a/src/window.c +++ b/src/window.c @@ -5148,15 +5148,13 @@ Signal an error when WINDOW is the only window on its frame. */) adjust_frame_glyphs (f); if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) - /* We deleted the frame's selected window. */ + /* We apparently deleted the frame's selected window; use the + frame's first window as substitute but don't record it yet. + `delete-window' may have something better up its sleeves. */ { /* Use the frame's first window as fallback ... */ Lisp_Object new_selected_window = Fframe_first_window (frame); - /* ... but preferably use its most recently used window. */ - Lisp_Object mru_window; - /* `get-mru-window' might fail for some reason so play it safe - - promote the first window _without recording it_ first. */ if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) Fselect_window (new_selected_window, Qt); else @@ -5164,24 +5162,9 @@ Signal an error when WINDOW is the only window on its frame. */) last selected window on F was an active minibuffer, we want to return to it on a later Fselect_frame. */ fset_selected_window (f, new_selected_window); - - unblock_input (); - - /* Now look whether `get-mru-window' gets us something. */ - mru_window = call1 (Qget_mru_window, frame); - if (WINDOW_LIVE_P (mru_window) - && EQ (XWINDOW (mru_window)->frame, frame)) - new_selected_window = mru_window; - - /* If all ended up well, we now promote the mru window. */ - if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) - Fselect_window (new_selected_window, Qnil); - else - fset_selected_window (f, new_selected_window); } - else - unblock_input (); + unblock_input (); FRAME_WINDOW_CHANGE (f) = true; } else commit dd9385b404c28a155a91960a4f1c4c77fdc5413d Author: Harald Jörg Date: Wed Jun 9 22:58:53 2021 +0200 ; perl-mode.el: Detect quote-like operator immediately after => * lisp/progmodes/perl-mode.el (perl-syntax-propertize-function): Detect a quotelike operator immediately after a fat comma "=>" (Bug#25098) * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-bug-25098): Test case for the bug with code from the bug report. * test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl: Resource file for the test. diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el index d13c9053d5..a20887621e 100644 --- a/lisp/progmodes/perl-mode.el +++ b/lisp/progmodes/perl-mode.el @@ -285,7 +285,7 @@ (put-text-property (match-beginning 2) (match-end 2) 'syntax-table (string-to-syntax "\"")) (perl-syntax-propertize-special-constructs end))))) - ("\\(^\\|[?:.,;=|&!~({[ \t]\\)\\([msy]\\|q[qxrw]?\\|tr\\)\\>\\s-*\\(?:\\([^])}>= \n\t]\\)\\|\\(?3:=\\)[^>]\\)" + ("\\(^\\|[?:.,;=|&!~({[ \t]\\|=>\\)\\([msy]\\|q[qxrw]?\\|tr\\)\\>\\s-*\\(?:\\([^])}>= \n\t]\\)\\|\\(?3:=\\)[^>]\\)" ;; Nasty cases: ;; /foo/m $a->m $#m $m @m %m ;; \s (appears often in regexps). diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl new file mode 100644 index 0000000000..0987b4e02c --- /dev/null +++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl @@ -0,0 +1,21 @@ +# Code from the bug report Bug#25098 + +my $good = XML::LibXML->load_xml( string => q{
}); +my $bad = XML::LibXML->load_xml( string =>q{
}); + +# Related: Method calls are no quotelike operators. That's why you +# can't just add '>' to the character class. + +my $method_call = $object->q(argument); + +# Also related, still not fontified correctly: +# +# my $method_call = $object -> q (argument); +# +# perl-mode interprets the method call as a quotelike op (because it +# is preceded by a space). +# cperl-mode gets the argument right, but marks q as a quotelike op. +# +# my $greater = 2>q/1/; +# +# perl-mode doesn't identify this as a quotelike op. diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el index 036e20d7cc..dcf4f398c2 100644 --- a/test/lisp/progmodes/cperl-mode-tests.el +++ b/test/lisp/progmodes/cperl-mode-tests.el @@ -397,6 +397,24 @@ Regular expressions are strings in both perl-mode and cperl-mode." (search-forward "RIGHT") (should (nth 3 (syntax-ppss))))) +(ert-deftest cperl-test-bug-25098 () + "Verify that a quotelike operator is recognized after a fat comma \"=>\". +Related, check that calling a method named q is not mistaken as a +quotelike operator." + (with-temp-buffer + (insert-file-contents (ert-resource-file "cperl-bug-25098.pl")) + (funcall cperl-test-mode) + (goto-char (point-min)) + ;; good example from the bug report, with a space + (search-forward "q{") + (should (nth 3 (syntax-ppss))) + ;; bad (but now fixed) example from the bug report, without space + (search-forward "q{") + (should (nth 3 (syntax-ppss))) + ;; calling a method "q" (parens instead of braces to make it valid) + (search-forward "q(") + (should-not (nth 3 (syntax-ppss))))) + (ert-deftest cperl-test-bug-28650 () "Verify that regular expressions are recognized after 'return'. The test uses the syntax property \"inside a string\" for the commit ff65ea932cdcf69a3f5109327ec8e6a7e3432107 Author: Alan Third Date: Sat Jun 5 14:38:17 2021 +0100 Remove pause on fullscreening in NS (bug#48406) * src/nsterm.m (ns_make_frame_visible): (ns_set_parent_frame): ([EmacsView windowWillEnterFullScreen:]): ([EmacsView windowDidEnterFullScreen:]): ([EmacsView windowWillExitFullScreen:]): ([EmacsView initFrameFromEmacs:]): Remove references to in_fullscreen_transition. ([EmacsView toggleFullScreen:]): Remove calls to removed methods. ([EmacsView inFullScreenTransition]): ([EmacsView waitFullScreenTransition]): Remove Methods. * src/nsterm.h (EmacsView): Remove defintions of removed methods, and the in_fullscreen_transition variable. diff --git a/src/nsterm.h b/src/nsterm.h index 0596f3f3c1..e7ea907569 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -443,7 +443,6 @@ typedef id instancetype; int maximized_width, maximized_height; NSWindow *nonfs_window; BOOL fs_is_native; - BOOL in_fullscreen_transition; #ifdef NS_DRAW_TO_BUFFER EmacsSurface *surface; #endif @@ -475,8 +474,6 @@ typedef id instancetype; - (void) toggleFullScreen: (id) sender; - (BOOL) fsIsNative; - (BOOL) isFullscreen; -- (BOOL) inFullScreenTransition; -- (void) waitFullScreenTransition; #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - (void) updateCollectionBehavior; #endif diff --git a/src/nsterm.m b/src/nsterm.m index f6168243a4..838c14d5ab 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1640,8 +1640,6 @@ -(void)remove fullscreen also. So skip handleFS as this will print an error. */ if ([view fsIsNative] && [view isFullscreen]) { - // maybe it is not necessary to wait - [view waitFullScreenTransition]; return; } @@ -2057,11 +2055,7 @@ so some key presses (TAB) are swallowed by the system. */ #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 // child frame must not be in fullscreen if ([view fsIsNative] && [view isFullscreen]) - { - // in case child is going fullscreen - [view waitFullScreenTransition]; - [view toggleFullScreen:child]; - } + [view toggleFullScreen:child]; NSTRACE ("child setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary"); [child setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; #endif @@ -7489,7 +7483,6 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f #endif fs_is_native = ns_use_native_fullscreen; #endif - in_fullscreen_transition = NO; maximized_width = maximized_height = -1; nonfs_window = nil; @@ -7862,7 +7855,6 @@ - (NSApplicationPresentationOptions)window:(NSWindow *)window - (void)windowWillEnterFullScreen:(NSNotification *)notification { NSTRACE ("[EmacsView windowWillEnterFullScreen:]"); - in_fullscreen_transition = YES; [self windowWillEnterFullScreen]; } - (void)windowWillEnterFullScreen /* provided for direct calls */ @@ -7875,7 +7867,6 @@ - (void)windowDidEnterFullScreen:(NSNotification *)notification { NSTRACE ("[EmacsView windowDidEnterFullScreen:]"); [self windowDidEnterFullScreen]; - in_fullscreen_transition = NO; } - (void)windowDidEnterFullScreen /* provided for direct calls */ @@ -7914,7 +7905,6 @@ - (void)windowDidEnterFullScreen /* provided for direct calls */ - (void)windowWillExitFullScreen:(NSNotification *)notification { NSTRACE ("[EmacsView windowWillExitFullScreen:]"); - in_fullscreen_transition = YES; [self windowWillExitFullScreen]; } @@ -7934,7 +7924,6 @@ - (void)windowDidExitFullScreen:(NSNotification *)notification { NSTRACE ("[EmacsView windowDidExitFullScreen:]"); [self windowDidExitFullScreen]; - in_fullscreen_transition = NO; } - (void)windowDidExitFullScreen /* provided for direct calls */ @@ -7963,22 +7952,6 @@ - (void)windowDidExitFullScreen /* provided for direct calls */ [[self window] performZoom:self]; } -- (BOOL)inFullScreenTransition -{ - return in_fullscreen_transition; -} - -- (void)waitFullScreenTransition -{ -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - while ([self inFullScreenTransition]) - { - NSTRACE ("wait for fullscreen"); - wait_reading_process_output (0, 300000000, 0, 1, Qnil, NULL, 0); - } -#endif -} - - (BOOL)fsIsNative { return fs_is_native; @@ -8058,14 +8031,8 @@ - (void)toggleFullScreen: (id)sender #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 if ([[self window] respondsToSelector: @selector(toggleFullScreen:)]) - { -#endif - [[self window] toggleFullScreen:sender]; - // wait for fullscreen animation complete (bug#28496) - [self waitFullScreenTransition]; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 - } #endif + [[self window] toggleFullScreen:sender]; #endif return; } commit 5b68e7b48805bd3d19c67591c28b140a4ed4a937 Author: Glenn Morris Date: Wed Jun 9 09:51:18 2021 -0700 * lib/Makefile.in (Makefile): Fix typo. diff --git a/lib/Makefile.in b/lib/Makefile.in index ec92f92fb3..ccb90c3d1b 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -64,7 +64,7 @@ endif ../config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 $(MAKE) -C .. $(notdir $@) Makefile: ../config.status $(srcdir)/Makefile.in - $(MAKE) -C .. src/$@ + $(MAKE) -C .. lib/$@ # Object modules that need not be built for Emacs. # Emacs does not need e-regex.o (it has its own regex-emacs.c), commit fb62846b68bd12f90dc16f1b0dd326546d41ec49 Author: Alan Third Date: Tue Jun 8 20:08:34 2021 +0100 Fix image filename encoding issues (bug#48902) * src/image.c (image_find_image_fd): Don't return an encoded filename string. * src/nsfns.m: ([NSString stringWithLispString:]): Clarify usage comment. * src/nsimage.m ([EmacsImage allocInitFromFile:]): No need to encode the filename when converting to NSString. diff --git a/src/image.c b/src/image.c index b34dc3e916..07de4d31aa 100644 --- a/src/image.c +++ b/src/image.c @@ -3153,19 +3153,16 @@ image_find_image_fd (Lisp_Object file, int *pfd) /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ fd = openp (search_path, file, Qnil, &file_found, pfd ? Qt : make_fixnum (R_OK), false, false); - if (fd >= 0 || fd == -2) + if (fd == -2) { - file_found = ENCODE_FILE (file_found); - if (fd == -2) - { - /* The file exists locally, but has a file name handler. - (This happens, e.g., under Auto Image File Mode.) - 'openp' didn't open the file, so we should, because the - caller expects that. */ - fd = emacs_open (SSDATA (file_found), O_RDONLY, 0); - } + /* The file exists locally, but has a file name handler. + (This happens, e.g., under Auto Image File Mode.) + 'openp' didn't open the file, so we should, because the + caller expects that. */ + Lisp_Object encoded_name = ENCODE_FILE (file_found); + fd = emacs_open (SSDATA (encoded_name), O_RDONLY, 0); } - else /* fd < 0, but not -2 */ + else if (fd < 0) return Qnil; if (pfd) *pfd = fd; @@ -3173,8 +3170,8 @@ image_find_image_fd (Lisp_Object file, int *pfd) } /* Find image file FILE. Look in data-directory/images, then - x-bitmap-file-path. Value is the encoded full name of the file - found, or nil if not found. */ + x-bitmap-file-path. Value is the full name of the file found, or + nil if not found. */ Lisp_Object image_find_image_file (Lisp_Object file) diff --git a/src/nsfns.m b/src/nsfns.m index d14f7b51ea..98801d8526 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -3024,7 +3024,8 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename } @implementation NSString (EmacsString) -/* Make an NSString from a Lisp string. */ +/* Make an NSString from a Lisp string. STRING must not be in an + encoded form (e.g. UTF-8). */ + (NSString *)stringWithLispString:(Lisp_Object)string { /* Shortcut for the common case. */ diff --git a/src/nsimage.m b/src/nsimage.m index fa81a41a51..3c16cd371e 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -254,15 +254,15 @@ + (instancetype)allocInitFromFile: (Lisp_Object)file NSImageRep *imgRep; Lisp_Object found; EmacsImage *image; + NSString *filename; /* Search bitmap-file-path for the file, if appropriate. */ found = image_find_image_file (file); if (!STRINGP (found)) return nil; - found = ENCODE_FILE (found); + filename = [NSString stringWithLispString:found]; - image = [[EmacsImage alloc] initByReferencingFile: - [NSString stringWithLispString: found]]; + image = [[EmacsImage alloc] initByReferencingFile:filename]; image->bmRep = nil; #ifdef NS_IMPL_COCOA @@ -277,8 +277,7 @@ + (instancetype)allocInitFromFile: (Lisp_Object)file } [image setSize: NSMakeSize([imgRep pixelsWide], [imgRep pixelsHigh])]; - - [image setName: [NSString stringWithLispString: file]]; + [image setName:filename]; return image; } commit a63587c546144b349122a2ec126167c2c10fc4d5 Author: Michael Albinus Date: Wed Jun 9 13:01:09 2021 +0200 * etc/NEWS: New user option 'shell-has-auto-cd'. diff --git a/etc/NEWS b/etc/NEWS index 3dca94f97b..3075fa0cd4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -892,7 +892,7 @@ instead of sets, the process mark. +++ *** New user option 'gnus-process-mark-toggle'. -If non-nil (the default), the `#' command in the Group and Summary +If non-nil (the default), the '#' command in the Group and Summary buffers will toggle, instead of set, the process mark. @@ -1319,6 +1319,12 @@ it when producing a doc string. This is bound to 'C-x n d' in 'shell-mode' buffers, and narrows to the command line under point (and any following output). +--- +*** New user option 'shell-has-auto-cd'. +If non-nil, 'shell-mode' handles implicit "cd" commands, changing the +directory if the command is a directory. Useful for shells like "zsh" +that has this feature. + ** Eshell --- commit e67883bc2b99f48a3c46c3d8a00123306a62b27d Author: Jason Kim Date: Wed Jun 9 11:44:34 2021 +0200 Handle auto-cd in shell-mode * lisp/shell.el (shell-has-auto-cd): New defcustom. (shell-directory-tracker): Handle implicit "cd". Copyright-paperwork-exempt: yes diff --git a/lisp/shell.el b/lisp/shell.el index 3098d3a14d..62de5be817 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -321,6 +321,15 @@ Thus, this does not include the shell's current directory.") (defvar shell-dirstack-query nil "Command used by `shell-resync-dirs' to query the shell.") +(defcustom shell-has-auto-cd nil + "If non-nil, `shell-mode' handles implicit \"cd\" commands. +Implicit \"cd\" is changing the directory if the command is a directory. +You can make this variable buffer-local to change it, per shell-mode instance. +Useful for shells like zsh that has this feature." + :type 'boolean + :group 'shell-directories + :version "28.1") + (defvar shell-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-c\C-f" 'shell-forward-command) @@ -836,13 +845,15 @@ Environment variables are expanded, see function `substitute-in-file-name'." str) ; skip whitespace (match-end 0))) (case-fold-search) - end cmd arg1) + end cmd arg1 cmd-subst-fn) (while (string-match shell-command-regexp str start) (setq end (match-end 0) cmd (comint-arguments (substring str start end) 0 0) arg1 (comint-arguments (substring str start end) 1 1)) (if arg1 (setq arg1 (shell-unquote-argument arg1))) + (if shell-has-auto-cd + (setq cmd-subst-fn (comint-substitute-in-file-name cmd))) (cond ((string-match (concat "\\`\\(" shell-popd-regexp "\\)\\($\\|[ \t]\\)") cmd) @@ -859,7 +870,9 @@ Environment variables are expanded, see function `substitute-in-file-name'." (string-match (concat "\\`\\(" shell-chdrive-regexp "\\)\\($\\|[ \t]\\)") cmd)) - (shell-process-cd (comint-substitute-in-file-name cmd)))) + (shell-process-cd (comint-substitute-in-file-name cmd))) + ((and shell-has-auto-cd (file-directory-p cmd-subst-fn)) + (shell-process-cd cmd-subst-fn))) (setq start (progn (string-match shell-command-separator-regexp str end) ;; skip again