[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: mouse-autoselect-window with menu pane
From: |
martin rudalics |
Subject: |
Re: mouse-autoselect-window with menu pane |
Date: |
Mon, 09 Oct 2006 14:42:09 +0200 |
User-agent: |
Mozilla Thunderbird 1.0 (Windows/20041206) |
> > While this might seem fairly innocuous, it bites in the more frequent
> > situation where you momentarily leave the menu pane before returning
> > to select an entry. So, instead of releasing mouse-1 after the
> > autoselect timeout, move back into the Help menu pane and select About
> > Emacs. The action occurs in the upper window, not the lower window
> > which was selected when you opened the Help menu. So, it seems that
> > by being outside the menu pane when the autoselect timeout occurs,
> > autoselection is performed. I think it is sensible to suppress
> > autoselection in this case (ie, reschedule the delay).
>
> I agree. I think that autoselection should not occur while the menu
> bar menus are active, even if the mouse temporarily moves out of the menus.
>
> If I wanted to do this, I'd have to intercept `x_activate_menubar',
> detect whether the `mouse-autoselect-window-timer' timer is active, and
> kill it. As a consequenece autoselection would be cancelled as soon as
> the user accesses the menubar. Rescheduling the timer seems hardly
> feasible since it would almost certainly break the behavior for users
> with a smaller delay.
>
> I don't think that is right either. Whenever the menu bar menus cease
> to be active, autoselection should resume. An outcome where the mouse
> remains for a longg time in the upper window but the lower window remains
> selected is not correct.
>
> But it would be good to restart the delay when the menus become
> inactive, so as to give the user a chance to move the mouse back to
> the lower window.
Attached find a patch which tries to do this.
It also removes HAVE_NTGUI from the check for popup_activated in the
xdisp.c code (it doesn't make sense to check this since popup_activated
always returns nil on w32).
* macmenu.c (Fmenu_or_popup_active_p): New function.
(syms_of_macmenu): Defsubr it.
* w32menu.c (Fmenu_or_popup_active_p): New function.
(syms_of_w32menu): Defsubr it.
(popup_activated_flag, popup_activated): Remove.
* xdisp.c (note_mouse_highlight) [HAVE_NTGUI]: Don't bother
to check popup_activated when HAVE_NTGUI is defined.
* xmenu.c (Fmenu_or_popup_active_p): New function.
(syms_of_xmenu): Defsubr it.
* window.el (mouse-autoselect-window-now): Remove variable.
(mouse-autoselect-window-state): New variable.
(mouse-autoselect-window-start, mouse-autoselect-window-cancel)
(mouse-autoselect-window-select, handle-select-window):
Rewritten to make mouse-autoselect-window-timer a one-shot timer.
Suspend delayed autoselection during menu or popup dialog.
*** macmenu.c Tue Jun 6 19:20:42 2006 1.42
--- macmenu.c Tue Sep 26 11:16:36 2006
***************
*** 1026,1031 ****
--- 1026,1042 ----
UNBLOCK_INPUT;
}
+ /* The following is used by delayed window autoselection. */
+
+ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p,
Smenu_or_popup_active_p, 0, 0, 0,
+ doc: /* Return t if a menu or popup dialog is active. */)
+ ()
+ {
+ /* Always return Qnil since menu selection functions do not return
+ until a selection has been made or cancelled. */
+ return Qnil;
+ }
+
/* This callback is called from the menu bar pulldown menu
when the user makes a selection.
Figure out what the user chose
***************
*** 2636,2641 ****
--- 2647,2653 ----
Vmenu_updating_frame = Qnil;
defsubr (&Sx_popup_menu);
+ defsubr (&Smenu_or_popup_active_p);
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif
*** w32menu.c Tue Aug 15 10:01:02 2006 1.81
--- w32menu.c Mon Sep 18 07:49:02 2006
***************
*** 235,244 ****
/* Current depth within submenus. */
static int menu_items_submenu_depth;
- /* Flag which when set indicates a dialog or menu has been posted by
- Xt on behalf of one of the widget sets. */
- static int popup_activated_flag;
-
static int next_menubar_widget_id;
/* This is set nonzero after the user activates the menu bar, and set
--- 235,240 ----
***************
*** 994,999 ****
--- 990,1006 ----
complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
}
+ /* The following is used by delayed window autoselection. */
+
+ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p,
Smenu_or_popup_active_p, 0, 0, 0,
+ doc: /* Return t if a menu or popup dialog is active on selected
frame. */)
+ ()
+ {
+ FRAME_PTR f;
+ f = SELECTED_FRAME ();
+ return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
+ }
+
/* This callback is called from the menu bar pulldown menu
when the user makes a selection.
Figure out what the user chose
***************
*** 2148,2154 ****
/* Display the menu. */
lw_pop_up_all_widgets (dialog_id);
- popup_activated_flag = 1;
/* Process events that apply to the menu. */
popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
--- 2155,2160 ----
***************
*** 2428,2440 ****
return 1;
}
- int
- popup_activated ()
- {
- /* popup_activated_flag not actually used on W32 */
- return 0;
- }
-
/* Display help string for currently pointed to menu item. Not
supported on NT 3.51 and earlier, as GetMenuItemInfo is not
available. */
--- 2434,2439 ----
***************
*** 2554,2559 ****
--- 2553,2559 ----
Vmenu_updating_frame = Qnil;
defsubr (&Sx_popup_menu);
+ defsubr (&Smenu_or_popup_active_p);
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif
*** xdisp.c Fri Sep 8 18:07:34 2006 1.1119
--- xdisp.c Mon Sep 18 07:47:46 2006
***************
*** 22604,22610 ****
struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
if (popup_activated ())
return;
#endif
--- 22604,22610 ----
struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
if (popup_activated ())
return;
#endif
*** xmenu.c Tue Jun 6 19:20:42 2006 1.307
--- xmenu.c Mon Sep 18 08:32:26 2006
***************
*** 1487,1492 ****
--- 1487,1501 ----
return popup_activated_flag;
}
+ /* The following is used by delayed window autoselection. */
+
+ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p,
Smenu_or_popup_active_p, 0, 0, 0,
+ doc: /* Return t if a menu or popup dialog is active. */)
+ ()
+ {
+ return (popup_activated ()) ? Qt : Qnil;
+ }
+
/* This callback is invoked when the user selects a menubar cascade
pushbutton, but before the pulldown menu is posted. */
***************
*** 3769,3774 ****
--- 3778,3784 ----
#endif
defsubr (&Sx_popup_menu);
+ defsubr (&Smenu_or_popup_active_p);
#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
defsubr (&Smenu_bar_open);
*** window.el Fri Sep 8 18:07:24 2006 1.117
--- window.el Tue Sep 26 08:47:28 2006
***************
*** 787,794 ****
(defvar mouse-autoselect-window-window nil
"Last window recorded by delayed window autoselection.")
! (defvar mouse-autoselect-window-now nil
! "When non-nil don't delay autoselection in `handle-select-window'.")
(defun mouse-autoselect-window-cancel (&optional force)
"Cancel delayed window autoselection.
--- 787,797 ----
(defvar mouse-autoselect-window-window nil
"Last window recorded by delayed window autoselection.")
! (defvar mouse-autoselect-window-state nil
! "When non-nil, special state of delayed window autoselection.
! Possible values are `suspend' \(suspend autoselection after a menu or
! scrollbar interaction\) and `select' \(the next invocation of
! 'handle-select-window' shall select the window immediately\).")
(defun mouse-autoselect-window-cancel (&optional force)
"Cancel delayed window autoselection.
***************
*** 798,829 ****
(eq this-command 'scroll-bar-toolkit-scroll)
(memq (nth 4 (event-end last-input-event))
'(handle end-scroll)))
! (setq mouse-autoselect-window-now nil)
(when (timerp mouse-autoselect-window-timer)
(cancel-timer mouse-autoselect-window-timer))
(remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
! (defun mouse-autoselect-window-start (window)
"Start delayed window autoselection.
! Called when Emacs detects that the mouse has moved to the non-selected
! window WINDOW and the variable `mouse-autoselect-window' has a numeric,
! non-zero value. The return value is non-nil iff delayed autoselection
! started successfully. Delayed window autoselection is canceled when the
! mouse position has stabilized or a command is executed."
! ;; Cancel any active window autoselection.
! (mouse-autoselect-window-cancel t)
! ;; Record current mouse position in `mouse-autoselect-window-position' and
! ;; WINDOW in `mouse-autoselect-window-window'.
! (setq mouse-autoselect-window-position (mouse-position))
! (setq mouse-autoselect-window-window window)
! ;; Install timer which runs `mouse-autoselect-window-select' every
;; `mouse-autoselect-window' seconds.
(setq mouse-autoselect-window-timer
(run-at-time
! (abs mouse-autoselect-window) (abs mouse-autoselect-window)
! 'mouse-autoselect-window-select))
! ;; Executing a command cancels window autoselection.
! (add-hook 'pre-command-hook 'mouse-autoselect-window-cancel))
(defun mouse-autoselect-window-select ()
"Select window with delayed window autoselection.
--- 801,826 ----
(eq this-command 'scroll-bar-toolkit-scroll)
(memq (nth 4 (event-end last-input-event))
'(handle end-scroll)))
! (setq mouse-autoselect-window-state nil)
(when (timerp mouse-autoselect-window-timer)
(cancel-timer mouse-autoselect-window-timer))
(remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
! (defun mouse-autoselect-window-start (mouse-position &optional window suspend)
"Start delayed window autoselection.
! MOUSE-POSITION is the last position where the mouse was seen as returned
! by `mouse-position'. Optional argument WINDOW non-nil denotes the
! window where the mouse was seen. Optional argument SUSPEND non-nil
! means suspend autoselection."
! ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
! (setq mouse-autoselect-window-position mouse-position)
! (when window (setq mouse-autoselect-window-window window))
! (setq mouse-autoselect-window-state (when suspend 'suspend))
! ;; Install timer which runs `mouse-autoselect-window-select' after
;; `mouse-autoselect-window' seconds.
(setq mouse-autoselect-window-timer
(run-at-time
! (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select)))
(defun mouse-autoselect-window-select ()
"Select window with delayed window autoselection.
***************
*** 832,840 ****
active. This function is run by `mouse-autoselect-window-timer'."
(condition-case nil
(let* ((mouse-position (mouse-position))
! (window (window-at (cadr mouse-position) (cddr mouse-position)
! (car mouse-position))))
(cond
((and window (not (eq window (selected-window)))
(or (not (numberp mouse-autoselect-window))
(and (> mouse-autoselect-window 0)
--- 829,849 ----
active. This function is run by `mouse-autoselect-window-timer'."
(condition-case nil
(let* ((mouse-position (mouse-position))
! (window
! (condition-case nil
! (window-at (cadr mouse-position) (cddr mouse-position)
! (car mouse-position))
! (error nil))))
(cond
+ ((or (menu-or-popup-active-p)
+ (and window
+ (not (coordinates-in-window-p (cdr mouse-position) window))))
+ ;; A menu / popup dialog is active or the mouse is on the scroll-bar
+ ;; of WINDOW, temporarily suspend delayed autoselection.
+ (mouse-autoselect-window-start mouse-position nil t))
+ ((eq mouse-autoselect-window-state 'suspend)
+ ;; Delayed autoselection was temporarily suspended, reenable it.
+ (mouse-autoselect-window-start mouse-position))
((and window (not (eq window (selected-window)))
(or (not (numberp mouse-autoselect-window))
(and (> mouse-autoselect-window 0)
***************
*** 843,866 ****
(eq window mouse-autoselect-window-window))
;; Otherwise select window iff the mouse is at the same
;; position as before. Observe that the first test after
! ;; `mouse-autoselect-window-start' usually fails since the
! ;; value of `mouse-autoselect-window-position' recorded there
! ;; is the position where the mouse has entered the new window
! ;; and not necessarily where the mouse has stopped moving.
(equal mouse-position mouse-autoselect-window-position))
;; The minibuffer is a candidate window iff it's active.
(or (not (window-minibuffer-p window))
(eq window (active-minibuffer-window))))
! ;; Mouse position has stabilized in non-selected window: Cancel window
! ;; autoselection and try to select that window.
(mouse-autoselect-window-cancel t)
;; Select window where mouse appears unless the selected window is the
;; minibuffer. Use `unread-command-events' in order to execute pre-
;; and post-command hooks and trigger idle timers. To avoid delaying
! ;; autoselection again, temporarily set `mouse-autoselect-window-now'
! ;; to t.
(unless (window-minibuffer-p (selected-window))
! (setq mouse-autoselect-window-now t)
(setq unread-command-events
(cons (list 'select-window (list window))
unread-command-events))))
--- 852,874 ----
(eq window mouse-autoselect-window-window))
;; Otherwise select window iff the mouse is at the same
;; position as before. Observe that the first test after
! ;; starting autoselection usually fails since the value of
! ;; `mouse-autoselect-window-position' recorded there is the
! ;; position where the mouse has entered the new window and
! ;; not necessarily where the mouse has stopped moving.
(equal mouse-position mouse-autoselect-window-position))
;; The minibuffer is a candidate window iff it's active.
(or (not (window-minibuffer-p window))
(eq window (active-minibuffer-window))))
! ;; Mouse position has stabilized in non-selected window: Cancel
! ;; delayed autoselection and try to select that window.
(mouse-autoselect-window-cancel t)
;; Select window where mouse appears unless the selected window is the
;; minibuffer. Use `unread-command-events' in order to execute pre-
;; and post-command hooks and trigger idle timers. To avoid delaying
! ;; autoselection again, set `mouse-autoselect-window-state'."
(unless (window-minibuffer-p (selected-window))
! (setq mouse-autoselect-window-state 'select)
(setq unread-command-events
(cons (list 'select-window (list window))
unread-command-events))))
***************
*** 868,881 ****
(not (numberp mouse-autoselect-window))
(equal mouse-position mouse-autoselect-window-position))
;; Mouse position has either stabilized in the selected window or at
! ;; `mouse-autoselect-window-position': Cancel window autoselection.
(mouse-autoselect-window-cancel t))
(t
! ;; Mouse position has not stabilized yet, record new mouse position in
! ;; `mouse-autoselect-window-position' and any window at that position
! ;; in `mouse-autoselect-window-window'.
! (setq mouse-autoselect-window-position mouse-position)
! (setq mouse-autoselect-window-window window))))
(error nil)))
(defun handle-select-window (event)
--- 876,887 ----
(not (numberp mouse-autoselect-window))
(equal mouse-position mouse-autoselect-window-position))
;; Mouse position has either stabilized in the selected window or at
! ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
(mouse-autoselect-window-cancel t))
(t
! ;; Mouse position has not stabilized yet, resume delayed
! ;; autoselection.
! (mouse-autoselect-window-start mouse-position window))))
(error nil)))
(defun handle-select-window (event)
***************
*** 893,906 ****
(minibuffer-window-active-p window)))
(unless (and (numberp mouse-autoselect-window)
(not (zerop mouse-autoselect-window))
! (not mouse-autoselect-window-now)
! ;; When `mouse-autoselect-window' has a numeric, non-zero
! ;; value, delay window autoselection by that value.
! ;; `mouse-autoselect-window-start' returns non-nil iff it
! ;; successfully installed a timer for this purpose.
! (mouse-autoselect-window-start window))
! ;; Re-enable delayed window autoselection.
! (setq mouse-autoselect-window-now nil)
(when mouse-autoselect-window
;; Run `mouse-leave-buffer-hook' when autoselecting window.
(run-hooks 'mouse-leave-buffer-hook))
--- 899,916 ----
(minibuffer-window-active-p window)))
(unless (and (numberp mouse-autoselect-window)
(not (zerop mouse-autoselect-window))
! (not (eq mouse-autoselect-window-state 'select))
! (progn
! ;; Cancel any delayed autoselection.
! (mouse-autoselect-window-cancel t)
! ;; Start delayed autoselection from current mouse position
! ;; and window.
! (mouse-autoselect-window-start (mouse-position) window)
! ;; Executing a command cancels delayed autoselection.
! (add-hook
! 'pre-command-hook 'mouse-autoselect-window-cancel)))
! ;; Reset state of delayed autoselection.
! (setq mouse-autoselect-window-state nil)
(when mouse-autoselect-window
;; Run `mouse-leave-buffer-hook' when autoselecting window.
(run-hooks 'mouse-leave-buffer-hook))
- Re: mouse-autoselect-window with menu pane,
martin rudalics <=