unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#745: pop-to-buffer, frames, and input focus
@ 2008-08-20  7:35 ` Helmut Eller
  2008-08-20 14:50   ` martin rudalics
  2008-09-11  7:05   ` bug#745: marked as done (pop-to-buffer, frames, and input focus) Emacs bug Tracking System
  0 siblings, 2 replies; 31+ messages in thread
From: Helmut Eller @ 2008-08-20  7:35 UTC (permalink / raw)
  To: bug-gnu-emacs

Hi,

The behavior of pop-to-buffer in combination with multiple frames is
rather unpredictable or at least not what I expected.

For example:

  shell$ cat pop-to-buffer-test.el
  
  (let ((frame (selected-frame))
        (pop-up-frames t))
    (display-buffer (get-buffer-create "foo"))
    (select-frame-set-input-focus frame))
  
  (let ((display-buffer-reuse-frames t))
    (pop-to-buffer "foo"))
  
  shell$ emacs -Q -l pop-to-buffer-test.el

Pops up two frames, one frame displays the "foo" buffer and the other
the "*scratch*" buffer (so far so good).  But the "foo" frame has not
the input focus.  Isn't pop-to-buffer supposed to switch input focus
too?

Also note that I had to save and restore the selected frame
around display-buffer.  If I try

  emacs -Q --eval '(let ((pop-up-frames t)) 
                     (display-buffer (get-buffer-create "foo")))' 

the "foo" buffer is selected, even though display-buffer should not
switch the selected window.

Not even save-window-excursion stops display-buffer from switching the
frame:

  emacs -Q --eval '(save-window-excursion 
                     (let ((pop-up-frames t)) 
                        (display-buffer (get-buffer-create "foo"))))'


This is with:
 GNU Emacs 23.0.60.4 (i686-pc-linux-gnu, GTK+ Version 2.8.20)
 of 2008-08-15 on xaital
Windowing system distributor `The X.Org Foundation', version 11.0.70101000
configured using `configure  '--without-sound' '--without-pop' '--without-gif' '--without-tiff''

My window manager is Sawfish 1.3.

Helmut.







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-20  7:35 ` bug#745: pop-to-buffer, frames, and input focus Helmut Eller
@ 2008-08-20 14:50   ` martin rudalics
  2008-08-20 18:42     ` Helmut Eller
  2008-09-11  7:05   ` bug#745: marked as done (pop-to-buffer, frames, and input focus) Emacs bug Tracking System
  1 sibling, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-20 14:50 UTC (permalink / raw)
  To: Helmut Eller, 745

 >   (let ((frame (selected-frame))
 >         (pop-up-frames t))
 >     (display-buffer (get-buffer-create "foo"))
 >     (select-frame-set-input-focus frame))
 >
 >   (let ((display-buffer-reuse-frames t))
 >     (pop-to-buffer "foo"))
 >
 >   shell$ emacs -Q -l pop-to-buffer-test.el
 >
 > Pops up two frames, one frame displays the "foo" buffer and the other
 > the "*scratch*" buffer (so far so good).  But the "foo" frame has not
 > the input focus.  Isn't pop-to-buffer supposed to switch input focus
 > too?

      (select-frame-set-input-focus frame))

gives input focus to the previously selected frame.

 > Also note that I had to save and restore the selected frame
 > around display-buffer.  If I try
 >
 >   emacs -Q --eval '(let ((pop-up-frames t))
 >                      (display-buffer (get-buffer-create "foo")))'
 >
 > the "foo" buffer is selected, even though display-buffer should not
 > switch the selected window.

I'm not sure whether on some system there were problems when raising a
frame and/or giving it input focus, and not selecting it.  At least with
Emacs 22 the frame was selected already.  Since there's only one window
on the new frame, that window must be selected as well.

In any case you're right: either the window must not be selected or the
documentation should tell when and why it selects the window.

 > Not even save-window-excursion stops display-buffer from switching the
 > frame:
 >
 >   emacs -Q --eval '(save-window-excursion
 >                      (let ((pop-up-frames t))
 >                         (display-buffer (get-buffer-create "foo"))))'

`save-window-excursion' is of no use here: It permits you to change the
contents of a frame in the body and restore the initial contents
afterwards.  You do that with the originally selected frame here.  The
new frame created by `display-buffer' is not affected by this.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-20 14:50   ` martin rudalics
@ 2008-08-20 18:42     ` Helmut Eller
  2008-08-20 20:42       ` David Reitter
  2008-08-20 20:56       ` martin rudalics
  0 siblings, 2 replies; 31+ messages in thread
From: Helmut Eller @ 2008-08-20 18:42 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-20 16:50+0200] writes:

>> Pops up two frames, one frame displays the "foo" buffer and the other
>> the "*scratch*" buffer (so far so good).  But the "foo" frame has not
>> the input focus.  Isn't pop-to-buffer supposed to switch input focus
>> too?
>
>      (select-frame-set-input-focus frame))
>
> gives input focus to the previously selected frame.

Are you saying, that pop-to-buffer can't be used to select the window,
the frame, and input focus at the same time?  If so, when should
pop-to-buffer be used?  Aren't that unusual situations when
pop-to-buffer should not also select the input focus?

If you have any hints or guidelines how be a good buffer/window/frame
citizen in different scenarios, that would be much appreciated.

I'm not using multiple frames myself, but I'm maintaining a package
called SLIME[*] which is used by a number of people who use frames.  I'm
not excited at all about rewriting a dozen or so uses of pop-to-buffer
just to support multiple frames.  There are some variables like
display-buffer-reuse-frames and special-display-buffer-names and I hoped
that those variables were supposed to make it easy to support multiple
frames without cluttering the source code.

[*] http://www.common-lisp.net/project/slime/

>
>> Also note that I had to save and restore the selected frame
>> around display-buffer.  If I try
>>
>>   emacs -Q --eval '(let ((pop-up-frames t))
>>                      (display-buffer (get-buffer-create "foo")))'
>>
>> the "foo" buffer is selected, even though display-buffer should not
>> switch the selected window.
>
> I'm not sure whether on some system there were problems when raising a
> frame and/or giving it input focus, and not selecting it.  At least with
> Emacs 22 the frame was selected already.  Since there's only one window
> on the new frame, that window must be selected as well.
>
> In any case you're right: either the window must not be selected or the
> documentation should tell when and why it selects the window.

The docstring of display-buffer reads
"Make buffer BUFFER-OR-NAME appear in some window but don't select it. ..."
I think it be would less surprising if the input focus would not be switched
to the new frame.

>> Not even save-window-excursion stops display-buffer from switching the
>> frame:
>>
>>   emacs -Q --eval '(save-window-excursion
>>                      (let ((pop-up-frames t))
>>                         (display-buffer (get-buffer-create "foo"))))'
>
> `save-window-excursion' is of no use here: It permits you to change the
> contents of a frame in the body and restore the initial contents
> afterwards.  You do that with the originally selected frame here.  The
> new frame created by `display-buffer' is not affected by this.

save-window-excursion is supposed to "... Also restore the choice of
selected window. ..."

If I do

   emacs -Q -nw --eval '(save-window-excursion
                          (let ((pop-up-frames t))
                            (display-buffer (get-buffer-create "foo"))))'

I end up in the "*scratch*" buffer not in "foo".  It would be more
consistent if the X11 version and the tty version would restore the
input focus to the same frame.  The tty version is the behavior that I
would expect.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-20 18:42     ` Helmut Eller
@ 2008-08-20 20:42       ` David Reitter
  2008-08-20 20:56       ` martin rudalics
  1 sibling, 0 replies; 31+ messages in thread
From: David Reitter @ 2008-08-20 20:42 UTC (permalink / raw)
  To: Helmut Eller, 745

[-- Attachment #1: Type: text/plain, Size: 2056 bytes --]

On 20 Aug 2008, at 14:42, Helmut Eller wrote:
>  Are you saying, that pop-to-buffer can't be used to select the  
> window,
> the frame, and input focus at the same time?  If so, when should
> pop-to-buffer be used?  Aren't that unusual situations when
> pop-to-buffer should not also select the input focus?


I have long used the patch below in Aquamacs to create consistency  
between multi-frame and multi-window operations.  Most packages are  
designed to work with the multi-window setup, and it is my conviction  
that most Emacs developers work with the Emacs default (multi- 
window).  Perhaps that is why some packages do not play ball when  
buffers are set to pop up in new frames...


*** src/buffer.c	25 Feb 2006 23:33:57 +0000	1.501
--- src/buffer.c	07 May 2006 22:45:45 +0100	
***************
*** 175,180 ****
--- 175,182 ----
   Lisp_Object Qinsert_in_front_hooks;
   Lisp_Object Qinsert_behind_hooks;

+ Lisp_Object Qselect_frame_set_input_focus;
+
   static void alloc_buffer_text P_ ((struct buffer *, size_t));
   static void free_buffer_text P_ ((struct buffer *b));
   static struct Lisp_Overlay * copy_overlays P_ ((struct buffer *,  
struct Lisp_Overlay *));
***************
*** 1723,1729 ****
   	}
       }
     Fset_buffer (buf);
!   Fselect_window (Fdisplay_buffer (buf, other_window, Qnil),  
norecord);
     return buf;
   }

--- 1725,1734 ----
   	}
       }
     Fset_buffer (buf);
!   call1(Qselect_frame_set_input_focus,
! 	Fwindow_frame( Fselect_window (Fdisplay_buffer (buf,
! 							other_window, Qnil),
! 				       norecord)));
     return buf;
   }

***************
*** 5227,5232 ****
--- 5232,5239 ----
     Qafter_change_functions = intern ("after-change-functions");
     staticpro (&Qafter_change_functions);
     staticpro (&Qucs_set_table_for_input);
