aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorMartin Rudalics2017-04-12 10:38:25 +0200
committerMartin Rudalics2017-04-12 10:38:25 +0200
commit3fdd3bb56c006a2a24761b8fcea0cbd9b0cba422 (patch)
treea0b8f5e431ba812b4fe69261a8515e973a3e7ed3 /lisp
parent449bc49c768a4733411c7e05186be7efc163cd7c (diff)
downloademacs-3fdd3bb56c006a2a24761b8fcea0cbd9b0cba422.tar.gz
emacs-3fdd3bb56c006a2a24761b8fcea0cbd9b0cba422.zip
Add new frame parameters and associated functions
Add new frame parameters `undecorated', `override-redirect', `parent-frame', `skip-taskbar', `no-focus-on-map', `no-accept-focus', `z-group', `delete-before', `no-other-frame', `mouse-wheel-frame', `min-width', `min-height'. Add new functions `frame-restack' and `frame-list-z-order'. * lisp/cus-start.el (focus-follows-mouse): Adapt customization type. * lisp/frame.el (handle-delete-frame): Handle child and `delete-before' frames. (other-frame): Stop looking for other frame after one round. (frame-list-z-order, frame-restack): New functions. (delete-other-frames): Handle child frames. * lisp/frameset.el (frameset-persistent-filter-alist) (frameset--record-relationships): Handle `delete-before', `parent-frame' and `mouse-wheel-frame' parameters. Rename latter from `frameset--record-minibuffer-relationships'. (frameset--restore-frame): Handle ‘parent-frame’ parameter specially. (frameset-restore): Handle `delete-before', `parent-frame' and `mouse-wheel-frame' parameters. * lisp/mwheel.el (mwheel-scroll): Handle `mouse-wheel-frame' parameter. * lisp/window.el (window--min-size-ignore-p): Fix doc-string. (mouse-autoselect-window-select, handle-select-window): Major rewrite. Try to not ignore errors. Handle auto-selection of child frames and different values of `focus-follows-mouse'. * src/frame.c (frame_windows_min_size): Handle new `min-width' and `min-height' frame parameters. (make_frame): Initialize new frame structure members. (do_switch_frame): Don't reset internal_last_event_frame for descendant frames. (Fframe_parent, frame_ancestor_p, Fframe_ancestor_p): New functions. (candidate_frame): Don't return `no-other-frame' frame. (other_frames): New function replacing other_visible_frames. (delete_frame): Rewrite. Handle child and `delete-before' frames. (Fmake_frame_invisible): Call other_frames. (store_frame_param): Check `delete-before' and `parent-frame' parameters for circular dependencies. (frame_parms, syms_of_frame): Add entries for and define new frame parameters. (focus_follows_mouse): New meaningful value `auto-raise'. * src/frame.h (z_group): New enumeration type. (frame): New slots parent_frame, undecorated, override_redirect, skip_taskbar, no_focus_on_map, no_accept_focus, z_group. (fset_parent_frame): New inlined function. (FRAME_UNDECORATED, FRAME_OVERRIDE_REDIRECT) (FRAME_PARENT_FRAME, FRAME_SKIP_TASKBAR, FRAME_NO_FOCUS_ON_MAP) (FRAME_NO_ACCEPT_FOCUS, FRAME_Z_GROUP, FRAME_Z_GROUP_NONE) (FRAME_Z_GROUP_ABOVE, FRAME_Z_GROUP_ABOVE_SUSPENDED) (FRAME_Z_GROUP_BELOW): New macros. (frame_ancestor_p): Add declaration. * src/gtkutil.c (xg_create_frame_widgets): Handle `undecorated' and `override-redirect' frame parameters. (x_wm_set_size_hint): None for child frames. (xg_set_undecorated, xg_frame_restack, xg_set_skip_taskbar) (xg_set_no_focus_on_map, xg_set_no_accept_focus) (xg_set_override_redirect): New functions. (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Don't let scrollbars obscure child frames. * src/gtkutil.h: (xg_set_undecorated, xg_frame_restack) (xg_set_skip_taskbar, xg_set_no_focus_on_map) (xg_set_no_accept_focus, xg_set_override_redirect): Add extern declarations. * src/nsfns.m (ns_frame_parm_handlers): Add entries for new frame parameters. (Fx_create_frame): Install `min-width' and `min-height' frame parameters. * src/nsterm.m (mouseMoved:): Handle focus_follows_mouse change. * src/w32fns.c (WS_EX_NOACTIVATE): Define if necessary. (x_real_positions): Handle child frames. (x_set_menu_bar_lines): Don't for child frames. (x_set_undecorated, x_set_parent_frame, x_set_skip_taskbar) (x_set_no_focus_on_map, x_set_no_accept_focus) (x_set_z_group): New functions. (w32_createvscrollbar, w32_createhscrollbar): Don't draw scroll bars over child frames. (w32_createwindow): Handle new frame parameters and child frames. (w32_wnd_proc): Let mouse clicks into a child frame activate the frame. Try to handle the `no-accept-focus' parameter. Do SetFocus when our window is brought to top or becomes the foreground window. (w32_window): Don't initialize menu bar for child frames. (Fx_create_frame): Handle new frame parameters. (x_create_tip_frame): Set explicit_parent slot. (w32_dialog_in_progress): New function. (Fx_file_dialog): Handle `z-group-above' frames. (w32_frame_list_z_order, Fw32_frame_list_z_order) (w32_frame_restack, Fw32_frame_restack): New functions. (w32_frame_parm_handlers): Add entries for new frame parameters. * src/w32font.c (Fx_select_font): Handle `z-group-above' frames during font selection dialogue. * src/w32term.c (construct_mouse_wheel): Construct mouse wheel event from F's w32 window. (w32_mouse_position): Handle child frames. (w32_set_vertical_scroll_bar, w32_set_horizontal_scroll_bar): Don't draw scroll bars over child frames. (w32_read_socket): Always erase background of child frames. When generating SELECT_WINDOW_EVENTs handle new value of `focus-follows-mouse' and handle `no-accept-focus' parameter. Handle `mouse-wheel-frame' parameter. (x_calc_absolute_position, x_set_offset, x_set_window_size): Handle child frames. (x_make_frame_visible): Handle child frames specially. Handle `no-focus-on-map' parameter. * src/w32term.h (w32_dialog_in_progress): Add external declaration. * src/xdisp.c (x_consider_frame_title, prepare_menu_bars): Not for child frames. * src/xfns.c (Xm/MwmUtil.h): Include for WM hints. (PropMotifWmHints, PROP_MOTIF_WM_HINTS_ELEMENTS): Define for non-Motif, non-GTK case. (x_real_pos_and_offsets): Handle child frames. (x_set_undecorated, x_set_parent_frame) (x_set_no_focus_on_map, x_set_no_accept_focus) (x_set_override_redirect): New functions. (x_set_menu_bar_lines): Not for child frames. (x_window): Handle `undecorated' and `override_redirect' cases. (Fx_create_frame): Handle new frame parameters. (frame_geometry): Handle child frames and outer border. (x_frame_list_z_order, Fx_frame_list_z_order) (x_frame_restack, Fx_frame_restack): New functions. (Fx_file_dialog, Fx_select_font): Set x_menu_set_in_use. (x_frame_parm_handlers): Add entries for new frame parameters. * src/xmenu.c (x_menu_set_in_use): Handle `z-group-above' frames. * src/xterm.c (x_set_frame_alpha): Don't set alpha of parent for child frames. (XTmouse_position): Handle child frames. (x_scroll_bar_create, x_scroll_bar_expose): Don't let scroll bars obscure child frames. (handle_one_xevent): Handle child frame positions. If necessary set `skip-taskbar' and reassign proper `z-group' when we are mapped. When generating SELECT_WINDOW_EVENTs handle new value of `focus-follows-mouse'. Handle `mouse-wheel-frame' parameter. Let mouse clicks into a child frame activate the frame. (x_calc_absolute_position, x_set_offset): Handle child frames specially. (x_set_skip_taskbar, x_set_z_group): New functions. (x_make_frame_visible): Handle child frames. (ATOM_REFS_INIT): Add entries for Xatom_net_wm_state_skip_taskbar, Xatom_net_wm_state_above, Xatom_net_wm_state_below. * src/xterm.h (top-level): Declare Xatom_net_wm_state_above, Xatom_net_wm_state_below and Xatom_net_wm_state_skip_taskbar. (x_set_skip_taskbar, x_set_z_group): Add extern declarations.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/cus-start.el6
-rw-r--r--lisp/frame.el117
-rw-r--r--lisp/frameset.el100
-rw-r--r--lisp/mwheel.el59
-rw-r--r--lisp/window.el169
5 files changed, 313 insertions, 138 deletions
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 51c43c7d21a..a507e30ca9c 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -286,7 +286,11 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
286 ;; fns.c 286 ;; fns.c
287 (use-dialog-box menu boolean "21.1") 287 (use-dialog-box menu boolean "21.1")
288 (use-file-dialog menu boolean "22.1") 288 (use-file-dialog menu boolean "22.1")
289 (focus-follows-mouse frames boolean "20.3") 289 (focus-follows-mouse
290 frames (choice
291 (const :tag "Off (nil)" :value nil)
292 (const :tag "On (t)" :value t)
293 (const :tag "Auto-raise" :value auto-raise)) "26.1")
290 ;; fontset.c 294 ;; fontset.c
291 ;; FIXME nil is the initial value, fontset.el setqs it. 295 ;; FIXME nil is the initial value, fontset.el setqs it.
292 (vertical-centering-font-regexp display 296 (vertical-centering-font-regexp display
diff --git a/lisp/frame.el b/lisp/frame.el
index 4768b5be002..86a0e26e393 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -115,15 +115,19 @@ appended when the minibuffer frame is created."
115(defun handle-delete-frame (event) 115(defun handle-delete-frame (event)
116 "Handle delete-frame events from the X server." 116 "Handle delete-frame events from the X server."
117 (interactive "e") 117 (interactive "e")
118 (let ((frame (posn-window (event-start event))) 118 (let* ((frame (posn-window (event-start event))))
119 (i 0) 119 (if (catch 'other-frame
120 (tail (frame-list))) 120 (dolist (frame-1 (frame-list))
121 (while tail 121 ;; A valid "other" frame is visible, owns its minibuffer
122 (and (frame-visible-p (car tail)) 122 ;; window, has its `delete-before' parameter unset and is
123 (not (eq (car tail) frame)) 123 ;; not a child frame.
124 (setq i (1+ i))) 124 (when (and (not (eq frame-1 frame))
125 (setq tail (cdr tail))) 125 (frame-visible-p frame-1)
126 (if (> i 0) 126 (window-live-p (minibuffer-window frame-1))
127 (eq (window-frame (minibuffer-window frame-1)) frame-1)
128 (not (frame-parent frame-1))
129 (not (frame-parameter frame-1 'delete-before)))
130 (throw 'other-frame t))))
127 (delete-frame frame t) 131 (delete-frame frame t)
128 ;; Gildea@x.org says it is ok to ask questions before terminating. 132 ;; Gildea@x.org says it is ok to ask questions before terminating.
129 (save-buffers-kill-emacs)))) 133 (save-buffers-kill-emacs))))
@@ -834,21 +838,24 @@ All frames are arranged in a cyclic order.
834This command selects the frame ARG steps away in that order. 838This command selects the frame ARG steps away in that order.
835A negative ARG moves in the opposite order. 839A negative ARG moves in the opposite order.
836 840
837To make this command work properly, you must tell Emacs 841To make this command work properly, you must tell Emacs how the
838how the system (or the window manager) generally handles 842system (or the window manager) generally handles focus-switching
839focus-switching between windows. If moving the mouse onto a window 843between windows. If moving the mouse onto a window selects
840selects it (gives it focus), set `focus-follows-mouse' to t. 844it (gives it focus), set `focus-follows-mouse' to t. Otherwise,
841Otherwise, that variable should be nil." 845that variable should be nil."
842 (interactive "p") 846 (interactive "p")
843 (let ((frame (selected-frame))) 847 (let ((sframe (selected-frame))
848 (frame (selected-frame)))
844 (while (> arg 0) 849 (while (> arg 0)
845 (setq frame (next-frame frame)) 850 (setq frame (next-frame frame))
846 (while (not (eq (frame-visible-p frame) t)) 851 (while (and (not (eq frame sframe))
852 (not (eq (frame-visible-p frame) t)))
847 (setq frame (next-frame frame))) 853 (setq frame (next-frame frame)))
848 (setq arg (1- arg))) 854 (setq arg (1- arg)))
849 (while (< arg 0) 855 (while (< arg 0)
850 (setq frame (previous-frame frame)) 856 (setq frame (previous-frame frame))
851 (while (not (eq (frame-visible-p frame) t)) 857 (while (and (not (eq frame sframe))
858 (not (eq (frame-visible-p frame) t)))
852 (setq frame (previous-frame frame))) 859 (setq frame (previous-frame frame)))
853 (setq arg (1+ arg))) 860 (setq arg (1+ arg)))
854 (select-frame-set-input-focus frame))) 861 (select-frame-set-input-focus frame)))
@@ -1380,6 +1387,7 @@ and width values are in pixels.
1380 '(outer-position 0 . 0) 1387 '(outer-position 0 . 0)
1381 (cons 'outer-size (cons (frame-width frame) (frame-height frame))) 1388 (cons 'outer-size (cons (frame-width frame) (frame-height frame)))
1382 '(external-border-size 0 . 0) 1389 '(external-border-size 0 . 0)
1390 '(outer-border-width . 0)
1383 '(title-bar-size 0 . 0) 1391 '(title-bar-size 0 . 0)
1384 '(menu-bar-external . nil) 1392 '(menu-bar-external . nil)
1385 (let ((menu-bar-lines (frame-parameter frame 'menu-bar-lines))) 1393 (let ((menu-bar-lines (frame-parameter frame 'menu-bar-lines)))
@@ -1490,6 +1498,59 @@ keys and their meanings."
1490 for frames = (cdr (assq 'frames attributes)) 1498 for frames = (cdr (assq 'frames attributes))
1491 if (memq frame frames) return attributes)) 1499 if (memq frame frames) return attributes))
1492 1500
1501(declare-function x-frame-list-z-order "xfns.c" (&optional display))
1502(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
1503
1504(defun frame-list-z-order (&optional display)
1505 "Return list of Emacs' frames, in Z (stacking) order.
1506The optional argument DISPLAY specifies which display to poll.
1507DISPLAY should be either a frame or a display name (a string).
1508If omitted or nil, that stands for the selected frame's display.
1509
1510Frames are listed from topmost (first) to bottommost (last). As
1511a special case, if DISPLAY is non-nil and specifies a live frame,
1512return the child frames of that frame in Z (stacking) order.
1513
1514Return nil if DISPLAY contains no Emacs frame."
1515 (let ((frame-type (framep-on-display display)))
1516 (cond
1517 ((eq frame-type 'x)
1518 (x-frame-list-z-order display))
1519 ((eq frame-type 'w32)
1520 (w32-frame-list-z-order display)))))
1521
1522(declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above))
1523(declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above))
1524
1525(defun frame-restack (frame1 frame2 &optional above)
1526 "Restack FRAME1 below FRAME2.
1527This implies that if both frames are visible and the display
1528areas of these frames overlap, FRAME2 will (partially) obscure
1529FRAME1. If the optional third argument ABOVE is non-nil, restack
1530FRAME1 above FRAME2. This means that if both frames are visible
1531and the display areas of these frames overlap, FRAME1 will
1532\(partially) obscure FRAME2.
1533
1534This may be thought of as an atomic action performed in two
1535steps: The first step removes FRAME1's window-system window from
1536the display. The second step reinserts FRAME1's window
1537below (above if ABOVE is true) that of FRAME2. Hence the
1538position of FRAME2 in its display's Z (stacking) order relative
1539to all other frames excluding FRAME1 remains unaltered.
1540
1541Some window managers may refuse to restack windows. "
1542 (if (and (frame-live-p frame1)
1543 (frame-live-p frame2)
1544 (equal (frame-parameter frame1 'display)
1545 (frame-parameter frame2 'display)))
1546 (let ((frame-type (framep-on-display frame1)))
1547 (cond
1548 ((eq frame-type 'x)
1549 (x-frame-restack frame1 frame2 above))
1550 ((eq frame-type 'w32)
1551 (w32-frame-restack frame1 frame2 above))))
1552 (error "Cannot restack frames")))
1553
1493(defun frame-size-changed-p (&optional frame) 1554(defun frame-size-changed-p (&optional frame)
1494 "Return non-nil when the size of FRAME has changed. 1555 "Return non-nil when the size of FRAME has changed.
1495More precisely, return non-nil when the inner width or height of 1556More precisely, return non-nil when the inner width or height of
@@ -1886,7 +1947,7 @@ A geometry specification equivalent to SPEC for FRAME is returned,
1886where the value is a cons with car `+', not numeric. 1947where the value is a cons with car `+', not numeric.
1887SPEC is a frame geometry spec: (left . VALUE) or (top . VALUE). 1948SPEC is a frame geometry spec: (left . VALUE) or (top . VALUE).
1888If VALUE is a number, then it is converted to a cons value, perhaps 1949If VALUE is a number, then it is converted to a cons value, perhaps
1889 relative to the opposite frame edge from that in the original spec. 1950relative to the opposite frame edge from that in the original spec.
1890FRAME defaults to the selected frame. 1951FRAME defaults to the selected frame.
1891 1952
1892Examples (measures in pixels) - 1953Examples (measures in pixels) -
@@ -1907,24 +1968,36 @@ the opposite frame edge from the edge indicated in the input spec."
1907(defun delete-other-frames (&optional frame) 1968(defun delete-other-frames (&optional frame)
1908 "Delete all frames on FRAME's terminal, except FRAME. 1969 "Delete all frames on FRAME's terminal, except FRAME.
1909If FRAME uses another frame's minibuffer, the minibuffer frame is 1970If FRAME uses another frame's minibuffer, the minibuffer frame is
1910left untouched. FRAME must be a live frame and defaults to the 1971left untouched. Do not delete any of FRAME's child frames. If
1911selected one." 1972FRAME is a child frame, delete its siblings only. FRAME must be
1973a live frame and defaults to the selected one."
1912 (interactive) 1974 (interactive)
1913 (setq frame (window-normalize-frame frame)) 1975 (setq frame (window-normalize-frame frame))
1914 (let ((minibuffer-frame (window-frame (minibuffer-window frame))) 1976 (let ((minibuffer-frame (window-frame (minibuffer-window frame)))
1915 (this (next-frame frame t)) 1977 (this (next-frame frame t))
1978 (parent (frame-parent frame))
1916 next) 1979 next)
1917 ;; In a first round consider minibuffer-less frames only. 1980 ;; In a first round consider minibuffer-less frames only.
1918 (while (not (eq this frame)) 1981 (while (not (eq this frame))
1919 (setq next (next-frame this t)) 1982 (setq next (next-frame this t))
1920 (unless (eq (window-frame (minibuffer-window this)) this) 1983 (unless (or (eq (window-frame (minibuffer-window this)) this)
1984 ;; When FRAME is a child frame, delete its siblings
1985 ;; only.
1986 (and parent (not (eq (frame-parent this) parent)))
1987 ;; Do not delete a child frame of FRAME.
1988 (eq (frame-parent this) frame))
1921 (delete-frame this)) 1989 (delete-frame this))
1922 (setq this next)) 1990 (setq this next))
1923 ;; In a second round consider all remaining frames. 1991 ;; In a second round consider all remaining frames.
1924 (setq this (next-frame frame t)) 1992 (setq this (next-frame frame t))
1925 (while (not (eq this frame)) 1993 (while (not (eq this frame))
1926 (setq next (next-frame this t)) 1994 (setq next (next-frame this t))
1927 (unless (eq this minibuffer-frame) 1995 (unless (or (eq this minibuffer-frame)
1996 ;; When FRAME is a child frame, delete its siblings
1997 ;; only.
1998 (and parent (not (eq (frame-parent this) parent)))
1999 ;; Do not delete a child frame of FRAME.
2000 (eq (frame-parent this) frame))
1928 (delete-frame this)) 2001 (delete-frame this))
1929 (setq this next)))) 2002 (setq this next))))
1930 2003
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 2dd3050ef76..ebf09d3ab5c 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -446,6 +446,7 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
446 (buffer-list . :never) 446 (buffer-list . :never)
447 (buffer-predicate . :never) 447 (buffer-predicate . :never)
448 (buried-buffer-list . :never) 448 (buried-buffer-list . :never)
449 (delete-before . :never)
449 (font . frameset-filter-shelve-param) 450 (font . frameset-filter-shelve-param)
450 (foreground-color . frameset-filter-sanitize-color) 451 (foreground-color . frameset-filter-sanitize-color)
451 (fullscreen . frameset-filter-shelve-param) 452 (fullscreen . frameset-filter-shelve-param)
@@ -455,7 +456,9 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
455 (GUI:width . frameset-filter-unshelve-param) 456 (GUI:width . frameset-filter-unshelve-param)
456 (height . frameset-filter-shelve-param) 457 (height . frameset-filter-shelve-param)
457 (outer-window-id . :never) 458 (outer-window-id . :never)
459 (parent-frame . :never)
458 (parent-id . :never) 460 (parent-id . :never)
461 (mouse-wheel-frame . :never)
459 (tty . frameset-filter-tty-to-GUI) 462 (tty . frameset-filter-tty-to-GUI)
460 (tty-type . frameset-filter-tty-to-GUI) 463 (tty-type . frameset-filter-tty-to-GUI)
461 (width . frameset-filter-shelve-param) 464 (width . frameset-filter-shelve-param)
@@ -717,9 +720,18 @@ If nil, check all live frames."
717 720
718;; Saving framesets 721;; Saving framesets
719 722
720(defun frameset--record-minibuffer-relationships (frame-list) 723(defun frameset--record-relationships (frame-list)
721 "Process FRAME-LIST and record minibuffer relationships. 724 "Process FRAME-LIST and record relationships.
722FRAME-LIST is a list of frames. Internal use only." 725FRAME-LIST is a list of frames.
726
727The relationships recorded for each frame are
728
729- `minibuffer' via `frameset--mini'
730- `delete-before' via `frameset--delete-before'
731- `parent-frame' via `frameset--parent-frame'
732- `mouse-wheel-frame' via `frameset--mouse-wheel-frame'
733
734Internal use only."
723 ;; Record frames with their own minibuffer 735 ;; Record frames with their own minibuffer
724 (dolist (frame (minibuffer-frame-list)) 736 (dolist (frame (minibuffer-frame-list))
725 (when (memq frame frame-list) 737 (when (memq frame frame-list)
@@ -730,22 +742,41 @@ FRAME-LIST is a list of frames. Internal use only."
730 (set-frame-parameter frame 742 (set-frame-parameter frame
731 'frameset--mini 743 'frameset--mini
732 (cons t (eq frame default-minibuffer-frame))))) 744 (cons t (eq frame default-minibuffer-frame)))))
733 ;; Now link minibufferless frames with their minibuffer frames 745 ;; Now link minibufferless frames with their minibuffer frames and
746 ;; store `parent-frame', `delete-before' and `mouse-wheel-frame'
747 ;; relationships in a similar way.
734 (dolist (frame frame-list) 748 (dolist (frame frame-list)
735 (unless (frame-parameter frame 'frameset--mini) 749 (let ((parent-frame (frame-parent frame))
736 (frameset--set-id frame) 750 (delete-before (frame-parameter frame 'delete-before))
737 (let ((mb-frame (window-frame (minibuffer-window frame)))) 751 (mouse-wheel-frame (frame-parameter frame 'mouse-wheel-frame))
738 ;; For minibufferless frames, frameset--mini is a cons 752 (nomini (not (frame-parameter frame 'frameset--mini))))
739 ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of 753 (when (or nomini parent-frame delete-before mouse-wheel-frame)
740 ;; the frame containing its minibuffer window. 754 (when nomini
741 ;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain 755 (frameset--set-id frame))
742 ;; the minibuffer frame of a minibufferless frame; we allow 756 (when parent-frame
743 ;; it without trying to second-guess the user. 757 (set-frame-parameter
744 (set-frame-parameter frame 758 frame 'frameset--parent-frame (frameset-frame-id parent-frame)))
745 'frameset--mini 759 (when delete-before
746 (cons nil 760 (set-frame-parameter
747 (and mb-frame 761 frame 'frameset--delete-before (frameset-frame-id delete-before)))
748 (frameset-frame-id mb-frame)))))))) 762 (when mouse-wheel-frame
763 (set-frame-parameter
764 frame 'frameset--mouse-wheel-frame
765 (frameset-frame-id mouse-wheel-frame)))
766 (when nomini
767 (let ((mb-frame (window-frame (minibuffer-window frame))))
768 ;; For minibufferless frames, frameset--mini is a cons
769 ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of
770 ;; the frame containing its minibuffer window.
771 ;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain
772 ;; the minibuffer frame of a minibufferless frame; we allow
773 ;; it without trying to second-guess the user.
774 (set-frame-parameter
775 frame
776 'frameset--mini
777 (cons nil
778 (and mb-frame
779 (frameset-frame-id mb-frame))))))))))
749 780
750;;;###autoload 781;;;###autoload
751(cl-defun frameset-save (frame-list 782(cl-defun frameset-save (frame-list
@@ -768,7 +799,7 @@ PROPERTIES is a user-defined property list to add to the frameset."
768 (cl-delete-if-not predicate list) 799 (cl-delete-if-not predicate list)
769 list))) 800 list)))
770 fs) 801 fs)
771 (frameset--record-minibuffer-relationships frames) 802 (frameset--record-relationships frames)
772 (setq fs (frameset--make 803 (setq fs (frameset--make
773 :app app 804 :app app
774 :name name 805 :name name
@@ -993,6 +1024,14 @@ Internal use only."
993 (frameset--initial-params filtered-cfg)))) 1024 (frameset--initial-params filtered-cfg))))
994 (puthash frame :created frameset--action-map)) 1025 (puthash frame :created frameset--action-map))
995 1026
1027 ;; Try to assign parent-frame right here - it will improve things
1028 ;; for minibuffer-less child frames.
1029 (let* ((frame-id (frame-parameter frame 'frameset--parent-frame))
1030 (parent-frame
1031 (and frame-id (frameset-frame-with-id frame-id))))
1032 (when (frame-live-p parent-frame)
1033 (set-frame-parameter frame 'parent-frame parent-frame)))
1034
996 (modify-frame-parameters frame 1035 (modify-frame-parameters frame
997 (if (eq (frame-parameter frame 'fullscreen) fullscreen) 1036 (if (eq (frame-parameter frame 'fullscreen) fullscreen)
998 ;; Workaround for bug#14949 1037 ;; Workaround for bug#14949
@@ -1205,6 +1244,29 @@ All keyword parameters default to nil."
1205 (error 1244 (error
1206 (delay-warning 'frameset (error-message-string err) :error)))))) 1245 (delay-warning 'frameset (error-message-string err) :error))))))
1207 1246
1247 ;; Setting the parent frame after the frame has been created is a
1248 ;; pain because one can see the frame move on the screen. Ideally,
1249 ;; we would restore minibuffer equipped child frames after their
1250 ;; respective parents have been made but this might interfere with
1251 ;; the reordering of minibuffer frames. Left to the experts ...
1252 (dolist (frame (frame-list))
1253 (let* ((frame-id (frame-parameter frame 'frameset--parent-frame))
1254 (parent-frame
1255 (and frame-id (frameset-frame-with-id frame-id))))
1256 (when (and (not (eq (frame-parameter frame 'parent-frame) parent-frame))
1257 (frame-live-p parent-frame))
1258 (set-frame-parameter frame 'parent-frame parent-frame)))
1259 (let* ((frame-id (frame-parameter frame 'frameset--delete-before))
1260 (delete-before
1261 (and frame-id (frameset-frame-with-id frame-id))))
1262 (when (frame-live-p delete-before)
1263 (set-frame-parameter frame 'delete-before delete-before)))
1264 (let* ((frame-id (frame-parameter frame 'frameset--mouse-wheel-frame))
1265 (mouse-wheel-frame
1266 (and frame-id (frameset-frame-with-id frame-id))))
1267 (when (frame-live-p mouse-wheel-frame)
1268 (set-frame-parameter frame 'mouse-wheel-frame mouse-wheel-frame))))
1269
1208 ;; In case we try to delete the initial frame, we want to make sure that 1270 ;; In case we try to delete the initial frame, we want to make sure that
1209 ;; other frames are already visible (discussed in thread for bug#14841). 1271 ;; other frames are already visible (discussed in thread for bug#14841).
1210 (sit-for 0 t) 1272 (sit-for 0 t)
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index eaeb831e844..958c6e831b7 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -190,14 +190,33 @@ This can be slightly disconcerting, but some people prefer it."
190This should be bound only to mouse buttons 4 and 5 on non-Windows 190This should be bound only to mouse buttons 4 and 5 on non-Windows
191systems." 191systems."
192 (interactive (list last-input-event)) 192 (interactive (list last-input-event))
193 (let* ((curwin (if mouse-wheel-follow-mouse 193 (let* ((selected-window (selected-window))
194 (prog1 194 (scroll-window
195 (selected-window) 195 (or (catch 'found
196 (select-window (mwheel-event-window event))))) 196 (let* ((window (if mouse-wheel-follow-mouse
197 (buffer (window-buffer curwin)) 197 (mwheel-event-window event)
198 (opoint (with-current-buffer buffer 198 (selected-window)))
199 (when (eq (car-safe transient-mark-mode) 'only) 199 (frame (when (window-live-p window)
200 (point)))) 200 (frame-parameter
201 (window-frame window) 'mouse-wheel-frame))))
202 (when (frame-live-p frame)
203 (let* ((pos (mouse-absolute-pixel-position))
204 (pos-x (car pos))
205 (pos-y (cdr pos)))
206 (walk-window-tree
207 (lambda (window-1)
208 (let ((edges (window-edges window-1 nil t t)))
209 (when (and (<= (nth 0 edges) pos-x)
210 (<= pos-x (nth 2 edges))
211 (<= (nth 1 edges) pos-y)
212 (<= pos-y (nth 3 edges)))
213 (throw 'found window-1))))
214 frame nil t)))))
215 (mwheel-event-window event)))
216 (old-point
217 (and (eq scroll-window selected-window)
218 (eq (car-safe transient-mark-mode) 'only)
219 (window-point)))
201 (mods 220 (mods
202 (delq 'click (delq 'double (delq 'triple (event-modifiers event))))) 221 (delq 'click (delq 'double (delq 'triple (event-modifiers event)))))
203 (amt (assoc mods mouse-wheel-scroll-amount))) 222 (amt (assoc mods mouse-wheel-scroll-amount)))
@@ -232,18 +251,18 @@ systems."
232 ;; Make sure we do indeed scroll to the end of the buffer. 251 ;; Make sure we do indeed scroll to the end of the buffer.
233 (end-of-buffer (while t (funcall mwheel-scroll-up-function))))) 252 (end-of-buffer (while t (funcall mwheel-scroll-up-function)))))
234 (t (error "Bad binding in mwheel-scroll")))) 253 (t (error "Bad binding in mwheel-scroll"))))
235 (if curwin (select-window curwin))) 254 (if (eq scroll-window selected-window)
236 ;; If there is a temporarily active region, deactivate it if 255 ;; If there is a temporarily active region, deactivate it if
237 ;; scrolling moves point. 256 ;; scrolling moved point.
238 (when opoint 257 (when (and old-point (/= old-point (window-point)))
239 (with-current-buffer buffer 258 ;; Call `deactivate-mark' at the original position, so that
240 (when (/= opoint (point)) 259 ;; the original region is saved to the X selection.
241 ;; Call `deactivate-mark' at the original position, so that 260 (let ((new-point (window-point)))
242 ;; the original region is saved to the X selection. 261 (goto-char old-point)
243 (let ((newpoint (point))) 262 (deactivate-mark)
244 (goto-char opoint) 263 (goto-char new-point)))
245 (deactivate-mark) 264 (select-window selected-window t))))
246 (goto-char newpoint)))))) 265
247 (when (and mouse-wheel-click-event mouse-wheel-inhibit-click-time) 266 (when (and mouse-wheel-click-event mouse-wheel-inhibit-click-time)
248 (if mwheel-inhibit-click-event-timer 267 (if mwheel-inhibit-click-event-timer
249 (cancel-timer mwheel-inhibit-click-event-timer) 268 (cancel-timer mwheel-inhibit-click-event-timer)
diff --git a/lisp/window.el b/lisp/window.el
index 505024342ed..bea8383fcde 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1533,7 +1533,7 @@ return the minimum pixel-size of WINDOW."
1533 (window-normalize-window window) horizontal ignore pixelwise)) 1533 (window-normalize-window window) horizontal ignore pixelwise))
1534 1534
1535(defun window--min-size-ignore-p (window ignore) 1535(defun window--min-size-ignore-p (window ignore)
1536 "Return non-nil if IGNORE says to ignore height restrictions for WINDOW." 1536 "Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
1537 (if (window-valid-p ignore) 1537 (if (window-valid-p ignore)
1538 (eq window ignore) 1538 (eq window ignore)
1539 (not (memq ignore '(nil preserved))))) 1539 (not (memq ignore '(nil preserved)))))
@@ -8735,13 +8735,14 @@ means suspend autoselection."
8735If the mouse position has stabilized in a non-selected window, select 8735If the mouse position has stabilized in a non-selected window, select
8736that window. The minibuffer window is selected only if the minibuffer 8736that window. The minibuffer window is selected only if the minibuffer
8737is active. This function is run by `mouse-autoselect-window-timer'." 8737is active. This function is run by `mouse-autoselect-window-timer'."
8738 (ignore-errors 8738 (let* ((mouse-position (mouse-position))
8739 (let* ((mouse-position (mouse-position)) 8739 (mouse-x (and (numberp (cadr mouse-position))
8740 (window 8740 (cadr mouse-position)))
8741 (ignore-errors 8741 (mouse-y (and (numberp (cddr mouse-position))
8742 (window-at (cadr mouse-position) (cddr mouse-position) 8742 (cddr mouse-position)))
8743 (car mouse-position))))) 8743 (frame (and mouse-x mouse-y (car mouse-position)))
8744 (cond 8744 (window (and frame (window-at mouse-x mouse-y frame))))
8745 (cond
8745 ((or (and (fboundp 'menu-or-popup-active-p) (menu-or-popup-active-p)) 8746 ((or (and (fboundp 'menu-or-popup-active-p) (menu-or-popup-active-p))
8746 (and window 8747 (and window
8747 (let ((coords (coordinates-in-window-p 8748 (let ((coords (coordinates-in-window-p
@@ -8752,72 +8753,63 @@ is active. This function is run by `mouse-autoselect-window-timer'."
8752 ;; text region of WINDOW: Suspend autoselection temporarily. 8753 ;; text region of WINDOW: Suspend autoselection temporarily.
8753 (mouse-autoselect-window-start mouse-position nil t)) 8754 (mouse-autoselect-window-start mouse-position nil t))
8754 ((or (eq mouse-autoselect-window-state 'suspend) 8755 ((or (eq mouse-autoselect-window-state 'suspend)
8755 ;; When the mouse is at its first recorded position, restart 8756 ;; When the mouse is at its first recorded position, restart
8756 ;; delayed autoselection. This works around a scenario with 8757 ;; delayed autoselection. This works around a scenario with
8757 ;; two two-window frames with identical dimensions: select the 8758 ;; two two-window frames with identical dimensions: select the
8758 ;; first window of the first frame, switch to the second 8759 ;; first window of the first frame, switch to the second
8759 ;; frame, move the mouse to its second window, minimize the 8760 ;; frame, move the mouse to its second window, minimize the
8760 ;; second frame. Now the second window of the first frame 8761 ;; second frame. Now the second window of the first frame
8761 ;; gets selected although the mouse never really "moved" into 8762 ;; gets selected although the mouse never really "moved" into
8762 ;; that window. 8763 ;; that window.
8763 (and (numberp mouse-autoselect-window) 8764 (and (numberp mouse-autoselect-window)
8764 (equal (mouse-position) mouse-autoselect-window-position-1))) 8765 (equal (mouse-position) mouse-autoselect-window-position-1)))
8765 ;; Delayed autoselection was temporarily suspended, reenable it. 8766 ;; Delayed autoselection was temporarily suspended, reenable it.
8766 (mouse-autoselect-window-start mouse-position)) 8767 (mouse-autoselect-window-start mouse-position))
8767 ((and window (not (eq window (selected-window))) 8768 ((and window
8768 (or (not (numberp mouse-autoselect-window)) 8769 (or (not (numberp mouse-autoselect-window))
8769 (and (>= mouse-autoselect-window 0) 8770 (and (>= mouse-autoselect-window 0)
8770 ;; If `mouse-autoselect-window' is non-negative, 8771 ;; If `mouse-autoselect-window' is non-negative,
8771 ;; select window if it's the same as before. 8772 ;; select window if it's the same as before.
8772 (eq window mouse-autoselect-window-window)) 8773 (eq window mouse-autoselect-window-window))
8773 ;; Otherwise select window iff the mouse is at the same 8774 ;; Otherwise select window iff the mouse is at the same
8774 ;; position as before. Observe that the first test 8775 ;; position as before. Observe that the first test
8775 ;; after starting autoselection usually fails since the 8776 ;; after starting autoselection usually fails since the
8776 ;; value of `mouse-autoselect-window-position' recorded 8777 ;; value of `mouse-autoselect-window-position' recorded
8777 ;; there is the position where the mouse has entered the 8778 ;; there is the position where the mouse has entered the
8778 ;; new window and not necessarily where the mouse has 8779 ;; new window and not necessarily where the mouse has
8779 ;; stopped moving. 8780 ;; stopped moving.
8780 (equal mouse-position mouse-autoselect-window-position)) 8781 (equal mouse-position mouse-autoselect-window-position))
8781 ;; The minibuffer is a candidate window if it's active. 8782 ;; The minibuffer is a candidate window if it's active.
8782 (or (not (window-minibuffer-p window)) 8783 (or (not (window-minibuffer-p window))
8783 (eq window (active-minibuffer-window)))) 8784 (eq window (active-minibuffer-window))))
8784 ;; Mouse position has stabilized in non-selected window: Cancel 8785 ;; Mouse position has stabilized in non-selected window: Cancel
8785 ;; delayed autoselection and try to select that window. 8786 ;; delayed autoselection and try to select that window.
8786 (mouse-autoselect-window-cancel t) 8787 (mouse-autoselect-window-cancel t)
8787 ;; Select window where mouse appears unless the selected window is the 8788 ;; Use `unread-command-events' in order to execute pre- and
8788 ;; minibuffer. Use `unread-command-events' in order to execute pre- 8789 ;; post-command hooks and trigger idle timers. To avoid delaying
8789 ;; and post-command hooks and trigger idle timers. To avoid delaying 8790 ;; autoselection again, set `mouse-autoselect-window-state'."
8790 ;; autoselection again, set `mouse-autoselect-window-state'." 8791 (setq mouse-autoselect-window-state 'select)
8791 (unless (window-minibuffer-p) 8792 (setq unread-command-events
8792 (setq mouse-autoselect-window-state 'select) 8793 (cons (list 'select-window (list window))
8793 (setq unread-command-events 8794 unread-command-events)))
8794 (cons (list 'select-window (list window)) 8795 ((or (not (numberp mouse-autoselect-window))
8795 unread-command-events)))) 8796 (equal mouse-position mouse-autoselect-window-position))
8796 ((or (and window (eq window (selected-window))) 8797 ;; Mouse position has stabilized at
8797 (not (numberp mouse-autoselect-window)) 8798 ;; `mouse-autoselect-window-position': Cancel delayed
8798 (equal mouse-position mouse-autoselect-window-position)) 8799 ;; autoselection.
8799 ;; Mouse position has either stabilized in the selected window or at 8800 (mouse-autoselect-window-cancel t))
8800 ;; `mouse-autoselect-window-position': Cancel delayed autoselection. 8801 (window
8801 (mouse-autoselect-window-cancel t)) 8802 ;; Mouse position has not stabilized yet, resume delayed
8802 (t 8803 ;; autoselection.
8803 ;; Mouse position has not stabilized yet, resume delayed 8804 (mouse-autoselect-window-start mouse-position window)))))
8804 ;; autoselection.
8805 (mouse-autoselect-window-start mouse-position window))))))
8806 8805
8807(defun handle-select-window (event) 8806(defun handle-select-window (event)
8808 "Handle select-window events." 8807 "Handle select-window events."
8809 (interactive "^e") 8808 (interactive "^e")
8810 (let ((window (posn-window (event-start event)))) 8809 (let* ((window (posn-window (event-start event)))
8810 (frame (and (window-live-p window) (window-frame window)))
8811 (old-frame (selected-frame)))
8811 (unless (or (not (window-live-p window)) 8812 (unless (or (not (window-live-p window))
8812 ;; Don't switch if we're currently in the minibuffer.
8813 ;; This tries to work around problems where the
8814 ;; minibuffer gets unselected unexpectedly, and where
8815 ;; you then have to move your mouse all the way down to
8816 ;; the minibuffer to select it.
8817 (window-minibuffer-p)
8818 ;; Don't switch to minibuffer window unless it's active.
8819 (and (window-minibuffer-p window)
8820 (not (minibuffer-window-active-p window)))
8821 ;; Don't switch when autoselection shall be delayed. 8813 ;; Don't switch when autoselection shall be delayed.
8822 (and (numberp mouse-autoselect-window) 8814 (and (numberp mouse-autoselect-window)
8823 (not (eq mouse-autoselect-window-state 'select)) 8815 (not (eq mouse-autoselect-window-state 'select))
@@ -8830,15 +8822,40 @@ is active. This function is run by `mouse-autoselect-window-timer'."
8830 (mouse-autoselect-window-start position window) 8822 (mouse-autoselect-window-start position window)
8831 ;; Executing a command cancels delayed autoselection. 8823 ;; Executing a command cancels delayed autoselection.
8832 (add-hook 8824 (add-hook
8833 'pre-command-hook 'mouse-autoselect-window-cancel)))) 8825 'pre-command-hook 'mouse-autoselect-window-cancel)))
8834 (when mouse-autoselect-window 8826 ;; Don't switch to a `no-accept-focus' frame unless it's
8835 ;; Reset state of delayed autoselection. 8827 ;; already selected.
8836 (setq mouse-autoselect-window-state nil) 8828 (and (not (eq frame (selected-frame)))
8837 ;; Run `mouse-leave-buffer-hook' when autoselecting window. 8829 (frame-parameter frame 'no-accept-focus))
8838 (run-hooks 'mouse-leave-buffer-hook)) 8830 ;; Don't switch to minibuffer window unless it's active.
8831 (and (window-minibuffer-p window)
8832 (not (minibuffer-window-active-p window))))
8833 ;; Reset state of delayed autoselection.
8834 (setq mouse-autoselect-window-state nil)
8835 ;; Run `mouse-leave-buffer-hook' when autoselecting window.
8836 (run-hooks 'mouse-leave-buffer-hook)
8839 ;; Clear echo area. 8837 ;; Clear echo area.
8840 (message nil) 8838 (message nil)
8841 (select-window window)))) 8839 ;; Select the window before giving the frame focus since otherwise
8840 ;; we might get two windows with an active cursor.
8841 (select-window window)
8842 (cond
8843 ((or (not (memq (window-system frame) '(x w32 ns)))
8844 (not focus-follows-mouse)
8845 ;; Focus FRAME if it's either a child frame or an ancestor
8846 ;; of the frame switched from.
8847 (and (not (frame-parameter frame 'parent-frame))
8848 (not (frame-ancestor-p frame old-frame)))))
8849 ((eq focus-follows-mouse 'auto-raise)
8850 ;; Focus and auto-raise frame.
8851 (x-focus-frame frame)
8852 ;; This doesn't seem to work when we move from a normal frame
8853 ;; right into the child frame of another frame - we should raise
8854 ;; that child frame's ancestor frame first ...
8855 (raise-frame frame))
8856 (t
8857 ;; Just focus frame.
8858 (x-focus-frame frame))))))
8842 8859
8843(defun truncated-partial-width-window-p (&optional window) 8860(defun truncated-partial-width-window-p (&optional window)
8844 "Return non-nil if lines in WINDOW are specifically truncated due to its width. 8861 "Return non-nil if lines in WINDOW are specifically truncated due to its width.