emacs-pretest-bug
[Top][All Lists]
Advanced

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]