+   Qselect_frame_set_input_focus = intern ("select-frame-set-input- 
focus");
+   staticpro (&Qselect_frame_set_input_focus);

     Qkill_buffer_query_functions = intern ("kill-buffer-query- 
functions");
     staticpro (&Qkill_buffer_query_functions);




[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2193 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-20 18:42     ` Helmut Eller
  2008-08-20 20:42       ` David Reitter
@ 2008-08-20 20:56       ` martin rudalics
  2008-08-21  8:07         ` Helmut Eller
  1 sibling, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-20 20:56 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > Are you saying, that pop-to-buffer can't be used to select the window,
 > the frame, and input focus at the same time?  If so, when should
 > pop-to-buffer be used?  Aren't that unusual situations when
 > pop-to-buffer should not also select the input focus?

With emacs -Q evaluating

(let ((pop-up-frames t)
       (buffer (get-buffer-create "foo")))
   (pop-to-buffer buffer))

here gets me a new frame on top of the previously selected one, the
window displaying buffer `foo' is the selected window, and when I now
start typing, characters get displayed in that window.  What did you
expect and what did you get?

 > If you have any hints or guidelines how be a good buffer/window/frame
 > citizen in different scenarios, that would be much appreciated.

I'm slightly confused because in your earlier scenario you bemoaned the
fact that the frame _was_ selected.  All I wanted to say that raising a
frame, giving it input focus, and _not_ selecting it might be difficult.

 > I'm not using multiple frames myself, but I'm maintaining a package
 > called SLIME[*] which is used by a number of people who use frames.  I'm
 > not excited at all about rewriting a dozen or so uses of pop-to-buffer
 > just to support multiple frames.  There are some variables like
 > display-buffer-reuse-frames and special-display-buffer-names and I hoped
 > that those variables were supposed to make it easy to support multiple
 > frames without cluttering the source code.
 >
 > [*] http://www.common-lisp.net/project/slime/

I moved `pop-to-buffer' to window.el so you can easier try to play
around with it and propose a solution that fits your needs ;-)

 > The docstring of display-buffer reads
 > "Make buffer BUFFER-OR-NAME appear in some window but don't select it. ..."
 > I think it be would less surprising if the input focus would not be switched
 > to the new frame.

You have a point here but it's not up to me to decide that.

 > If I do
 >
 >    emacs -Q -nw --eval '(save-window-excursion
 >                           (let ((pop-up-frames t))
 >                             (display-buffer (get-buffer-create "foo"))))'
 >
 > I end up in the "*scratch*" buffer not in "foo". It would be more
 > consistent if the X11 version and the tty version would restore the
 > input focus to the same frame.  The tty version is the behavior that I
 > would expect.

When I do

(save-window-excursion
   (let ((pop-up-frames t))
     (display-buffer (get-buffer-create "foo"))))

in the *scratch* buffer I end up in `foo' - whether this is TRT I don't
know.  Doing a `save-window-excursion' on the command line is beyond my
comprehension.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-20 20:56       ` martin rudalics
@ 2008-08-21  8:07         ` Helmut Eller
  2008-08-21  9:04           ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-21  8:07 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-20 22:56+0200] writes:

>> Are you saying, that pop-to-buffer can't be used to select the window,
>> the frame, and input focus at the same time?  If so, when should
>> pop-to-buffer be used?  Aren't that unusual situations when
>> pop-to-buffer should not also select the input focus?
>
> With emacs -Q evaluating
>
> (let ((pop-up-frames t)
>       (buffer (get-buffer-create "foo")))
>   (pop-to-buffer buffer))
>
> here gets me a new frame on top of the previously selected one, the
> window displaying buffer `foo' is the selected window, and when I now
> start typing, characters get displayed in that window.  What did you
> expect and what did you get?

Consider my original example:

(progn
  (let ((frame (selected-frame))
        (pop-up-frames t))
    (display-buffer (get-buffer-create "foo"))
    (select-frame-set-input-focus frame))
  
  (let ((display-buffer-reuse-frames t))
    (pop-to-buffer "foo")))

First, display-buffer is just used to create two frames.  This switches
(surprisingly) focus to the "foo" buffer.  select-frame-set-input-focus
is used to force the focus back to the "*scratch*" buffer.  Then we use
pop-to-buffer, but the input focus remains (surprisingly) in the
"*scratch*" buffer.

I expect this:

  pop-to-buffer     should switch the input focus
  display-buffer    should not change the input focus

>> If you have any hints or guidelines how be a good buffer/window/frame
>> citizen in different scenarios, that would be much appreciated.
>
> I'm slightly confused because in your earlier scenario you bemoaned the
> fact that the frame _was_ selected.  All I wanted to say that raising a
> frame, giving it input focus, and _not_ selecting it might be difficult.

I see.  But this is also not what I expect.

>> I'm not using multiple frames myself, but I'm maintaining a package
>> called SLIME[*] which is used by a number of people who use frames.  I'm
>> not excited at all about rewriting a dozen or so uses of pop-to-buffer
>> just to support multiple frames.  There are some variables like
>> display-buffer-reuse-frames and special-display-buffer-names and I hoped
>> that those variables were supposed to make it easy to support multiple
>> frames without cluttering the source code.
>>
>> [*] http://www.common-lisp.net/project/slime/
>
> I moved `pop-to-buffer' to window.el so you can easier try to play
> around with it and propose a solution that fits your needs ;-)

Thanks for the moving it :-)

pop-to-buffer is more or less (select-window (display-buffer ...)).
This looks very reasonable, but it doesn't transfer the input focus.
(under X; in a tty everything works well.)

On the other hand, display-buffer switches sometimes (when a new frame
is created) the input focus, even when that was not asked for.

Maybe pop-to-buffer could do something like 

  (let ((window (display-buffer ...)))
    (select-window window)
    (select-frame-set-input-focus (window-frame window)))

That would solve my immediate problem, but I suspect that select-window
should be smarter.  My naive interpretation of select-window's C source
is that select-window tries to select the frame.  But apparently forgets
about the input focus.  This may also be the reason why
save-window-excursion doesn't restore the input focus.

Selecting a window, without giving it the input focus is probably rarely
needed.  Perhaps select-window should transfer the input focus by
default.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-21  8:07         ` Helmut Eller
@ 2008-08-21  9:04           ` martin rudalics
  2008-08-21 13:20             ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-21  9:04 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > Consider my original example:
 >
 > (progn
 >   (let ((frame (selected-frame))
 >         (pop-up-frames t))
 >     (display-buffer (get-buffer-create "foo"))
 >     (select-frame-set-input-focus frame))
 >
 >   (let ((display-buffer-reuse-frames t))
 >     (pop-to-buffer "foo")))
 >
 > First, display-buffer is just used to create two frames.  This switches
 > (surprisingly) focus to the "foo" buffer.  select-frame-set-input-focus
 > is used to force the focus back to the "*scratch*" buffer.  Then we use
 > pop-to-buffer, but the input focus remains (surprisingly) in the
 > "*scratch*" buffer.

Ahhh, I can't reproduce that.  Evaluating your `progn' moves focus to
the `foo' buffer here (with emacs -Q).  So it seems we have a platform
(maybe window manager) specific problem.

 > I expect this:
 >
 >   pop-to-buffer     should switch the input focus
 >   display-buffer    should not change the input focus

`pop-to-buffer' has the sole additional twist WRT `display-buffer':

     (select-window (display-buffer buffer other-window) norecord)

That is, the window used by `display-buffer' should get definitively
selected.  So, if `display-buffer' has decided to use "another" frame,
raising that frame, giving it input focus, and implicitly selecting that
frame and the window used for displaying the buffer_must_ have been
already handled by `display-buffer'.  In this case, the `select-window'
done by `pop-to-buffer' looks like a NOOP though I didn't verify that.

 >> All I wanted to say that raising a
 >> frame, giving it input focus, and _not_ selecting it might be difficult.
 >
 > I see.  But this is also not what I expect.

So `pop-to-buffer' raising a frame + giving it input focus + selecting
it is always OK with you?

 > pop-to-buffer is more or less (select-window (display-buffer ...)).
 > This looks very reasonable, but it doesn't transfer the input focus.
 > (under X; in a tty everything works well.)
 >
 > On the other hand, display-buffer switches sometimes (when a new frame
 > is created) the input focus, even when that was not asked for.
 >
 > Maybe pop-to-buffer could do something like
 >
 >   (let ((window (display-buffer ...)))
 >     (select-window window)
 >     (select-frame-set-input-focus (window-frame window)))
 >
 > That would solve my immediate problem, ...

Does it solve all your problems in this context?  I suppose it won't be
of any help when you use `display-buffer' with `pop-up-frames' t :-(

 > ... but I suspect that select-window
 > should be smarter.  My naive interpretation of select-window's C source
 > is that select-window tries to select the frame.  But apparently forgets
 > about the input focus.  This may also be the reason why
 > save-window-excursion doesn't restore the input focus.
 >
 > Selecting a window, without giving it the input focus is probably rarely
 > needed.  Perhaps select-window should transfer the input focus by
 > default.

I suppose we can't do that.  `select-window' is frequently used to
temporarily switch to another window (compare `save-selected-window').
Shifting input focus to another frame and possibly back to the initial
frame might confuse the window manager.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-21  9:04           ` martin rudalics
@ 2008-08-21 13:20             ` Helmut Eller
  2008-08-21 20:31               ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-21 13:20 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-21 11:04+0200] writes:

>> Consider my original example:
>>
>> (progn
>>   (let ((frame (selected-frame))
>>         (pop-up-frames t))
>>     (display-buffer (get-buffer-create "foo"))
>>     (select-frame-set-input-focus frame))
>>
>>   (let ((display-buffer-reuse-frames t))
>>     (pop-to-buffer "foo")))
>>
>> First, display-buffer is just used to create two frames.  This switches
>> (surprisingly) focus to the "foo" buffer.  select-frame-set-input-focus
>> is used to force the focus back to the "*scratch*" buffer.  Then we use
>> pop-to-buffer, but the input focus remains (surprisingly) in the
>> "*scratch*" buffer.
>
> Ahhh, I can't reproduce that.  Evaluating your `progn' moves focus to
> the `foo' buffer here (with emacs -Q).  So it seems we have a platform
> (maybe window manager) specific problem.

I have tried a few window managers now.  

pop-to-buffer doesn't switch input focus with: Sawfish, kwin,
metacity, fluxbox, twm.  
It does with icewm.

display-buffer seems to switch focus with: Sawfish, kwin, fluxbox,
icewm, twm.

Metacity seems to make the decision based on the mouse pointer, but it's
not clear how.  The new buffer receives the input focus sometimes but
not always.

>
>> I expect this:
>>
>>   pop-to-buffer     should switch the input focus
>>   display-buffer    should not change the input focus
>
> `pop-to-buffer' has the sole additional twist WRT `display-buffer':
>
>     (select-window (display-buffer buffer other-window) norecord)
>
> That is, the window used by `display-buffer' should get definitively
> selected.  So, if `display-buffer' has decided to use "another" frame,
> raising that frame, giving it input focus, and implicitly selecting that
> frame and the window used for displaying the buffer_must_ have been
> already handled by `display-buffer'.  In this case, the `select-window'
> done by `pop-to-buffer' looks like a NOOP though I didn't verify that.

I still think that display-buffer should neither select the other frame
nor give it the input focus.  (Whether the other frame should be raised
or not should probably be customizable, but that's a minor issue.)

If the problem only occurs for new frames it's not so serious, tough.
Once created, frames will probably stay there for a while and not be
continuously closed/created.  It's probably also harder to stop window
managers from doing stupid things with new frames.

>>> All I wanted to say that raising a
>>> frame, giving it input focus, and _not_ selecting it might be difficult.
>>
>> I see.  But this is also not what I expect.
>
> So `pop-to-buffer' raising a frame + giving it input focus + selecting
> it is always OK with you?

Yes, I think so.

>
>> pop-to-buffer is more or less (select-window (display-buffer ...)).
>> This looks very reasonable, but it doesn't transfer the input focus.
>> (under X; in a tty everything works well.)
>>
>> On the other hand, display-buffer switches sometimes (when a new frame
>> is created) the input focus, even when that was not asked for.
>>
>> Maybe pop-to-buffer could do something like
>>
>>   (let ((window (display-buffer ...)))
>>     (select-window window)
>>     (select-frame-set-input-focus (window-frame window)))
>>
>> That would solve my immediate problem, ...
>
> Does it solve all your problems in this context?  

For now, yes :-)    

