Pungenday, the 31 day of The Aftermath in the YOLD 3176
Emacsclient flyttar Emacs-fönster!
Jag upptäckte för ett tag sedan en mystisk sak med Emacs beteende under X tillsammans med emacsclient.
Säg att du har en Emacs igång med Emacs-fönster på en annan workspace
och att du har server-raise-frame
satt som icke-nil (det är
default-värdet). Säg att du nu startar nu emacsclient. Då flyttas
plötsligt ett av dina Emacs-fönster, vilket som helst, till den
workspace du är på! Den flyttar också muspekaren till det flyttade
fönstret.
Jag upplevde detta först under min egen fönsterhanterare, mcwm, men verifierade beteendet också under ctwm, evilwm och openbox.
Jag tvingade Emacs att sluta göra så genom att helt enkelt i mcwm förbjuda fönster som redan finns i en annan workspace-lista att dyka upp på den aktuella workspacen (om det nu inte är mcwm själv som bestämt det, förstås). Det löste problemet, åtminstone delvis. Kvar är problemet med en flyttande markör. Emacs flyttar fortfarande markören dit den tror att den just flyttat fönstret.
Ett annat sätt att lösa problemet är förstås
(setq server-raise-frame nil)
och det löser ju också muspekarens förflyttning. Däremot löser det ju inte det generella fallet med X-klienter som själva försöker smita från workspaces. Det vill jag inte tillåta i mcwm.
Om man skall lösa problemet ordentligt, inklusive muspekarens flytt, så
kanske man kan ändra i select-frame-set-input-focus
i frame.el. Den
innehåller:
"Select FRAME, raise it, and set input focus, if possible. If `mouse-autoselect-window' is non-nil, also move mouse pointer to FRAME's selected window. Otherwise, if `focus-follows-mouse' is non-nil, move mouse cursor to FRAME." (select-frame frame) (raise-frame frame) ;; Ensure, if possible, that FRAME gets input focus. (when (memq (window-system frame) '(x w32 ns)) (x-focus-frame frame)) ;; Move mouse cursor if necessary. (cond (mouse-autoselect-window (let ((edges (window-inside-edges (frame-selected-window frame)))) ;; Move mouse cursor into FRAME's selected window to avoid that ;; Emacs mouse-autoselects another window. (set-mouse-position frame (nth 2 edges) (nth 1 edges)))) (focus-follows-mouse ;; Move mouse cursor into FRAME to avoid that another frame gets ;; selected by the window manager. (set-mouse-position frame (1- (frame-width frame)) 0))))
Här ser vi att koden antar att raise-frame
fungerade. Vad händer om
fönstret inte är mappat? Då flyttas alltså muspekaren i alla fall.
I Emacs-koden finns raise-frame
som C-funktion i frame.c. Den kallar
på make_frame_visible()
som sedan kallar på
xterm.c:x_make_frame_visible()
. Den ser ut att göra så rätt den kan,
tycker jag, men den returnerar inga hints om att den kanske gett upp
ifall fönsterhanteraren vägrade mappa fönstret.
Tillbaka till elispkoden i select-frame-set-input-focus
som jag
citerade ovan: Om man skulle peta in en koll med frame-visible-p
efter
raise-frame
för att se om operationen att göra Emacs-fönstret synlig
misslyckades så kan man ge upp. Det skulle lösa allas problem, vad jag
vet. Jag vet ännu inte vad Emacs-utvecklare tycker om det, men kanske
skall försöka nämna det någonstans.