diff options
| author | Daniel Colascione | 2018-06-11 14:58:09 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2018-06-11 16:10:34 -0700 |
| commit | 2f6c682061a281dc3e397ff4727a164880e86e7b (patch) | |
| tree | f5990303d483f7d80e1aa1e80a19dc64a6325b66 | |
| parent | a20fe5a7e3577f9b9ad5e88006962966240d9b0c (diff) | |
| download | emacs-2f6c682061a281dc3e397ff4727a164880e86e7b.tar.gz emacs-2f6c682061a281dc3e397ff4727a164880e86e7b.zip | |
New focus management interface
focus-in-hook and focus-out-hook don't accurately reflect actual
user-visible focus states. Add a new focus interface and mark the old
one obsolete.
* doc/lispref/frames.texi (Input Focus): Document new focus
functions. Remove references to the now-obsolete focus hooks.
* lisp/frame.el (frame-focus-state): New function.
(after-focus-change-function): New variable.
(focus-in-hook, focus-out-hook): Move to lisp from C;
mark obsolete.
* lisp/term/xterm.el (xterm-translate-focus-in)
(xterm-translate-focus-out): Track tty focus in `tty-focus-state'
terminal parameter; call `after-focus-change-function'.
(xterm--suspend-tty-function): New function.
* src/frame.c (Fhandle_switch_frame): Update docstring; don't call
focus hooks.
(focus-in-hook, focus-out-hook): Remove: moved to lisp.
(syms_of_frame): Remove unread_switch_frame; add
Vunread_switch_frame.
* src/keyboard.c:
(Finternal_handle_focus_in): New function.
(make_lispy_event): Always report focus events to lisp; don't
translate them to switch events sometimes. Lisp can take care of
creating synthetic switch-frame events via
`internal-handle-focus-in'.
* src/w32term.c (x_focus_changed): Remove switch-avoidance logic:
just directly report focus changes to lisp.
* src/xterm.c (x_focus_changed): Remove switch-avoidance logic:
just directly report focus changes to lisp.
| -rw-r--r-- | doc/lispref/frames.texi | 102 | ||||
| -rw-r--r-- | etc/NEWS | 6 | ||||
| -rw-r--r-- | lisp/frame.el | 106 | ||||
| -rw-r--r-- | lisp/term/xterm.el | 11 | ||||
| -rw-r--r-- | src/frame.c | 25 | ||||
| -rw-r--r-- | src/keyboard.c | 65 | ||||
| -rw-r--r-- | src/w32term.c | 14 | ||||
| -rw-r--r-- | src/xterm.c | 10 |
8 files changed, 217 insertions, 122 deletions
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 459f05cb1c9..3a97ec01384 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi | |||
| @@ -2702,14 +2702,22 @@ This function returns the selected frame. | |||
| 2702 | Some window systems and window managers direct keyboard input to the | 2702 | Some window systems and window managers direct keyboard input to the |
| 2703 | window object that the mouse is in; others require explicit clicks or | 2703 | window object that the mouse is in; others require explicit clicks or |
| 2704 | commands to @dfn{shift the focus} to various window objects. Either | 2704 | commands to @dfn{shift the focus} to various window objects. Either |
| 2705 | way, Emacs automatically keeps track of which frame has the focus. To | 2705 | way, Emacs automatically keeps track of which frames have focus. To |
| 2706 | explicitly switch to a different frame from a Lisp function, call | 2706 | explicitly switch to a different frame from a Lisp function, call |
| 2707 | @code{select-frame-set-input-focus}. | 2707 | @code{select-frame-set-input-focus}. |
| 2708 | 2708 | ||
| 2709 | Lisp programs can also switch frames temporarily by calling the | 2709 | The plural ``frames'' in the previous paragraph is deliberate: while |
| 2710 | function @code{select-frame}. This does not alter the window system's | 2710 | Emacs itself has only one selected frame, Emacs can have frames on |
| 2711 | concept of focus; rather, it escapes from the window manager's control | 2711 | many different terminals (recall that a connection to a window system |
| 2712 | until that control is somehow reasserted. | 2712 | counts as a terminal), and each terminal has its own idea of which |
| 2713 | frame has input focus. When you set the input focus to a frame, you | ||
| 2714 | set the focus for that frame's terminal, but frames on other terminals | ||
| 2715 | may still remain focused. | ||
| 2716 | |||
| 2717 | Lisp programs can switch frames temporarily by calling the function | ||
| 2718 | @code{select-frame}. This does not alter the window system's concept | ||
| 2719 | of focus; rather, it escapes from the window manager's control until | ||
| 2720 | that control is somehow reasserted. | ||
| 2713 | 2721 | ||
| 2714 | When using a text terminal, only one frame can be displayed at a time | 2722 | When using a text terminal, only one frame can be displayed at a time |
| 2715 | on the terminal, so after a call to @code{select-frame}, the next | 2723 | on the terminal, so after a call to @code{select-frame}, the next |
| @@ -2720,11 +2728,11 @@ before the buffer name (@pxref{Mode Line Variables}). | |||
| 2720 | 2728 | ||
| 2721 | @defun select-frame-set-input-focus frame &optional norecord | 2729 | @defun select-frame-set-input-focus frame &optional norecord |
| 2722 | This function selects @var{frame}, raises it (should it happen to be | 2730 | This function selects @var{frame}, raises it (should it happen to be |
| 2723 | obscured by other frames) and tries to give it the X server's focus. | 2731 | obscured by other frames) and tries to give it the window system's |
| 2724 | On a text terminal, the next redisplay displays the new frame on the | 2732 | focus. On a text terminal, the next redisplay displays the new frame |
| 2725 | entire terminal screen. The optional argument @var{norecord} has the | 2733 | on the entire terminal screen. The optional argument @var{norecord} |
| 2726 | same meaning as for @code{select-frame} (see below). The return value | 2734 | has the same meaning as for @code{select-frame} (see below). |
| 2727 | of this function is not significant. | 2735 | The return value of this function is not significant. |
| 2728 | @end defun | 2736 | @end defun |
| 2729 | 2737 | ||
| 2730 | Ideally, the function described next should focus a frame without also | 2738 | Ideally, the function described next should focus a frame without also |
| @@ -2772,17 +2780,31 @@ could switch to a different terminal without switching back when | |||
| 2772 | you're done. | 2780 | you're done. |
| 2773 | @end deffn | 2781 | @end deffn |
| 2774 | 2782 | ||
| 2775 | Emacs cooperates with the window system by arranging to select frames as | 2783 | Emacs cooperates with the window system by arranging to select frames |
| 2776 | the server and window manager request. It does so by generating a | 2784 | as the server and window manager request. When a window system |
| 2777 | special kind of input event, called a @dfn{focus} event, when | 2785 | informs Emacs that one of its frames has been selected, Emacs |
| 2778 | appropriate. The command loop handles a focus event by calling | 2786 | internally generates a @dfn{focus-in} event. Focus events are |
| 2779 | @code{handle-switch-frame}. @xref{Focus Events}. | 2787 | normally handled by @code{handle-focus-in}. |
| 2788 | |||
| 2789 | @deffn Command handle-focus-in event | ||
| 2790 | This function handles focus-in events from window systems and | ||
| 2791 | terminals that support explicit focus notifications. It updates the | ||
| 2792 | per-frame focus flags that @code{frame-focus-state} queries and calls | ||
| 2793 | @code{after-focus-change-function}. In addition, it generates a | ||
| 2794 | @code{switch-frame} event in order to switch the Emacs notion of the | ||
| 2795 | selected frame to the frame most recently focused in some terminal. | ||
| 2796 | It's important to note that this switching of the Emacs selected frame | ||
| 2797 | to the most recently focused frame does not mean that other frames do | ||
| 2798 | not continue to have the focus in their respective terminals. Do not | ||
| 2799 | invoke this function yourself: instead, attach logic to | ||
| 2800 | @code{after-focus-change-function}. | ||
| 2801 | @end deffn | ||
| 2780 | 2802 | ||
| 2781 | @deffn Command handle-switch-frame frame | 2803 | @deffn Command handle-switch-frame frame |
| 2782 | This function handles a focus event by selecting frame @var{frame}. | 2804 | This function handles a switch-frame event, which Emacs generates for |
| 2783 | 2805 | itself upon focus notification or under various other circumstances | |
| 2784 | Focus events normally do their job by invoking this command. | 2806 | involving an input event arriving at a different frame from the last |
| 2785 | Don't call it for any other reason. | 2807 | event. Do not invoke this function yourself. |
| 2786 | @end deffn | 2808 | @end deffn |
| 2787 | 2809 | ||
| 2788 | @defun redirect-frame-focus frame &optional focus-frame | 2810 | @defun redirect-frame-focus frame &optional focus-frame |
| @@ -2816,14 +2838,42 @@ The redirection lasts until @code{redirect-frame-focus} is called to | |||
| 2816 | change it. | 2838 | change it. |
| 2817 | @end defun | 2839 | @end defun |
| 2818 | 2840 | ||
| 2819 | @defvar focus-in-hook | 2841 | @defun frame-focus-state frame |
| 2820 | This is a normal hook run when an Emacs frame gains input focus. The | 2842 | This function retrieves the last known focus state of @var{frame}. |
| 2821 | frame gaining focus is selected when this hook is run. | 2843 | |
| 2822 | @end defvar | 2844 | It returns @code{nil} if the frame is known not to be focused, |
| 2845 | @code{t} if the frame is known to be focused, or @code{unknown} if | ||
| 2846 | Emacs does not know the focus state of the frame. (You may see this | ||
| 2847 | last state in TTY frames running on terminals that do not support | ||
| 2848 | explicit focus notifications.) | ||
| 2849 | @end defun | ||
| 2823 | 2850 | ||
| 2824 | @defvar focus-out-hook | 2851 | @defvar after-focus-change-function |
| 2825 | This is a normal hook run when an Emacs frame has lost input focus and | 2852 | This function is an extension point that code can use to receive a |
| 2826 | no other Emacs frame has gained input focus instead. | 2853 | notification that focus has changed. |
| 2854 | |||
| 2855 | This function is called with no arguments when Emacs notices that the | ||
| 2856 | set of focused frames may have changed. Code wanting to do something | ||
| 2857 | when frame focus changes should use @code{add-function} to add a | ||
| 2858 | function to this one, and in this added function, re-scan the set of | ||
| 2859 | focused frames, calling @code{frame-focus-state} to retrieve the last | ||
| 2860 | known focus state of each frame. Focus events are delivered | ||
| 2861 | asynchronously, and frame input focus according to an external system | ||
| 2862 | may not correspond to the notion of the Emacs selected frame. | ||
| 2863 | Multiple frames may appear to have input focus simultaneously due to | ||
| 2864 | focus event delivery differences, the presence of multiple Emacs | ||
| 2865 | terminals, and other factors, and code should be robust in the face of | ||
| 2866 | this situation. | ||
| 2867 | |||
| 2868 | Depending on window system, focus events may also be delivered | ||
| 2869 | repeatedly and with different focus states before settling to the | ||
| 2870 | expected values. Code relying on focus notifications should | ||
| 2871 | ``debounce'' any user-visible updates arising from focus changes, | ||
| 2872 | perhaps by deferring work until redisplay. | ||
| 2873 | |||
| 2874 | This function may be called in arbitrary contexts, including from | ||
| 2875 | inside @code{read-event}, so take the same care as you might when | ||
| 2876 | writing a process filter. | ||
| 2827 | @end defvar | 2877 | @end defvar |
| 2828 | 2878 | ||
| 2829 | @defopt focus-follows-mouse | 2879 | @defopt focus-follows-mouse |
| @@ -583,6 +583,12 @@ manual for more details. | |||
| 583 | * Lisp Changes in Emacs 27.1 | 583 | * Lisp Changes in Emacs 27.1 |
| 584 | 584 | ||
| 585 | +++ | 585 | +++ |
| 586 | ** New focus state inspection interface: `focus-in-hook' and | ||
| 587 | `focus-out-hook' are marked obsolete. Instead, attach to | ||
| 588 | `after-focus-change-function' using `add-function' and inspect the | ||
| 589 | focus state of each frame using `frame-focus-state'. | ||
| 590 | |||
| 591 | +++ | ||
| 586 | ** Emacs now requests and recognizes focus-change notifications from | 592 | ** Emacs now requests and recognizes focus-change notifications from |
| 587 | terminals that support the feature, meaning that `focus-in-hook' | 593 | terminals that support the feature, meaning that `focus-in-hook' |
| 588 | and `focus-out-hook' may run for TTY frames. | 594 | and `focus-out-hook' may run for TTY frames. |
diff --git a/lisp/frame.el b/lisp/frame.el index c3daff44406..2a2391e8a53 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -129,22 +129,104 @@ appended when the minibuffer frame is created." | |||
| 129 | ;; Gildea@x.org says it is ok to ask questions before terminating. | 129 | ;; Gildea@x.org says it is ok to ask questions before terminating. |
| 130 | (save-buffers-kill-emacs)))) | 130 | (save-buffers-kill-emacs)))) |
| 131 | 131 | ||
| 132 | (defun handle-focus-in (&optional _event) | 132 | (defun frame-focus-state (&optional frame) |
| 133 | "Return FRAME's last known focus state. | ||
| 134 | Return nil if the frame is definitely known not be focused, t if | ||
| 135 | the frame is known to be focused, and 'unknown if we don't know. If | ||
| 136 | FRAME is nil, query the selected frame." | ||
| 137 | (let* ((frame (or frame (selected-frame))) | ||
| 138 | (tty-top-frame (tty-top-frame frame))) | ||
| 139 | (if (not tty-top-frame) | ||
| 140 | (frame-parameter frame 'last-focus-update) | ||
| 141 | ;; All tty frames are frame-visible-p if the terminal is | ||
| 142 | ;; visible, so check whether the frame is the top tty frame | ||
| 143 | ;; before checking visibility. | ||
| 144 | (cond ((not (eq tty-top-frame frame)) nil) | ||
| 145 | ((not (frame-visible-p frame)) nil) | ||
| 146 | (t (let ((tty-focus-state | ||
| 147 | (terminal-parameter frame 'tty-focus-state))) | ||
| 148 | (cond ((eq tty-focus-state 'focused) t) | ||
| 149 | ((eq tty-focus-state 'defocused) nil) | ||
| 150 | (t 'unknown)))))))) | ||
| 151 | |||
| 152 | (defvar after-focus-change-function #'ignore | ||
| 153 | "Function called after frame focus may have changed. | ||
| 154 | |||
| 155 | This function is called with no arguments when Emacs notices that | ||
| 156 | the set of focused frames may have changed. Code wanting to do | ||
| 157 | something when frame focus changes should use `add-function' to | ||
| 158 | add a function to this one, and in this added function, re-scan | ||
| 159 | the set of focused frames, calling `frame-focus-state' to | ||
| 160 | retrieve the last known focus state of each frame. Focus events | ||
| 161 | are delivered asynchronously, and frame input focus according to | ||
| 162 | an external system may not correspond to the notion of the Emacs | ||
| 163 | selected frame. Multiple frames may appear to have input focus | ||
| 164 | simultaneously due to focus event delivery differences, the | ||
| 165 | presence of multiple Emacs terminals, and other factors, and code | ||
| 166 | should be robust in the face of this situation. | ||
| 167 | |||
| 168 | Depending on window system, focus events may also be delivered | ||
| 169 | repeatedly and with different focus states before settling to the | ||
| 170 | expected values. Code relying on focus notifications should | ||
| 171 | \"debounce\" any user-visible updates arising from focus changes, | ||
| 172 | perhaps by deferring work until redisplay. | ||
| 173 | |||
| 174 | This function may be called in arbitrary contexts, including from | ||
| 175 | inside `read-event', so take the same care as you might when | ||
| 176 | writing a process filter.") | ||
| 177 | |||
| 178 | (defvar focus-in-hook nil | ||
| 179 | "Normal hook run when a frame gains focus. | ||
| 180 | The frame gaining focus is selected at the time this hook is run. | ||
| 181 | |||
| 182 | This hook is obsolete. Despite its name, this hook may be run in | ||
| 183 | situations other than when a frame obtains input focus: for | ||
| 184 | example, we also run this hook when switching the selected frame | ||
| 185 | internally to handle certain input events (like mouse wheel | ||
| 186 | scrolling) even when the user's notion of input focus | ||
| 187 | hasn't changed. | ||
| 188 | |||
| 189 | Prefer using `after-focus-change-function'.") | ||
| 190 | (make-obsolete-variable | ||
| 191 | 'focus-in-hook "after-focus-change-function" "27.1" 'set) | ||
| 192 | |||
| 193 | (defvar focus-out-hook nil | ||
| 194 | "Normal hook run when all frames lost input focus. | ||
| 195 | |||
| 196 | This hook is obsolete; see `focus-in-hook'. Depending on timing, | ||
| 197 | this hook may be delivered when a frame does in fact have focus. | ||
| 198 | Prefer `after-focus-change-function'.") | ||
| 199 | (make-obsolete-variable | ||
| 200 | 'focus-out-hook "after-focus-change-function" "27.1" 'set) | ||
| 201 | |||
| 202 | (defun handle-focus-in (event) | ||
| 133 | "Handle a focus-in event. | 203 | "Handle a focus-in event. |
| 134 | Focus-in events are usually bound to this function. | 204 | Focus-in events are bound to this function; do not change this |
| 135 | Focus-in events occur when a frame has focus, but a switch-frame event | 205 | binding. Focus-in events occur when a frame receives focus from |
| 136 | is not generated. | 206 | the window system." |
| 137 | This function runs the hook `focus-in-hook'." | 207 | ;; N.B. tty focus goes down a different path; see xterm.el. |
| 138 | (interactive "e") | 208 | (interactive "e") |
| 139 | (run-hooks 'focus-in-hook)) | 209 | (unless (eq (car-safe event) 'focus-in) |
| 140 | 210 | (error "handle-focus-in should handle focus-in events")) | |
| 141 | (defun handle-focus-out (&optional _event) | 211 | (internal-handle-focus-in event) |
| 212 | (let ((frame (nth 1 event))) | ||
| 213 | (setf (frame-parameter frame 'last-focus-update) t) | ||
| 214 | (run-hooks 'focus-in-hook) | ||
| 215 | (funcall after-focus-change-function))) | ||
| 216 | |||
| 217 | (defun handle-focus-out (event) | ||
| 142 | "Handle a focus-out event. | 218 | "Handle a focus-out event. |
| 143 | Focus-out events are usually bound to this function. | 219 | Focus-out events are bound to this function; do not change this |
| 144 | Focus-out events occur when no frame has focus. | 220 | binding. Focus-out events occur when a frame loses focus, but |
| 145 | This function runs the hook `focus-out-hook'." | 221 | that's not the whole story: see `after-focus-change-function'." |
| 222 | ;; N.B. tty focus goes down a different path; see xterm.el. | ||
| 146 | (interactive "e") | 223 | (interactive "e") |
| 147 | (run-hooks 'focus-out-hook)) | 224 | (unless (eq (car event) 'focus-out) |
| 225 | (error "handle-focus-out should handle focus-out events")) | ||
| 226 | (let ((frame (nth 1 event))) | ||
| 227 | (setf (frame-parameter frame 'last-focus-update) nil) | ||
| 228 | (run-hooks 'focus-out-hook) | ||
| 229 | (funcall after-focus-change-function))) | ||
| 148 | 230 | ||
| 149 | (defun handle-move-frame (event) | 231 | (defun handle-move-frame (event) |
| 150 | "Handle a move-frame event. | 232 | "Handle a move-frame event. |
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index b3b7a216352..ce4e18efff8 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el | |||
| @@ -115,13 +115,20 @@ Return the pasted text as a string." | |||
| 115 | ;; notifications) instead of read-event (which can't). | 115 | ;; notifications) instead of read-event (which can't). |
| 116 | 116 | ||
| 117 | (defun xterm-translate-focus-in (_prompt) | 117 | (defun xterm-translate-focus-in (_prompt) |
| 118 | (handle-focus-in) | 118 | (setf (terminal-parameter nil 'tty-focus-state) 'focused) |
| 119 | (funcall after-focus-change-function) | ||
| 119 | []) | 120 | []) |
| 120 | 121 | ||
| 121 | (defun xterm-translate-focus-out (_prompt) | 122 | (defun xterm-translate-focus-out (_prompt) |
| 122 | (handle-focus-out) | 123 | (setf (terminal-parameter nil 'tty-focus-state) 'defocused) |
| 124 | (funcall after-focus-change-function) | ||
| 123 | []) | 125 | []) |
| 124 | 126 | ||
| 127 | (defun xterm--suspend-tty-function (_tty) | ||
| 128 | ;; We can't know what happens to the tty after we're suspended | ||
| 129 | (setf (terminal-parameter nil 'tty-focus-state) nil) | ||
| 130 | (funcall after-focus-change-function)) | ||
| 131 | |||
| 125 | ;; Similarly, we want to transparently slurp the entirety of a | 132 | ;; Similarly, we want to transparently slurp the entirety of a |
| 126 | ;; bracketed paste and encapsulate it into a single event. We used to | 133 | ;; bracketed paste and encapsulate it into a single event. We used to |
| 127 | ;; just slurp up the bracketed paste content in the event handler, but | 134 | ;; just slurp up the bracketed paste content in the event handler, but |
diff --git a/src/frame.c b/src/frame.c index da82621b8a0..bf0269292d6 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -1455,23 +1455,15 @@ This function returns FRAME, or nil if FRAME has been deleted. */) | |||
| 1455 | DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e", | 1455 | DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e", |
| 1456 | doc: /* Handle a switch-frame event EVENT. | 1456 | doc: /* Handle a switch-frame event EVENT. |
| 1457 | Switch-frame events are usually bound to this function. | 1457 | Switch-frame events are usually bound to this function. |
| 1458 | A switch-frame event tells Emacs that the window manager has requested | 1458 | A switch-frame event is an event Emacs sends itself to |
| 1459 | that the user's events be directed to the frame mentioned in the event. | 1459 | indicate that input is arriving in a new frame. It does not |
| 1460 | This function selects the selected window of the frame of EVENT. | 1460 | necessarily represent user-visible input focus. */) |
| 1461 | |||
| 1462 | If EVENT is frame object, handle it as if it were a switch-frame event | ||
| 1463 | to that frame. */) | ||
| 1464 | (Lisp_Object event) | 1461 | (Lisp_Object event) |
| 1465 | { | 1462 | { |
| 1466 | Lisp_Object value; | ||
| 1467 | |||
| 1468 | /* Preserve prefix arg that the command loop just cleared. */ | 1463 | /* Preserve prefix arg that the command loop just cleared. */ |
| 1469 | kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); | 1464 | kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); |
| 1470 | run_hook (Qmouse_leave_buffer_hook); | 1465 | run_hook (Qmouse_leave_buffer_hook); |
| 1471 | /* `switch-frame' implies a focus in. */ | 1466 | return do_switch_frame (event, 0, 0, Qnil); |
| 1472 | value = do_switch_frame (event, 0, 0, Qnil); | ||
| 1473 | call1 (intern ("handle-focus-in"), event); | ||
| 1474 | return value; | ||
| 1475 | } | 1467 | } |
| 1476 | 1468 | ||
| 1477 | DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, | 1469 | DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, |
| @@ -5888,15 +5880,6 @@ when the mouse is over clickable text. */); | |||
| 5888 | The pointer becomes visible again when the mouse is moved. */); | 5880 | The pointer becomes visible again when the mouse is moved. */); |
| 5889 | Vmake_pointer_invisible = Qt; | 5881 | Vmake_pointer_invisible = Qt; |
| 5890 | 5882 | ||
| 5891 | DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook, | ||
| 5892 | doc: /* Normal hook run when a frame gains input focus. | ||
| 5893 | The frame gaining focus is selected at the time this hook is run. */); | ||
| 5894 | Vfocus_in_hook = Qnil; | ||
| 5895 | |||
| 5896 | DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook, | ||
| 5897 | doc: /* Normal hook run when all frames lost input focus. */); | ||
| 5898 | Vfocus_out_hook = Qnil; | ||
| 5899 | |||
| 5900 | DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions, | 5883 | DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions, |
| 5901 | doc: /* Functions run after a frame was moved. | 5884 | doc: /* Functions run after a frame was moved. |
| 5902 | The functions are run with one arg, the frame that moved. */); | 5885 | The functions are run with one arg, the frame that moved. */); |
diff --git a/src/keyboard.c b/src/keyboard.c index c9e069c8653..84acb247228 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -5331,45 +5331,10 @@ make_lispy_event (struct input_event *event) | |||
| 5331 | } | 5331 | } |
| 5332 | 5332 | ||
| 5333 | case FOCUS_IN_EVENT: | 5333 | case FOCUS_IN_EVENT: |
| 5334 | { | 5334 | return make_lispy_focus_in (event->frame_or_window); |
| 5335 | /* Notification of a FocusIn event. The frame receiving the | ||
| 5336 | focus is in event->frame_or_window. Generate a | ||
| 5337 | switch-frame event if necessary. */ | ||
| 5338 | |||
| 5339 | Lisp_Object frame = event->frame_or_window; | ||
| 5340 | Lisp_Object focus = FRAME_FOCUS_FRAME (XFRAME (frame)); | ||
| 5341 | if (FRAMEP (focus)) | ||
| 5342 | frame = focus; | ||
| 5343 | bool switching | ||
| 5344 | = ( | ||
| 5345 | #ifdef HAVE_X11 | ||
| 5346 | ! NILP (event->arg) | ||
| 5347 | && | ||
| 5348 | #endif | ||
| 5349 | !EQ (frame, internal_last_event_frame) | ||
| 5350 | && !EQ (frame, selected_frame)); | ||
| 5351 | internal_last_event_frame = frame; | ||
| 5352 | |||
| 5353 | return (switching ? make_lispy_switch_frame (frame) | ||
| 5354 | : make_lispy_focus_in (frame)); | ||
| 5355 | } | ||
| 5356 | 5335 | ||
| 5357 | case FOCUS_OUT_EVENT: | 5336 | case FOCUS_OUT_EVENT: |
| 5358 | { | 5337 | return make_lispy_focus_out (event->frame_or_window); |
| 5359 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5360 | |||
| 5361 | Display_Info *di; | ||
| 5362 | Lisp_Object frame = event->frame_or_window; | ||
| 5363 | bool focused = false; | ||
| 5364 | |||
| 5365 | for (di = x_display_list; di && ! focused; di = di->next) | ||
| 5366 | focused = di->x_highlight_frame != 0; | ||
| 5367 | |||
| 5368 | return focused ? Qnil | ||
| 5369 | : make_lispy_focus_out (frame); | ||
| 5370 | |||
| 5371 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 5372 | } | ||
| 5373 | 5338 | ||
| 5374 | /* A simple keystroke. */ | 5339 | /* A simple keystroke. */ |
| 5375 | case ASCII_KEYSTROKE_EVENT: | 5340 | case ASCII_KEYSTROKE_EVENT: |
| @@ -6637,6 +6602,31 @@ has the same base event type and all the specified modifiers. */) | |||
| 6637 | error ("Invalid base event"); | 6602 | error ("Invalid base event"); |
| 6638 | } | 6603 | } |
| 6639 | 6604 | ||
| 6605 | DEFUN ("internal-handle-focus-in", Finternal_handle_focus_in, | ||
| 6606 | Sinternal_handle_focus_in, 1, 1, 0, | ||
| 6607 | doc: /* Internally handle focus-in events, possibly generating | ||
| 6608 | an artifical switch-frame event. */) | ||
| 6609 | (Lisp_Object event) | ||
| 6610 | { | ||
| 6611 | Lisp_Object frame; | ||
| 6612 | if (!EQ (CAR_SAFE (event), Qfocus_in) || | ||
| 6613 | !CONSP (XCDR (event)) || | ||
| 6614 | !FRAMEP ((frame = XCAR (XCDR (event))))) | ||
| 6615 | error ("invalid focus-in event"); | ||
| 6616 | |||
| 6617 | /* Conceptually, the concept of window manager focus on a particular | ||
| 6618 | frame and the Emacs selected frame shouldn't be related, but for a | ||
| 6619 | long time, we automatically switched the selected frame in response | ||
| 6620 | to focus events, so let's keep doing that. */ | ||
| 6621 | bool switching = (!EQ (frame, internal_last_event_frame) | ||
| 6622 | && !EQ (frame, selected_frame)); | ||
| 6623 | internal_last_event_frame = frame; | ||
| 6624 | if (switching || !NILP (unread_switch_frame)) | ||
| 6625 | unread_switch_frame = make_lispy_switch_frame (frame); | ||
| 6626 | |||
| 6627 | return Qnil; | ||
| 6628 | } | ||
| 6629 | |||
| 6640 | /* Try to recognize SYMBOL as a modifier name. | 6630 | /* Try to recognize SYMBOL as a modifier name. |
| 6641 | Return the modifier flag bit, or 0 if not recognized. */ | 6631 | Return the modifier flag bit, or 0 if not recognized. */ |
| 6642 | 6632 | ||
| @@ -11277,6 +11267,7 @@ syms_of_keyboard (void) | |||
| 11277 | defsubr (&Scurrent_idle_time); | 11267 | defsubr (&Scurrent_idle_time); |
| 11278 | defsubr (&Sevent_symbol_parse_modifiers); | 11268 | defsubr (&Sevent_symbol_parse_modifiers); |
| 11279 | defsubr (&Sevent_convert_list); | 11269 | defsubr (&Sevent_convert_list); |
| 11270 | defsubr (&Sinternal_handle_focus_in); | ||
| 11280 | defsubr (&Sread_key_sequence); | 11271 | defsubr (&Sread_key_sequence); |
| 11281 | defsubr (&Sread_key_sequence_vector); | 11272 | defsubr (&Sread_key_sequence_vector); |
| 11282 | defsubr (&Srecursive_edit); | 11273 | defsubr (&Srecursive_edit); |
diff --git a/src/w32term.c b/src/w32term.c index 24950dd25ec..ff0d2bf5ddb 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -2886,20 +2886,6 @@ x_focus_changed (int type, int state, struct w32_display_info *dpyinfo, | |||
| 2886 | { | 2886 | { |
| 2887 | x_new_focus_frame (dpyinfo, frame); | 2887 | x_new_focus_frame (dpyinfo, frame); |
| 2888 | dpyinfo->w32_focus_event_frame = frame; | 2888 | dpyinfo->w32_focus_event_frame = frame; |
| 2889 | |||
| 2890 | /* Don't stop displaying the initial startup message | ||
| 2891 | for a switch-frame event we don't need. */ | ||
| 2892 | if (NILP (Vterminal_frame) | ||
| 2893 | && CONSP (Vframe_list) | ||
| 2894 | && !NILP (XCDR (Vframe_list))) | ||
| 2895 | { | ||
| 2896 | bufp->arg = Qt; | ||
| 2897 | } | ||
| 2898 | else | ||
| 2899 | { | ||
| 2900 | bufp->arg = Qnil; | ||
| 2901 | } | ||
| 2902 | |||
| 2903 | bufp->kind = FOCUS_IN_EVENT; | 2889 | bufp->kind = FOCUS_IN_EVENT; |
| 2904 | XSETFRAME (bufp->frame_or_window, frame); | 2890 | XSETFRAME (bufp->frame_or_window, frame); |
| 2905 | } | 2891 | } |
diff --git a/src/xterm.c b/src/xterm.c index eb299c36759..decaa33670b 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -4387,16 +4387,6 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra | |||
| 4387 | { | 4387 | { |
| 4388 | x_new_focus_frame (dpyinfo, frame); | 4388 | x_new_focus_frame (dpyinfo, frame); |
| 4389 | dpyinfo->x_focus_event_frame = frame; | 4389 | dpyinfo->x_focus_event_frame = frame; |
| 4390 | |||
| 4391 | /* Don't stop displaying the initial startup message | ||
| 4392 | for a switch-frame event we don't need. */ | ||
| 4393 | /* When run as a daemon, Vterminal_frame is always NIL. */ | ||
| 4394 | bufp->arg = (((NILP (Vterminal_frame) | ||
| 4395 | || ! FRAME_X_P (XFRAME (Vterminal_frame)) | ||
| 4396 | || EQ (Fdaemonp (), Qt)) | ||
| 4397 | && CONSP (Vframe_list) | ||
| 4398 | && !NILP (XCDR (Vframe_list))) | ||
| 4399 | ? Qt : Qnil); | ||
| 4400 | bufp->kind = FOCUS_IN_EVENT; | 4390 | bufp->kind = FOCUS_IN_EVENT; |
| 4401 | XSETFRAME (bufp->frame_or_window, frame); | 4391 | XSETFRAME (bufp->frame_or_window, frame); |
| 4402 | } | 4392 | } |