> I suppose it won't be
> of any help when you use `display-buffer' with `pop-up-frames' t :-(

Well, yeah this wouldn't fix display-buffer.  

>> ... but I suspect that select-window
>> should be smarter.  My naive interpretation of select-window's C source
>> is that select-window tries to select the frame.  But apparently forgets
>> about the input focus.  This may also be the reason why
>> save-window-excursion doesn't restore the input focus.
>>
>> Selecting a window, without giving it the input focus is probably rarely
>> needed.  Perhaps select-window should transfer the input focus by
>> default.
>
> I suppose we can't do that.  `select-window' is frequently used to
> temporarily switch to another window (compare `save-selected-window').

Hmm, I see.  Yet, select-window calls Fselect_frame.
The distinction between select-frame and select-frame-set-input-focus
is certainly confusing.

> Shifting input focus to another frame and possibly back to the initial
> frame might confuse the window manager.

That would be a stupid window manager :-) 

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-21 13:20             ` Helmut Eller
@ 2008-08-21 20:31               ` martin rudalics
  2008-08-22 14:27                 ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-21 20:31 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > pop-to-buffer doesn't switch input focus with: Sawfish, kwin,
 > metacity, fluxbox, twm.
 > It does with icewm.
 >
 > display-buffer seems to switch focus with: Sawfish, kwin, fluxbox,
 > icewm, twm.

You probably mean display-buffer does _not_ switch focus with these.

 > I still think that display-buffer should neither select the other frame
 > nor give it the input focus.  (Whether the other frame should be raised
 > or not should probably be customizable, but that's a minor issue.)

I agree with you but I'm afraid there were issues with this.  If you
have some spare time please look at the threads starting with

http://lists.gnu.org/archive/html/emacs-devel/2006-04/msg00922.html

http://lists.gnu.org/archive/html/emacs-devel/2005-11/msg00107.html

http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg00946.html

respectively.  At the very least you will find out that you're not
alone.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-21 20:31               ` martin rudalics
@ 2008-08-22 14:27                 ` Helmut Eller
  2008-08-22 16:39                   ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-22 14:27 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-21 22:31+0200] writes:

>> pop-to-buffer doesn't switch input focus with: Sawfish, kwin,
>> metacity, fluxbox, twm.
>> It does with icewm.
>>
>> display-buffer seems to switch focus with: Sawfish, kwin, fluxbox,
>> icewm, twm.
>
> You probably mean display-buffer does _not_ switch focus with these.

I meant to say: display-buffer _does_ switch focus when creating a new
frame with those window managers: Sawfish, kwin, fluxbox, icewm, twm.

>> I still think that display-buffer should neither select the other frame
>> nor give it the input focus.  (Whether the other frame should be raised
>> or not should probably be customizable, but that's a minor issue.)
>
> I agree with you but I'm afraid there were issues with this.  If you
> have some spare time please look at the threads starting with
>
> http://lists.gnu.org/archive/html/emacs-devel/2006-04/msg00922.html
>
> http://lists.gnu.org/archive/html/emacs-devel/2005-11/msg00107.html
>
> http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg00946.html
>
> respectively.  At the very least you will find out that you're not
> alone.

Those messages are several years old.  And it looks like nobody is
going to fix the issue this time.  

Maybe we could move the input focus to the selected frame in a lazy
fashion.  E.g. when Emacs waits for new events, we could compare the
currently focused frame with the selected frame, and if they differ we
could switch the focus to the selected frame.  This would make
select-frame more useful.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-22 14:27                 ` Helmut Eller
@ 2008-08-22 16:39                   ` martin rudalics
  2008-08-23  8:55                     ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-22 16:39 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 >>> pop-to-buffer doesn't switch input focus with: Sawfish, kwin,
 >>> metacity, fluxbox, twm.
 >>> It does with icewm.
 >>>
 >>> display-buffer seems to switch focus with: Sawfish, kwin, fluxbox,
 >>> icewm, twm.
 >> You probably mean display-buffer does _not_ switch focus with these.
 >
 > I meant to say: display-buffer _does_ switch focus when creating a new
 > frame with those window managers: Sawfish, kwin, fluxbox, icewm, twm.

I still don't understand.  Simplistically spoken, `pop-to-buffer' is
`display-buffer' + `select-window'.  How can, using Sawfish say,
`display-buffer' switch focus and `pop-to-buffer' not switch focus?

 >>> I still think that display-buffer should neither select the other frame
 >>> nor give it the input focus.  (Whether the other frame should be raised
 >>> or not should probably be customizable, but that's a minor issue.)
 >> I agree with you but I'm afraid there were issues with this.  If you
 >> have some spare time please look at the threads starting with
 >>
 >> http://lists.gnu.org/archive/html/emacs-devel/2006-04/msg00922.html
 >>
 >> http://lists.gnu.org/archive/html/emacs-devel/2005-11/msg00107.html
 >>
 >> http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg00946.html
 >>
 >> respectively.  At the very least you will find out that you're not
 >> alone.
 >
 > Those messages are several years old.  And it looks like nobody is
 > going to fix the issue this time.

We should fix it this time.  Please try again two things with the
window-managers you listed above and `pop-up-frames' non-nil:

- tell whether `display-buffer' does switch focus.

- tell whether `pop-to-buffer' does switch focus.

- try both, if possible, with click-to-focus and a focus-follows-mouse
   settings (maybe you have to set the value of the Emacs variable
   `focus-follows-mouse' appropriately).

Here on Windos XP with a focus-follows-mouse policy, `display-buffer'
and `pop-to-buffer' both switch focus.  IIRC, people reported troubles
with the standard click-to-focus policy.  Honestly, I'm a bit reluctant
to try out click-to-focus here, maybe someone else can try?

 > Maybe we could move the input focus to the selected frame in a lazy
 > fashion.  E.g. when Emacs waits for new events, we could compare the
 > currently focused frame with the selected frame, and if they differ we
 > could switch the focus to the selected frame.  This would make
 > select-frame more useful.

I suppose we should introduce a customizable variable which allows to
call `select-frame-set-input-focus' (or something similar) at least in
`pop-to-buffer' but maybe also in `display-buffer'.  But we should also
provide a doc-string recommending what setting this variable should have
on which platform.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-22 16:39                   ` martin rudalics
@ 2008-08-23  8:55                     ` Helmut Eller
  2008-08-23 12:05                       ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-23  8:55 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

[-- Attachment #1: Type: text/plain, Size: 4821 bytes --]

* martin rudalics [2008-08-22 18:39+0200] writes:

>>>> pop-to-buffer doesn't switch input focus with: Sawfish, kwin,
>>>> metacity, fluxbox, twm.
>>>> It does with icewm.
>>>>
>>>> display-buffer seems to switch focus with: Sawfish, kwin, fluxbox,
>>>> icewm, twm.
>>> You probably mean display-buffer does _not_ switch focus with these.
>>
>> I meant to say: display-buffer _does_ switch focus when creating a new
>> frame with those window managers: Sawfish, kwin, fluxbox, icewm, twm.
>
> I still don't understand.  Simplistically spoken, `pop-to-buffer' is
> `display-buffer' + `select-window'.  How can, using Sawfish say,
> `display-buffer' switch focus and `pop-to-buffer' not switch focus?

Sorry, that was indeed confusing.
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.  (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.)

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.)

Let's call the display-buffer case, situation A and the pop-to-buffer
case, situation B.

>
> We should fix it this time.  Please try again two things with the
> window-managers you listed above and `pop-up-frames' non-nil:
>
> - tell whether `display-buffer' does switch focus.
>
> - tell whether `pop-to-buffer' does switch focus.
>
> - try both, if possible, with click-to-focus and a focus-follows-mouse
>   settings (maybe you have to set the value of the Emacs variable
>   `focus-follows-mouse' appropriately).

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)
?  N  Metacity   follow-mouse (mouse)
?  N  Metacity   follow-mouse (sloppy)
?  N  Metacity   click-to-focus (click)
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)
Y  N  FluxBox    click-to-focus
Y  Y  IceWM      click-to-focus
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.

>
> Here on Windos XP with a focus-follows-mouse policy, `display-buffer'
> and `pop-to-buffer' both switch focus.  IIRC, people reported troubles
> with the standard click-to-focus policy.  Honestly, I'm a bit reluctant
> to try out click-to-focus here, maybe someone else can try?
>
>> Maybe we could move the input focus to the selected frame in a lazy
>> fashion.  E.g. when Emacs waits for new events, we could compare the
>> currently focused frame with the selected frame, and if they differ we
>> could switch the focus to the selected frame.  This would make
>> select-frame more useful.
>
> I suppose we should introduce a customizable variable which allows to
> call `select-frame-set-input-focus' (or something similar) at least in
> `pop-to-buffer' but maybe also in `display-buffer'.  But we should also
> provide a doc-string recommending what setting this variable should have
> on which platform.

Yes, that would be good.  The docstring for select-window could perhaps
also state a bit more prominently that the "selected window" and the
"input focus" are different things or at least refer to
select-frame-set-input-focus.

BTW, below is a proof of concept implementation for the
update-focus-lazily idea.

Helmut.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lazy-focus.diff --]
[-- Type: text/x-diff, Size: 836 bytes --]

--- keyboard.c.~1.969.~	2008-08-15 14:47:16.000000000 +0200
+++ keyboard.c	2008-08-23 10:23:12.000000000 +0200
@@ -1602,6 +1602,21 @@ (at your option) any later version.
 	  && !EQ (internal_last_event_frame, selected_frame))
 	Fselect_frame (internal_last_event_frame);
 #endif
