unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Po Lu via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Vangelis Evangelou <evangelou@gmail.com>
Cc: Eli Zaretskii <eliz@gnu.org>, 70046-done@debbugs.gnu.org
Subject: bug#70046: 29.3; ebuffers mini frame loses focus
Date: Sun, 07 Apr 2024 11:43:29 +0800	[thread overview]
Message-ID: <877ch96dni.fsf@yahoo.com> (raw)
In-Reply-To: <CAD1AF2et7jq_PYdV8Lpurs0voQmz=-TOpos=RRmFGoheX0=rgw@mail.gmail.com> (Vangelis Evangelou's message of "Fri, 5 Apr 2024 09:31:36 +0100")

Vangelis Evangelou <evangelou@gmail.com> writes:

> I have run emacs like this
>
> emacs -Q --eval '(progn (setq x-allow-focus-stealing nil) (ebuffers (find-file "~/fileA") (find-file "~/fileB")))'
>
> This does not solve the issue.

Having debugged this under xfwm4, I've come to the conclusion that this
is the product of two separate bugs in the window manager itself.
Observe the result of running the following code, namely that F1 is
moved above F2 while it continues to possess the input focus:

  (setq f1 (selected-frame)
        f2 (make-frame '((name . "FRAME 2"))))
  (progn
    (raise-frame f2)
    (x-focus-frame f1))

Well-behaved window managers will not focus F2 in response to the call
to `raise-frame', but only raise the frame to the top of the window
stack, leaving the keyboard focus intact, while xfwm4 has adopted a
rather creative interpretation of the meaning of "raise" that holds it
to be synonymous with activating the frame unless "focus stealing
prevention" is enabled.  By itself, this is not sufficient to trigger
your problem, but when windows so acquire the input focus, the new focus
state is not registered by the window manager, with the result that
subsequent requests to activate (i.e. transfer the input focus) to the
previously selected window are disregarded to the extent that they
affect the keyboard focus:

TRACE[events.c:1334] handleConfigureRequest(): window "FRAME 2" (0x40035c)
TRACE[client.c:561] clientAdjustCoordGravity(): client "FRAME 2" (0x40035c)
TRACE[client.c:907] clientMoveResizeWindow(): client "FRAME 2" (0x40035c)
TRACE[display.c:767] myDisplayGetCurrentTime(): timestamp=1371435444
TRACE[hints.c:1305] getXServerTime(): timestamp=1371435444
TRACE[client.c:2595] clientActivate(): client "FRAME 2" (0x40035c)
TRACE[transients.c:336] clientGetTransientFor(): client "FRAME 2" (0x40035c)
TRACE[transients.c:54] clientIsDirectTransient(): client "FRAME 2" (0x40035c)
TRACE[transients.c:54] clientIsDirectTransient(): client "FRAME 2" (0x40035c)
TRACE[stacking.c:537] clientAdjustFullscreenLayer(): unsetting fullscreen layer for  "test.el" (0x40013c)
TRACE[client.c:2374] clientShow(): client "FRAME 2" (0x40035c)
TRACE[transients.c:429] clientListTransientOrModal(): client "FRAME 2" (0x40035c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[client.c:2254] clientSetWorkspaceSingle(): client "FRAME 2" (0x40035c)
TRACE[stacking.c:370] clientRaise(): client "FRAME 2" (0x40035c) above (0x0)
TRACE[stacking.c:176] clientGetNextTopMost(): layer 4
TRACE[stacking.c:182] clientGetNextTopMost(): *** stack window "FRAME 2" (0x40035c), layer 4
TRACE[stacking.c:182] clientGetNextTopMost(): *** stack window "test.el" (0x40013c), layer 4
TRACE[transients.c:336] clientGetTransientFor(): client "FRAME 2" (0x40035c)
TRACE[transients.c:54] clientIsDirectTransient(): client "FRAME 2" (0x40035c)
TRACE[transients.c:54] clientIsDirectTransient(): client "FRAME 2" (0x40035c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
DBG[stacking.c:52] clientApplyStackList(): applying stack list
DBG[stacking.c:71] clientApplyStackList():   [5] "FRAME 2" (0x40035c)
DBG[stacking.c:71] clientApplyStackList():   [6] "test.el" (0x40013c)
TRACE[netwm.c:966] clientSetNetClientList(): entering
TRACE[netwm.c:978] clientSetNetClientList(): 2 windows in list for 2 clients
TRACE[focus.c:547] clientSetFocus(): entering
TRACE[transients.c:309] clientGetModalFor(): client "FRAME 2" (0x40035c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "test.el" (0x40013c), client 2 "FRAME 2" (0x40035c)
TRACE[focus.c:562] clientSetFocus(): setting focus to client "FRAME 2" (0x40035c) with timestamp 1371435444
TRACE[focus.c:386] clientAcceptFocus(): client "FRAME 2" (0x40035c)
TRACE[client.c:734] clientConfigure(): client "FRAME 2" (0x40035c) not contrained, type 1
TRACE[client.c:777] clientConfigure(): above
TRACE[stacking.c:370] clientRaise(): client "FRAME 2" (0x40035c) above (0x0)
TRACE[stacking.c:382] clientRaise(): client "FRAME 2" (0x40035c) already raised
DBG[client.c:705] clientSendConfigureNotify(): Sending ConfigureNotify
TRACE[compositor.c:4544] compositorHandleEvent(): event type 23
TRACE[events.c:2303] xfwm4_event_filter(): leaving
TRACE[event_filter.c:117] default_event_filter(): unhandled ConfigureRequest event
TRACE[events.c:2301] xfwm4_event_filter(): entering
TRACE[events.c:2170] handleEvent(): entering
TRACE[events.c:1892] handleClientMessage(): window (0x40013c)
TRACE[client.c:2201] clientGetFromWindow(): client "test.el" (0x40013c)
TRACE[client.c:2207] clientGetFromWindow(): found "test.el" (mode WINDOW)
TRACE[events.c:1940] handleClientMessage(): client "test.el" (0x40013c) has received a NET_ACTIVE_WINDOW event
TRACE[netwm.c:1440] clientHandleNetActiveWindow(): client "test.el" (0x40013c)
TRACE[display.c:782] myDisplayGetTime(): timestamp=1371435444
TRACE[display.c:791] myDisplayGetLastUserTime(): timestamp=1371435444
TRACE[netwm.c:1454] clientHandleNetActiveWindow(): time of event received is 1371435444, current XServer time is 1371435444
TRACE[client.c:2595] clientActivate(): client "test.el" (0x40013c)
TRACE[transients.c:336] clientGetTransientFor(): client "test.el" (0x40013c)
TRACE[transients.c:54] clientIsDirectTransient(): client "test.el" (0x40013c)
TRACE[transients.c:54] clientIsDirectTransient(): client "test.el" (0x40013c)
TRACE[client.c:2374] clientShow(): client "test.el" (0x40013c)
TRACE[transients.c:429] clientListTransientOrModal(): client "test.el" (0x40013c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[client.c:2254] clientSetWorkspaceSingle(): client "test.el" (0x40013c)
TRACE[stacking.c:370] clientRaise(): client "test.el" (0x40013c) above (0x0)
TRACE[stacking.c:176] clientGetNextTopMost(): layer 4
TRACE[stacking.c:182] clientGetNextTopMost(): *** stack window "test.el" (0x40013c), layer 4
TRACE[stacking.c:182] clientGetNextTopMost(): *** stack window "FRAME 2" (0x40035c), layer 4
TRACE[transients.c:336] clientGetTransientFor(): client "test.el" (0x40013c)
TRACE[transients.c:54] clientIsDirectTransient(): client "test.el" (0x40013c)
TRACE[transients.c:54] clientIsDirectTransient(): client "test.el" (0x40013c)
TRACE[transients.c:227] clientIsTransientOrModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:177] clientIsTransientFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
DBG[stacking.c:52] clientApplyStackList(): applying stack list
DBG[stacking.c:71] clientApplyStackList():   [5] "test.el" (0x40013c)
DBG[stacking.c:71] clientApplyStackList():   [6] "FRAME 2" (0x40035c)
TRACE[netwm.c:966] clientSetNetClientList(): entering
TRACE[netwm.c:978] clientSetNetClientList(): 2 windows in list for 2 clients
TRACE[focus.c:547] clientSetFocus(): entering
TRACE[transients.c:309] clientGetModalFor(): client "test.el" (0x40013c)
TRACE[transients.c:205] clientIsModalFor(): client 1 "FRAME 2" (0x40035c), client 2 "test.el" (0x40013c)
TRACE[focus.c:562] clientSetFocus(): setting focus to client "test.el" (0x40013c) with timestamp 1371435444
TRACE[focus.c:572] clientSetFocus(): client "test.el" (0x40013c) is already focused, ignoring request

and in consequence this portion of ediff-recenter:

      (progn
	(if (window-live-p ediff-window-A)
	    (raise-frame (window-frame ediff-window-A)))
	(if (window-live-p ediff-window-B)
	    (raise-frame (window-frame ediff-window-B)))
	(if (window-live-p ediff-window-C)
	    (raise-frame (window-frame ediff-window-C)))))
  (if (and (display-graphic-p)
	   (frame-live-p ediff-control-frame)
	   (not ediff-use-long-help-message)
	   (not (ediff-frame-iconified-p ediff-control-frame)))
      (if (fboundp 'select-frame-set-input-focus)
	  (select-frame-set-input-focus ediff-control-frame)
	(raise-frame ediff-control-frame)
	(select-frame ediff-control-frame)))

whose purpose is to preserve the position of the ediff control frame
relative to the remainder instead prompts the window manager to transfer
the input focus to a diff-displaying frame, before being left with no
means of restoring the input focus to its original owner.  It is also
reproducible consistently with Emacs 28.1, so I suggest reporting this
issue to the xfwm developers; closing.





      reply	other threads:[~2024-04-07  3:43 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-28  8:36 bug#70046: 29.3; ebuffers mini frame loses focus Vangelis Evangelou
2024-03-28  9:22 ` Eli Zaretskii
2024-03-28 10:08   ` Vangelis Evangelou
2024-03-28 10:28     ` Eli Zaretskii
2024-03-28 10:35       ` Vangelis Evangelou
2024-03-28 10:39         ` Vangelis Evangelou
2024-03-28 11:30         ` Eli Zaretskii
2024-03-28 12:59         ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-28 14:27           ` Vangelis Evangelou
2024-04-05  7:55             ` Vangelis Evangelou
2024-04-05  8:13               ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-05  8:31                 ` Vangelis Evangelou
2024-04-07  3:43                   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877ch96dni.fsf@yahoo.com \
    --to=bug-gnu-emacs@gnu.org \
    --cc=70046-done@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=evangelou@gmail.com \
    --cc=luangruo@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).