ch11ng / exwm

Emacs X Window Manager
2.85k stars 134 forks source link

`vc-ediff` creates the Ediff control frame on /new/ workspace (i.e., diffed files are on workspace 0 while the ediff frame is on totally different workspace) #606

Closed emacksnotes closed 5 years ago

emacksnotes commented 5 years ago

vc-ediff creates the Ediff control frame on /new/ workspace (i.e., diffed files are on workspace 0 while the ediff frame is on totally different workspace)

See the screenshot below for what I mean. Pay particular attention to the workspace indicator on the bottom right of the panel.

exwm-gnome-flashback session ediff-panel

I can get around the above issue by customizing ediff as below.

'(ediff-window-setup-function (quote ediff-setup-windows-plain))

FWIW, I run EXWM GNOME Flashback, with the sole addition of gnome-panel. Screenshot above shows the changes I have made to the exwm-gnome-flashback repo.

What I tried

I experimented with these options. None of these helped.

    119: '(exwm-workspace-number 1)
    120: '(exwm-workspace-switch-create-limit 0)

     94: '(exwm-manage-configurations
    116:     ((string-match-p "Ediff" exwm-class-name)
    117:      workspace 0 floating t)

In regard to custom config for ediff panel, I have a feeling that I might have got the matcher predicate for wrong. In fact, I couldn't do any better. With the input focussed on the ediff panel, any invocations of M-x or M-: had exwm quickly flick to workspace 0 and back to the ediff control panel workspace with lightning speed, and I had no clue what was happening in the happening echo area. Toggling the floating-ness of the ediff frame didn't make much difference to the ediff control panel either.

My Preferences for EXWM

(This is for the benefit of users who search the issues for some hints to their problems)

I don't use multiple workspaces.

I have found that forcing modal dialogs to be non-floating (as below) gave me best experience. That is the best experience, until I ran in to this issue with ediff control panel.

    118: '(exwm-manage-force-tiling nil)

Suggestion

  1. If I want only one workspace, how should I configure exwm-workspace-number or exwm-workspace-switch-create-limit. The docstrings of these variables didn't give me quick hints on what I need to do.

IIUC, there is no min and max for number of workspaces. The min number of workspaces is setup when exwm initializes. The max number of workspaces is to limit the number of workspaces going beyond a certain number. (Thinking out of the box) I would have expected a configuration with a cons-cell like (min . max). Furthermore, I was confused if the min expected in workspaces is 0 (i.e., the lowest possible index) or 1 (i.e., the lowest possible /count/ of the workspaces)

  1. What is the predicate matcher for ediff control panels.

Thanks

I am liking exwm much, particularly after switching from the modern GNOME desktop to the GNOME flashback, and adding the GNOME Panel to session startup. I am a user who has worked /solely/ with the default GNOME DE for close to a decade so, and the total asceticism of EXWM left me clueless and dis-orienting.

Contributing Back

When time permits (and once I have figured out all the tweaks that I find necessary), I will publish a new article on my https://emacsnotes.wordpress.com.

emacksnotes commented 5 years ago

FWIW, here is the path that is taken when creating the ediff panel. To create the below log, at the beginning of exwm-workspace--on-after-make-frame, I have added

(exwm--log "Frame parameters: %S" (frame-parameters frame))

It looks like ... EXWM is basing decides if a frame is floating or not based on frame's unsplittable property. The Ediff frame has unsplittable property (but with value nil). Is it possible that exwm needs to grok more of the frame-parameters to decide if the frame is floating or not? Whatever it is, based on screenshot above, EXWM is not honoring the frame height requested by ediff panel.