+#if 1
+      {
+	if (!detect_input_pending()
+	    && NILP(internal_last_event_frame)) {
+	  Display *dpy = FRAME_X_DISPLAY (check_x_frame(selected_frame));
+	  Window focus;
+	  int revert_to;
+	  XGetInputFocus (dpy, &focus, &revert_to);
+	  if (focus != None
+	      && focus != FRAME_X_WINDOW (check_x_frame(selected_frame)))
+	    Fx_focus_frame (selected_frame);
+	}
+      }
+#endif
+
       /* If it has changed current-menubar from previous value,
 	 really recompute the menubar from the value.  */
       if (! NILP (Vlucid_menu_bar_dirty_flag)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-23  8:55                     ` Helmut Eller
@ 2008-08-23 12:05                       ` martin rudalics
  2008-08-24 13:14                         ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-23 12:05 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > 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.  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).

 > (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?  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?

 > 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 (this could be the selected frame as well).

 > 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 in this context
that `select-frame-set-input-focus' always raises the frame.

 > ?  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?

 > 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?
Could you try to GDB do_switch_frame for IceWM and one of the others to
see they do differently?

 > 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 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.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-23 12:05                       ` martin rudalics
@ 2008-08-24 13:14                         ` Helmut Eller
  2008-08-25 13:45                           ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-24 13:14 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

[-- Attachment #1: Type: text/plain, Size: 9288 bytes --]

* 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.



[-- Attachment #2: Sawfish log --]
[-- Type: text/plain, Size: 3018 bytes --]

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 

[-- Attachment #3: IceWM log --]
[-- Type: text/plain, Size: 3621 bytes --]

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 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-24 13:14                         ` Helmut Eller
@ 2008-08-25 13:45                           ` martin rudalics
  2008-08-26 21:45                             ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-25 13:45 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > I've read a little bit in the Xlib Manual[*] and here is what I learned:

I've tried to read that but for the time being I simply believe what you
say here.

 > 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.

So when `display-buffer' has called `pop-up-frame-function' we always
anticipate that the new frame is mapped (visible), has got input focus,
and is raised.  We cannot remove input focus from it or lower it because
we would risk some nasty race conditions with the window manager.  The
only reasonable alternative would be to make the new frame Withdrawn and
let `pop-to-buffer' etc. activate it but this seems hardly manageable.

We should document the current behavior to avoid going through these
torments again.

 >>> (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.

And raise it I presume.  IIUC we currently rely on the window-manager to
raise and focus the frame.

 >> 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.

Is `pop-to-buffer' free of complications when activating a just created
frame?  From your understanding would this be a NOOP for most window
managers?  Note that `x-focus-frame' uses XSetInputFocus together with
x_ewmh_activate_frame.  This mixture seems slightly frightening.

 >> Note in this context
 >> that `select-frame-set-input-focus' always raises the frame.
 >
 > Looks unnecessary.

For Metacity, maybe, because of their "can't raise without focusing"
invariant read backwards.  But would it harm?  IIRC some window-managers
may also move frames between desktops/workspaces when raising them.

 > 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.]

Does it do so even with `focus-follows-mouse' nil?

 > I didn't know what to look for.  Below I attach two event traces for
[...]
 > 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.

So far I can't :-(

Anyway: I could imagine something like the (completely untested) snippet
below to handle situation B - modulo whatever we should change in
`select-frame-set-input-focus', `x-focus-frame', ...


(defcustom pop-up-frame-activate nil
   "When non-nil try to explicitly activate popped up frames.
If this is nil leave it to Emacs how to activate the frame.  If
this is t always try to activate a new frame.  Anything else
means activate a frame if and only if it existed before the most
recent call to `display-buffer' ..."
   :type '(choice (const :tag "System Dependent" nil)
		 (const :tag "Existing frames only" 'existing-only)
		 (const :tag "Always" t))
   :group 'frames)

(defvar display-buffer-made-new-frame nil
   "When non-nil `display-buffer' created a new frame.")

(defun pop-to-buffer (buffer-or-name &optional other-window norecord)
   "Select buffer BUFFER-OR-NAME in some window, preferably a different one.
..."
   (let ((buffer
          ;; FIXME: This behavior is carried over from the previous C version
          ;; of pop-to-buffer, but really we should use just
          ;; `get-buffer' here.
          (if (null buffer-or-name) (other-buffer (current-buffer))
            (or (get-buffer buffer-or-name)
                (let ((buf (get-buffer-create buffer-or-name)))
                  (set-buffer-major-mode buf)
                  buf))))
	display-buffer-made-new-frame)
     (set-buffer buffer)
     (select-window (display-buffer buffer other-window) norecord)
     (when (and pop-up-frame-activate
	       (or (not display-buffer-made-new-frame)
		   (eq pop-up-frame-activate t)))
       (select-frame-set-input-focus (window-frame (selected-window))))
     buffer))

;;; In `display-buffer' replace the lines
      ((or pop-up-frames (not frame-to-use))
       ;; We want or need a new frame.
       (window--display-buffer-2
        buffer (frame-selected-window (funcall pop-up-frame-function))))

;;; by the lines
      ((or pop-up-frames (not frame-to-use))
       ;; We want or need a new frame.
       (window--display-buffer-2
        buffer (frame-selected-window (funcall pop-up-frame-function)))
       (setq display-buffer-made-new-frame t))







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-25 13:45                           ` martin rudalics
@ 2008-08-26 21:45                             ` Helmut Eller
  2008-08-27  8:12                               ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-26 21:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-25 15:45+0200] writes:

[...]
> So when `display-buffer' has called `pop-up-frame-function' we always
> anticipate that the new frame is mapped (visible), has got input focus,
> and is raised.  We cannot remove input focus from it or lower it because
> we would risk some nasty race conditions with the window manager. The
> only reasonable alternative would be to make the new frame Withdrawn and
> let `pop-to-buffer' etc. activate it but this seems hardly manageable.
>
> We should document the current behavior to avoid going through these
> torments again.

At the risk of repeating what you said, the current implementation can't
assume whether the frame created by display-buffer has got focus or not.
It's the window manager who decides that.

We only know definitely that a particular frame has got focus if we
receive a FocusIn event.  But display-buffer (which AFAICT ultimately
calls x_make_frame_visible) only waits until the frame is mapped.

[I found this entertaining comment in xterm.c:x_make_frame_visible:

    /* Wait until the frame is visible.  Process X events until a
       MapNotify event has been seen, or until we think we won't get a
       MapNotify at all..  */

In other words, we don't even know that the frame is mapped!]

However, even documenting that the input focus is unspecified would be
of some use.

>>>> (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.
>
> And raise it I presume.

Yes.

>  IIUC we currently rely on the window-manager to
> raise and focus the frame.

Currently Emacs does both.  Requesting the focus from the X server
(XSetInputFocus) and telling the window manager to activate
(x_ewmh_activate_frame [which for most WMs is focus+raise]) the frame.

>>> 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.
>
> Is `pop-to-buffer' free of complications when activating a just created
> frame?  From your understanding would this be a NOOP for most window
> managers?  

Good question.  I guess the usual sequence of events is this:

1. Emacs tries to map a frame and waits for notification
2. WM intercepts map request
3. WM maps the frame + gives focus to frame + raises frame
4. Emacs receives MapNotify

If we add a fifth step:

5. Emacs requests focus and informs WM to activate the frame

we probably do something twice, but activating the same frame twice
shouldn't hurt.  We have a problem if the WM decides to activate a
different frame, but that seems unlikely.

> Note that `x-focus-frame' uses XSetInputFocus together with
> x_ewmh_activate_frame.  This mixture seems slightly frightening.

Yes, this looks like "programming by accident".

>>> Note in this context
>>> that `select-frame-set-input-focus' always raises the frame.
>>
>> Looks unnecessary.
>
> For Metacity, maybe, because of their "can't raise without focusing"
> invariant read backwards.  But would it harm?  IIRC some window-managers
> may also move frames between desktops/workspaces when raising them.

The only harm, that I can think of right now, is the understandability
of the implementation :-)

>> 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.]
>
> Does it do so even with `focus-follows-mouse' nil?

select-frame-set-input-focus seems to work identical for
focus-follows-mouse and click-to-focus mode.  The frame receives the
input focus, is raised, and the mouse pointer is moved to its upper
right corner.

> Anyway: I could imagine something like the (completely untested) snippet
> below to handle situation B - modulo whatever we should change in
> `select-frame-set-input-focus', `x-focus-frame', ...
>
>
> (defcustom pop-up-frame-activate nil
>   "When non-nil try to explicitly activate popped up frames.
> If this is nil leave it to Emacs how to activate the frame.  If
> this is t always try to activate a new frame.  Anything else
> means activate a frame if and only if it existed before the most
> recent call to `display-buffer' ..."
>   :type '(choice (const :tag "System Dependent" nil)
> 		 (const :tag "Existing frames only" 'existing-only)
> 		 (const :tag "Always" t))
>   :group 'frames)

I'm not sure that this issue must be customizable at all.  As a user of
pop-to-buffer, I don't quite see the usefulness of the "System
Dependent" and "Existing frames only" choices.  An Emacs implementor
could argue that "System Dependent" is simpler to implement, but if the
more complicated variants are implemented too it's no longer "simpler".

I propose this change instead:

(defun pop-to-buffer (buffer-or-name &optional other-window norecord)
  "Select buffer BUFFER-OR-NAME in some window, preferably a different one.
... "
  (let ((buffer
         ;; FIXME: This behavior is carried over from the previous C version
         ;; of pop-to-buffer, but really we should use just
         ;; `get-buffer' here.
         (if (null buffer-or-name) (other-buffer (current-buffer))
           (or (get-buffer buffer-or-name)
               (let ((buf (get-buffer-create buffer-or-name)))
                 (set-buffer-major-mode buf)
                 buf)))))
    (set-buffer buffer)
    (let ((old-frame (selected-frame)))
      (select-window (display-buffer buffer other-window) norecord)
      (unless (eq old-frame (selected-frame))
	;; select-window doesn't set the input focus.  Set it explicitly.
	;; FIXME: select-window should request focus (perhaps lazily).
	(select-frame-set-input-focus (select-frame))))
    buffer))


Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-26 21:45                             ` Helmut Eller
@ 2008-08-27  8:12                               ` martin rudalics
  2008-08-27 12:54                                 ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-27  8:12 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 >> So when `display-buffer' has called `pop-up-frame-function' we always
 >> anticipate that the new frame is mapped (visible), has got input focus,
 >> and is raised.
[...]
 > In other words, we don't even know that the frame is mapped!]
 >
 > However, even documenting that the input focus is unspecified would be
 > of some use.

Yes.  Nevertheless, the idea that we "anticipate" the window manager to
do all these things is valid I presume - even it we don't "know" whether
the frame is visible in the first place.

 >>  IIUC we currently rely on the window-manager to
 >> raise and focus the frame.
 >
 > Currently Emacs does both.  Requesting the focus from the X server
 > (XSetInputFocus) and telling the window manager to activate
 > (x_ewmh_activate_frame [which for most WMs is focus+raise]) the frame.

