From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Helmut Eller Newsgroups: gmane.emacs.bugs Subject: bug#745: pop-to-buffer, frames, and input focus Date: Sun, 24 Aug 2008 15:14:31 +0200 Message-ID: References: <48AC2F4A.1000507@gmx.at> <48AC851A.3020906@gmx.at> <48AD2FB5.3000204@gmx.at> <48ADD085.50505@gmx.at> <48AEEBB8.50201@gmx.at> <48AFFD26.3040204@gmx.at> Reply-To: Helmut Eller , 745@emacsbugs.donarmstrong.com NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1219584468 5149 80.91.229.12 (24 Aug 2008 13:27:48 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 24 Aug 2008 13:27:48 +0000 (UTC) Cc: 745@emacsbugs.donarmstrong.com To: martin rudalics Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Aug 24 15:28:40 2008 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1KXFe2-0002k4-GI for geb-bug-gnu-emacs@m.gmane.org; Sun, 24 Aug 2008 15:28:39 +0200 Original-Received: from localhost ([127.0.0.1]:48635 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KXFd4-00009J-52 for geb-bug-gnu-emacs@m.gmane.org; Sun, 24 Aug 2008 09:27:38 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KXFcy-00006A-RX for bug-gnu-emacs@gnu.org; Sun, 24 Aug 2008 09:27:32 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KXFcx-00005u-Km for bug-gnu-emacs@gnu.org; Sun, 24 Aug 2008 09:27:32 -0400 Original-Received: from [199.232.76.173] (port=35204 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KXFcx-00005p-Fa for bug-gnu-emacs@gnu.org; Sun, 24 Aug 2008 09:27:31 -0400 Original-Received: from rzlab.ucr.edu ([138.23.92.77]:37444) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KXFcw-0003KV-N4 for bug-gnu-emacs@gnu.org; Sun, 24 Aug 2008 09:27:31 -0400 Original-Received: from rzlab.ucr.edu (rzlab.ucr.edu [127.0.0.1]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m7ODRSYV026889; Sun, 24 Aug 2008 06:27:28 -0700 Original-Received: (from debbugs@localhost) by rzlab.ucr.edu (8.13.8/8.13.8/Submit) id m7ODK4K4023765; Sun, 24 Aug 2008 06:20:04 -0700 X-Loop: don@donarmstrong.com Resent-From: Helmut Eller Resent-To: bug-submit-list@donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 24 Aug 2008 13:20:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 745 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Original-Received: via spool by 745-submit@emacsbugs.donarmstrong.com id=B745.121958359422078 (code B ref 745); Sun, 24 Aug 2008 13:20:03 +0000 Original-Received: (at 745) by emacsbugs.donarmstrong.com; 24 Aug 2008 13:13:14 +0000 Original-Received: from rolmail.net (cgp1.rolmail.net [195.254.252.190]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m7ODD77Q022072 for <745@emacsbugs.donarmstrong.com>; Sun, 24 Aug 2008 06:13:09 -0700 Original-Received: from dummy.name; Sun, 24 Aug 2008 15:13:03 +0200 Original-Received: from dummy.name; Sun, 24 Aug 2008 15:14:31 +0200 In-Reply-To: <48AFFD26.3040204@gmx.at> (martin rudalics's message of "Sat, 23 Aug 2008 14:05:58 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-detected-kernel: by monty-python.gnu.org: Linux 2.6 (newer, 3) Resent-Date: Sun, 24 Aug 2008 09:27:32 -0400 X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:19684 Archived-At: --=-=-= * martin rudalics [2008-08-23 14:05+0200] writes: >> The problematic cases are >> >> (let ((pop-up-frames t)) (display-buffer ...)) >> >> for display-buffer, if the buffer was not visible before. In this case >> a new frame appears, which (wrongly) has the input focus. > > Rather "which (wrongly) has the input focus for window managers able to > handle mapping a new frame without giving input focus to it" because > IIUC with certain settings (focus-follows-mouse) some window managers > automatically do give focus to the new frame. Yes, I agree. I didn't know before that Sawfish has a focus-window-when-mapped option. Situation A is probably a window manager issue. > I also suppose that the > only means to take focus away from the new frame is by giving focus to > the previously selected frame (though we can't even be sure that frame > had focus or was risen). I've read a little bit in the Xlib Manual[*] and here is what I learned: If we set the focus to the old frame by calling select-frame-set-input-focus in display-buffer we have something like a race condition. The window manager may decide at the same time that the new frame should have the focus and either Emacs or the WM will win the race. Emacs sets the "input-hint" flag in WM_HINTS when creating new frames. This can be seen with: shell$ xprop WM_HINTS WM_HINTS(WM_HINTS): Client accepts input or input focus: True Initial state is Normal State. bitmap id # to use for icon: 0xa00710 bitmap id # of mask for icon: 0xa00712 window id # of group leader: 0xa00001 If the input-hint flag is set, some window managers will assume that Emacs doesn't switch the input focus by itself and so the WM does it. In theory, Emacs could clear the input-hint flag (to stop the WM from switching focus) and instead listen to WM_TAKE_FOCUS events. The window manager sends WM_TAKE_FOCUS to Emacs, when the WM thinks that Emacs should now be focused. Emacs can then decide to set (or not) the focus to the appropriate frame. I don't know how well that would work in practice or if all window managers follow the conventions. But if the input-hint flag is set, Emacs has to fight with the window manager. OTOH, some people will prefer that the WM does all the focus switching. I guess it's not worth fixing situation A. People with decent window managers will be able to configure their preferred focus behavior anyway. [*] http://tronche.com/gui/x/icccm/sec-4.html >> (If the >> buffer is already visible in some frame, that frame is raised but the >> focus is not moved to that frame. This is IMO correct.) > > I think so. But what happens in the `pop-to-buffer' case when a _new_ > frame gets displayed. Should we give it input-focus? Yes. I don't see why not. > I suppose so from > your situation B comments below. So in all cases where situation A has > Y (that is `display-buffer' fails TDTRT) `pop-to-buffer' DTRT? Yes, right. In this case pop-up-frames must be t when pop-to-buffer is called. >> For pop-to-buffer: >> >> (let ((display-buffer-reuse-frames t)) (pop-to-buffer ...)) >> >> if the buffer is already visible in a frame which has not the input >> focus. This should move input focus to that frame, but it currently >> doesn't. (If the frame has already the focus, pop-to-buffer works as it >> should.) > > Do we agree on the general rule that > > - `display-buffer' should never try to move input focus to another (new > or existing) frame, while > > - `pop-to-buffer' should try to give input focus to the frame where > BUFFER is displayed Yes, we agree. > (this could be the selected frame as well). [I guess, it would be an optimization for a common case not to give input focus to the frame that is already focused. But despite efficiency, it wouldn't make a difference.] > >> Let's call the display-buffer case, situation A and the pop-to-buffer >> case, situation B. > [...] >> OK, here is what I see: >> >> A B WM WM focus mode >> --------------------------------------- >> Y N Sawfish follow-mouse (enter-only + focus-window-when-mapped) >> N N Sawfish follow-mouse (enter-only + !focus-window-when-mapped) >> Y N Sawfish follow-mouse (enter-exit + focus-window-when-mapped) >> N N Sawfish follow-mouse (enter-exit + !focus-window-when-mapped) >> Y N Sawfish click-to-focus (click + focus-window-when-mapped) >> N N Sawfish click-to-focus (click + !focus-window-when-mapped) >> Y N Sawfish click-to-focus (click + focus-window-when-mapped + focus-click-through) >> N N Sawfish click-to-focus (click + !focus-window-when-mapped + focus-click-through) > > I'm completely ignorant WRT to focus-window-when-mapped: Does this mean > that a window that is not risen can get focus? [Note, this "window" is X jargon. Emacs would call this a frame.] AFAIK, it's possible to give the focus to a window without raising it. I guess though, that the window must be mapped (displayed). > Note in this context > that `select-frame-set-input-focus' always raises the frame. Looks unnecessary. Emacs also calls XSetInputFocus together with x_ewmh_activate_frame in Fx_focus_frame. One of those is probably unnecessary. x_ewmh_activate_frame tells the WM to try to focus the frame, but some WMs will also raise the window at the same time. >> ? N Metacity follow-mouse (mouse) >> ? N Metacity follow-mouse (sloppy) >> ? N Metacity click-to-focus (click) > > Does Metacity respect `select-frame-set-input-focus' at all? Yes, this seems to work. [Though, it also moves the mouse pointer to the upper right corner of the new frame. Maybe some Metacity idiosyncrasy.] >> Y N KWin follow-mouse >> Y N KWin click-to-focus >> Y M FluxBox follow-mouse (Sloppy Focus) >> Y M FluxBox follow-mouse (Auto Raise) > > For the M cases `raise-frame' could move the mouse pointer to that frame > which seems to call for yet another option. > >> Y N FluxBox click-to-focus >> Y Y IceWM click-to-focus > > So IceWM is the only window manager to handle situation B. IIUC it does > so because do_switch-frame manages to get Fredirect_frame_focus through > to redirect input to that frame. Or do you have another explanation? It could be, that IceWM gives focus to the other frame because Emacs called raise-frame (in window--display-buffer-1). I'm just speculating, though. I don't know what Fredirect_frame_focus is used for; but it looks like something exotic. > Could you try to GDB do_switch_frame for IceWM and one of the others to > see they do differently? I didn't know what to look for. Below I attach two event traces for emacs -Q --eval '(progn (let ((pop-up-frames t)) (select-frame-set-input-focus (window-frame (display-buffer (get-buffer-create "foo"))))) (let ((display-buffer-reuse-frames t)) (pop-to-buffer "foo")) (sleep-for 1) (kill-emacs))' 2> wm-log One for Sawfish (with focus-window-when-mapped) and one for IceWM. I traced the events in xterm.c:handle_one_xevent and calls to x_raise_frame. Maybe you can make some sense out of it. >> Y N Twm follow-mouse (new frames need mouse click for placement) >> >> A and B are the scenarios described above. >> Y means: Yes, does switch focus. >> N means: No, doesn't switch focus. >> ? means: sometimes (probably depending on mouse and window positions) >> M means: No, doesn't switch focus, except when raising the frame >> also moves the mouse pointer into the frame. >> >> I set Emacs' focus-follows-mouse according to the WM focus mode (except >> when I forgot it :-) >> >> The Ys for Sawfish are apparently directly related to the >> focus-window-when-mapped option. So, it's probably not Emacs that >> switches the focus in the A scenario, but the window managers. > > Can we conclucde that the other window managers implicitly focus a frame > when mapping it? The probability is at least not zero :-) I guess though, that if the input-hint flag is true, the WM may switch focus to whatever and whenever it thinks is appropriate (see Metacity). >> The docstring for select-window could perhaps >> also state a bit more prominently that the "selected window" and the >> "input focus" are different things > > ... if the implementation is bogus this will hardly help ... > >> or at least refer to >> select-frame-set-input-focus. > > That function lumps together too many things. At least `raise-frame' > should probably be optional there. > >> BTW, below is a proof of concept implementation for the >> update-focus-lazily idea. > > Would this work with `redirect-frame-focus'? I haven't studied it in > detail. I don't know. It's hard for me to guess for what or when redirect-frame-focus is used, just by staring at the code. Helmut. Lines like the following in the logs means: xevent: FocusOut serial: 2176 send: 0 win: c00184 mode: NotifyNormal detail: NotifyNonlinear FocusOut is the event type serial: is the number of last request processed by server send: true if this came from a SendEvent request (i.e. by WM) win: the window id of the event target and "x_raise_frame: win: c00183 ... done." is a call to x_raise_frame with argument c00183. --=-=-= Content-Disposition: attachment; filename=sawfish-log Content-Description: Sawfish log xevent: ConfigureNotify serial: 1157 send: 0 win: c0009a xevent: MapNotify serial: 1161 send: 0 win: c0009a xevent: ConfigureNotify serial: 1168 send: 0 win: c00011 xevent: ConfigureNotify serial: 1168 send: 0 win: c00011 xevent: ReparentNotify serial: 1168 send: 0 win: c00011 xevent: ConfigureNotify serial: 1168 send: 0 win: c00011 xevent: ConfigureNotify serial: 1168 send: 1 win: c00011 xevent: ConfigureNotify serial: 1168 send: 1 win: c00011 xevent: MapNotify serial: 1168 send: 0 win: c00011 xevent: VisibilityNotify serial: 1168 send: 0 win: c0009a xevent: Expose serial: 1168 send: 0 win: c0009a xevent: EnterNotify serial: 1168 send: 0 win: c00011 xevent: EnterNotify serial: 1168 send: 0 win: c0009a xevent: ConfigureNotify serial: 1168 send: 1 win: c00011 xevent: ClientMessage serial: 1168 send: 1 win: c00011 TAKE_FOCUS timestamp: f47403ea xevent: FocusIn serial: 1168 send: 0 win: c00011 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusIn serial: 1168 send: 0 win: c0009a mode: NotifyNormal detail: NotifyPointer xevent: FocusOut serial: 1246 send: 0 win: c0009a mode: NotifyNormal detail: NotifyPointer xevent: FocusOut serial: 1246 send: 0 win: c00011 mode: NotifyNormal detail: NotifyInferior xevent: FocusIn serial: 1246 send: 0 win: c00012 mode: NotifyNormal detail: NotifyAncestor xevent: ConfigureNotify serial: 2031 send: 0 win: c00186 xevent: MapNotify serial: 2035 send: 0 win: c00186 xevent: ConfigureNotify serial: 2042 send: 0 win: c00183 xevent: ConfigureNotify serial: 2042 send: 0 win: c00183 xevent: ReparentNotify serial: 2042 send: 0 win: c00183 xevent: ConfigureNotify serial: 2042 send: 0 win: c00183 xevent: ConfigureNotify serial: 2042 send: 1 win: c00183 xevent: ConfigureNotify serial: 2042 send: 1 win: c00183 xevent: MapNotify serial: 2042 send: 0 win: c00183 xevent: VisibilityNotify serial: 2042 send: 0 win: c00186 xevent: Expose serial: 2042 send: 0 win: c00186 xevent: ConfigureNotify serial: 2042 send: 1 win: c00183 xevent: ClientMessage serial: 2042 send: 1 win: c00183 TAKE_FOCUS timestamp: f4740496 xevent: FocusOut serial: 2042 send: 0 win: c00012 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusOut serial: 2042 send: 0 win: c00011 mode: NotifyNormal detail: NotifyNonlinearVirtual xevent: FocusIn serial: 2042 send: 0 win: c00183 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusOut serial: 2119 send: 0 win: c00183 mode: NotifyNormal detail: NotifyInferior xevent: FocusIn serial: 2119 send: 0 win: c00184 mode: NotifyNormal detail: NotifyAncestor x_raise_frame: win: c00183 ... done. x_raise_frame: win: c00183 ... done. xevent: ConfigureNotify serial: 2174 send: 1 win: c00183 xevent: ConfigureNotify serial: 2174 send: 1 win: c00183 xevent: FocusOut serial: 2176 send: 0 win: c00184 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusIn serial: 2176 send: 0 win: c00186 mode: NotifyNormal detail: NotifyNonlinear xevent: ClientMessage serial: 2190 send: 1 win: c00183 TAKE_FOCUS timestamp: f47404b5 --=-=-= Content-Disposition: attachment; filename=icewm-log Content-Description: IceWM log xevent: ConfigureNotify serial: 1788 send: 0 win: 6000f0 xevent: MapNotify serial: 1792 send: 0 win: 6000f0 xevent: ConfigureNotify serial: 1800 send: 0 win: 600011 xevent: ReparentNotify serial: 1800 send: 0 win: 600011 xevent: ConfigureNotify serial: 1800 send: 1 win: 600011 xevent: MapNotify serial: 1800 send: 0 win: 600011 xevent: VisibilityNotify serial: 1800 send: 0 win: 6000f0 xevent: Expose serial: 1800 send: 0 win: 6000f0 xevent: EnterNotify serial: 1800 send: 0 win: 600011 xevent: EnterNotify serial: 1800 send: 0 win: 6000f0 xevent: FocusIn serial: 1800 send: 0 win: 600011 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusIn serial: 1800 send: 0 win: 6000f0 mode: NotifyNormal detail: NotifyPointer xevent: ClientMessage serial: 1800 send: 1 win: 600011 TAKE_FOCUS timestamp: 2bbbe xevent: ClientMessage serial: 1800 send: 1 win: 600011 TAKE_FOCUS timestamp: 2bbbe xevent: ConfigureNotify serial: 1800 send: 1 win: 600011 xevent: ClientMessage serial: 1800 send: 1 win: 600011 TAKE_FOCUS timestamp: 2bbbe xevent: FocusOut serial: 1851 send: 0 win: 6000f0 mode: NotifyNormal detail: NotifyPointer xevent: FocusOut serial: 1851 send: 0 win: 600011 mode: NotifyNormal detail: NotifyInferior xevent: FocusIn serial: 1851 send: 0 win: 600012 mode: NotifyNormal detail: NotifyAncestor xevent: ConfigureNotify serial: 3079 send: 0 win: 600290 xevent: MapNotify serial: 3083 send: 0 win: 600290 xevent: ConfigureNotify serial: 3091 send: 0 win: 60028d xevent: ReparentNotify serial: 3091 send: 0 win: 60028d xevent: ConfigureNotify serial: 3091 send: 1 win: 60028d xevent: MapNotify serial: 3091 send: 0 win: 60028d xevent: VisibilityNotify serial: 3091 send: 0 win: 600290 xevent: VisibilityNotify serial: 3091 send: 0 win: 6000f0 xevent: Expose serial: 3091 send: 0 win: 600290 xevent: LeaveNotify serial: 3091 send: 0 win: 6000f0 xevent: LeaveNotify serial: 3091 send: 0 win: 600011 xevent: FocusOut serial: 3091 send: 0 win: 600012 mode: NotifyNormal detail: NotifyNonlinear xevent: FocusOut serial: 3091 send: 0 win: 600011 mode: NotifyNormal detail: NotifyNonlinearVirtual xevent: FocusIn serial: 3091 send: 0 win: 60028d mode: NotifyNormal detail: NotifyNonlinear xevent: ClientMessage serial: 3091 send: 1 win: 60028d TAKE_FOCUS timestamp: 2ffeb xevent: ClientMessage serial: 3091 send: 1 win: 60028d TAKE_FOCUS timestamp: 2ffeb xevent: ConfigureNotify serial: 3091 send: 1 win: 60028d xevent: ClientMessage serial: 3091 send: 1 win: 60028d TAKE_FOCUS timestamp: 2ffeb xevent: FocusOut serial: 3145 send: 0 win: 60028d mode: NotifyNormal detail: NotifyInferior xevent: FocusIn serial: 3145 send: 0 win: 60028e mode: NotifyNormal detail: NotifyAncestor x_raise_frame: win: 60028d ... done. x_raise_frame: win: 60028d ... done. xevent: FocusOut serial: 3220 send: 0 win: 60028e mode: NotifyNormal detail: NotifyAncestor xevent: FocusIn serial: 3220 send: 0 win: 60028d mode: NotifyNormal detail: NotifyInferior xevent: ClientMessage serial: 3220 send: 1 win: 60028d TAKE_FOCUS timestamp: 30059 xevent: ConfigureNotify serial: 3220 send: 1 win: 60028d xevent: ClientMessage serial: 3220 send: 1 win: 60028d TAKE_FOCUS timestamp: 30059 xevent: ConfigureNotify serial: 3220 send: 1 win: 60028d xevent: FocusOut serial: 3221 send: 0 win: 60028d mode: NotifyNormal detail: NotifyInferior xevent: FocusIn serial: 3221 send: 0 win: 600290 mode: NotifyNormal detail: NotifyAncestor xevent: ClientMessage serial: 3236 send: 1 win: 60028d TAKE_FOCUS timestamp: 30062 xevent: EnterNotify serial: 3283 send: 0 win: 60028d xevent: EnterNotify serial: 3283 send: 0 win: 600290 --=-=-=--