exwm-workspace--x-create-frame: 
exwm-workspace--on-after-make-frame:    Frame parameters: (
 (parent-id) 
 (explicit-name . t) 
 (display . ":0") 
 (icon-name) 
 (outer-window-id . "27265602") 
 (window-id . "27265606") 
 (top . 769) 
 (left . 1367) 
 (buried-buffer-list) 
 (buffer-list #<buffer *Ediff Control Panel*>) 
 (unsplittable) 
 (modeline . t) 
 (width . 10) 
 (height . 1) 
 (name . "Ediff") 
 (cursor-color . "red") 
 (background-mode . light) 
 (display-type . color) 
 (scrollbar-height . 0) 
 (scrollbar-width . 0) 
 (z-group) 
 (skip-taskbar) 
 (visibility) 
 (fullscreen) 
 (no-accept-focus) 
 (no-focus-on-map) 
 (alpha) 
 (scroll-bar-height . 0) 
 (scroll-bar-width . 0) 
 (cursor-type . box) 
 (auto-lower) 
 (auto-raise . t) 
 (icon-type . t) 
 (inhibit-double-buffering) 
 (tool-bar-position . top) 
 (wait-for-wm . t) 
 (title) 
 (buffer-predicate . exwm-layout--other-buffer-predicate) 
 (tool-bar-lines . 0) 
 (menu-bar-lines . 0) 
 (scroll-bar-background) 
 (scroll-bar-foreground) 
 (no-special-glyphs) 
 (right-fringe . 0) 
 (left-fringe . 0) 
 (line-spacing) 
 (screen-gamma) 
 (border-color . "black") 
 (mouse-color . "black") 
 (background-color . "white") 
 (foreground-color . "black") 
 (horizontal-scroll-bars) 
 (vertical-scroll-bars) 
 (bottom-divider-width . 6) 
 (right-divider-width . 6) 
 (internal-border-width . 0) 
 (border-width . 0) 
 (font-parameter . "Monospace 11") 
 (font . "-PfEd-DejaVu Sans Mono-normal-normal-normal-*-15-*-*-*-m-0-iso10646-1") 
 (font-backend xft x) 
 (override-redirect) 
 (undecorated) 
 (parent-frame) 
 (minibuffer . #<window 4 on  *Minibuf-0*>))
exwm-workspace--on-after-make-frame:    Adding frame `#<frame Ediff 0x681c450>' as workspacee
xwm-workspace--add-frame-as-workspace:  #<frame Ediff 0x681c450>
exwm-workspace--update-ewmh-props:  
exwm-workspace--set-desktop-geometry:   
exwm-workspace--update-workareas:   ([0 24 1366 720] [0 24 1366 720] [0 24 1366 720] [0 24 1366 720] [0 24 1366 720])
exwm-workspace-switch:  
exwm-workspace--set-active: active=#<frame Ediff 0x681c450>; frame=t
exwm-workspace--set-fullscreen: frame=#<frame Ediff 0x681c450>
exwm-workspace--set-fullscreen: x=0; y=24; w=1366; h=720
emacksnotes commented 5 years ago

Here is the stack trace leading up to the frame creation:

Debugger entered--entering a function:
* exwm-workspace--add-frame-as-workspace(#<frame Ediff 0x7366300>)
  (cond ((exwm-workspace--workspace-p frame) (if exwm-debug (progn (xcb-debug:message "%s:\011Frame `%s' is already a workspace\n" "exwm-workspace--on-after-make-frame" frame) nil))) ((not (display-graphic-p frame)) (if exwm-debug (progn (xcb-debug:message "%s:\011Frame `%s' is not graphical\n" "exwm-workspace--on-after-make-frame" frame) nil))) ((not (string-equal (replace-regexp-in-string "\\.0$" "" (slot-value exwm--connection 'display)) (replace-regexp-in-string "\\.0$" "" (frame-parameter frame 'display)))) (if exwm-debug (progn (xcb-debug:message "%s:\011Frame `%s' is on a different DISPLAY (%S instead of %S)\n" "exwm-workspace--on-after-make-frame" frame (frame-parameter frame 'display) (slot-value exwm--connection 'display)) nil))) ((frame-parameter frame 'unsplittable) (if exwm-debug (progn (xcb-debug:message "%s:\011Frame `%s' is floating\n" "exwm-workspace--on-after-make-frame" frame) nil))) (t (if exwm-debug (progn (xcb-debug:message "%s:\011Adding frame `%s' as workspace\n" "exwm-workspace--on-after-make-frame" frame) nil)) (exwm-workspace--add-frame-as-workspace frame)))
  exwm-workspace--on-after-make-frame(#<frame Ediff 0x7366300>)
  run-hook-with-args(exwm-workspace--on-after-make-frame #<frame Ediff 0x7366300>)
  make-frame(((name . "Ediff") (minibuffer) (user-position . t) (vertical-scroll-bars) (scrollbar-width . 0) (scrollbar-height . 0) (menu-bar-lines . 0) (tool-bar-lines . 0) (left-fringe . 0) (right-fringe . 0) (auto-lower) (auto-raise . t) (visibility) (width . 1) (height . 1) (fullscreen) (top . 769) (left . 1367)))
  ediff-setup-control-frame(#<buffer *Ediff Control Panel*> #<frame  *Minibuf-1* 0x1025c30>)
  ediff-setup-windows-multiframe-compare(#<buffer exwm-gnome-flashback.session.~c6012ae59432bd39b2d556734ec2ded07a24e42b~> #<buffer exwm-gnome-flashback.session> nil #<buffer *Ediff Control Panel*>)
  ediff-setup-windows-multiframe(#<buffer exwm-gnome-flashback.session.~c6012ae59432bd39b2d556734ec2ded07a24e42b~> #<buffer exwm-gnome-flashback.session> nil #<buffer *Ediff Control Panel*>)
  ediff-setup-windows-default(#<buffer exwm-gnome-flashback.session.~c6012ae59432bd39b2d556734ec2ded07a24e42b~> #<buffer exwm-gnome-flashback.session> nil #<buffer *Ediff Control Panel*>)
  ediff-setup-windows(#<buffer exwm-gnome-flashback.session.~c6012ae59432bd39b2d556734ec2ded07a24e42b~> #<buffer exwm-gnome-flashback.session> nil #<buffer *Ediff Control Panel*>)
emacksnotes commented 5 years ago

It looks like ... EXWM is basing decides if a frame is floating or not based on frame's unsplittable property. The Ediff frame has unsplittable property (but with value nil). Is it possible that exwm needs to grok more of the frame-parameters to decide if the frame is floating or not?

Does EXWM create all new frames on a new workspace?

If yes, were I to declare myself as 1-workspace-only-user, is there a way to float the ediff control panel (as it would on non-exwm Emacs).

(ps: The user guide mentions the issue I have raised here, in the context of magit. The issue is not localized to magit usage, but to any one who relies on ediff and is habituated to the /default/ behaviour of ediff on graphical displays.)

emacksnotes commented 5 years ago

The user guide mentions the issue I have raised here, in the context of magit. The issue is not localized to magit usage, but to any one who relies on ediff and is habituated to the /default/ behaviour of ediff on graphical displays.

It looks like ... EXWM is basing decides if a frame is floating or not based on frame's unsplittable property. The Ediff frame has unsplittable property (but with value nil).

I took the above question a bit further, and did this

 (with-eval-after-load 'ediff-wind
  (push '(unsplittable . t) ediff-control-frame-parameters))

Once that was done, I was able to get the ediff control panel right on the current workspace and floating above the source buffers being diffed. See below for the results.

Make Ediff Control Panel Unsplittable

The ediff control panel looks a bit off to me because

  1. It has no title (which is understandable)
  2. It is positioned right above the gnome panel (and hiding parts of it). I would have expected that it will be positioned relative /within/ the Emacs frame and not outside of it.

Is there any explanation for (2)? Is that a bug in how EXWM handles ediff control panel.

ps: ediff-control-frame-parameters is a defconst. IME, the Elisp compiler doesn't do constant propagation. So, modifying ediff-control-frame-parameters at runtime will indeed /work/.

medranocalvo commented 5 years ago

(I started writing this a couple of days ago, but never sent it.)

Thank you for the thorough report.

With regards to the core point, [... checks Wiki ...] I was going to suggest to add it to the Wiki, but it's already there! https://github.com/ch11ng/exwm/wiki#an-issue-with-ediff-mode-in-magit. It might help to add vc-ediff there, so that it would be easier to find. Would you do that?


As to your trials, you write that you possibly got the matcher predicate for wrong. I'm pretty sure exwm-manage-configurations only applies to X applications, but not to Emacs buffers. I might get corrected on this point. You raise a valid point, though: should it be possible to configure newly-spawned emacs frames via this mechanism? As in your example: you wanted the Ediff control buffer to be floating, instead of creating a new workspace. Other examples might include speedbar, etc. In any case this would be a new feature, and I'm not sure of its feasibility, clunkyness...

Does EXWM create all new frames on a new workspace?

Indeed: new frames become workspaces in EXWM. There are some exceptions: frames spawned by emacsclient, unsplittable frames... you can see the whole thing in exwm-workspace--on-after-make-frame. As you found out, setting the unsplittable frame parameter on the Ediff control frame works. I think controlling how regular Emacs buffers and frames behave within EXWM should be better integrated and documented, but this needs someone to push for it, and someone to implement it. I personally think we should integrate with display-buffer-alist and we should document in the Wiki what to do with particular "important" packages, such as Ediff.

Please, file a feature request.


You'd like to limit the number of workspaces... I don't think there's specific support for that; exwm-workspace-number controls the number of initial workspaces, while exwm-workspace-switch-create-limit affects only the switcher (exwm-workspace-switch). Moreover: creating a frame implies (in most cases) creating a workspace. I would try advising make-frame to create a window instead...


I would say launching Emacs frames as floating frames is currently not well supported. I don't think any floating frame should be positioned above the panel by default. I would ask you to file a new ticket about that (linking to this discussion).

It's helpful to have the perspective of a new user, thanks. You are welcome to write your experiences and suggestions in the Wiki, as well as your workflow (single workspace, tiling modal windows) and how you got it to work, for the benefit of other users. Needless to say, a link to your article will be welcome in the Wiki as well!

emacksnotes commented 5 years ago

https://github.com/ch11ng/exwm/wiki#an-issue-with-ediff-mode-in-magit. It might help to add vc-ediff there, so that it would be easier to find. Would you do that?

Done. Please review the changes.

emacksnotes commented 5 years ago

Hello @medranocalvo, Thanks for putting up with my 'stream-of-consciousness'-style bug report. Thanks. I am closing this issue. I have opened sister issues for parts that need more attention.

emacksnotes commented 5 years ago

Please review this new addition to Wiki: https://github.com/ch11ng/exwm/wiki/EXWM-User-Guide#emacs-frame--workspaces. In that section, I have linked to an issue which informed my edit.