I suppose we do both just because up to Emacs 22 we used XSetInputFocus
exclusively and maybe some window managers won't handle EWMHs yet (or
won't handle them in the sense of Emacs).  Should we, in your opinion
make this customizable?  That is, an option `frame-activate-method'
which if nil does both (as now), if 'explicit does XSetInputFocus only,
and if 'implicit does x_ewmh_activate_frame only?.

 > I guess the usual sequence of events is this:
 >
 > 1. Emacs tries to map a frame and waits for notification
 > 2. WM intercepts map request
 > 3. WM maps the frame + gives focus to frame + raises frame
 > 4. Emacs receives MapNotify
 >
 > If we add a fifth step:
 >
 > 5. Emacs requests focus and informs WM to activate the frame

.... without waiting for a FocusIn event?

 > we probably do something twice, but activating the same frame twice
 > shouldn't hurt.  We have a problem if the WM decides to activate a
 > different frame, but that seems unlikely.

IIRC window managers relying on EWMHs do not like explicit focus and
raise frame requests.  They might do something with such requests but
this something could be quite unpredictable.  I also STR that people
reported some flickering with two subsequent raise or focus requests.
Hence, once again: Should we try - with the help of an option - do this
either the old-style way without calling window-manager hints or do it
new-style with such hints and possibly waiting for a FocusIn event?

 >> Note that `x-focus-frame' uses XSetInputFocus together with
 >> x_ewmh_activate_frame.  This mixture seems slightly frightening.
 >
 > Yes, this looks like "programming by accident".

... rather "better safe than sorry".

 >> Does it do so even with `focus-follows-mouse' nil?
 >
 > select-frame-set-input-focus seems to work identical for
 > focus-follows-mouse and click-to-focus mode.  The frame receives the
 > input focus, is raised, and the mouse pointer is moved to its upper
 > right corner.

Ahhh no, this time I meant the Emacs option `focus-follows-mouse'.
`select-frame-set-input-focus' moves the mouse iff that is non-nil.

 >> (defcustom pop-up-frame-activate nil
 >>   "When non-nil try to explicitly activate popped up frames.
 >> If this is nil leave it to Emacs how to activate the frame.  If
 >> this is t always try to activate a new frame.  Anything else
 >> means activate a frame if and only if it existed before the most
 >> recent call to `display-buffer' ..."
 >>   :type '(choice (const :tag "System Dependent" nil)
 >> 		 (const :tag "Existing frames only" 'existing-only)
 >> 		 (const :tag "Always" t))
 >>   :group 'frames)
 >
 > I'm not sure that this issue must be customizable at all.  As a user of
 > pop-to-buffer, I don't quite see the usefulness of the "System
 > Dependent" and "Existing frames only" choices.  An Emacs implementor
 > could argue that "System Dependent" is simpler to implement, but if the
 > more complicated variants are implemented too it's no longer "simpler".

The "System Dependent" choice is necessary to let the current (maybe
faulty for some or many of us) behavior carry over for those who like it
as it is.  The question is whether we want to distinguish the other two.

 > I propose this change instead:
[...]
 >     (let ((old-frame (selected-frame)))
 >       (select-window (display-buffer buffer other-window) norecord)
 >       (unless (eq old-frame (selected-frame))
 > 	;; select-window doesn't set the input focus.  Set it explicitly.
 > 	;; FIXME: select-window should request focus (perhaps lazily).
 > 	(select-frame-set-input-focus (select-frame))))
 >     buffer))

I suppose you mean

  	(select-frame-set-input-focus (selected-frame))))

here.  This has the drawback that we unconditionally do
`select-frame-set-input-focus' for new frames.  If we decide that this
won't harm ...

My experience is that once in a while some window manager won't get
along with whatever we decide here.  Hence I'd like to put in one or two
options so users can try an alternative without immediately affecting
the behavior of this on other systems.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-27  8:12                               ` martin rudalics
@ 2008-08-27 12:54                                 ` Helmut Eller
  2008-08-28 11:46                                   ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-27 12:54 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-27 10:12+0200] writes:

>> Currently Emacs does both.  Requesting the focus from the X server
>> (XSetInputFocus) and telling the window manager to activate
>> (x_ewmh_activate_frame [which for most WMs is focus+raise]) the frame.
>
> I suppose we do both just because up to Emacs 22 we used XSetInputFocus
> exclusively and maybe some window managers won't handle EWMHs yet (or
> won't handle them in the sense of Emacs).  Should we, in your opinion
> make this customizable?  That is, an option `frame-activate-method'
> which if nil does both (as now), if 'explicit does XSetInputFocus only,
> and if 'implicit does x_ewmh_activate_frame only?.

A way to call one of XSetInputFocus or x_ewmh_activate_frame without
calling the other would be useful for experimentation.  But I think that
few people will use/need that.  So, no, it shouldn't be customizable.


It think it would be nice (but not worth to implement) if Emacs could be
customized with two "focus models":

 1. Let the window manager do all the focus handling.  This is similar
    to what Emacs does currently.  In this model Emacs should use
    x_ewmh_activate_frame without XSetInputFocus [I think that this would 
    avoid some race conditions].  pop-to-buffer could
    still "activate" the frame, but it would be merely a hint and no
    guarantee.  Creating frames which aren't focused initially is
    probably hard(er) in this model.

 2. Emacs does its own focus management.  In this model, Emacs should
    clear the input flag in WM_HINTS, handle WM_TAKE_FOCUS events, and
    explicitly call XSetInputFocus.  A reasonable window manager will
    handle FocusIn events to decorate the focused frame appropriately.
    Since the input flag is cleared, the WM shouldn't focus new frames.
    [This model may be incompatible with toolkits, like GTK.]

>> I guess the usual sequence of events is this:
>>
>> 1. Emacs tries to map a frame and waits for notification
>> 2. WM intercepts map request
>> 3. WM maps the frame + gives focus to frame + raises frame
>> 4. Emacs receives MapNotify
>>
>> If we add a fifth step:
>>
>> 5. Emacs requests focus and informs WM to activate the frame
>
> .... without waiting for a FocusIn event?

Yes, without waiting.  If we call

  (select-frame-set-input-focus (window-frame (display-buffer ...)))

we don't wait for FocusIn.

>> we probably do something twice, but activating the same frame twice
>> shouldn't hurt.  We have a problem if the WM decides to activate a
>> different frame, but that seems unlikely.
>
> IIRC window managers relying on EWMHs do not like explicit focus and
> raise frame requests.  They might do something with such requests but
> this something could be quite unpredictable.  I also STR that people
> reported some flickering with two subsequent raise or focus requests.
> Hence, once again: Should we try - with the help of an option - do this
> either the old-style way without calling window-manager hints or do it
> new-style with such hints and possibly waiting for a FocusIn event?

Since we don't have a window manager which causes trouble, we can't even
test whether the change makes any difference.  Let's wait until somebody
reports actual problems :-)

>>> Does it do so even with `focus-follows-mouse' nil?
>>
>> select-frame-set-input-focus seems to work identical for
>> focus-follows-mouse and click-to-focus mode.  The frame receives the
>> input focus, is raised, and the mouse pointer is moved to its upper
>> right corner.
>
> Ahhh no, this time I meant the Emacs option `focus-follows-mouse'.
> `select-frame-set-input-focus' moves the mouse iff that is non-nil.

I read to fast :-)  No with focus-follows-mouse=nil the mouse pointer
doesn't move but the other frame receives the input focus.

>>> (defcustom pop-up-frame-activate nil
>>>   "When non-nil try to explicitly activate popped up frames.
>>> If this is nil leave it to Emacs how to activate the frame.  If
>>> this is t always try to activate a new frame.  Anything else
>>> means activate a frame if and only if it existed before the most
>>> recent call to `display-buffer' ..."
>>>   :type '(choice (const :tag "System Dependent" nil)
>>> 		 (const :tag "Existing frames only" 'existing-only)
>>> 		 (const :tag "Always" t))
>>>   :group 'frames)
>>
>> I'm not sure that this issue must be customizable at all.  As a user of
>> pop-to-buffer, I don't quite see the usefulness of the "System
>> Dependent" and "Existing frames only" choices.  An Emacs implementor
>> could argue that "System Dependent" is simpler to implement, but if the
>> more complicated variants are implemented too it's no longer "simpler".
>
> The "System Dependent" choice is necessary to let the current (maybe
> faulty for some or many of us) behavior carry over for those who like it
> as it is.  The question is whether we want to distinguish the other two.

I think that, if "System Dependent" stays the default, then few people
will profit from the other choices, simply because few people take the
time to customize it.  Despite that, I think that very few people prefer
the current behavior.

>> I propose this change instead:
> [...]
>>     (let ((old-frame (selected-frame)))
>>       (select-window (display-buffer buffer other-window) norecord)
>>       (unless (eq old-frame (selected-frame))
>> 	;; select-window doesn't set the input focus.  Set it explicitly.
>> 	;; FIXME: select-window should request focus (perhaps lazily).
>> 	(select-frame-set-input-focus (select-frame))))
>>     buffer))
>
> I suppose you mean
>
>  	(select-frame-set-input-focus (selected-frame))))
>
> here.  

Yes, you are right.

> This has the drawback that we unconditionally do
> `select-frame-set-input-focus' for new frames.  If we decide that this
> won't harm ...

Most of the time it will work flawlessly on new frames.  What's the
worst that could happen?  Some flickering.  I think that we can live
with that imperfection.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-27 12:54                                 ` Helmut Eller
@ 2008-08-28 11:46                                   ` martin rudalics
  2008-08-28 16:47                                     ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-28 11:46 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > A way to call one of XSetInputFocus or x_ewmh_activate_frame without
 > calling the other would be useful for experimentation.  But I think that
 > few people will use/need that.  So, no, it shouldn't be customizable.

I'm afraid that we fix this just for the platforms we use.  If someone
reports a breakage of this on another platform before the release we
might be able to fix it there as well.  Otherwise this will go the way
of most "fixes" in this department.

 > It think it would be nice (but not worth to implement) if Emacs could be
 > customized with two "focus models":
 >
 >  1. Let the window manager do all the focus handling.  This is similar
 >     to what Emacs does currently.  In this model Emacs should use
 >     x_ewmh_activate_frame without XSetInputFocus [I think that this would
 >     avoid some race conditions].  pop-to-buffer could
 >     still "activate" the frame, but it would be merely a hint and no
 >     guarantee.  Creating frames which aren't focused initially is
 >     probably hard(er) in this model.

We agreed that the latter isn't realistic anyway.

 >  2. Emacs does its own focus management.  In this model, Emacs should
 >     clear the input flag in WM_HINTS, handle WM_TAKE_FOCUS events, and
 >     explicitly call XSetInputFocus.  A reasonable window manager will
 >     handle FocusIn events to decorate the focused frame appropriately.
 >     Since the input flag is cleared, the WM shouldn't focus new frames.
 >     [This model may be incompatible with toolkits, like GTK.]

And why do you think this not worth implementing?

 > Yes, without waiting.  If we call
 >
 >   (select-frame-set-input-focus (window-frame (display-buffer ...)))
 >
 > we don't wait for FocusIn.

Is there a place where Emacs _should_ wait for a FocusIn?

 > Since we don't have a window manager which causes trouble, we can't even
 > test whether the change makes any difference.  Let's wait until somebody
 > reports actual problems :-)

You've read some of the earlier threads - and there's a lot more of
these (some of them related to frame resizing).  We do have to
anticipate such problems now: People usually don't go through the
troubles testing this with any window-manager but their own.

 > I think that, if "System Dependent" stays the default, then few people
 > will profit from the other choices, simply because few people take the
 > time to customize it.

But if they complain we can give them an option to test.

 > Despite that, I think that very few people prefer
 > the current behavior.

It's not a question of preference.  It might simply work for them.  So
let's not cause unwanted breakage.

 >> This has the drawback that we unconditionally do
 >> `select-frame-set-input-focus' for new frames.  If we decide that this
 >> won't harm ...
 >
 > Most of the time it will work flawlessly on new frames.  What's the
 > worst that could happen?  Some flickering.  I think that we can live
 > with that imperfection.

