OK, I really really think this is right this time. I talked to Ben
and Kyle some and have tested it a bit with more complicated cases.
(this is the (setq focus-follows-mouse t) (select-frame (next-frame))
bug in case you've lost track.)
One issue is that investigate_focus_change and focus_follows_mouse are
now used in cmdloop.c, so prototypes should be placed into some
appropriate header file. I wasn't sure where was right so I just put
externs in Fcommand_loop_1, which is a bit yucko.
greg
1998-04-27 Greg Klanderman <greg(a)alphatech.com>
* cmdloop.c (Fcommand_loop_1): Call investigate_frame_change if
focus_follows_mouse is true.
* event-stream.c (next_event_internal): Only call
investigate_frame_change if focus_follows_mouse is false.
* event-stream.c (investigate_frame_change): Fix
focus_follows_mouse handling. It was the case that, with
focus_follows_mouse true, (select-frame (next-frame)) could leave
next-frame with input focus, but not window manager focus. Now
needs to be called from 2 places, conditional on the value of
focus_follows_mouse.
Index: src/event-stream.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs-20/src/event-stream.c,v
retrieving revision 1.39
diff -u -r1.39 event-stream.c
--- event-stream.c 1998/04/14 07:47:12 1.39
+++ event-stream.c 1998/04/28 08:39:46
@@ -1718,8 +1718,9 @@
run_hook (Qdeselect_frame_hook);
}
-/* When select-frame is called, we want to tell the window system that
- the focus should be changed to point to the new frame. However,
+/* When select-frame is called and focus_follows_mouse is false, we want
+ to tell the window system that the focus should be changed to point to
+ the new frame. However,
sometimes Lisp functions will temporarily change the selected frame
(e.g. to call a function that operates on the selected frame),
and it's annoying if this focus-change happens exactly when
@@ -1729,9 +1730,17 @@
an event from the user. To do this, we keep track of the frame
where the window-manager focus lies on, and just before waiting
for user events, check the currently selected frame and change
- the focus as necessary. */
+ the focus as necessary.
-static void
+ On the other hand, if focus_follows_mouse is true, we need to switch the
+ selected frame back to the frame with window manager focus just before we
+ execute the next command in Fcommand_loop_1, just as the selected buffer is
+ reverted after a set-buffer.
+
+ Both cases are handled by this function. It must be called as appropriate
+ from these two places, depending on the value of focus_follows_mouse. */
+
+void
investigate_frame_change (void)
{
Lisp_Object devcons, concons;
@@ -1751,14 +1760,46 @@
in emacs_handle_focus_change_final() is based on the _FOR_HOOKS
value, we need to do so too. */
if (!NILP (sel_frame) &&
- !focus_follows_mouse &&
!EQ (DEVICE_FRAME_THAT_OUGHT_TO_HAVE_FOCUS (d), sel_frame) &&
!NILP (DEVICE_FRAME_WITH_FOCUS_FOR_HOOKS (d)) &&
!EQ (DEVICE_FRAME_WITH_FOCUS_FOR_HOOKS (d), sel_frame))
{
- /* prevent us from issuing the same request more than once */
- DEVICE_FRAME_THAT_OUGHT_TO_HAVE_FOCUS (d) = sel_frame;
- MAYBE_DEVMETH (d, focus_on_frame, (XFRAME (sel_frame)));
+ /* At this point, we know that the frame has been changed. Now, if
+ * focus_follows_mouse is not set, we finish off the frame change,
+ * so that user events will now come from the new frame. Otherwise,
+ * if focus_follows_mouse is set, no gratuitous frame changing
+ * should take place. Set the focus back to the frame which was
+ * originally selected for user input.
+ */
+ if (!focus_follows_mouse)
+ {
+ /* prevent us from issuing the same request more than once */
+ DEVICE_FRAME_THAT_OUGHT_TO_HAVE_FOCUS (d) = sel_frame;
+ MAYBE_DEVMETH (d, focus_on_frame, (XFRAME (sel_frame)));
+ }
+ else
+ {
+ Lisp_Object old_frame = Qnil;
+
+ /* #### Do we really want to check OUGHT ??
+ * It seems to make sense, though I have never seen us
+ * get here and have it be non-nil.
+ */
+ if (FRAMEP (DEVICE_FRAME_THAT_OUGHT_TO_HAVE_FOCUS (d)))
+ old_frame = DEVICE_FRAME_THAT_OUGHT_TO_HAVE_FOCUS (d);
+ else if (FRAMEP (DEVICE_FRAME_WITH_FOCUS_FOR_HOOKS (d)))
+ old_frame = DEVICE_FRAME_WITH_FOCUS_FOR_HOOKS (d);
+
+ /* #### Can old_frame ever be NIL? play it safe.. */
+ if (!NILP (old_frame))
+ {
+ /* Fselect_frame is not really the right thing: it frobs the
+ * buffer stack. But there's no easy way to do the right
+ * thing, and this code already had this problem anyway.
+ */
+ Fselect_frame (old_frame);
+ }
+ }
}
}
}
@@ -1932,7 +1973,12 @@
assert (NILP (XEVENT_NEXT (target_event)));
GCPRO1 (target_event);
- investigate_frame_change ();
+
+ /* When focus_follows_mouse is nil, if a frame change took place, we need
+ * to actually switch window manager focus to the selected window now.
+ */
+ if (!focus_follows_mouse)
+ investigate_frame_change ();
if (allow_queued && !NILP (command_event_queue))
{
Index: src/cmdloop.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs-20/src/cmdloop.c,v
retrieving revision 1.6
diff -u -r1.6 cmdloop.c
--- cmdloop.c 1998/03/31 20:11:27 1.6
+++ cmdloop.c 1998/04/28 08:39:46
@@ -533,6 +533,15 @@
while (EQ (Vcommand_loop, old_loop))
#endif /* LISP_COMMAND_LOOP */
{
+ /* If focus_follows_mouse, make sure the frame with window manager
+ focus is selected. */
+ { extern void investigate_frame_change (void);
+ extern int focus_follows_mouse;
+
+ if (focus_follows_mouse)
+ investigate_frame_change ();
+ }
+
/* Make sure the current window's buffer is selected. */
{
Lisp_Object selected_window = Fselected_window (Qnil);