Maybe there's more than just some imperfection.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-28 11:46                                   ` martin rudalics
@ 2008-08-28 16:47                                     ` Helmut Eller
  2008-08-28 21:26                                       ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-28 16:47 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-28 13:46+0200] writes:

>>  2. Emacs does its own focus management.  In this model, Emacs should
>>     clear the input flag in WM_HINTS, handle WM_TAKE_FOCUS events, and
>>     explicitly call XSetInputFocus.  A reasonable window manager will
>>     handle FocusIn events to decorate the focused frame appropriately.
>>     Since the input flag is cleared, the WM shouldn't focus new frames.
>>     [This model may be incompatible with toolkits, like GTK.]
>
> And why do you think this not worth implementing?

This takes more than a few hours of hacking.  At least a few days, more
likely a few weeks.  That's to much time for such a minor nicety.

Improving select-window so that it request input focus (somewhat
efficiently) would be more worthwhile.

>> Yes, without waiting.  If we call
>>
>>   (select-frame-set-input-focus (window-frame (display-buffer ...)))
>>
>> we don't wait for FocusIn.
>
> Is there a place where Emacs _should_ wait for a FocusIn?

No.  select-frame-set-input-focus seems to be the only focus related
function (despite x-focus-frame which is presumably internal).  If we
interpret select-frame-set-input-focus as "request input focus" and not
as "request input focus and wait until we know that we actually have the
focus" then we don't need to wait.  IMO, the former interpretation is
consistent with the usual assumption that Emacs updates the display
"later" or at least not in lock step with Lisp code.

>> Since we don't have a window manager which causes trouble, we can't even
>> test whether the change makes any difference.  Let's wait until somebody
>> reports actual problems :-)
>
> You've read some of the earlier threads - and there's a lot more of
> these (some of them related to frame resizing).  We do have to
> anticipate such problems now: People usually don't go through the
> troubles testing this with any window-manager but their own.

I know about the following problems:

 1. pop-to-buffer doesn't switch input focus
 2. select-window doesn't switch input focus
 3. x-create-frame does switch input focus (with most WMs)

Is there something else?  

We agreed that we wont fix 3.  

1 would be fixed by calling select-frame-set-input-focus in
pop-to-buffer (either customizable or not).  Do we need to test
something?

Fixing 2 isn't so clear.  This was shortly discussed on the mailing list
but RMS said, at that time, that more important things should be done.


>> I think that, if "System Dependent" stays the default, then few
>> people will profit from the other choices, simply because few people
>> take the time to customize it.
>
> But if they complain we can give them an option to test.

It would be reasonable to minimize the number of people who need to
change the defaults.

>> Despite that, I think that very few people prefer the current
>> behavior.
>
> It's not a question of preference.  It might simply work for them.  So
> let's not cause unwanted breakage.

Some people, like me, who do actually care, also like to keep the code
readable, simple, and predictable.  New customization options cost a lot
in terms of readability.

Helmut.







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-28 16:47                                     ` Helmut Eller
@ 2008-08-28 21:26                                       ` martin rudalics
  2008-08-29  7:39                                         ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-28 21:26 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745, Chong Yidong, Stefan Monnier

 > I know about the following problems:
 >
 >  1. pop-to-buffer doesn't switch input focus
 >  2. select-window doesn't switch input focus
 >  3. x-create-frame does switch input focus (with most WMs)
 >
 > Is there something else?

The XSetInputFocus vs x_ewmh_activate_frame dichotomy in
`x-focus-frame'.

 > We agreed that we wont fix 3.

Yes.

 > 1 would be fixed by calling select-frame-set-input-focus in
 > pop-to-buffer (either customizable or not).  Do we need to test
 > something?

Let's try without an option.  Stefan, Chong, any objections?

*** window.el.~1.146.~	2008-08-23 09:41:38.156250000 +0200
--- window.el	2008-08-28 19:32:50.765625000 +0200
***************
*** 1061,1066 ****
--- 1061,1067 ----
                    buf)))))
       (set-buffer buffer)
       (select-window (display-buffer buffer other-window) norecord)
+     (select-frame-set-input-focus (selected-frame))
       buffer))

   ;; I think this should be the default; I think people will prefer it--rms.

 > Fixing 2 isn't so clear.  This was shortly discussed on the mailing list
 > but RMS said, at that time, that more important things should be done.

You mean we could solve this with your update-focus-lazily approach?

martin






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-28 21:26                                       ` martin rudalics
@ 2008-08-29  7:39                                         ` Helmut Eller
  2008-08-29  9:26                                           ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-29  7:39 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-28 23:26+0200] writes:

>> I know about the following problems:
>>
>>  1. pop-to-buffer doesn't switch input focus
>>  2. select-window doesn't switch input focus
>>  3. x-create-frame does switch input focus (with most WMs)
>>
>> Is there something else?
>
> The XSetInputFocus vs x_ewmh_activate_frame dichotomy in
> `x-focus-frame'.

Emacs could first test whether the window manager is EWMH compliant and
depending on the outcome only call one of those functions.
x_ewmh_activate_frame seems to test whether the WM supports
"_NET_ACTIVE_WINDOW".  I guess, we could just move that over to
x-focus-frame.

>> We agreed that we wont fix 3.
>
> Yes.

Over night I had a little idea that could be useful.  I'm just writing
it down here so that it's not lost: We could avoid the focus-when-mapped
problem, if we clear the input flag in WM_HINTS (the GTK equivalent
seems to be gtk_window_set_accept_focus) when we create the frame.  But
when we receive the MapNotify event, we enable the flag.  This should
prevent the window manager from focusing the frame initially but
afterwards it should be treated as usual.

I also found the gtk_window_set_focus_on_map function.  This seems to
rely on the _NET_WM_USER_TIME EWMH.  Sawfish ignores _NET_WM_USER_TIME,
but it could be useful for other window managers.

>> Fixing 2 isn't so clear.  This was shortly discussed on the mailing list
>> but RMS said, at that time, that more important things should be done.
>
> You mean we could solve this with your update-focus-lazily approach?

I think it's feasible, yes.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-29  7:39                                         ` Helmut Eller
@ 2008-08-29  9:26                                           ` martin rudalics
  2008-08-29 15:02                                             ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-29  9:26 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 > Emacs could first test whether the window manager is EWMH compliant

How?  Emacs can't even test whether the window manager is click to focus
or focus follows mouse.

 > and
 > depending on the outcome only call one of those functions.
 > x_ewmh_activate_frame seems to test whether the WM supports
 > "_NET_ACTIVE_WINDOW".  I guess, we could just move that over to
 > x-focus-frame.
 >
 >>> We agreed that we wont fix 3.
 >> Yes.
 >
 > Over night I had a little idea that could be useful.  I'm just writing
 > it down here so that it's not lost: We could avoid the focus-when-mapped
 > problem, if we clear the input flag in WM_HINTS (the GTK equivalent
 > seems to be gtk_window_set_accept_focus) when we create the frame.

Again this would work iff we knew that the window manager is EWMH
compliant.

 > But
 > when we receive the MapNotify event, we enable the flag.  This should
 > prevent the window manager from focusing the frame initially but
 > afterwards it should be treated as usual.
 >
 > I also found the gtk_window_set_focus_on_map function.  This seems to
 > rely on the _NET_WM_USER_TIME EWMH.  Sawfish ignores _NET_WM_USER_TIME,
 > but it could be useful for other window managers.

And this would have to be supplied by the user separately.  Or is there
some way to get such basic information from window-managers?

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-29  9:26                                           ` martin rudalics
@ 2008-08-29 15:02                                             ` Helmut Eller
  2008-08-30  8:15                                               ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-29 15:02 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-29 11:26+0200] writes:

>> Emacs could first test whether the window manager is EWMH compliant
>
> How?  Emacs can't even test whether the window manager is click to focus
> or focus follows mouse.

xterm.c:wm_supports implements the test already.  By inspecting the
_NET_SUPPORTED property on the root window.  A compliant window manager
must enumerate the supported features there.

See http://standards.freedesktop.org/wm-spec/1.4/ar01s03.html#id2523263.

E.g. for Sawfish I get

shell$ xprop _NET_SUPPORTED
_NET_SUPPORTED(ATOM) = _NET_ACTIVE_WINDOW, _NET_CLIENT_LIST,
_NET_CLIENT_LIST_STACKING, _NET_CLOSE_WINDOW, _NET_CURRENT_DESKTOP,
_NET_DESKTOP_GEOMETRY, _NET_DESKTOP_NAMES, _NET_DESKTOP_VIEWPORT,
_NET_NUMBER_OF_DESKTOPS, _NET_PROTOCOLS, _NET_SHOWING_DESKTOP,
_NET_SUPPORTED, _NET_SUPPORTING_WM_CHECK, _NET_WORKAREA,
_NET_WM_DESKTOP, _NET_WM_ICON_GEOMETRY, _NET_WM_MOVERESIZE,
_NET_WM_MOVERESIZE_MOVE, _NET_WM_MOVERESIZE_SIZE_BOTTOM,
_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
_NET_WM_MOVERESIZE_SIZE_LEFT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
_NET_WM_MOVERESIZE_SIZE_TOP, _NET_WM_MOVERESIZE_SIZE_TOPLEFT,
_NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_KEYBOARD,
_NET_WM_MOVERESIZE_MOVE_KEYBOARD, _NET_WM_PING, _NET_WM_STATE,
_NET_WM_STATE_ABOVE, _NET_WM_STATE_ADD, _NET_WM_STATE_BELOW,
_NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_MAXIMIZED,
_NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_REMOVE, _NET_WM_STATE_SHADED, _NET_WM_STATE_SKIP_PAGER,
_NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_STICKY, _NET_WM_STATE_TOGGLE,
_NET_WM_STRUT, _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DESKTOP,
_NET_WM_WINDOW_TYPE_DIALOG, _NET_WM_WINDOW_TYPE_DOCK,
_NET_WM_WINDOW_TYPE_TOOLBAR, _NET_WM_WINDOW_TYPE_MENU,
_NET_WM_WINDOW_TYPE_UTILITY, _NET_WM_WINDOW_TYPE_SPLASH


>> I also found the gtk_window_set_focus_on_map function.  This seems to
>> rely on the _NET_WM_USER_TIME EWMH.  Sawfish ignores _NET_WM_USER_TIME,
>> but it could be useful for other window managers.
>
> And this would have to be supplied by the user separately.  Or is there
> some way to get such basic information from window-managers?

For a window manager which supports it, _NET_SUPPORTED will contain
_NET_WM_USER_TIME.  But it wouldn't hurt to set _NET_WM_USER_TIME to 0,
because that should be interpreted as "disable focus-on-map".  At least
gtk_window_set_focus_on_map sets the property unconditionally.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-29 15:02                                             ` Helmut Eller
@ 2008-08-30  8:15                                               ` martin rudalics
  2008-08-30 11:06                                                 ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-30  8:15 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 >>> I also found the gtk_window_set_focus_on_map function.  This seems to
 >>> rely on the _NET_WM_USER_TIME EWMH.  Sawfish ignores _NET_WM_USER_TIME,
 >>> but it could be useful for other window managers.

How do you find out that Sawfish ignores that?

 > For a window manager which supports it, _NET_SUPPORTED will contain
 > _NET_WM_USER_TIME.  But it wouldn't hurt to set _NET_WM_USER_TIME to 0,
 > because that should be interpreted as "disable focus-on-map".  At least
 > gtk_window_set_focus_on_map sets the property unconditionally.

Do you have one window-manager setting where you can get Emacs

(1) do a `display-buffer' making a new frame without that frame getting
raised and/or input focus, and

(2) give input focus to/raise a frame that hasn't input focus/is not
raised.

entirely using _NET_WM_USER_TIME?  I faintly recall a discussion about a
misinterpretation of timestamps sent to the window-manager (Metacity?)
by Emacs.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-30  8:15                                               ` martin rudalics
@ 2008-08-30 11:06                                                 ` Helmut Eller
  2008-08-30 13:42                                                   ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-30 11:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-30 10:15+0200] writes:

>>>> I also found the gtk_window_set_focus_on_map function.  This seems to
>>>> rely on the _NET_WM_USER_TIME EWMH.  Sawfish ignores _NET_WM_USER_TIME,
>>>> but it could be useful for other window managers.
>
> How do you find out that Sawfish ignores that?

a) by looking at the _NET_SUPPORTS property on the root window.  I posted
the content of that in my last email.  It doesn't contain
_NET_WM_USER_TIME.
b) by grepping through Sawfish's source code.

>> For a window manager which supports it, _NET_SUPPORTED will contain
>> _NET_WM_USER_TIME.  But it wouldn't hurt to set _NET_WM_USER_TIME to 0,
>> because that should be interpreted as "disable focus-on-map".  At least
>> gtk_window_set_focus_on_map sets the property unconditionally.
>
> Do you have one window-manager setting where you can get Emacs
>
> (1) do a `display-buffer' making a new frame without that frame getting
> raised and/or input focus, and

If I call gtk_window_set_focus_on_map (GTK_WINDOW (wtop), FALSE) in
gtkutil.c:xg_create_frame_widgets, then Metacity dosn't give the focus
to new frames.  The initial Emacs frame is also not focused.

gtk_window_set_focus_on_map sets _NET_WM_USER_TIME to 0.  I know that
because I read the GTK source.  It can be verified by calling xprop on
the resulting Emacs frame.

> (2) give input focus to/raise a frame that hasn't input focus/is not
> raised.
>
> entirely using _NET_WM_USER_TIME?

I don't know how to that with _NET_WM_USER_TIME.  But the EWMH-spec says
this:

   _NET_ACTIVE_WINDOW, WINDOW/32
   
   The window ID of the currently active window or None if no window has
   the focus. This is a read-only property set by the Window Manager. If
   a Client wants to activate another window, it MUST send a
   _NET_ACTIVE_WINDOW client message to the root window:

   _NET_ACTIVE_WINDOW
     window  = window to activate
     message_type = _NET_ACTIVE_WINDOW
     format = 32
     data.l[0] = source indication 
     data.l[1] = timestamp
     data.l[2] = requestor's currently active window, 0 if none
     other data.l[] elements = 0
   
   Source indication should be 1 when the request comes from an
   application, and 2 when it comes from a pager. Clients using older
   version of this spec use 0 as source indication, see the section called
   "Source indication in request" for details. The timestamp is Client's
   last user activity timestamp (see _NET_WM_USER_TIME) at the time of the
   request, and the currently active window is the Client's active toplevel
   window, if any (the Window Manager may be e.g. more likely to obey the
   request if it will mean transferring focus from one active window to
   another).
   
   Depending on the information provided with the message, the Window
   Manager may decide to refuse the request (either completely ignore it,
   or e.g. use _NET_WM_STATE_DEMANDS_ATTENTION).

The current implementation of x_ewmh_activate_frame seems to work fine.

> I faintly recall a discussion about a
> misinterpretation of timestamps sent to the window-manager (Metacity?)
> by Emacs.

I've seen Metacity spit out warnings along the lines that XSetInputFocus
was called with a wrong timestamp.  But I can't reproduce that right now.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-30 11:06                                                 ` Helmut Eller
@ 2008-08-30 13:42                                                   ` martin rudalics
  2008-08-31  8:55                                                     ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-08-30 13:42 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

 >> (1) do a `display-buffer' making a new frame without that frame getting
 >> raised and/or input focus, and
 >
 > If I call gtk_window_set_focus_on_map (GTK_WINDOW (wtop), FALSE) in
 > gtkutil.c:xg_create_frame_widgets, then Metacity dosn't give the focus
 > to new frames.  The initial Emacs frame is also not focused.
 > gtk_window_set_focus_on_map sets _NET_WM_USER_TIME to 0.  I know that
 > because I read the GTK source.  It can be verified by calling xprop on
 > the resulting Emacs frame.

In this case we'd have to make `pop-to-buffer' give focus to the frame,
look out for applications that ("wrongly") expect `display-buffer' to
focus the frame, focus the initial frame, and decide what to do about
`select-window/frame'.  After the release we could implement this for
all ewmh-compliant window-managers.

 >> (2) give input focus to/raise a frame that hasn't input focus/is not
 >> raised.
 >>
 >> entirely using _NET_WM_USER_TIME?
 >
 > I don't know how to that with _NET_WM_USER_TIME.

For _NET_WM_USER_TIME I read

    This property allows a Window Manager to alter the focus, stacking,
    and/or placement behavior of windows when they are mapped depending
    on whether the new window was created by a user action or is a
    "pop-up" window activated by a timer or some other event.

but I fail to understand what "new window" means here.

 > But the EWMH-spec says this:
 >
 >    _NET_ACTIVE_WINDOW, WINDOW/32
 >
 >    The window ID of the currently active window or None if no window has
 >    the focus. This is a read-only property set by the Window Manager. If
 >    a Client wants to activate another window, it MUST send a
 >    _NET_ACTIVE_WINDOW client message to the root window:
 >
 >    _NET_ACTIVE_WINDOW
 >      window  = window to activate
 >      message_type = _NET_ACTIVE_WINDOW
 >      format = 32
 >      data.l[0] = source indication
 >      data.l[1] = timestamp
 >      data.l[2] = requestor's currently active window, 0 if none
 >      other data.l[] elements = 0
 >
 >    Source indication should be 1 when the request comes from an
 >    application, and 2 when it comes from a pager. Clients using older
 >    version of this spec use 0 as source indication, see the section called
 >    "Source indication in request" for details. The timestamp is Client's
 >    last user activity timestamp (see _NET_WM_USER_TIME) at the time of the
 >    request, and the currently active window is the Client's active toplevel
 >    window, if any (the Window Manager may be e.g. more likely to obey the
 >    request if it will mean transferring focus from one active window to
 >    another).
 >
 >    Depending on the information provided with the message, the Window
 >    Manager may decide to refuse the request (either completely ignore it,
 >    or e.g. use _NET_WM_STATE_DEMANDS_ATTENTION).
 >
 > The current implementation of x_ewmh_activate_frame seems to work fine.

OK.

 >> I faintly recall a discussion about a
 >> misinterpretation of timestamps sent to the window-manager (Metacity?)
 >> by Emacs.
 >
 > I've seen Metacity spit out warnings along the lines that XSetInputFocus
 > was called with a wrong timestamp.  But I can't reproduce that right now.

Ahh, I recall that discussion.  Yet another reason why XSetInputFocus
should be avoided for ewmh-compliant window managers.  We should avoid
calling XSetInputFocus for these in the present release.

So I think we can distinguish three types of window managers according
to our needs and what _NET_SUPPORTS tells us:

- _NET_WM_USER_TIME capable ones, where we can have `display-buffer' not
   set the input focus for new frames (and thus not implicitly select the
   new window thus contradicting the doc-string of `display-buffer').  I
   suppose Metacity falls into this group.

- _NET_ACTIVE_WINDOW capable ones, where `display-buffer' will behave as
   now but x_ewmh_activate_frame works.  Sawfish seems to belong here.

- Non-ewmh-compliant ones where we have to use XSetInputFocus.

martin







^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-30 13:42                                                   ` martin rudalics
@ 2008-08-31  8:55                                                     ` Helmut Eller
  2008-09-06 11:56                                                       ` martin rudalics
  0 siblings, 1 reply; 31+ messages in thread
From: Helmut Eller @ 2008-08-31  8:55 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-08-30 15:42+0200] writes:

>>> (1) do a `display-buffer' making a new frame without that frame getting
>>> raised and/or input focus, and
>>
>> If I call gtk_window_set_focus_on_map (GTK_WINDOW (wtop), FALSE) in
>> gtkutil.c:xg_create_frame_widgets, then Metacity dosn't give the focus
>> to new frames.  The initial Emacs frame is also not focused.
>> gtk_window_set_focus_on_map sets _NET_WM_USER_TIME to 0.  I know that
>> because I read the GTK source.  It can be verified by calling xprop on
>> the resulting Emacs frame.
>
> In this case we'd have to make `pop-to-buffer' give focus to the frame,
> look out for applications that ("wrongly") expect `display-buffer' to
> focus the frame, focus the initial frame, and decide what to do about
> `select-window/frame'.  After the release we could implement this for
> all ewmh-compliant window-managers.

Sounds good.

>>> (2) give input focus to/raise a frame that hasn't input focus/is not
>>> raised.
>>>
>>> entirely using _NET_WM_USER_TIME?
>>
>> I don't know how to that with _NET_WM_USER_TIME.
>
> For _NET_WM_USER_TIME I read
>
>    This property allows a Window Manager to alter the focus, stacking,
>    and/or placement behavior of windows when they are mapped depending
>    on whether the new window was created by a user action or is a
>    "pop-up" window activated by a timer or some other event.
>
> but I fail to understand what "new window" means here.

Perhaps it means "newly mapped window".  I guess some window manager
could give the focus to a newly mapped window only if its timestamp is
newer than the timestamp of the currently focused window.  I would be
surprised though, if some application would rely on this behavior :-)
Continuously updating this timestamp, e.g. on every keypress, sounds
rather excessive just to give the WM this possibility.

>>> I faintly recall a discussion about a
>>> misinterpretation of timestamps sent to the window-manager (Metacity?)
>>> by Emacs.
>>
>> I've seen Metacity spit out warnings along the lines that XSetInputFocus
>> was called with a wrong timestamp.  But I can't reproduce that right now.
>
> Ahh, I recall that discussion.  Yet another reason why XSetInputFocus
> should be avoided for ewmh-compliant window managers.  We should avoid
> calling XSetInputFocus for these in the present release.
>
> So I think we can distinguish three types of window managers according
> to our needs and what _NET_SUPPORTS tells us:
>
> - _NET_WM_USER_TIME capable ones, where we can have `display-buffer' not
>   set the input focus for new frames (and thus not implicitly select the
>   new window thus contradicting the doc-string of `display-buffer').  I
>   suppose Metacity falls into this group.
>
> - _NET_ACTIVE_WINDOW capable ones, where `display-buffer' will behave as
>   now but x_ewmh_activate_frame works.  Sawfish seems to belong here.
>
> - Non-ewmh-compliant ones where we have to use XSetInputFocus.

Yes, I think the same.

Helmut.

>  LocalWords:  timestamp keypress






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-08-31  8:55                                                     ` Helmut Eller
@ 2008-09-06 11:56                                                       ` martin rudalics
  2008-09-09  6:24                                                         ` Helmut Eller
  0 siblings, 1 reply; 31+ messages in thread
From: martin rudalics @ 2008-09-06 11:56 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 745

I'm currently using

(defun pop-to-buffer (buffer-or-name &optional other-window norecord)
   "Select buffer BUFFER-OR-NAME in some window, preferably a different one.
...."
   (let ((buffer
          ;; FIXME: This behavior is carried over from the previous C version
          ;; of pop-to-buffer, but really we should use just
          ;; `get-buffer' here.
          (if (null buffer-or-name) (other-buffer (current-buffer))
            (or (get-buffer buffer-or-name)
                (let ((buf (get-buffer-create buffer-or-name)))
                  (set-buffer-major-mode buf)
                  buf))))
	(old-window (selected-window))
	(old-frame (selected-frame))
	new-window new-frame)
     (set-buffer buffer)
     (setq new-window (display-buffer buffer other-window) norecord)
     (unless (eq new-window old-window)
       ;; `display-buffer' has chosen another window.
       (setq new-frame (window-frame new-window))
       (unless (eq new-frame old-frame)
	;; `display-buffer' has chosen another frame, make sure it gets
	;; input focus and is risen.
	(select-frame-set-input-focus new-frame))
       ;; Make sure the window chosen by `display-buffer' gets selected.
       (select-window new-window))
     buffer))

so `select-frame-set-input-focus' gets called iff `display-buffer' did
choose another frame.  I noticed that I cannot use
`select-frame-set-input-focus' unconditionally for the following reason:
On my Emacs `focus-follows-mouse' is t so the final check in
`select-frame-set-input-focus'

     (when focus-follows-mouse
       (set-mouse-position (selected-frame) (1- (frame-width)) 0)))

_always_ succeeds and sends my mouse cursor to the upper right corner of
the corresponding frame.  This is annoying whenever I click, for
example, on a button in a help buffer to follow a link, causing the
window returned by `display-buffer' show up on the already _selected_
frame.  Since I additionally have `mouse-autoselect-window' non-nil, an
unrelated window on top of the selected frame may get selected too.

One annyoing aspect of the rigid use of `set-mouse-position' in
`select-frame-set-input-focus' obviously remains, namely that with
`mouse-autoselect-window' non-nil `other-frame' (and related functions)
may change the selected window on the other frame :-( This has to be
fixed independently.

Please check whether `pop-to-buffer' as defined above fits your needs.
If so, and no one else protests, I'll install this next week.

martin






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: pop-to-buffer, frames, and input focus
  2008-09-06 11:56                                                       ` martin rudalics
@ 2008-09-09  6:24                                                         ` Helmut Eller
  0 siblings, 0 replies; 31+ messages in thread
From: Helmut Eller @ 2008-09-09  6:24 UTC (permalink / raw)
  To: martin rudalics; +Cc: 745

* martin rudalics [2008-09-06 13:56+0200] writes:

> Please check whether `pop-to-buffer' as defined above fits your needs.

Yes, this does what I need.
Thanks you for fixing it.

Helmut.






^ permalink raw reply	[flat|nested] 31+ messages in thread

* bug#745: marked as done (pop-to-buffer, frames, and input focus)
  2008-08-20  7:35 ` bug#745: pop-to-buffer, frames, and input focus Helmut Eller
  2008-08-20 14:50   ` martin rudalics
@ 2008-09-11  7:05   ` Emacs bug Tracking System
  1 sibling, 0 replies; 31+ messages in thread
From: Emacs bug Tracking System @ 2008-09-11  7:05 UTC (permalink / raw)
  To: martin rudalics

[-- Attachment #1: Type: text/plain, Size: 839 bytes --]


Your message dated Thu, 11 Sep 2008 08:52:54 +0200
with message-id <48C8C046.50203@gmx.at>
and subject line Re: bug#745: pop-to-buffer, frames, and input focus
has caused the Emacs bug report #745,
regarding pop-to-buffer, frames, and input focus
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact don@donarmstrong.com
immediately.)


-- 
745: http://emacsbugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=745
Emacs Bug Tracking System
Contact don@donarmstrong.com with problems

[-- Attachment #2: Type: message/rfc822, Size: 3647 bytes --]

From: Helmut Eller <eller.helmut@gmail.com>
To: bug-gnu-emacs@gnu.org
Subject: pop-to-buffer, frames, and input focus
Date: Wed, 20 Aug 2008 09:35:31 +0200
Message-ID: <m2tzdgdtq4.fsf@gmail.com>

Hi,

The behavior of pop-to-buffer in combination with multiple frames is
rather unpredictable or at least not what I expected.

For example:

  shell$ cat pop-to-buffer-test.el
  
  (let ((frame (selected-frame))
        (pop-up-frames t))
    (display-buffer (get-buffer-create "foo"))
    (select-frame-set-input-focus frame))
  
  (let ((display-buffer-reuse-frames t))
    (pop-to-buffer "foo"))
  
  shell$ emacs -Q -l pop-to-buffer-test.el

Pops up two frames, one frame displays the "foo" buffer and the other
the "*scratch*" buffer (so far so good).  But the "foo" frame has not
the input focus.  Isn't pop-to-buffer supposed to switch input focus
too?

Also note that I had to save and restore the selected frame
around display-buffer.  If I try

  emacs -Q --eval '(let ((pop-up-frames t)) 
                     (display-buffer (get-buffer-create "foo")))' 

the "foo" buffer is selected, even though display-buffer should not
switch the selected window.

Not even save-window-excursion stops display-buffer from switching the
frame:

  emacs -Q --eval '(save-window-excursion 
                     (let ((pop-up-frames t)) 
                        (display-buffer (get-buffer-create "foo"))))'


This is with:
 GNU Emacs 23.0.60.4 (i686-pc-linux-gnu, GTK+ Version 2.8.20)
 of 2008-08-15 on xaital
Windowing system distributor `The X.Org Foundation', version 11.0.70101000
configured using `configure  '--without-sound' '--without-pop' '--without-gif' '--without-tiff''

My window manager is Sawfish 1.3.

Helmut.




[-- Attachment #3: Type: message/rfc822, Size: 2164 bytes --]

From: martin rudalics <rudalics@gmx.at>
To: 745-done@emacsbugs.donarmstrong.com
Cc: Helmut Eller <eller.helmut@gmail.com>
Subject: Re: bug#745: pop-to-buffer, frames, and input focus
Date: Thu, 11 Sep 2008 08:52:54 +0200
Message-ID: <48C8C046.50203@gmx.at>

Fixed as

2008-09-11  Martin Rudalics  <rudalics@gmx.at>

	* window.el (pop-to-buffer): If the window for buffer-or-name is
	not on the selected frame, raise that window's frame and give it
	input focus.  (Bug#745)


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2008-09-11  7:05 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <48C8C046.50203@gmx.at>
2008-08-20  7:35 ` bug#745: pop-to-buffer, frames, and input focus Helmut Eller
2008-08-20 14:50   ` martin rudalics
2008-08-20 18:42     ` Helmut Eller
2008-08-20 20:42       ` David Reitter
2008-08-20 20:56       ` martin rudalics
2008-08-21  8:07         ` Helmut Eller
2008-08-21  9:04           ` martin rudalics
2008-08-21 13:20             ` Helmut Eller
2008-08-21 20:31               ` martin rudalics
2008-08-22 14:27                 ` Helmut Eller
2008-08-22 16:39                   ` martin rudalics
2008-08-23  8:55                     ` Helmut Eller
2008-08-23 12:05                       ` martin rudalics
2008-08-24 13:14                         ` Helmut Eller
2008-08-25 13:45                           ` martin rudalics
2008-08-26 21:45                             ` Helmut Eller
2008-08-27  8:12                               ` martin rudalics
2008-08-27 12:54                                 ` Helmut Eller
2008-08-28 11:46                                   ` martin rudalics
2008-08-28 16:47                                     ` Helmut Eller
2008-08-28 21:26                                       ` martin rudalics
2008-08-29  7:39                                         ` Helmut Eller
2008-08-29  9:26                                           ` martin rudalics
2008-08-29 15:02                                             ` Helmut Eller
2008-08-30  8:15                                               ` martin rudalics
2008-08-30 11:06                                                 ` Helmut Eller
2008-08-30 13:42                                                   ` martin rudalics
2008-08-31  8:55                                                     ` Helmut Eller
2008-09-06 11:56                                                       ` martin rudalics
2008-09-09  6:24                                                         ` Helmut Eller
2008-09-11  7:05   ` bug#745: marked as done (pop-to-buffer, frames, and input focus) Emacs bug Tracking System

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).