aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Rudalics2017-04-12 10:38:25 +0200
committerMartin Rudalics2017-04-12 10:38:25 +0200
commit3fdd3bb56c006a2a24761b8fcea0cbd9b0cba422 (patch)
treea0b8f5e431ba812b4fe69261a8515e973a3e7ed3
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.
-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
-rw-r--r--src/frame.c402
-rw-r--r--src/frame.h86
-rw-r--r--src/gtkutil.c135
-rw-r--r--src/gtkutil.h7
-rw-r--r--src/nsfns.m13
-rw-r--r--src/nsterm.m2
-rw-r--r--src/w32fns.c659
-rw-r--r--src/w32font.c19
-rw-r--r--src/w32term.c200
-rw-r--r--src/w32term.h1
-rw-r--r--src/xdisp.c6
-rw-r--r--src/xfns.c605
-rw-r--r--src/xmenu.c14
-rw-r--r--src/xterm.c389
-rw-r--r--src/xterm.h8
20 files changed, 2543 insertions, 454 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.
diff --git a/src/frame.c b/src/frame.c
index 5f57d4a0c24..ed6c527d4d8 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -324,11 +324,51 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
324 return make_number (0); 324 return make_number (0);
325} 325}
326 326
327/**
328 * frame_windows_min_size:
329 *
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum height (width)
332 * in pixels.
333 *
334 * This value is calculated by the function `frame-windows-min-size' in
335 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
336 * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
337 * value to be returned. In that latter case IGNORE is ignored.
338 *
339 * If `frame-windows-min-size' is called, it will make sure that the
340 * return value accomodates all windows of FRAME respecting the values
341 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
342 * With IGNORE non-nil the values of these variables are ignored.
343 *
344 * In either case never return a value less than 1.
345 */
327static int 346static int
328frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, 347frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
329 Lisp_Object ignore, Lisp_Object pixelwise) 348 Lisp_Object ignore, Lisp_Object pixelwise)
330{ 349{
331 return XINT (call4 (Qframe_windows_min_size, frame, horizontal, 350 struct frame *f = XFRAME (frame);
351 Lisp_Object par_size;
352
353 if ((!NILP (horizontal)
354 && NUMBERP (par_size = get_frame_param (f, Qmin_width)))
355 || (NILP (horizontal)
356 && NUMBERP (par_size = get_frame_param (f, Qmin_height))))
357 {
358 int min_size = XINT (par_size);
359
360 /* Don't allow phantom frames. */
361 if (min_size < 1)
362 min_size = 1;
363
364 return (NILP (pixelwise)
365 ? min_size
366 : min_size * (NILP (horizontal)
367 ? FRAME_LINE_HEIGHT (f)
368 : FRAME_COLUMN_WIDTH (f)));
369 }
370 else
371 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
332 ignore, pixelwise)); 372 ignore, pixelwise));
333} 373}
334 374
@@ -643,6 +683,16 @@ make_frame (bool mini_p)
643 f->vertical_scroll_bar_type = vertical_scroll_bar_none; 683 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
644 f->horizontal_scroll_bars = false; 684 f->horizontal_scroll_bars = false;
645 f->want_fullscreen = FULLSCREEN_NONE; 685 f->want_fullscreen = FULLSCREEN_NONE;
686#if ! defined (HAVE_NS)
687 f->undecorated = false;
688#ifndef HAVE_NTGUI
689 f->override_redirect = false;
690#endif
691 f->skip_taskbar = false;
692 f->no_focus_on_map = false;
693 f->no_accept_focus = false;
694 f->z_group = z_group_none;
695#endif
646#if ! defined (USE_GTK) && ! defined (HAVE_NS) 696#if ! defined (USE_GTK) && ! defined (HAVE_NS)
647 f->last_tool_bar_item = -1; 697 f->last_tool_bar_item = -1;
648#endif 698#endif
@@ -1215,7 +1265,10 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1215 (select-window (frame-root-window (new-frame))) doesn't end up 1265 (select-window (frame-root-window (new-frame))) doesn't end up
1216 with your typing being interpreted in the new frame instead of 1266 with your typing being interpreted in the new frame instead of
1217 the one you're actually typing in. */ 1267 the one you're actually typing in. */
1218 internal_last_event_frame = Qnil; 1268#ifdef HAVE_WINDOW_SYSTEM
1269 if (!frame_ancestor_p (f, sf))
1270#endif
1271 internal_last_event_frame = Qnil;
1219 1272
1220 return frame; 1273 return frame;
1221} 1274}
@@ -1283,6 +1336,72 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
1283 return frames; 1336 return frames;
1284} 1337}
1285 1338
1339DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1340 0, 1, 0,
1341 doc: /* Return the parent frame of FRAME.
1342The parent frame of FRAME is the Emacs frame whose window-system window
1343is the parent window of FRAME's window-system window. When such a frame
1344exists, FRAME is considered a child frame of that frame.
1345
1346Return nil if FRAME has no parent frame. This means that FRAME's
1347window-system window is either a "top-level" window (a window whose
1348parent window is the window-system's root window) or an embedded window
1349\(a window whose parent window is owned by some other application). */)
1350 (Lisp_Object frame)
1351{
1352 struct frame *f = decode_live_frame (frame);
1353 struct frame *p = FRAME_PARENT_FRAME (f);
1354 Lisp_Object parent;
1355
1356 /* Can't return f->parent_frame directly since it might not be defined
1357 for this platform. */
1358 if (p)
1359 {
1360 XSETFRAME (parent, p);
1361
1362 return parent;
1363 }
1364 else
1365 return Qnil;
1366}
1367
1368#ifdef HAVE_WINDOW_SYSTEM
1369bool
1370frame_ancestor_p (struct frame *af, struct frame *df)
1371{
1372 struct frame *pf = FRAME_PARENT_FRAME (df);
1373
1374 while (pf)
1375 {
1376 if (pf == af)
1377 return true;
1378 else
1379 pf = FRAME_PARENT_FRAME (pf);
1380 }
1381
1382 return false;
1383}
1384#endif
1385
1386DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1387 2, 2, 0,
1388 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1389ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1390parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1391ANCESTOR and DESCENDANT must be live frames and default to the selected
1392frame. */)
1393 (Lisp_Object ancestor, Lisp_Object descendant)
1394{
1395#ifdef HAVE_WINDOW_SYSTEM
1396 struct frame *af = decode_live_frame (ancestor);
1397 struct frame *df = decode_live_frame (descendant);
1398
1399 return frame_ancestor_p (af, df) ? Qt : Qnil;
1400#else
1401 return Qnil;
1402#endif
1403 }
1404
1286/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the 1405/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1287 same tty (for tty frames) or among frames which uses FRAME's keyboard. 1406 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1288 If MINIBUF is nil, do not consider minibuffer-only candidate. 1407 If MINIBUF is nil, do not consider minibuffer-only candidate.
@@ -1303,7 +1422,9 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1303 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f) 1422 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1304 && FRAME_TTY (c) == FRAME_TTY (f))) 1423 && FRAME_TTY (c) == FRAME_TTY (f)))
1305 { 1424 {
1306 if (NILP (minibuf)) 1425 if (!NILP (get_frame_param (c, Qno_other_frame)))
1426 return Qnil;
1427 else if (NILP (minibuf))
1307 { 1428 {
1308 if (!FRAME_MINIBUF_ONLY_P (c)) 1429 if (!FRAME_MINIBUF_ONLY_P (c))
1309 return candidate; 1430 return candidate;
@@ -1441,35 +1562,65 @@ DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1441 return frame; 1562 return frame;
1442} 1563}
1443 1564
1444/* Return 1 if it is ok to delete frame F; 1565/**
1445 0 if all frames aside from F are invisible. 1566 * other_frames:
1446 (Exception: if F is the terminal frame, and we are using X, return 1.) */ 1567 *
1568 * Return true if there exists at least one visible or iconified frame
1569 * but F. Return false otherwise.
1570 *
1571 * Always return false when all remaining frames are either tooltip or
1572 * child frames or frames with a non-nil `delete-before' parameter. If
1573 * INVISIBLE is false, also return false when the minibuffer window of
1574 * all remaining frames is on F.
1575
1576 * If F is the terminal frame and we are using X, return true if at
1577 * least one X frame exists. */
1578static bool
1579other_frames (struct frame *f, bool invisible)
1580{
1581 Lisp_Object frames, frame, frame1;
1582 struct frame *f1;
1583 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1447 1584
1448static int 1585 XSETFRAME (frame, f);
1449other_visible_frames (struct frame *f) 1586 if (WINDOWP (minibuffer_window)
1450{ 1587 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1451 Lisp_Object frames, this; 1588 minibuffer_window = Qnil;
1452 1589
1453 FOR_EACH_FRAME (frames, this) 1590 FOR_EACH_FRAME (frames, frame1)
1454 { 1591 {
1455 if (f == XFRAME (this)) 1592 f1 = XFRAME (frame1);
1456 continue; 1593 if (f != f1)
1457 1594 {
1458 /* Verify that we can still talk to the frame's X window, 1595 /* Verify that we can still talk to the frame's X window, and
1459 and note any recent change in visibility. */ 1596 note any recent change in visibility. */
1460#ifdef HAVE_X_WINDOWS 1597#ifdef HAVE_X_WINDOWS
1461 if (FRAME_WINDOW_P (XFRAME (this))) 1598 if (FRAME_WINDOW_P (f1))
1462 x_sync (XFRAME (this)); 1599 x_sync (f1);
1463#endif 1600#endif
1464 1601 if (NILP (Fframe_parameter (frame1, Qtooltip))
1465 if (FRAME_VISIBLE_P (XFRAME (this)) 1602 /* Tooltips and child frames don't count. */
1466 || FRAME_ICONIFIED_P (XFRAME (this)) 1603 && !FRAME_PARENT_FRAME (f1)
1467 /* Allow deleting the terminal frame when at least one X 1604 /* Frames with a non-nil `delete-before' parameter don't
1468 frame exists. */ 1605 count - either they depend on us or they depend on a
1469 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f))) 1606 frame that we will have to find right here. */
1470 return 1; 1607 && NILP (get_frame_param (f1, Qdelete_before))
1608 /* Frames whose minibuffer window is on F don't count
1609 unless INVISIBLE is set - in that case F is either made
1610 invisible and may be autoraised from such a frame or
1611 the FORCE argument of delete_frame was non-nil. */
1612 && (invisible || NILP (minibuffer_window)
1613 || !EQ (FRAME_MINIBUF_WINDOW (f1), minibuffer_window))
1614 /* At least one visible/iconified frame must remain. */
1615 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1616 /* Allow deleting the terminal frame when at least one
1617 X frame exists. */
1618 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))
1619 return true;
1620 }
1471 } 1621 }
1472 return 0; 1622
1623 return false;
1473} 1624}
1474 1625
1475/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer 1626/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
@@ -1518,53 +1669,65 @@ check_minibuf_window (Lisp_Object frame, int select)
1518} 1669}
1519 1670
1520 1671
1521/* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME 1672/**
1522 unconditionally. x_connection_closed and delete_terminal use 1673 * delete_frame:
1523 this. Any other value of FORCE implements the semantics 1674 *
1524 described for Fdelete_frame. */ 1675 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1676 * unconditionally. x_connection_closed and delete_terminal use this.
1677 * Any other value of FORCE implements the semantics described for
1678 * Fdelete_frame. */
1525Lisp_Object 1679Lisp_Object
1526delete_frame (Lisp_Object frame, Lisp_Object force) 1680delete_frame (Lisp_Object frame, Lisp_Object force)
1527{ 1681{
1528 struct frame *f = decode_any_frame (frame); 1682 struct frame *f = decode_any_frame (frame);
1529 struct frame *sf; 1683 struct frame *sf;
1530 struct kboard *kb; 1684 struct kboard *kb;
1531 1685 Lisp_Object frames, frame1;
1532 int minibuffer_selected, is_tooltip_frame; 1686 int minibuffer_selected, is_tooltip_frame;
1687 bool nochild = !FRAME_PARENT_FRAME (f);
1533 1688
1534 if (! FRAME_LIVE_P (f)) 1689 if (!FRAME_LIVE_P (f))
1535 return Qnil; 1690 return Qnil;
1536 1691 else if (!EQ (force, Qnoelisp) && !other_frames (f, !NILP (force)))
1537 if (NILP (force) && !other_visible_frames (f)) 1692 {
1538 error ("Attempt to delete the sole visible or iconified frame"); 1693 if (NILP (force))
1539 1694 error ("Attempt to delete the sole visible or iconified frame");
1540 /* x_connection_closed must have set FORCE to `noelisp' in order 1695 else
1541 to delete the last frame, if it is gone. */ 1696 error ("Attempt to delete the only frame");
1542 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp)) 1697 }
1543 error ("Attempt to delete the only frame");
1544 1698
1545 XSETFRAME (frame, f); 1699 XSETFRAME (frame, f);
1546 1700
1701 /* Softly delete all frames with this frame as their parent frame or
1702 as their `delete-before' frame parameter value. */
1703 FOR_EACH_FRAME (frames, frame1)
1704 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1705 /* Process `delete-before' parameter iff FRAME is not a child
1706 frame. This avoids that we enter an infinite chain of mixed
1707 dependencies. */
1708 || (nochild
1709 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1710 delete_frame (frame1, Qnil);
1711
1547 /* Does this frame have a minibuffer, and is it the surrogate 1712 /* Does this frame have a minibuffer, and is it the surrogate
1548 minibuffer for any other frame? */ 1713 minibuffer for any other frame? */
1549 if (FRAME_HAS_MINIBUF_P (f)) 1714 if (FRAME_HAS_MINIBUF_P (f))
1550 { 1715 {
1551 Lisp_Object frames, this; 1716 FOR_EACH_FRAME (frames, frame1)
1552
1553 FOR_EACH_FRAME (frames, this)
1554 { 1717 {
1555 Lisp_Object fminiw; 1718 Lisp_Object fminiw;
1556 1719
1557 if (EQ (this, frame)) 1720 if (EQ (frame1, frame))
1558 continue; 1721 continue;
1559 1722
1560 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this)); 1723 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1561 1724
1562 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw)))) 1725 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1563 { 1726 {
1564 /* If we MUST delete this frame, delete the other first. 1727 /* If we MUST delete this frame, delete the other first.
1565 But do this only if FORCE equals `noelisp'. */ 1728 But do this only if FORCE equals `noelisp'. */
1566 if (EQ (force, Qnoelisp)) 1729 if (EQ (force, Qnoelisp))
1567 delete_frame (this, Qnoelisp); 1730 delete_frame (frame1, Qnoelisp);
1568 else 1731 else
1569 error ("Attempt to delete a surrogate minibuffer frame"); 1732 error ("Attempt to delete a surrogate minibuffer frame");
1570 } 1733 }
@@ -1593,20 +1756,26 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1593 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame); 1756 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1594 } 1757 }
1595 1758
1596 /* The hook may sometimes (indirectly) cause the frame to be deleted. */ 1759 /* delete_frame_functions may have deleted any frame, including this
1597 if (! FRAME_LIVE_P (f)) 1760 one. */
1761 if (!FRAME_LIVE_P (f))
1598 return Qnil; 1762 return Qnil;
1763 else if (!EQ (force, Qnoelisp) && !other_frames (f, !NILP (force)))
1764 {
1765 if (NILP (force))
1766 error ("Attempt to delete the sole visible or iconified frame");
1767 else
1768 error ("Attempt to delete the only frame");
1769 }
1599 1770
1600 /* At this point, we are committed to deleting the frame. 1771 /* At this point, we are committed to deleting the frame.
1601 There is no more chance for errors to prevent it. */ 1772 There is no more chance for errors to prevent it. */
1602
1603 minibuffer_selected = EQ (minibuf_window, selected_window); 1773 minibuffer_selected = EQ (minibuf_window, selected_window);
1604 sf = SELECTED_FRAME (); 1774 sf = SELECTED_FRAME ();
1605 /* Don't let the frame remain selected. */ 1775 /* Don't let the frame remain selected. */
1606 if (f == sf) 1776 if (f == sf)
1607 { 1777 {
1608 Lisp_Object tail; 1778 Lisp_Object tail;
1609 Lisp_Object frame1 = Qnil;
1610 1779
1611 /* Look for another visible frame on the same terminal. 1780 /* Look for another visible frame on the same terminal.
1612 Do not call next_frame here because it may loop forever. 1781 Do not call next_frame here because it may loop forever.
@@ -1746,16 +1915,15 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1746 another one. */ 1915 another one. */
1747 if (f == last_nonminibuf_frame) 1916 if (f == last_nonminibuf_frame)
1748 { 1917 {
1749 Lisp_Object frames, this;
1750
1751 last_nonminibuf_frame = 0; 1918 last_nonminibuf_frame = 0;
1752 1919
1753 FOR_EACH_FRAME (frames, this) 1920 FOR_EACH_FRAME (frames, frame1)
1754 { 1921 {
1755 f = XFRAME (this); 1922 struct frame *f1 = XFRAME (frame1);
1756 if (!FRAME_MINIBUF_ONLY_P (f)) 1923
1924 if (!FRAME_MINIBUF_ONLY_P (f1))
1757 { 1925 {
1758 last_nonminibuf_frame = f; 1926 last_nonminibuf_frame = f1;
1759 break; 1927 break;
1760 } 1928 }
1761 } 1929 }
@@ -1765,13 +1933,12 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1765 single-kboard state if we're in it for this kboard. */ 1933 single-kboard state if we're in it for this kboard. */
1766 if (kb != NULL) 1934 if (kb != NULL)
1767 { 1935 {
1768 Lisp_Object frames, this;
1769 /* Some frame we found on the same kboard, or nil if there are none. */ 1936 /* Some frame we found on the same kboard, or nil if there are none. */
1770 Lisp_Object frame_on_same_kboard = Qnil; 1937 Lisp_Object frame_on_same_kboard = Qnil;
1771 1938
1772 FOR_EACH_FRAME (frames, this) 1939 FOR_EACH_FRAME (frames, frame1)
1773 if (kb == FRAME_KBOARD (XFRAME (this))) 1940 if (kb == FRAME_KBOARD (XFRAME (frame1)))
1774 frame_on_same_kboard = this; 1941 frame_on_same_kboard = frame1;
1775 1942
1776 if (NILP (frame_on_same_kboard)) 1943 if (NILP (frame_on_same_kboard))
1777 not_single_kboard_state (kb); 1944 not_single_kboard_state (kb);
@@ -1783,29 +1950,27 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1783 frames with other windows. */ 1950 frames with other windows. */
1784 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame))) 1951 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1785 { 1952 {
1786 Lisp_Object frames, this;
1787
1788 /* The last frame we saw with a minibuffer, minibuffer-only or not. */ 1953 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1789 Lisp_Object frame_with_minibuf = Qnil; 1954 Lisp_Object frame_with_minibuf = Qnil;
1790 /* Some frame we found on the same kboard, or nil if there are none. */ 1955 /* Some frame we found on the same kboard, or nil if there are none. */
1791 Lisp_Object frame_on_same_kboard = Qnil; 1956 Lisp_Object frame_on_same_kboard = Qnil;
1792 1957
1793 FOR_EACH_FRAME (frames, this) 1958 FOR_EACH_FRAME (frames, frame1)
1794 { 1959 {
1795 struct frame *f1 = XFRAME (this); 1960 struct frame *f1 = XFRAME (frame1);
1796 1961
1797 /* Consider only frames on the same kboard 1962 /* Consider only frames on the same kboard
1798 and only those with minibuffers. */ 1963 and only those with minibuffers. */
1799 if (kb == FRAME_KBOARD (f1) 1964 if (kb == FRAME_KBOARD (f1)
1800 && FRAME_HAS_MINIBUF_P (f1)) 1965 && FRAME_HAS_MINIBUF_P (f1))
1801 { 1966 {
1802 frame_with_minibuf = this; 1967 frame_with_minibuf = frame1;
1803 if (FRAME_MINIBUF_ONLY_P (f1)) 1968 if (FRAME_MINIBUF_ONLY_P (f1))
1804 break; 1969 break;
1805 } 1970 }
1806 1971
1807 if (kb == FRAME_KBOARD (f1)) 1972 if (kb == FRAME_KBOARD (f1))
1808 frame_on_same_kboard = this; 1973 frame_on_same_kboard = frame1;
1809 } 1974 }
1810 1975
1811 if (!NILP (frame_on_same_kboard)) 1976 if (!NILP (frame_on_same_kboard))
@@ -2118,7 +2283,7 @@ displayed in the terminal. */)
2118{ 2283{
2119 struct frame *f = decode_live_frame (frame); 2284 struct frame *f = decode_live_frame (frame);
2120 2285
2121 if (NILP (force) && !other_visible_frames (f)) 2286 if (NILP (force) && !other_frames (f, true))
2122 error ("Attempt to make invisible the sole visible or iconified frame"); 2287 error ("Attempt to make invisible the sole visible or iconified frame");
2123 2288
2124 /* Don't allow minibuf_window to remain on an invisible frame. */ 2289 /* Don't allow minibuf_window to remain on an invisible frame. */
@@ -2453,9 +2618,39 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2453 } 2618 }
2454 } 2619 }
2455 2620
2621 /* Check these parameters for circular dependeny. This does not check
2622 for interdependencies between these properties. Hence you can
2623 still create circular dependencies with different properties, for
2624 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2625 frame of Fn and thus cannot be deleted before Fn and a second chain
2626 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2627 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2628 {
2629 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2630
2631 if (!EQ (oldval, val) && !NILP (val))
2632 {
2633 Lisp_Object frame;
2634 Lisp_Object frame1 = val;
2635
2636 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2637 error ("Invalid `%s' frame parameter",
2638 SSDATA (SYMBOL_NAME (prop)));
2639
2640 XSETFRAME (frame, f);
2641
2642 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2643 if (EQ (frame1, frame))
2644 error ("Circular specification of `%s' frame parameter",
2645 SSDATA (SYMBOL_NAME (prop)));
2646 else
2647 frame1 = get_frame_param (XFRAME (frame1), prop);
2648 }
2649 }
2650
2456 /* The buffer-list parameters are stored in a special place and not 2651 /* The buffer-list parameters are stored in a special place and not
2457 in the alist. All buffers must be live. */ 2652 in the alist. All buffers must be live. */
2458 if (EQ (prop, Qbuffer_list)) 2653 else if (EQ (prop, Qbuffer_list))
2459 { 2654 {
2460 Lisp_Object list = Qnil; 2655 Lisp_Object list = Qnil;
2461 for (; CONSP (val); val = XCDR (val)) 2656 for (; CONSP (val); val = XCDR (val))
@@ -2464,7 +2659,7 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2464 fset_buffer_list (f, Fnreverse (list)); 2659 fset_buffer_list (f, Fnreverse (list));
2465 return; 2660 return;
2466 } 2661 }
2467 if (EQ (prop, Qburied_buffer_list)) 2662 else if (EQ (prop, Qburied_buffer_list))
2468 { 2663 {
2469 Lisp_Object list = Qnil; 2664 Lisp_Object list = Qnil;
2470 for (; CONSP (val); val = XCDR (val)) 2665 for (; CONSP (val); val = XCDR (val))
@@ -3095,6 +3290,13 @@ static const struct frame_parm_table frame_parms[] =
3095 {"sticky", SYMBOL_INDEX (Qsticky)}, 3290 {"sticky", SYMBOL_INDEX (Qsticky)},
3096 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, 3291 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3097 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)}, 3292 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3293 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3294 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3295 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3296 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3297 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3298 {"z-group", SYMBOL_INDEX (Qz_group)},
3299 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3098}; 3300};
3099 3301
3100#ifdef HAVE_WINDOW_SYSTEM 3302#ifdef HAVE_WINDOW_SYSTEM
@@ -4882,6 +5084,14 @@ syms_of_frame (void)
4882 DEFSYM (Qheight, "height"); 5084 DEFSYM (Qheight, "height");
4883 DEFSYM (Qicon, "icon"); 5085 DEFSYM (Qicon, "icon");
4884 DEFSYM (Qminibuffer, "minibuffer"); 5086 DEFSYM (Qminibuffer, "minibuffer");
5087 DEFSYM (Qundecorated, "undecorated");
5088 DEFSYM (Qparent_frame, "parent-frame");
5089 DEFSYM (Qskip_taskbar, "skip-taskbar");
5090 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5091 DEFSYM (Qno_accept_focus, "no-accept-focus");
5092 DEFSYM (Qz_group, "z-group");
5093 DEFSYM (Qoverride_redirect, "override-redirect");
5094 DEFSYM (Qdelete_before, "delete-before");
4885 DEFSYM (Qmodeline, "modeline"); 5095 DEFSYM (Qmodeline, "modeline");
4886 DEFSYM (Qonly, "only"); 5096 DEFSYM (Qonly, "only");
4887 DEFSYM (Qnone, "none"); 5097 DEFSYM (Qnone, "none");
@@ -4978,6 +5188,7 @@ syms_of_frame (void)
4978 DEFSYM (Qauto_raise, "auto-raise"); 5188 DEFSYM (Qauto_raise, "auto-raise");
4979 DEFSYM (Qborder_color, "border-color"); 5189 DEFSYM (Qborder_color, "border-color");
4980 DEFSYM (Qborder_width, "border-width"); 5190 DEFSYM (Qborder_width, "border-width");
5191 DEFSYM (Qouter_border_width, "outer-border-width");
4981 DEFSYM (Qbottom_divider_width, "bottom-divider-width"); 5192 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
4982 DEFSYM (Qcursor_color, "cursor-color"); 5193 DEFSYM (Qcursor_color, "cursor-color");
4983 DEFSYM (Qcursor_type, "cursor-type"); 5194 DEFSYM (Qcursor_type, "cursor-type");
@@ -5011,6 +5222,12 @@ syms_of_frame (void)
5011 DEFSYM (Qvisibility, "visibility"); 5222 DEFSYM (Qvisibility, "visibility");
5012 DEFSYM (Qwait_for_wm, "wait-for-wm"); 5223 DEFSYM (Qwait_for_wm, "wait-for-wm");
5013 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering"); 5224 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5225 DEFSYM (Qno_other_frame, "no-other-frame");
5226 DEFSYM (Qbelow, "below");
5227 DEFSYM (Qabove_suspended, "above-suspended");
5228 DEFSYM (Qmin_width, "min-width");
5229 DEFSYM (Qmin_height, "min-height");
5230 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5014 5231
5015 { 5232 {
5016 int i; 5233 int i;
@@ -5179,12 +5396,51 @@ displayed.
5179 5396
5180This variable is local to the current terminal and cannot be buffer-local. */); 5397This variable is local to the current terminal and cannot be buffer-local. */);
5181 5398
5182 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse, 5399 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5183 doc: /* Non-nil if window system changes focus when you move the mouse. 5400 doc: /* Non-nil if window system changes focus when you move the mouse.
5184You should set this variable to tell Emacs how your window manager 5401You should set this variable to tell Emacs how your window manager
5185handles focus, since there is no way in general for Emacs to find out 5402handles focus, since there is no way in general for Emacs to find out
5186automatically. See also `mouse-autoselect-window'. */); 5403automatically.
5187 focus_follows_mouse = 0; 5404
5405There are three meaningful values:
5406
5407- The default nil should be used when your window manager follows a
5408 "click-to-focus" policy where you have to click the mouse inside of a
5409 frame in order for that frame to get focus.
5410
5411- The value t should be used when your window manager has the focus
5412 automatically follow the position of the mouse pointer but a window
5413 that gains focus is not raised automatically.
5414
5415- The value `auto-raise' should be used when your window manager has the
5416 focus automatically follow the position of the mouse pointer and a
5417 window that gains focus is raised automatically.
5418
5419If this option is non-nil, Emacs moves the mouse pointer to the frame
5420selected by `select-frame-set-input-focus'. This function is used by a
5421number of commands like, for example, `other-frame' and `pop-to-buffer'.
5422If this option is nil and your focus follows mouse window manager does
5423not autonomously move the mouse pointer to the newly selected frame, the
5424previously selected window manager window might get reselected instead
5425immediately.
5426
5427The distinction between the values t and `auto-raise' is not needed for
5428"normal" frames because the window manager takes care of raising them.
5429Setting this to `auto-raise' will, however, override the standard
5430behavior of a window manager that does not automatically raise the frame
5431that gets focus. Setting this to `auto-raise' is also necessary to
5432automatically raise child frames which are usually left alone by the
5433window manager.
5434
5435Note that this option does not distinguish "sloppy" focus (where the
5436frame that previously had focus retains focus as long as the mouse
5437pointer does not move into another window manager window) from "strict"
5438focus (where a frame immediately loses focus when it's left by the mouse
5439pointer).
5440
5441In order to extend a "focus follows mouse" policy to individual Emacs
5442windows, customize the variable `mouse-autoselect-window'. */);
5443 focus_follows_mouse = Qnil;
5188 5444
5189 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise, 5445 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5190 doc: /* Non-nil means resize frames pixelwise. 5446 doc: /* Non-nil means resize frames pixelwise.
@@ -5286,6 +5542,8 @@ Gtk+ tooltips are not used) and on Windows. */);
5286 defsubr (&Sselect_frame); 5542 defsubr (&Sselect_frame);
5287 defsubr (&Sselected_frame); 5543 defsubr (&Sselected_frame);
5288 defsubr (&Sframe_list); 5544 defsubr (&Sframe_list);
5545 defsubr (&Sframe_parent);
5546 defsubr (&Sframe_ancestor_p);
5289 defsubr (&Snext_frame); 5547 defsubr (&Snext_frame);
5290 defsubr (&Sprevious_frame); 5548 defsubr (&Sprevious_frame);
5291 defsubr (&Slast_nonminibuf_frame); 5549 defsubr (&Slast_nonminibuf_frame);
diff --git a/src/frame.h b/src/frame.h
index 5f18901a17c..376df528466 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -45,6 +45,13 @@ enum fullscreen_type
45#endif 45#endif
46}; 46};
47 47
48enum z_group
49{
50 z_group_none,
51 z_group_above,
52 z_group_below,
53 z_group_above_suspended,
54};
48#endif /* HAVE_WINDOW_SYSTEM */ 55#endif /* HAVE_WINDOW_SYSTEM */
49 56
50/* The structure representing a frame. */ 57/* The structure representing a frame. */
@@ -68,6 +75,11 @@ struct frame
68 Usually it is nil. */ 75 Usually it is nil. */
69 Lisp_Object title; 76 Lisp_Object title;
70 77
78#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
79 /* This frame's parent frame, if it has one. */
80 Lisp_Object parent_frame;
81#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
82
71 /* The frame which should receive keystrokes that occur in this 83 /* The frame which should receive keystrokes that occur in this
72 frame, or nil if they should go to the frame itself. This is 84 frame, or nil if they should go to the frame itself. This is
73 usually nil, but if the frame is minibufferless, we can use this 85 usually nil, but if the frame is minibufferless, we can use this
@@ -320,6 +332,30 @@ struct frame
320 bool_bf horizontal_scroll_bars : 1; 332 bool_bf horizontal_scroll_bars : 1;
321#endif /* HAVE_WINDOW_SYSTEM */ 333#endif /* HAVE_WINDOW_SYSTEM */
322 334
335#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
336 /* True if this is an undecorated frame. */
337 bool_bf undecorated : 1;
338
339#ifndef HAVE_NTGUI
340 /* True if this is an override_redirect frame. */
341 bool_bf override_redirect : 1;
342#endif
343
344 /* Nonzero if this frame's icon should not appear on its display's taskbar. */
345 bool_bf skip_taskbar : 1;
346
347 /* Nonzero if this frame's window F's X window does not want to
348 receive input focus when it is mapped. */
349 bool_bf no_focus_on_map : 1;
350
351 /* Nonzero if this frame's window does not want to receive input focus
352 via mouse clicks or by moving the mouse into it. */
353 bool_bf no_accept_focus : 1;
354
355 /* The z-group this frame's window belongs to. */
356 ENUM_BF (z_group) z_group : 2;
357#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
358
323 /* Whether new_height and new_width shall be interpreted 359 /* Whether new_height and new_width shall be interpreted
324 in pixels. */ 360 in pixels. */
325 bool_bf new_pixelwise : 1; 361 bool_bf new_pixelwise : 1;
@@ -534,6 +570,13 @@ fset_face_alist (struct frame *f, Lisp_Object val)
534{ 570{
535 f->face_alist = val; 571 f->face_alist = val;
536} 572}
573#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
574INLINE void
575fset_parent_frame (struct frame *f, Lisp_Object val)
576{
577 f->parent_frame = val;
578}
579#endif
537INLINE void 580INLINE void
538fset_focus_frame (struct frame *f, Lisp_Object val) 581fset_focus_frame (struct frame *f, Lisp_Object val)
539{ 582{
@@ -854,7 +897,6 @@ default_pixels_per_inch_y (void)
854#define FRAME_FOCUS_FRAME(f) f->focus_frame 897#define FRAME_FOCUS_FRAME(f) f->focus_frame
855 898
856#ifdef HAVE_WINDOW_SYSTEM 899#ifdef HAVE_WINDOW_SYSTEM
857
858/* This frame slot says whether scroll bars are currently enabled for frame F, 900/* This frame slot says whether scroll bars are currently enabled for frame F,
859 and which side they are on. */ 901 and which side they are on. */
860#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type) 902#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type)
@@ -864,17 +906,47 @@ default_pixels_per_inch_y (void)
864 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_left) 906 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_left)
865#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ 907#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \
866 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) 908 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right)
867
868#else /* not HAVE_WINDOW_SYSTEM */ 909#else /* not HAVE_WINDOW_SYSTEM */
869
870/* If there is no window system, there are no scroll bars. */ 910/* If there is no window system, there are no scroll bars. */
871#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none) 911#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none)
872#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0) 912#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0)
873#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) 913#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0)
874#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) 914#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0)
875
876#endif /* HAVE_WINDOW_SYSTEM */ 915#endif /* HAVE_WINDOW_SYSTEM */
877 916
917#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
918#define FRAME_UNDECORATED(f) ((f)->undecorated)
919#ifdef HAVE_NTGUI
920#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0)
921#else
922#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect)
923#endif
924#define FRAME_PARENT_FRAME(f) \
925 (NILP ((f)->parent_frame) \
926 ? NULL \
927 : XFRAME ((f)->parent_frame))
928#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar)
929#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map)
930#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus)
931#define FRAME_Z_GROUP(f) ((f)->z_group)
932#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none)
933#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above)
934#define FRAME_Z_GROUP_ABOVE_SUSPENDED(f) \
935 ((f)->z_group == z_group_above_suspended)
936#define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below)
937#else /* not HAVE_WINDOW_SYSTEM or HAVE_NS */
938#define FRAME_UNDECORATED(f) ((void) f, 0)
939#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0)
940#define FRAME_PARENT_FRAME(f) ((void) f, NULL)
941#define FRAME_SKIP_TASKBAR(f) ((void) f, 0)
942#define FRAME_NO_FOCUS_ON_MAP(f) ((void) f, 0)
943#define FRAME_NO_ACCEPT_FOCUS(f) ((void) f, 0)
944#define FRAME_Z_GROUP(f) ((void) f, z_group_none)
945#define FRAME_Z_GROUP_NONE(f) ((void) f, true)
946#define FRAME_Z_GROUP_ABOVE(f) ((void) f, false)
947#define FRAME_Z_GROUP_BELOW(f) ((void) f, false)
948#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
949
878/* Whether horizontal scroll bars are currently enabled for frame F. */ 950/* Whether horizontal scroll bars are currently enabled for frame F. */
879#if USE_HORIZONTAL_SCROLL_BARS 951#if USE_HORIZONTAL_SCROLL_BARS
880#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \ 952#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
@@ -1041,7 +1113,8 @@ default_pixels_per_inch_y (void)
1041 loop will set FRAME_VAR, a Lisp_Object, to each frame in 1113 loop will set FRAME_VAR, a Lisp_Object, to each frame in
1042 Vframe_list in succession and execute the statement. LIST_VAR 1114 Vframe_list in succession and execute the statement. LIST_VAR
1043 should be a Lisp_Object too; it is used to iterate through the 1115 should be a Lisp_Object too; it is used to iterate through the
1044 Vframe_list. 1116 Vframe_list. Note that this macro walks over child frames and
1117 the tooltip frame as well.
1045 1118
1046 This macro is a holdover from a time when multiple frames weren't always 1119 This macro is a holdover from a time when multiple frames weren't always
1047 supported. An alternate definition of the macro would expand to 1120 supported. An alternate definition of the macro would expand to
@@ -1221,7 +1294,7 @@ FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
1221 return frame_dimension (f->internal_border_width); 1294 return frame_dimension (f->internal_border_width);
1222} 1295}
1223 1296
1224/* Pixel-size of window border lines */ 1297/* Pixel-size of window divider lines */
1225INLINE int 1298INLINE int
1226FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f) 1299FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f)
1227{ 1300{
@@ -1446,6 +1519,7 @@ extern void x_activate_menubar (struct frame *);
1446extern void x_real_positions (struct frame *, int *, int *); 1519extern void x_real_positions (struct frame *, int *, int *);
1447extern void free_frame_menubar (struct frame *); 1520extern void free_frame_menubar (struct frame *);
1448extern void x_free_frame_resources (struct frame *); 1521extern void x_free_frame_resources (struct frame *);
1522extern bool frame_ancestor_p (struct frame *af, struct frame *df);
1449 1523
1450#if defined HAVE_X_WINDOWS 1524#if defined HAVE_X_WINDOWS
1451extern void x_wm_set_icon_position (struct frame *, int, int); 1525extern void x_wm_set_icon_position (struct frame *, int, int);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 63f01436413..227a062bff3 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1200,7 +1200,14 @@ xg_create_frame_widgets (struct frame *f)
1200 else if (! NILP (f->name)) 1200 else if (! NILP (f->name))
1201 title = SSDATA (ENCODE_UTF_8 (f->name)); 1201 title = SSDATA (ENCODE_UTF_8 (f->name));
1202 1202
1203 if (title) gtk_window_set_title (GTK_WINDOW (wtop), title); 1203 if (title)
1204 gtk_window_set_title (GTK_WINDOW (wtop), title);
1205
1206 if (FRAME_UNDECORATED (f))
1207 {
1208 gtk_window_set_decorated (GTK_WINDOW (wtop), FALSE);
1209 store_frame_param (f, Qundecorated, Qt);
1210 }
1204 1211
1205 FRAME_GTK_OUTER_WIDGET (f) = wtop; 1212 FRAME_GTK_OUTER_WIDGET (f) = wtop;
1206 FRAME_GTK_WIDGET (f) = wfixed; 1213 FRAME_GTK_WIDGET (f) = wfixed;
@@ -1275,6 +1282,14 @@ xg_create_frame_widgets (struct frame *f)
1275 gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); 1282 gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE);
1276#endif 1283#endif
1277 1284
1285 if (FRAME_OVERRIDE_REDIRECT (f))
1286 {
1287 GdkWindow *gwin = gtk_widget_get_window (wtop);
1288
1289 if (gwin)
1290 gdk_window_set_override_redirect (gwin, TRUE);
1291 }
1292
1278#ifdef USE_GTK_TOOLTIP 1293#ifdef USE_GTK_TOOLTIP
1279 /* Steal a tool tip window we can move ourselves. */ 1294 /* Steal a tool tip window we can move ourselves. */
1280 f->output_data.x->ttip_widget = 0; 1295 f->output_data.x->ttip_widget = 0;
@@ -1356,7 +1371,9 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1356 /* Don't set size hints during initialization; that apparently leads 1371 /* Don't set size hints during initialization; that apparently leads
1357 to a race condition. See the thread at 1372 to a race condition. See the thread at
1358 http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */ 1373 http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */
1359 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f)) 1374 if (NILP (Vafter_init_time)
1375 || !FRAME_GTK_OUTER_WIDGET (f)
1376 || FRAME_PARENT_FRAME (f))
1360 return; 1377 return;
1361 1378
1362 XSETFRAME (frame, f); 1379 XSETFRAME (frame, f);
@@ -1489,6 +1506,100 @@ xg_set_background_color (struct frame *f, unsigned long bg)
1489 } 1506 }
1490} 1507}
1491 1508
1509/* Change the frame's decoration (title bar + resize borders). This
1510 might not work with all window managers. */
1511void
1512xg_set_undecorated (struct frame *f, Lisp_Object undecorated)
1513{
1514 if (FRAME_GTK_WIDGET (f))
1515 {
1516 block_input ();
1517 gtk_window_set_decorated (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1518 NILP (undecorated) ? TRUE : FALSE);
1519 unblock_input ();
1520 }
1521}
1522
1523
1524/* Restack F1 below F2, above if ABOVE_FLAG is true. This might not
1525 work with all window managers. */
1526void
1527xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
1528{
1529 block_input ();
1530 if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))
1531 {
1532 GdkWindow *gwin1 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f1));
1533 GdkWindow *gwin2 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f2));
1534 Lisp_Object frame1, frame2;
1535
1536 XSETFRAME (frame1, f1);
1537 XSETFRAME (frame2, f2);
1538
1539 gdk_window_restack (gwin1, gwin2, above_flag);
1540 x_sync (f1);
1541 }
1542 unblock_input ();
1543}
1544
1545
1546/* Don't show frame in taskbar, don't ALT-TAB to it. */
1547void
1548xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar)
1549{
1550 block_input ();
1551 if (FRAME_GTK_WIDGET (f))
1552 gdk_window_set_skip_taskbar_hint
1553 (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
1554 NILP (skip_taskbar) ? FALSE : TRUE);
1555 unblock_input ();
1556}
1557
1558
1559/* Don't give frame focus. */
1560void
1561xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map)
1562{
1563 block_input ();
1564 if (FRAME_GTK_WIDGET (f))
1565 {
1566 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
1567 gboolean gno_focus_on_map = NILP (no_focus_on_map) ? TRUE : FALSE;
1568
1569 gtk_window_set_focus_on_map (gwin, gno_focus_on_map);
1570 }
1571 unblock_input ();
1572}
1573
1574
1575void
1576xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus)
1577{
1578 block_input ();
1579 if (FRAME_GTK_WIDGET (f))
1580 {
1581 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
1582 gboolean gno_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE;
1583
1584 gtk_window_set_accept_focus (gwin, gno_accept_focus);
1585 }
1586 unblock_input ();
1587}
1588
1589void
1590xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect)
1591{
1592 block_input ();
1593
1594 if (FRAME_GTK_OUTER_WIDGET (f))
1595 {
1596 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
1597
1598 gdk_window_set_override_redirect (gwin, NILP (override_redirect) ? FALSE : TRUE);
1599 }
1600
1601 unblock_input ();
1602}
1492 1603
1493/* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK 1604/* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK
1494 functions so GTK does not overwrite the icon. */ 1605 functions so GTK does not overwrite the icon. */
@@ -3769,6 +3880,7 @@ xg_update_scrollbar_pos (struct frame *f,
3769 GtkWidget *wparent = gtk_widget_get_parent (wscroll); 3880 GtkWidget *wparent = gtk_widget_get_parent (wscroll);
3770 gint msl; 3881 gint msl;
3771 int scale = xg_get_gdk_scale (); 3882 int scale = xg_get_gdk_scale ();
3883 bool hidden;
3772 3884
3773 top /= scale; 3885 top /= scale;
3774 left /= scale; 3886 left /= scale;
@@ -3793,6 +3905,7 @@ xg_update_scrollbar_pos (struct frame *f,
3793 the height is less than the min size. */ 3905 the height is less than the min size. */
3794 gtk_widget_hide (wparent); 3906 gtk_widget_hide (wparent);
3795 gtk_widget_hide (wscroll); 3907 gtk_widget_hide (wscroll);
3908 hidden = true;
3796 } 3909 }
3797 else 3910 else
3798 { 3911 {
@@ -3807,6 +3920,15 @@ xg_update_scrollbar_pos (struct frame *f,
3807 x_clear_area (f, oldx, oldy, oldw, oldh); 3920 x_clear_area (f, oldx, oldy, oldw, oldh);
3808 } 3921 }
3809 3922
3923 if (!hidden)
3924 {
3925 GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id);
3926 GtkWidget *webox = gtk_widget_get_parent (scrollbar);
3927
3928 /* Don't obscure any child frames. */
3929 XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
3930 }
3931
3810 /* GTK does not redraw until the main loop is entered again, but 3932 /* GTK does not redraw until the main loop is entered again, but
3811 if there are no X events pending we will not enter it. So we sync 3933 if there are no X events pending we will not enter it. So we sync
3812 here to get some events. */ 3934 here to get some events. */
@@ -3872,6 +3994,15 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
3872 if there are no X events pending we will not enter it. So we sync 3994 if there are no X events pending we will not enter it. So we sync
3873 here to get some events. */ 3995 here to get some events. */
3874 3996
3997 {
3998 GtkWidget *scrollbar =
3999 xg_get_widget_from_map (scrollbar_id);
4000 GtkWidget *webox = gtk_widget_get_parent (scrollbar);
4001
4002 /* Don't obscure any child frames. */
4003 XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
4004 }
4005
3875 x_sync (f); 4006 x_sync (f);
3876 SET_FRAME_GARBAGED (f); 4007 SET_FRAME_GARBAGED (f);
3877 cancel_mouse_face (f); 4008 cancel_mouse_face (f);
diff --git a/src/gtkutil.h b/src/gtkutil.h
index d67a7bc4328..244549fc54b 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -172,6 +172,13 @@ extern void xg_set_frame_icon (struct frame *f,
172 Pixmap icon_pixmap, 172 Pixmap icon_pixmap,
173 Pixmap icon_mask); 173 Pixmap icon_mask);
174 174
175extern void xg_set_undecorated (struct frame *f, Lisp_Object undecorated);
176extern void xg_frame_restack (struct frame *f1, struct frame *f2, bool above);
177extern void xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar);
178extern void xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map);
179extern void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus);
180extern void xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect);
181
175extern bool xg_prepare_tooltip (struct frame *f, 182extern bool xg_prepare_tooltip (struct frame *f,
176 Lisp_Object string, 183 Lisp_Object string,
177 int *width, 184 int *width,
diff --git a/src/nsfns.m b/src/nsfns.m
index 9e904c68382..e8f035f0e57 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -972,6 +972,13 @@ frame_parm_handler ns_frame_parm_handlers[] =
972 0, /* x_set_sticky */ 972 0, /* x_set_sticky */
973 0, /* x_set_tool_bar_position */ 973 0, /* x_set_tool_bar_position */
974 0, /* x_set_inhibit_double_buffering */ 974 0, /* x_set_inhibit_double_buffering */
975 0, /* x_set_undecorated */
976 0, /* x_set_parent_frame */
977 0, /* x_set_skip_taskbar */
978 0, /* x_set_no_focus_on_map */
979 0, /* x_set_no_accept_focus */
980 0, /* x_set_z_group */
981 0, /* x_set_override_redirect */
975}; 982};
976 983
977 984
@@ -1248,6 +1255,12 @@ This function is an internal primitive--use `make-frame' instead. */)
1248 init_frame_faces (f); 1255 init_frame_faces (f);
1249 1256
1250 /* Read comment about this code in corresponding place in xfns.c. */ 1257 /* Read comment about this code in corresponding place in xfns.c. */
1258 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
1259 if (NUMBERP (tem))
1260 store_frame_param (f, Qmin_width, tem);
1261 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
1262 if (NUMBERP (tem))
1263 store_frame_param (f, Qmin_height, tem);
1251 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 1264 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1252 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, 1265 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1253 Qx_create_frame_1); 1266 Qx_create_frame_1);
diff --git a/src/nsterm.m b/src/nsterm.m
index b03ad526212..162980a651b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -6288,7 +6288,7 @@ not_in_argv (NSString *arg)
6288 if (WINDOWP (window) 6288 if (WINDOWP (window)
6289 && !EQ (window, last_mouse_window) 6289 && !EQ (window, last_mouse_window)
6290 && !EQ (window, selected_window) 6290 && !EQ (window, selected_window)
6291 && (focus_follows_mouse 6291 && (!NILP (focus_follows_mouse)
6292 || (EQ (XWINDOW (window)->frame, 6292 || (EQ (XWINDOW (window)->frame,
6293 XWINDOW (selected_window)->frame)))) 6293 XWINDOW (selected_window)->frame))))
6294 { 6294 {
diff --git a/src/w32fns.c b/src/w32fns.c
index dd16d74439f..f7d3b722abf 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -256,6 +256,10 @@ static unsigned int sound_type = 0xFFFFFFFF;
256# define WTS_SESSION_LOCK 0x7 256# define WTS_SESSION_LOCK 0x7
257#endif 257#endif
258 258
259#ifndef WS_EX_NOACTIVATE
260#define WS_EX_NOACTIVATE 0x08000000L
261#endif
262
259/* Keyboard hook state data. */ 263/* Keyboard hook state data. */
260static struct 264static struct
261{ 265{
@@ -367,17 +371,20 @@ void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
367void 371void
368x_real_positions (struct frame *f, int *xptr, int *yptr) 372x_real_positions (struct frame *f, int *xptr, int *yptr)
369{ 373{
370 POINT pt;
371 RECT rect; 374 RECT rect;
372 375
373 /* Get the bounds of the WM window. */ 376 /* Get the bounds of the WM window. */
374 GetWindowRect (FRAME_W32_WINDOW (f), &rect); 377 GetWindowRect (FRAME_W32_WINDOW (f), &rect);
375 378
376 pt.x = 0; 379 if (FRAME_PARENT_FRAME (f))
377 pt.y = 0; 380 {
381 /* For a child window we have to get its coordinates wrt its
382 parent. */
383 HWND parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
378 384
379 /* Convert (0, 0) in the client area to screen co-ordinates. */ 385 if (parent_hwnd)
380 ClientToScreen (FRAME_W32_WINDOW (f), &pt); 386 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
387 }
381 388
382 *xptr = rect.left; 389 *xptr = rect.left;
383 *yptr = rect.top; 390 *yptr = rect.top;
@@ -1682,7 +1689,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1682 most of the commands try to apply themselves to the minibuffer 1689 most of the commands try to apply themselves to the minibuffer
1683 frame itself, and get an error because you can't switch buffers 1690 frame itself, and get an error because you can't switch buffers
1684 in or split the minibuffer window. */ 1691 in or split the minibuffer window. */
1685 if (FRAME_MINIBUF_ONLY_P (f)) 1692 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1686 return; 1693 return;
1687 1694
1688 if (INTEGERP (value)) 1695 if (INTEGERP (value))
@@ -1955,6 +1962,233 @@ x_set_scroll_bar_default_height (struct frame *f)
1955 FRAME_CONFIG_SCROLL_BAR_LINES (f) 1962 FRAME_CONFIG_SCROLL_BAR_LINES (f)
1956 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit; 1963 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
1957} 1964}
1965
1966/**
1967 * x_set_undecorated:
1968 *
1969 * Set frame F's `undecorated' parameter. If non-nil, F's window-system
1970 * window is drawn without decorations, title, minimize/maximize boxes
1971 * and external borders. This usually means that the window cannot be
1972 * dragged, resized, iconified, maximized or deleted with the mouse. If
1973 * nil, draw the frame with all the elements listed above unless these
1974 * have been suspended via window manager settings.
1975 *
1976 * Some window managers may not honor this parameter.
1977 */
1978static void
1979x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1980{
1981 HWND hwnd = FRAME_W32_WINDOW (f);
1982 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
1983 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
1984
1985 block_input ();
1986 if (!NILP (new_value) && !FRAME_UNDECORATED (f))
1987 {
1988 dwStyle = ((dwStyle & ~WS_THICKFRAME & ~WS_CAPTION)
1989 | ((NUMBERP (border_width) && (XINT (border_width) > 0))
1990 ? WS_BORDER : false));
1991 SetWindowLong (hwnd, GWL_STYLE, dwStyle);
1992 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
1993 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
1994 | SWP_FRAMECHANGED);
1995 FRAME_UNDECORATED (f) = true;
1996 }
1997 else if (NILP (new_value) && FRAME_UNDECORATED (f))
1998 {
1999 SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_CAPTION
2000 | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU);
2001 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
2002 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
2003 | SWP_FRAMECHANGED);
2004 FRAME_UNDECORATED (f) = false;
2005 }
2006 unblock_input ();
2007}
2008
2009/**
2010 * x_set_parent_frame:
2011 *
2012 * Set frame F's `parent-frame' parameter. If non-nil, make F a child
2013 * frame of the frame specified by that parameter. Technically, this
2014 * makes F's window-system window a child window of the parent frame's
2015 * window-system window. If nil, make F's window-system window a
2016 * top-level window--a child of its display's root window.
2017 *
2018 * A child frame is clipped at the native edges of its parent frame.
2019 * Its `left' and `top' parameters specify positions relative to the
2020 * top-left corner of its parent frame's native rectangle. Usually,
2021 * moving a parent frame moves all its child frames too, keeping their
2022 * position relative to the parent unaltered. When a parent frame is
2023 * iconified or made invisible, its child frames are made invisible.
2024 * When a parent frame is deleted, its child frames are deleted too.
2025 *
2026 * A visible child frame always appears on top of its parent frame thus
2027 * obscuring parts of it. When a frame has more than one child frame,
2028 * their stacking order is specified just as that of non-child frames
2029 * relative to their display.
2030 *
2031 * Whether a child frame has a menu or tool bar may be window-system or
2032 * window manager dependent. It's advisable to disable both via the
2033 * frame parameter settings.
2034 *
2035 * Some window managers may not honor this parameter.
2036 */
2037static void
2038x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2039{
2040 struct frame *p = NULL;
2041
2042 if (!NILP (new_value)
2043 && (!FRAMEP (new_value)
2044 || !FRAME_LIVE_P (p = XFRAME (new_value))
2045 || !FRAME_W32_P (p)))
2046 {
2047 store_frame_param (f, Qparent_frame, old_value);
2048 error ("Invalid specification of `parent-frame'");
2049 }
2050
2051 if (p != FRAME_PARENT_FRAME (f))
2052 {
2053 HWND hwnd = FRAME_W32_WINDOW (f);
2054 HWND hwnd_parent = p ? FRAME_W32_WINDOW (p) : NULL;
2055 HWND hwnd_value;
2056
2057 block_input ();
2058 hwnd_value = SetParent (hwnd, hwnd_parent);
2059 unblock_input ();
2060
2061 if (hwnd_value)
2062 fset_parent_frame (f, new_value);
2063 else
2064 {
2065 store_frame_param (f, Qparent_frame, old_value);
2066 error ("Reparenting frame failed");
2067 }
2068 }
2069}
2070
2071/**
2072 * x_set_skip_taskbar:
2073 *
2074 * Set frame F's `skip-taskbar' parameter. If non-nil, this should
2075 * remove F's icon from the taskbar associated with the display of F's
2076 * window-system window and inhibit switching to F's window via
2077 * <Alt>-<TAB>. On Windows iconifying F will "roll in" its window at
2078 * the bottom of the desktop. If nil, lift these restrictions.
2079 *
2080 * Some window managers may not honor this parameter.
2081 */
2082static void
2083x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2084{
2085 if (!EQ (new_value, old_value))
2086 {
2087 HWND hwnd = FRAME_W32_WINDOW (f);
2088 DWORD exStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
2089
2090 block_input ();
2091 /* Temporarily hide the window while changing its WS_EX_NOACTIVATE
2092 setting. */
2093 ShowWindow (hwnd, SW_HIDE);
2094 if (!NILP (new_value))
2095 SetWindowLong (hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
2096 else
2097 SetWindowLong (hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
2098 ShowWindow (hwnd, SW_SHOWNOACTIVATE);
2099 unblock_input ();
2100
2101 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
2102 }
2103}
2104
2105/**
2106 * x_set_no_focus_on_map:
2107 *
2108 * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
2109 * that F's window-system window does not want to receive input focus
2110 * when it is mapped. (A frame's window is mapped when the frame is
2111 * displayed for the first time and when the frame changes its state
2112 * from `iconified' or `invisible' to `visible'.)
2113 *
2114 * Some window managers may not honor this parameter.
2115 */
2116static void
2117x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2118{
2119 if (!EQ (new_value, old_value))
2120 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
2121}
2122
2123/**
2124 * x_set_no_accept_focus:
2125 *
2126 * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
2127 * that F's window-system window does not want to receive input focus
2128 * via mouse clicks or by moving the mouse into it.
2129 *
2130 * If non-nil, this may have the unwanted side-effect that a user cannot
2131 * scroll a non-selected frame with the mouse.
2132 *
2133 * Some window managers may not honor this parameter.
2134 */
2135static void
2136x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2137{
2138 if (!EQ (new_value, old_value))
2139 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
2140}
2141
2142/**
2143 * x_set_z_group:
2144 *
2145 * Set frame F's `z-group' parameter. If `above', F's window-system
2146 * window is displayed above all windows that do not have the `above'
2147 * property set. If nil, F's window is shown below all windows that
2148 * have the `above' property set and above all windows that have the
2149 * `below' property set. If `below', F's window is displayed below all
2150 * windows that do not have the `below' property set.
2151 *
2152 * Some window managers may not honor this parameter. The value `below'
2153 * is not supported on Windows.
2154 */
2155static void
2156x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2157{
2158 HWND hwnd = FRAME_W32_WINDOW (f);
2159
2160 if (NILP (new_value))
2161 {
2162 block_input ();
2163 SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
2164 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2165 | SWP_NOOWNERZORDER);
2166 unblock_input ();
2167 FRAME_Z_GROUP (f) = z_group_none;
2168 }
2169 else if (EQ (new_value, Qabove))
2170 {
2171 block_input ();
2172 SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2173 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2174 | SWP_NOOWNERZORDER);
2175 unblock_input ();
2176 FRAME_Z_GROUP (f) = z_group_above;
2177 }
2178 else if (EQ (new_value, Qabove_suspended))
2179 {
2180 block_input ();
2181 SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
2182 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2183 | SWP_NOOWNERZORDER);
2184 unblock_input ();
2185 FRAME_Z_GROUP (f) = z_group_above_suspended;
2186 }
2187 else if (EQ (new_value, Qbelow))
2188 error ("Value `below' for z-group is not supported on Windows");
2189 else
2190 error ("Invalid z-group specification");
2191}
1958 2192
1959/* Subroutines for creating a frame. */ 2193/* Subroutines for creating a frame. */
1960 2194
@@ -2013,7 +2247,12 @@ w32_init_class (HINSTANCE hinst)
2013static HWND 2247static HWND
2014w32_createvscrollbar (struct frame *f, struct scroll_bar * bar) 2248w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
2015{ 2249{
2016 return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE, 2250 return CreateWindow ("SCROLLBAR", "",
2251 /* Clip siblings so we don't draw over child
2252 frames. Apparently this is not always
2253 sufficient so we also try to make bar windows
2254 bottommost. */
2255 SBS_VERT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
2017 /* Position and size of scroll bar. */ 2256 /* Position and size of scroll bar. */
2018 bar->left, bar->top, bar->width, bar->height, 2257 bar->left, bar->top, bar->width, bar->height,
2019 FRAME_W32_WINDOW (f), NULL, hinst, NULL); 2258 FRAME_W32_WINDOW (f), NULL, hinst, NULL);
@@ -2022,7 +2261,12 @@ w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
2022static HWND 2261static HWND
2023w32_createhscrollbar (struct frame *f, struct scroll_bar * bar) 2262w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
2024{ 2263{
2025 return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE, 2264 return CreateWindow ("SCROLLBAR", "",
2265 /* Clip siblings so we don't draw over child
2266 frames. Apparently this is not always
2267 sufficient so we also try to make bar windows
2268 bottommost. */
2269 SBS_HORZ | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
2026 /* Position and size of scroll bar. */ 2270 /* Position and size of scroll bar. */
2027 bar->left, bar->top, bar->width, bar->height, 2271 bar->left, bar->top, bar->width, bar->height,
2028 FRAME_W32_WINDOW (f), NULL, hinst, NULL); 2272 FRAME_W32_WINDOW (f), NULL, hinst, NULL);
@@ -2031,20 +2275,55 @@ w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
2031static void 2275static void
2032w32_createwindow (struct frame *f, int *coords) 2276w32_createwindow (struct frame *f, int *coords)
2033{ 2277{
2034 HWND hwnd; 2278 HWND hwnd = NULL, parent_hwnd = NULL;
2035 RECT rect; 2279 RECT rect;
2036 int top; 2280 DWORD dwStyle;
2037 int left; 2281 int top, left;
2282 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
2283
2284 if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
2285 {
2286 parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
2287 f->output_data.w32->dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
2288
2289 if (FRAME_UNDECORATED (f))
2290 {
2291 /* If we want a thin border, specify it here. */
2292 if (NUMBERP (border_width) && (XINT (border_width) > 0))
2293 f->output_data.w32->dwStyle =
2294 f->output_data.w32->dwStyle | WS_BORDER;
2295 }
2296 else
2297 /* To decorate a child frame, list all needed elements. */
2298 f->output_data.w32->dwStyle =
2299 f->output_data.w32->dwStyle | WS_THICKFRAME | WS_CAPTION
2300 | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU;
2301 }
2302 else if (FRAME_UNDECORATED (f))
2303 {
2304 /* All attempts to start with ~WS_OVERLAPPEDWINDOW or overlapped
2305 with all other style elements negated failed here. */
2306 f->output_data.w32->dwStyle = WS_POPUP;
2307
2308 /* If we want a thin border, specify it here. */
2309 if (NUMBERP (border_width) && (XINT (border_width) > 0))
2310 f->output_data.w32->dwStyle =
2311 f->output_data.w32->dwStyle | WS_BORDER;
2312 }
2313 else
2314 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
2315
2316 /* Always clip children. */
2317 f->output_data.w32->dwStyle = f->output_data.w32->dwStyle | WS_CLIPCHILDREN;
2038 2318
2039 rect.left = rect.top = 0; 2319 rect.left = rect.top = 0;
2040 rect.right = FRAME_PIXEL_WIDTH (f); 2320 rect.right = FRAME_PIXEL_WIDTH (f);
2041 rect.bottom = FRAME_PIXEL_HEIGHT (f); 2321 rect.bottom = FRAME_PIXEL_HEIGHT (f);
2042 2322
2043 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, 2323 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
2044 FRAME_EXTERNAL_MENU_BAR (f)); 2324 FRAME_EXTERNAL_MENU_BAR (f) && !parent_hwnd);
2045 2325
2046 /* Do first time app init */ 2326 /* Do first time app init */
2047
2048 w32_init_class (hinst); 2327 w32_init_class (hinst);
2049 2328
2050 if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition) 2329 if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
@@ -2059,18 +2338,16 @@ w32_createwindow (struct frame *f, int *coords)
2059 } 2338 }
2060 2339
2061 FRAME_W32_WINDOW (f) = hwnd 2340 FRAME_W32_WINDOW (f) = hwnd
2062 = CreateWindow (EMACS_CLASS, 2341 = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
2063 f->namebuf, 2342 left, top, rect.right - rect.left, rect.bottom - rect.top,
2064 f->output_data.w32->dwStyle | WS_CLIPCHILDREN, 2343 parent_hwnd, NULL, hinst, NULL);
2065 left, top,
2066 rect.right - rect.left, rect.bottom - rect.top,
2067 NULL,
2068 NULL,
2069 hinst,
2070 NULL);
2071 2344
2072 if (hwnd) 2345 if (hwnd)
2073 { 2346 {
2347 if (FRAME_SKIP_TASKBAR (f))
2348 SetWindowLong (hwnd, GWL_EXSTYLE,
2349 GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
2350
2074 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); 2351 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
2075 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); 2352 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
2076 SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); 2353 SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
@@ -2086,6 +2363,12 @@ w32_createwindow (struct frame *f, int *coords)
2086 2363
2087 /* Update frame positions. */ 2364 /* Update frame positions. */
2088 GetWindowRect (hwnd, &rect); 2365 GetWindowRect (hwnd, &rect);
2366
2367 if (parent_hwnd)
2368 /* For a child window we have to get its coordinates wrt its
2369 parent. */
2370 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
2371
2089 f->left_pos = rect.left; 2372 f->left_pos = rect.left;
2090 f->top_pos = rect.top; 2373 f->top_pos = rect.top;
2091 } 2374 }
@@ -4381,6 +4664,22 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4381 } 4664 }
4382 } 4665 }
4383 4666
4667 if (f && (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN
4668 || msg == WM_MBUTTONDOWN ||msg == WM_XBUTTONDOWN)
4669 && !FRAME_NO_ACCEPT_FOCUS (f))
4670 /* When clicking into a child frame or when clicking into a
4671 parent frame with the child frame selected and
4672 `no-accept-focus' is not set, select the clicked frame. */
4673 {
4674 struct frame *p = FRAME_PARENT_FRAME (XFRAME (selected_frame));
4675
4676 if (FRAME_PARENT_FRAME (f) || f == p)
4677 {
4678 SetFocus (hwnd);
4679 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
4680 }
4681 }
4682
4384 wmsg.dwModifiers = w32_get_modifiers (); 4683 wmsg.dwModifiers = w32_get_modifiers ();
4385 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4684 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4386 signal_user_input (); 4685 signal_user_input ();
@@ -4486,6 +4785,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4486 if (w32_pass_multimedia_buttons_to_system) 4785 if (w32_pass_multimedia_buttons_to_system)
4487 goto dflt; 4786 goto dflt;
4488 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */ 4787 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
4788
4789 /* FIXME!!! This is never reached so what's the purpose? If the
4790 non-zero return remark below is right we're doing it wrong all
4791 the time. */
4489 case WM_MOUSEHWHEEL: 4792 case WM_MOUSEHWHEEL:
4490 wmsg.dwModifiers = w32_get_modifiers (); 4793 wmsg.dwModifiers = w32_get_modifiers ();
4491 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4794 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -4712,19 +5015,34 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4712 } 5015 }
4713 return 0; 5016 return 0;
4714 5017
4715#if 0 5018 case WM_MOUSEACTIVATE:
5019 /* WM_MOUSEACTIVATE is the only way on Windows to implement the
5020 `no-accept-focus' frame parameter. This means that one can't
5021 use the mouse to scroll a window on a non-selected frame. */
5022
4716 /* Still not right - can't distinguish between clicks in the 5023 /* Still not right - can't distinguish between clicks in the
4717 client area of the frame from clicks forwarded from the scroll 5024 client area of the frame from clicks forwarded from the scroll
4718 bars - may have to hook WM_NCHITTEST to remember the mouse 5025 bars - may have to hook WM_NCHITTEST to remember the mouse
4719 position and then check if it is in the client area ourselves. */ 5026 position and then check if it is in the client area
4720 case WM_MOUSEACTIVATE: 5027 ourselves. */
5028
4721 /* Discard the mouse click that activates a frame, allowing the 5029 /* Discard the mouse click that activates a frame, allowing the
4722 user to click anywhere without changing point (or worse!). 5030 user to click anywhere without changing point (or worse!).
4723 Don't eat mouse clicks on scrollbars though!! */ 5031 Don't eat mouse clicks on scrollbars though!! */
4724 if (LOWORD (lParam) == HTCLIENT ) 5032
4725 return MA_ACTIVATEANDEAT; 5033 if ((f = x_window_to_frame (dpyinfo, hwnd))
5034 && FRAME_NO_ACCEPT_FOCUS (f)
5035 /* Ignore child frames, they don't accept focus anyway. */
5036 && !FRAME_PARENT_FRAME (f))
5037 {
5038 Lisp_Object frame;
5039
5040 XSETFRAME (frame, f);
5041 if (!EQ (selected_frame, frame))
5042 /* Don't discard the message, GTK doesn't either. */
5043 return MA_NOACTIVATE; /* ANDEAT; */
5044 }
4726 goto dflt; 5045 goto dflt;
4727#endif
4728 5046
4729 case WM_MOUSELEAVE: 5047 case WM_MOUSELEAVE:
4730 /* No longer tracking mouse. */ 5048 /* No longer tracking mouse. */
@@ -4903,6 +5221,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4903 AttachThreadInput (GetCurrentThreadId (), 5221 AttachThreadInput (GetCurrentThreadId (),
4904 foreground_thread, FALSE); 5222 foreground_thread, FALSE);
4905 5223
5224 /* SetFocus to give/remove focus to/from a child window. */
5225 if (msg == WM_EMACS_SETFOREGROUND)
5226 SetFocus ((HWND) wParam);
5227
4906 return retval; 5228 return retval;
4907 } 5229 }
4908 5230
@@ -5134,7 +5456,8 @@ w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
5134 5456
5135 unblock_input (); 5457 unblock_input ();
5136 5458
5137 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 5459 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)
5460 && !FRAME_PARENT_FRAME (f))
5138 initialize_frame_menubar (f); 5461 initialize_frame_menubar (f);
5139 5462
5140 if (FRAME_W32_WINDOW (f) == 0) 5463 if (FRAME_W32_WINDOW (f) == 0)
@@ -5322,7 +5645,7 @@ This function is an internal primitive--use `make-frame' instead. */)
5322 ptrdiff_t count = SPECPDL_INDEX (); 5645 ptrdiff_t count = SPECPDL_INDEX ();
5323 Lisp_Object display; 5646 Lisp_Object display;
5324 struct w32_display_info *dpyinfo = NULL; 5647 struct w32_display_info *dpyinfo = NULL;
5325 Lisp_Object parent; 5648 Lisp_Object parent, parent_frame;
5326 struct kboard *kb; 5649 struct kboard *kb;
5327 int x_width = 0, x_height = 0; 5650 int x_width = 0, x_height = 0;
5328 5651
@@ -5359,10 +5682,11 @@ This function is an internal primitive--use `make-frame' instead. */)
5359 Vx_resource_name = name; 5682 Vx_resource_name = name;
5360 5683
5361 /* See if parent window is specified. */ 5684 /* See if parent window is specified. */
5362 parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); 5685 parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
5686 RES_TYPE_NUMBER);
5363 if (EQ (parent, Qunbound)) 5687 if (EQ (parent, Qunbound))
5364 parent = Qnil; 5688 parent = Qnil;
5365 if (! NILP (parent)) 5689 else if (!NILP (parent))
5366 CHECK_NUMBER (parent); 5690 CHECK_NUMBER (parent);
5367 5691
5368 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */ 5692 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
@@ -5385,6 +5709,31 @@ This function is an internal primitive--use `make-frame' instead. */)
5385 5709
5386 XSETFRAME (frame, f); 5710 XSETFRAME (frame, f);
5387 5711
5712 parent_frame = x_get_arg (dpyinfo, parameters, Qparent_frame, NULL, NULL,
5713 RES_TYPE_SYMBOL);
5714 /* Apply `parent-frame' parameter only when no `parent-id' was
5715 specified. */
5716 if (!NILP (parent_frame)
5717 && (!NILP (parent)
5718 || !FRAMEP (parent_frame)
5719 || !FRAME_LIVE_P (XFRAME (parent_frame))
5720 || !FRAME_W32_P (XFRAME (parent_frame))))
5721 parent_frame = Qnil;
5722
5723 fset_parent_frame (f, parent_frame);
5724 store_frame_param (f, Qparent_frame, parent_frame);
5725
5726 tem = x_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
5727 RES_TYPE_BOOLEAN);
5728 FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
5729 store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
5730
5731 tem = x_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
5732 RES_TYPE_BOOLEAN);
5733 FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
5734 store_frame_param (f, Qskip_taskbar,
5735 (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
5736
5388 /* By default, make scrollbars the system standard width and height. */ 5737 /* By default, make scrollbars the system standard width and height. */
5389 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); 5738 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
5390 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL); 5739 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
@@ -5412,7 +5761,9 @@ This function is an internal primitive--use `make-frame' instead. */)
5412 dpyinfo_refcount = dpyinfo->reference_count; 5761 dpyinfo_refcount = dpyinfo->reference_count;
5413#endif /* GLYPH_DEBUG */ 5762#endif /* GLYPH_DEBUG */
5414 5763
5415 /* Specify the parent under which to make this window. */ 5764 /* Specify the parent under which to make this window - this seems to
5765 have no effect on Windows because parent_desc is explicitly reset
5766 below. */
5416 if (!NILP (parent)) 5767 if (!NILP (parent))
5417 { 5768 {
5418 /* Cast to UINT_PTR shuts up compiler warnings about cast to 5769 /* Cast to UINT_PTR shuts up compiler warnings about cast to
@@ -5496,23 +5847,42 @@ This function is an internal primitive--use `make-frame' instead. */)
5496 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 5847 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5497 x_default_parameter (f, parameters, Qright_fringe, Qnil, 5848 x_default_parameter (f, parameters, Qright_fringe, Qnil,
5498 "rightFringe", "RightFringe", RES_TYPE_NUMBER); 5849 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5499 /* Process alpha here (Bug#16619). */ 5850 x_default_parameter (f, parameters, Qno_focus_on_map, Qnil,
5500 x_default_parameter (f, parameters, Qalpha, Qnil, 5851 NULL, NULL, RES_TYPE_BOOLEAN);
5501 "alpha", "Alpha", RES_TYPE_NUMBER); 5852 x_default_parameter (f, parameters, Qno_accept_focus, Qnil,
5853 NULL, NULL, RES_TYPE_BOOLEAN);
5854
5855 /* Process alpha here (Bug#16619). On XP this fails with child
5856 frames. For `no-focus-on-map' frames delay processing of alpha
5857 until the frame becomes visible. */
5858 if (!FRAME_NO_FOCUS_ON_MAP (f))
5859 x_default_parameter (f, parameters, Qalpha, Qnil,
5860 "alpha", "Alpha", RES_TYPE_NUMBER);
5502 5861
5503 /* Init faces first since we need the frame's column width/line 5862 /* Init faces first since we need the frame's column width/line
5504 height in various occasions. */ 5863 height in various occasions. */
5505 init_frame_faces (f); 5864 init_frame_faces (f);
5506 5865
5507 /* The following call of change_frame_size is needed since otherwise 5866 /* We have to call adjust_frame_size here since otherwise
5508 x_set_tool_bar_lines will already work with the character sizes 5867 x_set_tool_bar_lines will already work with the character sizes
5509 installed by init_frame_faces while the frame's pixel size is 5868 installed by init_frame_faces while the frame's pixel size is still
5510 still calculated from a character size of 1 and we subsequently 5869 calculated from a character size of 1 and we subsequently hit the
5511 hit the (height >= 0) assertion in window_box_height. 5870 (height >= 0) assertion in window_box_height.
5512 5871
5513 The non-pixelwise code apparently worked around this because it 5872 The non-pixelwise code apparently worked around this because it
5514 had one frame line vs one toolbar line which left us with a zero 5873 had one frame line vs one toolbar line which left us with a zero
5515 root window height which was obviously wrong as well ... */ 5874 root window height which was obviously wrong as well ...
5875
5876 Also process `min-width' and `min-height' parameters right here
5877 because `frame-windows-min-size' needs them. */
5878 tem = x_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
5879 RES_TYPE_NUMBER);
5880 if (NUMBERP (tem))
5881 store_frame_param (f, Qmin_width, tem);
5882 tem = x_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
5883 RES_TYPE_NUMBER);
5884 if (NUMBERP (tem))
5885 store_frame_param (f, Qmin_height, tem);
5516 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 5886 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
5517 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, 5887 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
5518 Qx_create_frame_1); 5888 Qx_create_frame_1);
@@ -5520,10 +5890,17 @@ This function is an internal primitive--use `make-frame' instead. */)
5520 /* The X resources controlling the menu-bar and tool-bar are 5890 /* The X resources controlling the menu-bar and tool-bar are
5521 processed specially at startup, and reflected in the mode 5891 processed specially at startup, and reflected in the mode
5522 variables; ignore them here. */ 5892 variables; ignore them here. */
5523 x_default_parameter (f, parameters, Qmenu_bar_lines, 5893 if (NILP (parent_frame))
5524 NILP (Vmenu_bar_mode) 5894 {
5525 ? make_number (0) : make_number (1), 5895 x_default_parameter (f, parameters, Qmenu_bar_lines,
5526 NULL, NULL, RES_TYPE_NUMBER); 5896 NILP (Vmenu_bar_mode)
5897 ? make_number (0) : make_number (1),
5898 NULL, NULL, RES_TYPE_NUMBER);
5899 }
5900 else
5901 /* No menu bar for child frames. */
5902 store_frame_param (f, Qmenu_bar_lines, make_number (0));
5903
5527 x_default_parameter (f, parameters, Qtool_bar_lines, 5904 x_default_parameter (f, parameters, Qtool_bar_lines,
5528 NILP (Vtool_bar_mode) 5905 NILP (Vtool_bar_mode)
5529 ? make_number (0) : make_number (1), 5906 ? make_number (0) : make_number (1),
@@ -5534,9 +5911,7 @@ This function is an internal primitive--use `make-frame' instead. */)
5534 x_default_parameter (f, parameters, Qtitle, Qnil, 5911 x_default_parameter (f, parameters, Qtitle, Qnil,
5535 "title", "Title", RES_TYPE_STRING); 5912 "title", "Title", RES_TYPE_STRING);
5536 5913
5537 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
5538 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; 5914 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
5539
5540 f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM); 5915 f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
5541 f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW); 5916 f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
5542 f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW); 5917 f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
@@ -5601,29 +5976,36 @@ This function is an internal primitive--use `make-frame' instead. */)
5601 adjust_frame_size call. */ 5976 adjust_frame_size call. */
5602 x_default_parameter (f, parameters, Qfullscreen, Qnil, 5977 x_default_parameter (f, parameters, Qfullscreen, Qnil,
5603 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); 5978 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
5979 x_default_parameter (f, parameters, Qz_group, Qnil,
5980 NULL, NULL, RES_TYPE_SYMBOL);
5604 5981
5605 /* Make the window appear on the frame and enable display, unless 5982 /* Make the window appear on the frame and enable display, unless
5606 the caller says not to. However, with explicit parent, Emacs 5983 the caller says not to. However, with explicit parent, Emacs
5607 cannot control visibility, so don't try. */ 5984 cannot control visibility, so don't try. */
5608 if (! f->output_data.w32->explicit_parent) 5985 if (!f->output_data.w32->explicit_parent)
5609 { 5986 {
5610 Lisp_Object visibility; 5987 Lisp_Object visibility
5611 5988 = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5612 visibility = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5613 if (EQ (visibility, Qunbound))
5614 visibility = Qt;
5615 5989
5616 if (EQ (visibility, Qicon)) 5990 if (EQ (visibility, Qicon))
5617 x_iconify_frame (f); 5991 x_iconify_frame (f);
5618 else if (! NILP (visibility))
5619 x_make_frame_visible (f);
5620 else 5992 else
5621 { 5993 {
5622 /* Must have been Qnil. */ 5994 if (EQ (visibility, Qunbound))
5623 ; 5995 visibility = Qt;
5996
5997 if (!NILP (visibility))
5998 x_make_frame_visible (f);
5624 } 5999 }
6000
6001 store_frame_param (f, Qvisibility, visibility);
5625 } 6002 }
5626 6003
6004 /* For `no-focus-on-map' frames set alpha here. */
6005 if (FRAME_NO_FOCUS_ON_MAP (f))
6006 x_default_parameter (f, parameters, Qalpha, Qnil,
6007 "alpha", "Alpha", RES_TYPE_NUMBER);
6008
5627 /* Initialize `default-minibuffer-frame' in case this is the first 6009 /* Initialize `default-minibuffer-frame' in case this is the first
5628 frame on this terminal. */ 6010 frame on this terminal. */
5629 if (FRAME_HAS_MINIBUF_P (f) 6011 if (FRAME_HAS_MINIBUF_P (f)
@@ -6572,8 +6954,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6572 dpyinfo_refcount = dpyinfo->reference_count; 6954 dpyinfo_refcount = dpyinfo->reference_count;
6573#endif /* GLYPH_DEBUG */ 6955#endif /* GLYPH_DEBUG */
6574 FRAME_KBOARD (f) = kb; 6956 FRAME_KBOARD (f) = kb;
6575 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6576 f->output_data.w32->explicit_parent = false;
6577 6957
6578 /* Set the name; the functions to which we pass f expect the name to 6958 /* Set the name; the functions to which we pass f expect the name to
6579 be set. */ 6959 be set. */
@@ -6639,6 +7019,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6639 7019
6640 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED; 7020 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
6641 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; 7021 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
7022 f->output_data.w32->explicit_parent = false;
6642 7023
6643 x_figure_window_size (f, parms, true, &x_width, &x_height); 7024 x_figure_window_size (f, parms, true, &x_width, &x_height);
6644 7025
@@ -7282,6 +7663,23 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
7282 return 0; 7663 return 0;
7283} 7664}
7284 7665
7666void
7667w32_dialog_in_progress (Lisp_Object in_progress)
7668{
7669 Lisp_Object frames, frame;
7670
7671 /* Don't let frames in `above' z-group obscure popups. */
7672 FOR_EACH_FRAME (frames, frame)
7673 {
7674 struct frame *f = XFRAME (frame);
7675
7676 if (!NILP (in_progress) && FRAME_Z_GROUP_ABOVE (f))
7677 x_set_z_group (f, Qabove_suspended, Qabove);
7678 else if (NILP (in_progress) && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
7679 x_set_z_group (f, Qabove, Qabove_suspended);
7680 }
7681}
7682
7285DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, 7683DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7286 doc: /* Read file name, prompting with PROMPT in directory DIR. 7684 doc: /* Read file name, prompting with PROMPT in directory DIR.
7287Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file 7685Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
@@ -7513,8 +7911,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
7513 7911
7514 { 7912 {
7515 int count = SPECPDL_INDEX (); 7913 int count = SPECPDL_INDEX ();
7914
7915 w32_dialog_in_progress (Qt);
7916
7516 /* Prevent redisplay. */ 7917 /* Prevent redisplay. */
7517 specbind (Qinhibit_redisplay, Qt); 7918 specbind (Qinhibit_redisplay, Qt);
7919 record_unwind_protect (w32_dialog_in_progress, Qnil);
7518 block_input (); 7920 block_input ();
7519 if (use_unicode) 7921 if (use_unicode)
7520 { 7922 {
@@ -8559,6 +8961,136 @@ menu bar or tool bar of FRAME. */)
8559 } 8961 }
8560} 8962}
8561 8963
8964/**
8965 * w32_frame_list_z_order:
8966 *
8967 * Recursively add list of all frames on the display specified via
8968 * DPYINFO and whose window-system window's parent is specified by
8969 * WINDOW to FRAMES and return FRAMES.
8970 */
8971static Lisp_Object
8972w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window)
8973{
8974 Lisp_Object frame, frames = Qnil;
8975
8976 while (window)
8977 {
8978 struct frame *f = x_window_to_frame (dpyinfo, window);
8979
8980 if (f)
8981 {
8982 XSETFRAME (frame, f);
8983 frames = Fcons (frame, frames);
8984 }
8985
8986 block_input ();
8987 window = GetNextWindow (window, GW_HWNDNEXT);
8988 unblock_input ();
8989 }
8990
8991 return Fnreverse (frames);
8992}
8993
8994DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
8995 Sw32_frame_list_z_order, 0, 1, 0,
8996 doc: /* Return list of Emacs' frames, in Z (stacking) order.
8997The optional argument DISPLAY specifies which display to ask about.
8998DISPLAY should be either a frame or a display name (a string). If
8999omitted or nil, that stands for the selected frame's display.
9000
9001As a special case, if DISPLAY is non-nil and specifies a live frame,
9002return the child frames of that frame in Z (stacking) order.
9003
9004Frames are listed from topmost (first) to bottommost (last). */)
9005 (Lisp_Object display)
9006{
9007 struct w32_display_info *dpyinfo = check_x_display_info (display);
9008 HWND window;
9009
9010 block_input ();
9011 if (FRAMEP (display) && FRAME_LIVE_P (XFRAME (display)))
9012 window = GetWindow (FRAME_W32_WINDOW (XFRAME (display)), GW_CHILD);
9013 else
9014 window = GetTopWindow (NULL);
9015 unblock_input ();
9016
9017 return w32_frame_list_z_order (dpyinfo, window);
9018}
9019
9020/**
9021 * w32_frame_restack:
9022 *
9023 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
9024 * practice this is a two-step action: The first step removes F1's
9025 * window-system window from the display. The second step reinserts
9026 * F1's window below (above if ABOVE_FLAG is true) that of F2.
9027 */
9028static void
9029w32_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
9030{
9031 HWND hwnd1 = FRAME_W32_WINDOW (f1);
9032 HWND hwnd2 = FRAME_W32_WINDOW (f2);
9033
9034 block_input ();
9035 if (above_flag)
9036 /* Put F1 above F2 in the z-order. */
9037 {
9038 if (GetNextWindow (hwnd1, GW_HWNDNEXT) != hwnd2)
9039 {
9040 /* Make sure F1 is below F2 first because we must not
9041 change the relative position of F2 wrt any other
9042 window but F1. */
9043 if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
9044 SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
9045 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9046 | SWP_FRAMECHANGED);
9047 /* Now put F1 above F2. */
9048 SetWindowPos (hwnd2, hwnd1, 0, 0, 0, 0,
9049 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9050 | SWP_FRAMECHANGED);
9051 }
9052 }
9053 else if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
9054 /* Put F1 below F2 in the z-order. */
9055 SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
9056 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9057 | SWP_FRAMECHANGED);
9058 unblock_input ();
9059}
9060
9061DEFUN ("w32-frame-restack", Fw32_frame_restack, Sw32_frame_restack, 2, 3, 0,
9062 doc: /* Restack FRAME1 below FRAME2.
9063This means that if both frames are visible and the display areas of
9064these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
9065third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
9066means that if both frames are visible and the display areas of these
9067frames overlap, FRAME1 (partially) obscures FRAME2.
9068
9069This may be thought of as an atomic action performed in two steps: The
9070first step removes FRAME1's window-system window from the display. The
9071second step reinserts FRAME1's window below (above if ABOVE is true)
9072that of FRAME2. Hence the position of FRAME2 in its display's Z
9073\(stacking) order relative to all other frames excluding FRAME1 remains
9074unaltered.
9075
9076Some window managers may refuse to restack windows. */)
9077 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
9078{
9079 struct frame *f1 = decode_live_frame (frame1);
9080 struct frame *f2 = decode_live_frame (frame2);
9081
9082 if (FRAME_W32_P (f1) && FRAME_W32_P (f2))
9083 {
9084 w32_frame_restack (f1, f2, !NILP (above));
9085 return Qt;
9086 }
9087 else
9088 {
9089 error ("Cannot restack frames");
9090 return Qnil;
9091 }
9092}
9093
8562DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position, 9094DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
8563 Sw32_mouse_absolute_pixel_position, 0, 0, 0, 9095 Sw32_mouse_absolute_pixel_position, 0, 0, 0,
8564 doc: /* Return absolute position of mouse cursor in pixels. 9096 doc: /* Return absolute position of mouse cursor in pixels.
@@ -9753,6 +10285,13 @@ frame_parm_handler w32_frame_parm_handlers[] =
9753 0, /* x_set_sticky */ 10285 0, /* x_set_sticky */
9754 0, /* x_set_tool_bar_position */ 10286 0, /* x_set_tool_bar_position */
9755 0, /* x_set_inhibit_double_buffering */ 10287 0, /* x_set_inhibit_double_buffering */
10288 x_set_undecorated,
10289 x_set_parent_frame,
10290 x_set_skip_taskbar,
10291 x_set_no_focus_on_map,
10292 x_set_no_accept_focus,
10293 x_set_z_group,
10294 0, /* x_set_override_redirect */
9756}; 10295};
9757 10296
9758void 10297void
@@ -10132,6 +10671,8 @@ tip frame. */);
10132 defsubr (&Sx_display_list); 10671 defsubr (&Sx_display_list);
10133 defsubr (&Sw32_frame_geometry); 10672 defsubr (&Sw32_frame_geometry);
10134 defsubr (&Sw32_frame_edges); 10673 defsubr (&Sw32_frame_edges);
10674 defsubr (&Sw32_frame_list_z_order);
10675 defsubr (&Sw32_frame_restack);
10135 defsubr (&Sw32_mouse_absolute_pixel_position); 10676 defsubr (&Sw32_mouse_absolute_pixel_position);
10136 defsubr (&Sw32_set_mouse_absolute_pixel_position); 10677 defsubr (&Sw32_set_mouse_absolute_pixel_position);
10137 defsubr (&Sx_synchronize); 10678 defsubr (&Sx_synchronize);
diff --git a/src/w32font.c b/src/w32font.c
index 37df1bc43c0..ef6eac44a68 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -2553,11 +2553,22 @@ in the font selection dialog. */)
2553 SelectObject (hdc, oldobj); 2553 SelectObject (hdc, oldobj);
2554 ReleaseDC (FRAME_W32_WINDOW (f), hdc); 2554 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
2555 2555
2556 if (!ChooseFont (&cf) 2556 {
2557 || logfont_to_fcname (&lf, cf.iPointSize, buf, 100) < 0) 2557 int count = SPECPDL_INDEX ();
2558 return Qnil; 2558 Lisp_Object value = Qnil;
2559
2560 w32_dialog_in_progress (Qt);
2561 specbind (Qinhibit_redisplay, Qt);
2562 record_unwind_protect (w32_dialog_in_progress, Qnil);
2563
2564 if (ChooseFont (&cf)
2565 && logfont_to_fcname (&lf, cf.iPointSize, buf, 100) >= 0)
2566 value = DECODE_SYSTEM (build_string (buf));
2559 2567
2560 return DECODE_SYSTEM (build_string (buf)); 2568 unbind_to (count, Qnil);
2569
2570 return value;
2571 }
2561} 2572}
2562 2573
2563static const char *const w32font_booleans [] = { 2574static const char *const w32font_booleans [] = {
diff --git a/src/w32term.c b/src/w32term.c
index 31f0b4a2fa0..b50f0d39a48 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -3095,7 +3095,8 @@ construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
3095 coordinates, so cast to short to interpret them correctly. */ 3095 coordinates, so cast to short to interpret them correctly. */
3096 p.x = (short) LOWORD (msg->msg.lParam); 3096 p.x = (short) LOWORD (msg->msg.lParam);
3097 p.y = (short) HIWORD (msg->msg.lParam); 3097 p.y = (short) HIWORD (msg->msg.lParam);
3098 ScreenToClient (msg->msg.hwnd, &p); 3098 /* For the case that F's w32 window is not msg->msg.hwnd. */
3099 ScreenToClient (FRAME_W32_WINDOW (f), &p);
3099 XSETINT (result->x, p.x); 3100 XSETINT (result->x, p.x);
3100 XSETINT (result->y, p.y); 3101 XSETINT (result->y, p.y);
3101 XSETFRAME (result->frame_or_window, f); 3102 XSETFRAME (result->frame_or_window, f);
@@ -3446,8 +3447,22 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3446 /* If mouse was grabbed on a frame, give coords for that 3447 /* If mouse was grabbed on a frame, give coords for that
3447 frame even if the mouse is now outside it. Otherwise 3448 frame even if the mouse is now outside it. Otherwise
3448 check for window under mouse on one of our frames. */ 3449 check for window under mouse on one of our frames. */
3449 f1 = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame 3450 if (x_mouse_grabbed (dpyinfo))
3450 : x_any_window_to_frame (dpyinfo, WindowFromPoint (pt))); 3451 f1 = dpyinfo->last_mouse_frame;
3452 else
3453 {
3454 HWND wfp = WindowFromPoint (pt);
3455
3456 if (wfp && (f1 = x_any_window_to_frame (dpyinfo, wfp)))
3457 {
3458 HWND cwfp = ChildWindowFromPoint (wfp, pt);
3459 struct frame *f2;
3460
3461 /* If cwfp exists it should be one of our windows ... */
3462 if (cwfp && (f2 = x_any_window_to_frame (dpyinfo, cwfp)))
3463 f1 = f2;
3464 }
3465 }
3451 3466
3452 /* If not, is it one of our scroll bars? */ 3467 /* If not, is it one of our scroll bars? */
3453 if (! f1) 3468 if (! f1)
@@ -3897,7 +3912,10 @@ w32_set_vertical_scroll_bar (struct window *w,
3897 /* Make sure scroll bar is "visible" before moving, to ensure the 3912 /* Make sure scroll bar is "visible" before moving, to ensure the
3898 area of the parent window now exposed will be refreshed. */ 3913 area of the parent window now exposed will be refreshed. */
3899 my_show_window (f, hwnd, SW_HIDE); 3914 my_show_window (f, hwnd, SW_HIDE);
3900 MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); 3915/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
3916 /* Try to not draw over child frames. */
3917 SetWindowPos (hwnd, HWND_BOTTOM, left, top, width, max (height, 1),
3918 SWP_FRAMECHANGED);
3901 3919
3902 si.cbSize = sizeof (si); 3920 si.cbSize = sizeof (si);
3903 si.fMask = SIF_RANGE; 3921 si.fMask = SIF_RANGE;
@@ -3995,7 +4013,10 @@ w32_set_horizontal_scroll_bar (struct window *w,
3995 /* Make sure scroll bar is "visible" before moving, to ensure the 4013 /* Make sure scroll bar is "visible" before moving, to ensure the
3996 area of the parent window now exposed will be refreshed. */ 4014 area of the parent window now exposed will be refreshed. */
3997 my_show_window (f, hwnd, SW_HIDE); 4015 my_show_window (f, hwnd, SW_HIDE);
3998 MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); 4016/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
4017 /* Try to not draw over child frames. */
4018 SetWindowPos (hwnd, HWND_BOTTOM, left, top, max (width, 1), height,
4019 SWP_FRAMECHANGED);
3999 4020
4000 /* +++ SetScrollInfo +++ */ 4021 /* +++ SetScrollInfo +++ */
4001 si.cbSize = sizeof (si); 4022 si.cbSize = sizeof (si);
@@ -4649,7 +4670,7 @@ w32_read_socket (struct terminal *terminal,
4649 in that case expose_frame will do nothing, and if 4670 in that case expose_frame will do nothing, and if
4650 the various redisplay flags happen to be unset, 4671 the various redisplay flags happen to be unset,
4651 we are left with a blank frame. */ 4672 we are left with a blank frame. */
4652 if (!FRAME_GARBAGED_P (f)) 4673 if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
4653 { 4674 {
4654 HDC hdc = get_frame_dc (f); 4675 HDC hdc = get_frame_dc (f);
4655 4676
@@ -4835,8 +4856,15 @@ w32_read_socket (struct terminal *terminal,
4835 4856
4836 if (f) 4857 if (f)
4837 { 4858 {
4838 /* Generate SELECT_WINDOW_EVENTs when needed. */ 4859 /* Maybe generate SELECT_WINDOW_EVENTs for
4839 if (!NILP (Vmouse_autoselect_window)) 4860 `mouse-autoselect-window'. */
4861 if (!NILP (Vmouse_autoselect_window)
4862 && (f == XFRAME (selected_frame)
4863 /* Switch to f from another frame iff
4864 focus_follows_mouse is set and f accepts
4865 focus. */
4866 || (!NILP (focus_follows_mouse)
4867 && !FRAME_NO_ACCEPT_FOCUS (f))))
4840 { 4868 {
4841 static Lisp_Object last_mouse_window; 4869 static Lisp_Object last_mouse_window;
4842 Lisp_Object window = window_from_coordinates 4870 Lisp_Object window = window_from_coordinates
@@ -4848,20 +4876,16 @@ w32_read_socket (struct terminal *terminal,
4848 only when it is active. */ 4876 only when it is active. */
4849 if (WINDOWP (window) 4877 if (WINDOWP (window)
4850 && !EQ (window, last_mouse_window) 4878 && !EQ (window, last_mouse_window)
4851 && !EQ (window, selected_window) 4879 && !EQ (window, selected_window))
4852 /* For click-to-focus window managers
4853 create event iff we don't leave the
4854 selected frame. */
4855 && (focus_follows_mouse
4856 || (EQ (XWINDOW (window)->frame,
4857 XWINDOW (selected_window)->frame))))
4858 { 4880 {
4859 inev.kind = SELECT_WINDOW_EVENT; 4881 inev.kind = SELECT_WINDOW_EVENT;
4860 inev.frame_or_window = window; 4882 inev.frame_or_window = window;
4861 } 4883 }
4884
4862 /* Remember the last window where we saw the mouse. */ 4885 /* Remember the last window where we saw the mouse. */
4863 last_mouse_window = window; 4886 last_mouse_window = window;
4864 } 4887 }
4888
4865 if (!note_mouse_movement (f, &msg.msg)) 4889 if (!note_mouse_movement (f, &msg.msg))
4866 help_echo_string = previous_help_echo_string; 4890 help_echo_string = previous_help_echo_string;
4867 } 4891 }
@@ -4927,7 +4951,10 @@ w32_read_socket (struct terminal *terminal,
4927 4951
4928 if (tool_bar_p 4952 if (tool_bar_p
4929 || (dpyinfo->w32_focus_frame 4953 || (dpyinfo->w32_focus_frame
4930 && f != dpyinfo->w32_focus_frame)) 4954 && f != dpyinfo->w32_focus_frame
4955 /* This does not help when the click happens in
4956 a grand-parent frame. */
4957 && !frame_ancestor_p (f, dpyinfo->w32_focus_frame)))
4931 inev.kind = NO_EVENT; 4958 inev.kind = NO_EVENT;
4932 } 4959 }
4933 4960
@@ -4964,21 +4991,40 @@ w32_read_socket (struct terminal *terminal,
4964 4991
4965 if (f) 4992 if (f)
4966 { 4993 {
4967
4968 if (!dpyinfo->w32_focus_frame 4994 if (!dpyinfo->w32_focus_frame
4969 || f == dpyinfo->w32_focus_frame) 4995 || f == dpyinfo->w32_focus_frame)
4996 /* Emit an Emacs wheel-up/down event. */
4970 { 4997 {
4971 /* Emit an Emacs wheel-up/down event. */
4972 construct_mouse_wheel (&inev, &msg, f); 4998 construct_mouse_wheel (&inev, &msg, f);
4999
5000 /* Ignore any mouse motion that happened before this
5001 event; any subsequent mouse-movement Emacs events
5002 should reflect only motion after the ButtonPress. */
5003 f->mouse_moved = false;
5004 f->last_tool_bar_item = -1;
5005 dpyinfo->last_mouse_frame = f;
5006 }
5007 else if (FRAME_NO_ACCEPT_FOCUS (f)
5008 && !x_mouse_grabbed (dpyinfo))
5009 {
5010 Lisp_Object frame1 = get_frame_param (f, Qmouse_wheel_frame);
5011 struct frame *f1 = FRAMEP (frame1) ? XFRAME (frame1) : NULL;
5012
5013 if (f1 && FRAME_LIVE_P (f1) && FRAME_W32_P (f1))
5014 {
5015 construct_mouse_wheel (&inev, &msg, f1);
5016 f1->mouse_moved = false;
5017 f1->last_tool_bar_item = -1;
5018 dpyinfo->last_mouse_frame = f1;
5019 }
5020 else
5021 dpyinfo->last_mouse_frame = f;
4973 } 5022 }
4974 /* Ignore any mouse motion that happened before this 5023 else
4975 event; any subsequent mouse-movement Emacs events 5024 dpyinfo->last_mouse_frame = f;
4976 should reflect only motion after the
4977 ButtonPress. */
4978 f->mouse_moved = false;
4979 f->last_tool_bar_item = -1;
4980 } 5025 }
4981 dpyinfo->last_mouse_frame = f; 5026 else
5027 dpyinfo->last_mouse_frame = f;
4982 } 5028 }
4983 break; 5029 break;
4984 5030
@@ -5031,6 +5077,7 @@ w32_read_socket (struct terminal *terminal,
5031 w32fullscreen_hook (f); 5077 w32fullscreen_hook (f);
5032 } 5078 }
5033 } 5079 }
5080
5034 check_visibility = 1; 5081 check_visibility = 1;
5035 break; 5082 break;
5036 5083
@@ -5969,6 +6016,8 @@ x_calc_absolute_position (struct frame *f)
5969 are computed correctly (Bug#21173). */ 6016 are computed correctly (Bug#21173). */
5970 int display_left = 0; 6017 int display_left = 0;
5971 int display_top = 0; 6018 int display_top = 0;
6019 struct frame *p = FRAME_PARENT_FRAME (f);
6020
5972 if (flags & (XNegative | YNegative)) 6021 if (flags & (XNegative | YNegative))
5973 { 6022 {
5974 Lisp_Object list; 6023 Lisp_Object list;
@@ -5997,18 +6046,34 @@ x_calc_absolute_position (struct frame *f)
5997 /* Treat negative positions as relative to the rightmost bottommost 6046 /* Treat negative positions as relative to the rightmost bottommost
5998 position that fits on the screen. */ 6047 position that fits on the screen. */
5999 if (flags & XNegative) 6048 if (flags & XNegative)
6000 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) 6049 {
6001 + display_left 6050 if (p)
6002 - FRAME_PIXEL_WIDTH (f) 6051 f->left_pos = (FRAME_PIXEL_WIDTH (p)
6003 + f->left_pos 6052 - FRAME_PIXEL_WIDTH (f)
6004 - (left_right_borders_width - 1)); 6053 + f->left_pos
6054 - (left_right_borders_width - 1));
6055 else
6056 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
6057 + display_left
6058 - FRAME_PIXEL_WIDTH (f)
6059 + f->left_pos
6060 - (left_right_borders_width - 1));
6061 }
6005 6062
6006 if (flags & YNegative) 6063 if (flags & YNegative)
6007 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) 6064 {
6008 + display_top 6065 if (p)
6009 - FRAME_PIXEL_HEIGHT (f) 6066 f->top_pos = (FRAME_PIXEL_HEIGHT (p)
6010 + f->top_pos 6067 - FRAME_PIXEL_HEIGHT (f)
6011 - (top_bottom_borders_height - 1)); 6068 + f->top_pos
6069 - (top_bottom_borders_height - 1));
6070 else
6071 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
6072 + display_top
6073 - FRAME_PIXEL_HEIGHT (f)
6074 + f->top_pos
6075 - (top_bottom_borders_height - 1));
6076 }
6012 6077
6013 /* The left_pos and top_pos are now relative to the top and left 6078 /* The left_pos and top_pos are now relative to the top and left
6014 screen edges, so the flags should correspond. */ 6079 screen edges, so the flags should correspond. */
@@ -6046,11 +6111,16 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
6046 modified_left = f->left_pos; 6111 modified_left = f->left_pos;
6047 modified_top = f->top_pos; 6112 modified_top = f->top_pos;
6048 6113
6049 my_set_window_pos (FRAME_W32_WINDOW (f), 6114 if (!FRAME_PARENT_FRAME (f))
6050 NULL, 6115 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6051 modified_left, modified_top, 6116 modified_left, modified_top,
6052 0, 0, 6117 0, 0,
6053 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); 6118 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6119 else
6120 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6121 modified_left, modified_top,
6122 0, 0,
6123 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6054 unblock_input (); 6124 unblock_input ();
6055} 6125}
6056 6126
@@ -6254,11 +6324,18 @@ x_set_window_size (struct frame *f, bool change_gravity,
6254 Fcons (make_number (rect.right - rect.left), 6324 Fcons (make_number (rect.right - rect.left),
6255 make_number (rect.bottom - rect.top)))); 6325 make_number (rect.bottom - rect.top))));
6256 6326
6257 my_set_window_pos (FRAME_W32_WINDOW (f), NULL, 6327 if (!FRAME_PARENT_FRAME (f))
6258 0, 0, 6328 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6259 rect.right - rect.left, 6329 0, 0,
6260 rect.bottom - rect.top, 6330 rect.right - rect.left,
6261 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 6331 rect.bottom - rect.top,
6332 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
6333 else
6334 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6335 0, 0,
6336 rect.right - rect.left,
6337 rect.bottom - rect.top,
6338 SWP_NOMOVE | SWP_NOACTIVATE);
6262 6339
6263 change_frame_size (f, 6340 change_frame_size (f,
6264 ((pixelwidth == 0) 6341 ((pixelwidth == 0)
@@ -6447,18 +6524,21 @@ x_make_frame_visible (struct frame *f)
6447 if (! FRAME_ICONIFIED_P (f) 6524 if (! FRAME_ICONIFIED_P (f)
6448 && ! f->output_data.w32->asked_for_visible) 6525 && ! f->output_data.w32->asked_for_visible)
6449 { 6526 {
6450 RECT workarea_rect; 6527 if (!FRAME_PARENT_FRAME (f))
6451 RECT window_rect; 6528 {
6452 6529 RECT workarea_rect;
6453 /* Adjust vertical window position in order to avoid being 6530 RECT window_rect;
6454 covered by a taskbar placed at the bottom of the desktop. */ 6531
6455 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0); 6532 /* Adjust vertical window position in order to avoid being
6456 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect); 6533 covered by a taskbar placed at the bottom of the desktop. */
6457 if (window_rect.bottom > workarea_rect.bottom 6534 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
6458 && window_rect.top > workarea_rect.top) 6535 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
6459 f->top_pos = max (window_rect.top 6536 if (window_rect.bottom > workarea_rect.bottom
6460 - window_rect.bottom + workarea_rect.bottom, 6537 && window_rect.top > workarea_rect.top)
6461 workarea_rect.top); 6538 f->top_pos = max (window_rect.top
6539 - window_rect.bottom + workarea_rect.bottom,
6540 workarea_rect.top);
6541 }
6462 6542
6463 x_set_offset (f, f->left_pos, f->top_pos, 0); 6543 x_set_offset (f, f->left_pos, f->top_pos, 0);
6464 } 6544 }
@@ -6473,7 +6553,11 @@ x_make_frame_visible (struct frame *f)
6473 set for minimized windows that are still visible, so use that to 6553 set for minimized windows that are still visible, so use that to
6474 determine the appropriate flag to pass ShowWindow. */ 6554 determine the appropriate flag to pass ShowWindow. */
6475 my_show_window (f, FRAME_W32_WINDOW (f), 6555 my_show_window (f, FRAME_W32_WINDOW (f),
6476 FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL); 6556 FRAME_ICONIFIED_P (f)
6557 ? SW_RESTORE
6558 : FRAME_NO_FOCUS_ON_MAP (f)
6559 ? SW_SHOWNOACTIVATE
6560 : SW_SHOWNORMAL);
6477 } 6561 }
6478 6562
6479 /* Synchronize to ensure Emacs knows the frame is visible 6563 /* Synchronize to ensure Emacs knows the frame is visible
diff --git a/src/w32term.h b/src/w32term.h
index 990d3794b22..6896ef4f2c6 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -246,6 +246,7 @@ extern void x_set_internal_border_width (struct frame *f,
246 Lisp_Object value, 246 Lisp_Object value,
247 Lisp_Object oldval); 247 Lisp_Object oldval);
248extern void initialize_frame_menubar (struct frame *); 248extern void initialize_frame_menubar (struct frame *);
249extern void w32_dialog_in_progress (Lisp_Object in_progress);
249 250
250/* w32inevt.c */ 251/* w32inevt.c */
251extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId); 252extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId);
diff --git a/src/xdisp.c b/src/xdisp.c
index af086d17eb8..42a59d63b13 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11767,6 +11767,7 @@ x_consider_frame_title (Lisp_Object frame)
11767 && FRAME_KBOARD (tf) == FRAME_KBOARD (f) 11767 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
11768 && !FRAME_MINIBUF_ONLY_P (tf) 11768 && !FRAME_MINIBUF_ONLY_P (tf)
11769 && !EQ (other_frame, tip_frame) 11769 && !EQ (other_frame, tip_frame)
11770 && !FRAME_PARENT_FRAME (tf)
11770 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) 11771 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
11771 break; 11772 break;
11772 } 11773 }
@@ -11883,6 +11884,7 @@ prepare_menu_bars (void)
11883 continue; 11884 continue;
11884 11885
11885 if (!EQ (frame, tooltip_frame) 11886 if (!EQ (frame, tooltip_frame)
11887 && !FRAME_PARENT_FRAME (f)
11886 && (FRAME_ICONIFIED_P (f) 11888 && (FRAME_ICONIFIED_P (f)
11887 || FRAME_VISIBLE_P (f) == 1 11889 || FRAME_VISIBLE_P (f) == 1
11888 /* Exclude TTY frames that are obscured because they 11890 /* Exclude TTY frames that are obscured because they
@@ -11929,6 +11931,10 @@ prepare_menu_bars (void)
11929 continue; 11931 continue;
11930 11932
11931 run_window_size_change_functions (frame); 11933 run_window_size_change_functions (frame);
11934
11935 if (FRAME_PARENT_FRAME (f))
11936 continue;
11937
11932 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); 11938 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
11933#ifdef HAVE_WINDOW_SYSTEM 11939#ifdef HAVE_WINDOW_SYSTEM
11934 update_tool_bar (f, false); 11940 update_tool_bar (f, false);
diff --git a/src/xfns.c b/src/xfns.c
index d3e0839d8ac..3d667446e67 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -90,6 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
90#include <Xm/FileSB.h> 90#include <Xm/FileSB.h>
91#include <Xm/List.h> 91#include <Xm/List.h>
92#include <Xm/TextF.h> 92#include <Xm/TextF.h>
93#include <Xm/MwmUtil.h>
93#endif 94#endif
94 95
95#ifdef USE_LUCID 96#ifdef USE_LUCID
@@ -117,6 +118,35 @@ static ptrdiff_t image_cache_refcount;
117static int dpyinfo_refcount; 118static int dpyinfo_refcount;
118#endif 119#endif
119 120
121#ifndef USE_MOTIF
122#ifndef USE_GTK
123/** #define MWM_HINTS_FUNCTIONS (1L << 0) **/
124#define MWM_HINTS_DECORATIONS (1L << 1)
125/** #define MWM_HINTS_INPUT_MODE (1L << 2) **/
126/** #define MWM_HINTS_STATUS (1L << 3) **/
127
128#define MWM_DECOR_ALL (1L << 0)
129/** #define MWM_DECOR_BORDER (1L << 1) **/
130/** #define MWM_DECOR_RESIZEH (1L << 2) **/
131/** #define MWM_DECOR_TITLE (1L << 3) **/
132/** #define MWM_DECOR_MENU (1L << 4) **/
133/** #define MWM_DECOR_MINIMIZE (1L << 5) **/
134/** #define MWM_DECOR_MAXIMIZE (1L << 6) **/
135
136/** #define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS" **/
137
138typedef struct {
139 unsigned long flags;
140 unsigned long functions;
141 unsigned long decorations;
142 long input_mode;
143 unsigned long status;
144} PropMotifWmHints;
145
146#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
147#endif /* NOT USE_GTK */
148#endif /* NOT USE_MOTIF */
149
120static struct x_display_info *x_display_info_for_name (Lisp_Object); 150static struct x_display_info *x_display_info_for_name (Lisp_Object);
121static void set_up_x_back_buffer (struct frame *f); 151static void set_up_x_back_buffer (struct frame *f);
122 152
@@ -185,7 +215,9 @@ x_real_pos_and_offsets (struct frame *f,
185 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0; 215 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
186 int real_x = 0, real_y = 0; 216 int real_x = 0, real_y = 0;
187 bool had_errors = false; 217 bool had_errors = false;
188 Window win = f->output_data.x->parent_desc; 218 Window win = (FRAME_PARENT_FRAME (f)
219 ? FRAME_X_WINDOW (FRAME_PARENT_FRAME (f))
220 : f->output_data.x->parent_desc);
189 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 221 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
190 long max_len = 400; 222 long max_len = 400;
191 Atom target_type = XA_CARDINAL; 223 Atom target_type = XA_CARDINAL;
@@ -323,7 +355,8 @@ x_real_pos_and_offsets (struct frame *f,
323 outer_geom_cookie = xcb_get_geometry (xcb_conn, 355 outer_geom_cookie = xcb_get_geometry (xcb_conn,
324 FRAME_OUTER_WINDOW (f)); 356 FRAME_OUTER_WINDOW (f));
325 357
326 if (dpyinfo->root_window == f->output_data.x->parent_desc) 358 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
359 && !FRAME_PARENT_FRAME (f))
327 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */ 360 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
328 prop_cookie = xcb_get_property (xcb_conn, 0, win, 361 prop_cookie = xcb_get_property (xcb_conn, 0, win,
329 dpyinfo->Xatom_net_frame_extents, 362 dpyinfo->Xatom_net_frame_extents,
@@ -437,7 +470,8 @@ x_real_pos_and_offsets (struct frame *f,
437#endif 470#endif
438 } 471 }
439 472
440 if (dpyinfo->root_window == f->output_data.x->parent_desc) 473 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
474 && !FRAME_PARENT_FRAME (f))
441 { 475 {
442 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */ 476 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
443#ifdef USE_XCB 477#ifdef USE_XCB
@@ -735,6 +769,204 @@ x_set_inhibit_double_buffering (struct frame *f,
735 unblock_input (); 769 unblock_input ();
736} 770}
737 771
772/**
773 * x_set_undecorated:
774 *
775 * Set frame F's `undecorated' parameter. If non-nil, F's window-system
776 * window is drawn without decorations, title, minimize/maximize boxes
777 * and external borders. This usually means that the window cannot be
778 * dragged, resized, iconified, maximized or deleted with the mouse. If
779 * nil, draw the frame with all the elements listed above unless these
780 * have been suspended via window manager settings.
781 *
782 * Some window managers may not honor this parameter.
783 */
784static void
785x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
786{
787 if (!EQ (new_value, old_value))
788 {
789 FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
790#ifdef USE_GTK
791 xg_set_undecorated (f, new_value);
792#else
793 Display *dpy = FRAME_X_DISPLAY (f);
794 PropMotifWmHints hints;
795 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
796
797 memset (&hints, 0, sizeof(hints));
798 hints.flags = MWM_HINTS_DECORATIONS;
799 hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
800
801 block_input ();
802 /* For some reason the third and fourth argument in the following
803 call must be identic: In the corresponding XGetWindowProperty
804 call in getMotifHints, xfwm has the third and seventh arg both
805 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
806 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
807 PropModeReplace, (unsigned char *) &hints,
808 PROP_MOTIF_WM_HINTS_ELEMENTS);
809 unblock_input ();
810
811#endif /* USE_GTK */
812 }
813}
814
815/**
816 * x_set_parent_frame:
817 *
818 * Set frame F's `parent-frame' parameter. If non-nil, make F a child
819 * frame of the frame specified by that parameter. Technically, this
820 * makes F's window-system window a child window of the parent frame's
821 * window-system window. If nil, make F's window-system window a
822 * top-level window--a child of its display's root window.
823 *
824 * A child frame is clipped at the native edges of its parent frame.
825 * Its `left' and `top' parameters specify positions relative to the
826 * top-left corner of its parent frame's native rectangle. Usually,
827 * moving a parent frame moves all its child frames too, keeping their
828 * position relative to the parent unaltered. When a parent frame is
829 * iconified or made invisible, its child frames are made invisible.
830 * When a parent frame is deleted, its child frames are deleted too.
831 *
832 * A visible child frame always appears on top of its parent frame thus
833 * obscuring parts of it. When a frame has more than one child frame,
834 * their stacking order is specified just as that of non-child frames
835 * relative to their display.
836 *
837 * Whether a child frame has a menu or tool bar may be window-system or
838 * window manager dependent. It's advisable to disable both via the
839 * frame parameter settings.
840 *
841 * Some window managers may not honor this parameter.
842 */
843static void
844x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
845{
846 struct frame *p = NULL;
847
848 if (!NILP (new_value)
849 && (!FRAMEP (new_value)
850 || !FRAME_LIVE_P (p = XFRAME (new_value))
851 || !FRAME_X_P (p)))
852 {
853 store_frame_param (f, Qparent_frame, old_value);
854 error ("Invalid specification of `parent-frame'");
855 }
856
857 if (p != FRAME_PARENT_FRAME (f))
858 {
859 block_input ();
860 XReparentWindow
861 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
862 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
863 f->left_pos, f->top_pos);
864 unblock_input ();
865
866 fset_parent_frame (f, new_value);
867 }
868}
869
870/**
871 * x_set_no_focus_on_map:
872 *
873 * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
874 * that F's window-system window does not want to receive input focus
875 * when it is mapped. (A frame's window is mapped when the frame is
876 * displayed for the first time and when the frame changes its state
877 * from `iconified' or `invisible' to `visible'.)
878 *
879 * Some window managers may not honor this parameter.
880 */
881static void
882x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
883{
884 if (!EQ (new_value, old_value))
885 {
886#ifdef USE_GTK
887 xg_set_no_focus_on_map (f, new_value);
888#else /* not USE_GTK */
889 Display *dpy = FRAME_X_DISPLAY (f);
890 Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
891 Time timestamp = NILP (new_value) ? CurrentTime : 0;
892
893 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
894 XA_CARDINAL, 32, PropModeReplace,
895 (unsigned char *) &timestamp, 1);
896#endif /* USE_GTK */
897 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
898 }
899}
900
901/**
902 * x_set_no_accept_focus:
903 *
904 * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
905 * that F's window-system window does not want to receive input focus
906 * via mouse clicks or by moving the mouse into it.
907 *
908 * If non-nil, this may have the unwanted side-effect that a user cannot
909 * scroll a non-selected frame with the mouse.
910 *
911 * Some window managers may not honor this parameter.
912 */
913static void
914x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
915{
916 if (!EQ (new_value, old_value))
917 {
918#ifdef USE_GTK
919 xg_set_no_accept_focus (f, new_value);
920#else /* not USE_GTK */
921#ifdef USE_X_TOOLKIT
922 Arg al[1];
923
924 XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
925 XtSetValues (f->output_data.x->widget, al, 1);
926#else /* not USE_X_TOOLKIT */
927 Window window = FRAME_X_WINDOW (f);
928
929 f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
930 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
931#endif /* USE_X_TOOLKIT */
932#endif /* USE_GTK */
933 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
934 }
935}
936
937/**
938 * x_set_override_redirect:
939 *
940 * Set frame F's `override_redirect' parameter which, if non-nil, hints
941 * that the window manager doesn't want to deal with F. Usually, such
942 * frames have no decorations and always appear on top of all frames.
943 *
944 * Some window managers may not honor this parameter.
945 */
946static void
947x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
948{
949 if (!EQ (new_value, old_value))
950 {
951 /* Here (xfwm) override_redirect can be changed for invisible
952 frames only. */
953 x_make_frame_invisible (f);
954
955#ifdef USE_GTK
956 xg_set_override_redirect (f, new_value);
957#else /* not USE_GTK */
958 XSetWindowAttributes attributes;
959
960 attributes.override_redirect = NILP (new_value) ? False : True;
961 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
962 CWOverrideRedirect, &attributes);
963#endif
964 x_make_frame_visible (f);
965 FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
966 }
967}
968
969
738#ifdef USE_GTK 970#ifdef USE_GTK
739 971
740/* Set icon from FILE for frame F. By using GTK functions the icon 972/* Set icon from FILE for frame F. By using GTK functions the icon
@@ -1272,7 +1504,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1272 most of the commands try to apply themselves to the minibuffer 1504 most of the commands try to apply themselves to the minibuffer
1273 frame itself, and get an error because you can't switch buffers 1505 frame itself, and get an error because you can't switch buffers
1274 in or split the minibuffer window. */ 1506 in or split the minibuffer window. */
1275 if (FRAME_MINIBUF_ONLY_P (f)) 1507 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1276 return; 1508 return;
1277 1509
1278 if (TYPE_RANGED_INTEGERP (int, value)) 1510 if (TYPE_RANGED_INTEGERP (int, value))
@@ -2693,7 +2925,7 @@ x_window (struct frame *f, long window_prompting)
2693 and specify it. 2925 and specify it.
2694 Note that we do not specify here whether the position 2926 Note that we do not specify here whether the position
2695 is a user-specified or program-specified one. 2927 is a user-specified or program-specified one.
2696 We pass that information later, in x_wm_set_size_hints. */ 2928 We pass that information later, in x_wm_set_size_hint. */
2697 { 2929 {
2698 int left = f->left_pos; 2930 int left = f->left_pos;
2699 bool xneg = (window_prompting & XNegative) != 0; 2931 bool xneg = (window_prompting & XNegative) != 0;
@@ -2783,7 +3015,8 @@ x_window (struct frame *f, long window_prompting)
2783 } 3015 }
2784#endif /* HAVE_X_I18N */ 3016#endif /* HAVE_X_I18N */
2785 3017
2786 attribute_mask = CWEventMask; 3018 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3019 attribute_mask = CWEventMask | CWOverrideRedirect;
2787 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget), 3020 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2788 attribute_mask, &attributes); 3021 attribute_mask, &attributes);
2789 3022
@@ -2803,6 +3036,25 @@ x_window (struct frame *f, long window_prompting)
2803 x_set_name (f, name, explicit); 3036 x_set_name (f, name, explicit);
2804 } 3037 }
2805 3038
3039 if (FRAME_UNDECORATED (f))
3040 {
3041 Display *dpy = FRAME_X_DISPLAY (f);
3042 PropMotifWmHints hints;
3043 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3044
3045 memset (&hints, 0, sizeof(hints));
3046 hints.flags = MWM_HINTS_DECORATIONS;
3047 hints.decorations = 0;
3048
3049 /* For some reason the third and fourth argument in the following
3050 call must be identic: In the corresponding XGetWindowProperty
3051 call in getMotifHints, xfwm has the third and seventh arg both
3052 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3053 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3054 PropModeReplace, (unsigned char *) &hints,
3055 PROP_MOTIF_WM_HINTS_ELEMENTS);
3056 }
3057
2806 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3058 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2807 f->output_data.x->current_cursor 3059 f->output_data.x->current_cursor
2808 = f->output_data.x->text_cursor); 3060 = f->output_data.x->text_cursor);
@@ -2870,8 +3122,9 @@ x_window (struct frame *f)
2870 attributes.save_under = True; 3122 attributes.save_under = True;
2871 attributes.event_mask = STANDARD_EVENT_SET; 3123 attributes.event_mask = STANDARD_EVENT_SET;
2872 attributes.colormap = FRAME_X_COLORMAP (f); 3124 attributes.colormap = FRAME_X_COLORMAP (f);
3125 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
2873 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask 3126 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2874 | CWColormap); 3127 | CWOverrideRedirect | CWColormap);
2875 3128
2876 block_input (); 3129 block_input ();
2877 FRAME_X_WINDOW (f) 3130 FRAME_X_WINDOW (f)
@@ -2943,6 +3196,26 @@ x_window (struct frame *f)
2943 x_set_name (f, name, explicit); 3196 x_set_name (f, name, explicit);
2944 } 3197 }
2945 3198
3199 if (FRAME_UNDECORATED (f))
3200 {
3201 Display *dpy = FRAME_X_DISPLAY (f);
3202 PropMotifWmHints hints;
3203 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3204
3205 memset (&hints, 0, sizeof(hints));
3206 hints.flags = MWM_HINTS_DECORATIONS;
3207 hints.decorations = 0;
3208
3209 /* For some reason the third and fourth argument in the following
3210 call must be identic: In the corresponding XGetWindowProperty
3211 call in getMotifHints, xfwm has the third and seventh arg both
3212 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3213 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3214 PropModeReplace, (unsigned char *) &hints,
3215 PROP_MOTIF_WM_HINTS_ELEMENTS);
3216 }
3217
3218
2946 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3219 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2947 f->output_data.x->current_cursor 3220 f->output_data.x->current_cursor
2948 = f->output_data.x->text_cursor); 3221 = f->output_data.x->text_cursor);
@@ -3285,11 +3558,12 @@ This function is an internal primitive--use `make-frame' instead. */)
3285 Lisp_Object frame, tem; 3558 Lisp_Object frame, tem;
3286 Lisp_Object name; 3559 Lisp_Object name;
3287 bool minibuffer_only = false; 3560 bool minibuffer_only = false;
3561 bool undecorated = false, override_redirect = false;
3288 long window_prompting = 0; 3562 long window_prompting = 0;
3289 ptrdiff_t count = SPECPDL_INDEX (); 3563 ptrdiff_t count = SPECPDL_INDEX ();
3290 Lisp_Object display; 3564 Lisp_Object display;
3291 struct x_display_info *dpyinfo = NULL; 3565 struct x_display_info *dpyinfo = NULL;
3292 Lisp_Object parent; 3566 Lisp_Object parent, parent_frame;
3293 struct kboard *kb; 3567 struct kboard *kb;
3294 int x_width = 0, x_height = 0; 3568 int x_width = 0, x_height = 0;
3295 3569
@@ -3341,6 +3615,36 @@ This function is an internal primitive--use `make-frame' instead. */)
3341 else 3615 else
3342 f = make_frame (true); 3616 f = make_frame (true);
3343 3617
3618 parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
3619 RES_TYPE_SYMBOL);
3620 /* Accept parent-frame iff parent-id was not specified. */
3621 if (!NILP (parent)
3622 || EQ (parent_frame, Qunbound)
3623 || NILP (parent_frame)
3624 || !FRAMEP (parent_frame)
3625 || !FRAME_LIVE_P (XFRAME (parent_frame))
3626 || !FRAME_X_P (XFRAME (parent_frame)))
3627 parent_frame = Qnil;
3628
3629 fset_parent_frame (f, parent_frame);
3630 store_frame_param (f, Qparent_frame, parent_frame);
3631
3632 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
3633 RES_TYPE_BOOLEAN)))
3634 && !(EQ (tem, Qunbound)))
3635 undecorated = true;
3636
3637 FRAME_UNDECORATED (f) = undecorated;
3638 store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
3639
3640 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
3641 RES_TYPE_BOOLEAN)))
3642 && !(EQ (tem, Qunbound)))
3643 override_redirect = true;
3644
3645 FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
3646 store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
3647
3344 XSETFRAME (frame, f); 3648 XSETFRAME (frame, f);
3345 3649
3346 f->terminal = dpyinfo->terminal; 3650 f->terminal = dpyinfo->terminal;
@@ -3528,15 +3832,24 @@ This function is an internal primitive--use `make-frame' instead. */)
3528 init_iterator with a null face cache, which should not happen. */ 3832 init_iterator with a null face cache, which should not happen. */
3529 init_frame_faces (f); 3833 init_frame_faces (f);
3530 3834
3531 /* The following call of change_frame_size is needed since otherwise 3835 /* We have to call adjust_frame_size here since otherwise
3532 x_set_tool_bar_lines will already work with the character sizes 3836 x_set_tool_bar_lines will already work with the character sizes
3533 installed by init_frame_faces while the frame's pixel size is 3837 installed by init_frame_faces while the frame's pixel size is still
3534 still calculated from a character size of 1 and we subsequently 3838 calculated from a character size of 1 and we subsequently hit the
3535 hit the (height >= 0) assertion in window_box_height. 3839 (height >= 0) assertion in window_box_height.
3536 3840
3537 The non-pixelwise code apparently worked around this because it 3841 The non-pixelwise code apparently worked around this because it
3538 had one frame line vs one toolbar line which left us with a zero 3842 had one frame line vs one toolbar line which left us with a zero
3539 root window height which was obviously wrong as well ... */ 3843 root window height which was obviously wrong as well ...
3844
3845 Also process `min-width' and `min-height' parameters right here
3846 because `frame-windows-min-size' needs them. */
3847 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
3848 if (NUMBERP (tem))
3849 store_frame_param (f, Qmin_width, tem);
3850 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
3851 if (NUMBERP (tem))
3852 store_frame_param (f, Qmin_height, tem);
3540 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 3853 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
3541 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, 3854 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
3542 Qx_create_frame_1); 3855 Qx_create_frame_1);
@@ -3611,6 +3924,21 @@ This function is an internal primitive--use `make-frame' instead. */)
3611 x_default_parameter (f, parms, Qalpha, Qnil, 3924 x_default_parameter (f, parms, Qalpha, Qnil,
3612 "alpha", "Alpha", RES_TYPE_NUMBER); 3925 "alpha", "Alpha", RES_TYPE_NUMBER);
3613 3926
3927 if (!NILP (parent_frame))
3928 {
3929 struct frame *p = XFRAME (parent_frame);
3930
3931 block_input ();
3932 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
3933 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
3934 unblock_input ();
3935 }
3936
3937 x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
3938 NULL, NULL, RES_TYPE_BOOLEAN);
3939 x_default_parameter (f, parms, Qno_accept_focus, Qnil,
3940 NULL, NULL, RES_TYPE_BOOLEAN);
3941
3614#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 3942#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3615 /* Create the menu bar. */ 3943 /* Create the menu bar. */
3616 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 3944 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
@@ -3656,23 +3984,23 @@ This function is an internal primitive--use `make-frame' instead. */)
3656 /* Make the window appear on the frame and enable display, unless 3984 /* Make the window appear on the frame and enable display, unless
3657 the caller says not to. However, with explicit parent, Emacs 3985 the caller says not to. However, with explicit parent, Emacs
3658 cannot control visibility, so don't try. */ 3986 cannot control visibility, so don't try. */
3659 if (! f->output_data.x->explicit_parent) 3987 if (!f->output_data.x->explicit_parent)
3660 { 3988 {
3661 Lisp_Object visibility; 3989 Lisp_Object visibility
3662 3990 = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
3663 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3664 RES_TYPE_SYMBOL);
3665 if (EQ (visibility, Qunbound))
3666 visibility = Qt;
3667 3991
3668 if (EQ (visibility, Qicon)) 3992 if (EQ (visibility, Qicon))
3669 x_iconify_frame (f); 3993 x_iconify_frame (f);
3670 else if (! NILP (visibility))
3671 x_make_frame_visible (f);
3672 else 3994 else
3673 { 3995 {
3674 /* Must have been Qnil. */ 3996 if (EQ (visibility, Qunbound))
3997 visibility = Qt;
3998
3999 if (!NILP (visibility))
4000 x_make_frame_visible (f);
3675 } 4001 }
4002
4003 store_frame_param (f, Qvisibility, visibility);
3676 } 4004 }
3677 4005
3678 block_input (); 4006 block_input ();
@@ -3685,14 +4013,21 @@ This function is an internal primitive--use `make-frame' instead. */)
3685 if (dpyinfo->client_leader_window != 0) 4013 if (dpyinfo->client_leader_window != 0)
3686 { 4014 {
3687 XChangeProperty (FRAME_X_DISPLAY (f), 4015 XChangeProperty (FRAME_X_DISPLAY (f),
3688 FRAME_OUTER_WINDOW (f), 4016 FRAME_OUTER_WINDOW (f),
3689 dpyinfo->Xatom_wm_client_leader, 4017 dpyinfo->Xatom_wm_client_leader,
3690 XA_WINDOW, 32, PropModeReplace, 4018 XA_WINDOW, 32, PropModeReplace,
3691 (unsigned char *) &dpyinfo->client_leader_window, 1); 4019 (unsigned char *) &dpyinfo->client_leader_window, 1);
3692 } 4020 }
3693 4021
3694 unblock_input (); 4022 unblock_input ();
3695 4023
4024 /* Works iff frame has been already mapped. */
4025 x_default_parameter (f, parms, Qskip_taskbar, Qnil,
4026 NULL, NULL, RES_TYPE_BOOLEAN);
4027 /* The `z-group' parameter works only for visible frames. */
4028 x_default_parameter (f, parms, Qz_group, Qnil,
4029 NULL, NULL, RES_TYPE_SYMBOL);
4030
3696 /* Initialize `default-minibuffer-frame' in case this is the first 4031 /* Initialize `default-minibuffer-frame' in case this is the first
3697 frame on this terminal. */ 4032 frame on this terminal. */
3698 if (FRAME_HAS_MINIBUF_P (f) 4033 if (FRAME_HAS_MINIBUF_P (f)
@@ -3710,7 +4045,7 @@ This function is an internal primitive--use `make-frame' instead. */)
3710 and similar functions. */ 4045 and similar functions. */
3711 Vwindow_list = Qnil; 4046 Vwindow_list = Qnil;
3712 4047
3713 return unbind_to (count, frame); 4048 return unbind_to (count, frame);
3714} 4049}
3715 4050
3716 4051
@@ -4644,9 +4979,9 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4644 struct frame *f = decode_live_frame (frame); 4979 struct frame *f = decode_live_frame (frame);
4645 /** XWindowAttributes atts; **/ 4980 /** XWindowAttributes atts; **/
4646 Window rootw; 4981 Window rootw;
4647 unsigned int ign, native_width, native_height; 4982 unsigned int ign, native_width, native_height, x_border_width = 0;
4648 int xy_ign, xptr, yptr; 4983 int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
4649 int left_off, right_off, top_off, bottom_off; 4984 int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
4650 int outer_left, outer_top, outer_right, outer_bottom; 4985 int outer_left, outer_top, outer_right, outer_bottom;
4651 int native_left, native_top, native_right, native_bottom; 4986 int native_left, native_top, native_right, native_bottom;
4652 int inner_left, inner_top, inner_right, inner_bottom; 4987 int inner_left, inner_top, inner_right, inner_bottom;
@@ -4660,25 +4995,51 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4660 4995
4661 block_input (); 4996 block_input ();
4662 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 4997 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4663 &rootw, &xy_ign, &xy_ign, &native_width, &native_height, 4998 &rootw, &x_native, &y_native, &native_width, &native_height,
4664 &ign, &ign); 4999 &x_border_width, &ign);
4665 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/ 5000 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
4666 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off, 5001 if (!FRAME_PARENT_FRAME (f))
4667 NULL, NULL, &xptr, &yptr, NULL); 5002 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
5003 NULL, NULL, &xptr, &yptr, NULL);
4668 unblock_input (); 5004 unblock_input ();
4669 5005
4670 /** native_width = atts.width; **/ 5006 /** native_width = atts.width; **/
4671 /** native_height = atts.height; **/ 5007 /** native_height = atts.height; **/
4672 5008
4673 outer_left = xptr; 5009 if (FRAME_PARENT_FRAME (f))
4674 outer_top = yptr; 5010 {
4675 outer_right = outer_left + left_off + native_width + right_off; 5011 Lisp_Object parent, edges;
4676 outer_bottom = outer_top + top_off + native_height + bottom_off; 5012
5013 XSETFRAME (parent, FRAME_PARENT_FRAME (f));
5014 edges = Fx_frame_edges (parent, Qnative_edges);
5015 if (!NILP (edges))
5016 {
5017 x_native += XINT (Fnth (make_number (0), edges));
5018 y_native += XINT (Fnth (make_number (1), edges));
5019 }
5020
5021 outer_left = x_native;
5022 outer_top = y_native;
5023 outer_right = outer_left + native_width + 2 * x_border_width;
5024 outer_bottom = outer_top + native_height + 2 * x_border_width;
5025
5026 native_left = x_native + x_border_width;
5027 native_top = y_native + x_border_width;
5028 native_right = native_left + native_width;
5029 native_bottom = native_top + native_height;
5030 }
5031 else
5032 {
5033 outer_left = xptr;
5034 outer_top = yptr;
5035 outer_right = outer_left + left_off + native_width + right_off;
5036 outer_bottom = outer_top + top_off + native_height + bottom_off;
4677 5037
4678 native_left = outer_left + left_off; 5038 native_left = outer_left + left_off;
4679 native_top = outer_top + top_off; 5039 native_top = outer_top + top_off;
4680 native_right = native_left + native_width; 5040 native_right = native_left + native_width;
4681 native_bottom = native_top + native_height; 5041 native_bottom = native_top + native_height;
5042 }
4682 5043
4683 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f); 5044 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
4684 inner_left = native_left + internal_border_width; 5045 inner_left = native_left + internal_border_width;
@@ -4749,7 +5110,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4749 make_number (inner_right), make_number (inner_bottom)); 5110 make_number (inner_right), make_number (inner_bottom));
4750 else 5111 else
4751 return 5112 return
4752 listn (CONSTYPE_HEAP, 10, 5113 listn (CONSTYPE_HEAP, 11,
4753 Fcons (Qouter_position, 5114 Fcons (Qouter_position,
4754 Fcons (make_number (outer_left), 5115 Fcons (make_number (outer_left),
4755 make_number (outer_top))), 5116 make_number (outer_top))),
@@ -4760,6 +5121,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4760 Fcons (Qexternal_border_size, 5121 Fcons (Qexternal_border_size,
4761 Fcons (make_number (right_off), 5122 Fcons (make_number (right_off),
4762 make_number (bottom_off))), 5123 make_number (bottom_off))),
5124 Fcons (Qouter_border_width, make_number (x_border_width)),
4763 /* Approximate. */ 5125 /* Approximate. */
4764 Fcons (Qtitle_bar_size, 5126 Fcons (Qtitle_bar_size,
4765 Fcons (make_number (0), 5127 Fcons (make_number (0),
@@ -4788,7 +5150,8 @@ and width values are in pixels.
4788 5150
4789`outer-size' is a cons of the outer width and height of FRAME. The 5151`outer-size' is a cons of the outer width and height of FRAME. The
4790 outer size includes the title bar and the external borders as well as 5152 outer size includes the title bar and the external borders as well as
4791 any menu and/or tool bar of frame. 5153 any menu and/or tool bar of frame. For a child frame the value
5154 includes FRAME's X borders, if any.
4792 5155
4793`external-border-size' is a cons of the horizontal and vertical width of 5156`external-border-size' is a cons of the horizontal and vertical width of
4794 FRAME's external borders as supplied by the window manager. 5157 FRAME's external borders as supplied by the window manager.
@@ -4815,7 +5178,11 @@ and width values are in pixels.
4815 FRAME. 5178 FRAME.
4816 5179
4817`internal-border-width' is the width of the internal border of 5180`internal-border-width' is the width of the internal border of
4818 FRAME. */) 5181 FRAME.
5182
5183`outer-border-width' is the width of the X border of FRAME. The X
5184 border is usually only shown for frames without window manager
5185 decorations like child and tooltip frames. */)
4819 (Lisp_Object frame) 5186 (Lisp_Object frame)
4820{ 5187{
4821 return frame_geometry (frame, Qnil); 5188 return frame_geometry (frame, Qnil);
@@ -4845,6 +5212,139 @@ menu bar or tool bar of FRAME. */)
4845 : Qnative_edges)); 5212 : Qnative_edges));
4846} 5213}
4847 5214
5215/**
5216 * x_frame_list_z_order:
5217 *
5218 * Recursively add list of all frames on the display specified via
5219 * DPYINFO and whose window-system window's parent is specified by
5220 * WINDOW to FRAMES and return FRAMES.
5221 */
5222static Lisp_Object
5223x_frame_list_z_order (Display* dpy, Window window)
5224{
5225 Window root, parent, *children;
5226 unsigned int nchildren;
5227 int i;
5228 Lisp_Object frames = Qnil;
5229
5230 block_input ();
5231 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
5232 {
5233 unblock_input ();
5234 for (i = 0; i < nchildren; i++)
5235 {
5236 Lisp_Object frame, tail;
5237
5238 FOR_EACH_FRAME (tail, frame)
5239 /* With a reparenting window manager the parent_desc field
5240 usually specifies the topmost windows of our frames.
5241 Otherwise FRAME_OUTER_WINDOW should do. */
5242 if (XFRAME (frame)->output_data.x->parent_desc == children[i]
5243 || FRAME_OUTER_WINDOW (XFRAME (frame)) == children[i])
5244 frames = Fcons (frame, frames);
5245 }
5246
5247 if (children) XFree ((char *)children);
5248 }
5249 else
5250 unblock_input ();
5251
5252 return frames;
5253}
5254
5255
5256DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
5257 Sx_frame_list_z_order, 0, 1, 0,
5258 doc: /* Return list of Emacs' frames, in Z (stacking) order.
5259The optional argument TERMINAL specifies which display to ask about.
5260TERMINAL should be either a frame or a display name (a string). If
5261omitted or nil, that stands for the selected frame's display. Return
5262nil if TERMINAL contains no Emacs frame.
5263
5264As a special case, if TERMINAL is non-nil and specifies a live frame,
5265return the child frames of that frame in Z (stacking) order.
5266
5267Frames are listed from topmost (first) to bottommost (last). */)
5268 (Lisp_Object terminal)
5269{
5270 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5271 Display *dpy = dpyinfo->display;
5272 Window window;
5273
5274 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
5275 window = FRAME_X_WINDOW (XFRAME (terminal));
5276 else
5277 window = dpyinfo->root_window;
5278
5279 return x_frame_list_z_order (dpy, window);
5280}
5281
5282/**
5283 * x_frame_restack:
5284 *
5285 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
5286 * practice this is a two-step action: The first step removes F1's
5287 * window-system window from the display. The second step reinserts
5288 * F1's window below (above if ABOVE_FLAG is true) that of F2.
5289 */
5290static void
5291x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5292{
5293#ifdef USE_GTK
5294 block_input ();
5295 xg_frame_restack (f1, f2, above_flag);
5296 unblock_input ();
5297#else
5298 Display *dpy = FRAME_X_DISPLAY (f1);
5299 Window window1 = FRAME_OUTER_WINDOW (f1);
5300 XWindowChanges wc;
5301 unsigned long mask = (CWSibling | CWStackMode);
5302
5303 wc.sibling = FRAME_OUTER_WINDOW (f2);
5304 wc.stack_mode = above_flag ? Above : Below;
5305 block_input ();
5306 /* Configure the window manager window (a normal XConfigureWindow
5307 won't cut it). This should also work for child frames. */
5308 XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
5309 unblock_input ();
5310#endif /* USE_GTK */
5311}
5312
5313
5314DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
5315 doc: /* Restack FRAME1 below FRAME2.
5316This means that if both frames are visible and the display areas of
5317these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
5318third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
5319means that if both frames are visible and the display areas of these
5320frames overlap, FRAME1 (partially) obscures FRAME2.
5321
5322This may be thought of as an atomic action performed in two steps: The
5323first step removes FRAME1's window-step window from the display. The
5324second step reinserts FRAME1's window below (above if ABOVE is true)
5325that of FRAME2. Hence the position of FRAME2 in its display's Z
5326\(stacking) order relative to all other frames excluding FRAME1 remains
5327unaltered.
5328
5329Some window managers may refuse to restack windows. */)
5330 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
5331{
5332 struct frame *f1 = decode_live_frame (frame1);
5333 struct frame *f2 = decode_live_frame (frame2);
5334
5335 if (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2))
5336 {
5337 x_frame_restack (f1, f2, !NILP (above));
5338 return Qt;
5339 }
5340 else
5341 {
5342 error ("Cannot restack frames");
5343 return Qnil;
5344 }
5345}
5346
5347
4848DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position, 5348DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
4849 Sx_mouse_absolute_pixel_position, 0, 0, 0, 5349 Sx_mouse_absolute_pixel_position, 0, 0, 0,
4850 doc: /* Return absolute position of mouse cursor in pixels. 5350 doc: /* Return absolute position of mouse cursor in pixels.
@@ -6585,6 +7085,8 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
6585 7085
6586 if (popup_activated ()) 7086 if (popup_activated ())
6587 error ("Trying to use a menu from within a menu-entry"); 7087 error ("Trying to use a menu from within a menu-entry");
7088 else
7089 x_menu_set_in_use (true);
6588 7090
6589 CHECK_STRING (prompt); 7091 CHECK_STRING (prompt);
6590 CHECK_STRING (dir); 7092 CHECK_STRING (dir);
@@ -6641,6 +7143,8 @@ nil, it defaults to the selected frame. */)
6641 7143
6642 if (popup_activated ()) 7144 if (popup_activated ())
6643 error ("Trying to use a menu from within a menu-entry"); 7145 error ("Trying to use a menu from within a menu-entry");
7146 else
7147 x_menu_set_in_use (true);
6644 7148
6645 /* Prevent redisplay. */ 7149 /* Prevent redisplay. */
6646 specbind (Qinhibit_redisplay, Qt); 7150 specbind (Qinhibit_redisplay, Qt);
@@ -6979,6 +7483,13 @@ frame_parm_handler x_frame_parm_handlers[] =
6979 x_set_sticky, 7483 x_set_sticky,
6980 x_set_tool_bar_position, 7484 x_set_tool_bar_position,
6981 x_set_inhibit_double_buffering, 7485 x_set_inhibit_double_buffering,
7486 x_set_undecorated,
7487 x_set_parent_frame,
7488 x_set_skip_taskbar,
7489 x_set_no_focus_on_map,
7490 x_set_no_accept_focus,
7491 x_set_z_group,
7492 x_set_override_redirect,
6982}; 7493};
6983 7494
6984void 7495void
@@ -7183,6 +7694,8 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
7183 defsubr (&Sx_display_monitor_attributes_list); 7694 defsubr (&Sx_display_monitor_attributes_list);
7184 defsubr (&Sx_frame_geometry); 7695 defsubr (&Sx_frame_geometry);
7185 defsubr (&Sx_frame_edges); 7696 defsubr (&Sx_frame_edges);
7697 defsubr (&Sx_frame_list_z_order);
7698 defsubr (&Sx_frame_restack);
7186 defsubr (&Sx_mouse_absolute_pixel_position); 7699 defsubr (&Sx_mouse_absolute_pixel_position);
7187 defsubr (&Sx_set_mouse_absolute_pixel_position); 7700 defsubr (&Sx_set_mouse_absolute_pixel_position);
7188 defsubr (&Sx_wm_set_size_hint); 7701 defsubr (&Sx_wm_set_size_hint);
diff --git a/src/xmenu.c b/src/xmenu.c
index 249cd6903fa..28052491646 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -140,14 +140,26 @@ menubar_id_to_frame (LWLIB_ID id)
140void 140void
141x_menu_set_in_use (bool in_use) 141x_menu_set_in_use (bool in_use)
142{ 142{
143 Lisp_Object frames, frame;
144
143 menu_items_inuse = in_use ? Qt : Qnil; 145 menu_items_inuse = in_use ? Qt : Qnil;
144 popup_activated_flag = in_use; 146 popup_activated_flag = in_use;
145#ifdef USE_X_TOOLKIT 147#ifdef USE_X_TOOLKIT
146 if (popup_activated_flag) 148 if (popup_activated_flag)
147 x_activate_timeout_atimer (); 149 x_activate_timeout_atimer ();
148#endif 150#endif
149}
150 151
152 /* Don't let frames in `above' z-group obscure popups. */
153 FOR_EACH_FRAME (frames, frame)
154 {
155 struct frame *f = XFRAME (frame);
156
157 if (in_use && FRAME_Z_GROUP_ABOVE (f))
158 x_set_z_group (f, Qabove_suspended, Qabove);
159 else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
160 x_set_z_group (f, Qabove, Qabove_suspended);
161 }
162}
151#endif 163#endif
152 164
153/* Wait for an X event to arrive or for a timer to expire. */ 165/* Wait for an X event to arrive or for a timer to expire. */
diff --git a/src/xterm.c b/src/xterm.c
index 1d14407aa43..4444a5c187a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -945,11 +945,14 @@ x_set_frame_alpha (struct frame *f)
945 Do this unconditionally as this function is called on reparent when 945 Do this unconditionally as this function is called on reparent when
946 alpha has not changed on the frame. */ 946 alpha has not changed on the frame. */
947 947
948 parent = x_find_topmost_parent (f); 948 if (!FRAME_PARENT_FRAME (f))
949 if (parent != None) 949 {
950 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, 950 parent = x_find_topmost_parent (f);
951 XA_CARDINAL, 32, PropModeReplace, 951 if (parent != None)
952 (unsigned char *) &opac, 1); 952 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
953 XA_CARDINAL, 32, PropModeReplace,
954 (unsigned char *) &opac, 1);
955 }
953 956
954 /* return unless necessary */ 957 /* return unless necessary */
955 { 958 {
@@ -4964,6 +4967,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4964 containing the pointer. */ 4967 containing the pointer. */
4965 { 4968 {
4966 Window win, child; 4969 Window win, child;
4970#ifdef USE_GTK
4971 Window first_win = 0;
4972#endif
4967 int win_x, win_y; 4973 int win_x, win_y;
4968 int parent_x = 0, parent_y = 0; 4974 int parent_x = 0, parent_y = 0;
4969 4975
@@ -5010,20 +5016,37 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
5010 &child); 5016 &child);
5011 5017
5012 if (child == None || child == win) 5018 if (child == None || child == win)
5013 break; 5019 {
5020#ifdef USE_GTK
5021 /* On GTK we have not inspected WIN yet. If it has
5022 a frame and that frame has a parent, use it. */
5023 struct frame *f = x_window_to_frame (dpyinfo, win);
5024
5025 if (f && FRAME_PARENT_FRAME (f))
5026 first_win = win;
5027#endif
5028 break;
5029 }
5014#ifdef USE_GTK 5030#ifdef USE_GTK
5015 /* We don't wan't to know the innermost window. We 5031 /* We don't wan't to know the innermost window. We
5016 want the edit window. For non-Gtk+ the innermost 5032 want the edit window. For non-Gtk+ the innermost
5017 window is the edit window. For Gtk+ it might not 5033 window is the edit window. For Gtk+ it might not
5018 be. It might be the tool bar for example. */ 5034 be. It might be the tool bar for example. */
5019 if (x_window_to_frame (dpyinfo, win)) 5035 if (x_window_to_frame (dpyinfo, win))
5020 break; 5036 /* But don't hurry. We might find a child frame
5037 beneath. */
5038 first_win = win;
5021#endif 5039#endif
5022 win = child; 5040 win = child;
5023 parent_x = win_x; 5041 parent_x = win_x;
5024 parent_y = win_y; 5042 parent_y = win_y;
5025 } 5043 }
5026 5044
5045#ifdef USE_GTK
5046 if (first_win)
5047 win = first_win;
5048#endif
5049
5027 /* Now we know that: 5050 /* Now we know that:
5028 win is the innermost window containing the pointer 5051 win is the innermost window containing the pointer
5029 (XTC says it has no child containing the pointer), 5052 (XTC says it has no child containing the pointer),
@@ -6496,10 +6519,14 @@ x_scroll_bar_create (struct window *w, int top, int left,
6496 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); 6519 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6497 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); 6520 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
6498 XtMapWidget (scroll_bar); 6521 XtMapWidget (scroll_bar);
6522 /* Don't obscure any child frames. */
6523 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6499#endif /* not USE_GTK */ 6524#endif /* not USE_GTK */
6500 } 6525 }
6501#else /* not USE_TOOLKIT_SCROLL_BARS */ 6526#else /* not USE_TOOLKIT_SCROLL_BARS */
6502 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window); 6527 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
6528 /* Don't obscure any child frames. */
6529 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6503#endif /* not USE_TOOLKIT_SCROLL_BARS */ 6530#endif /* not USE_TOOLKIT_SCROLL_BARS */
6504 6531
6505 unblock_input (); 6532 unblock_input ();
@@ -7067,10 +7094,10 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
7067 /* x, y, width, height */ 7094 /* x, y, width, height */
7068 0, 0, bar->width - 1, bar->height - 1); 7095 0, 0, bar->width - 1, bar->height - 1);
7069 7096
7070 /* Restore the foreground color of the GC if we changed it above. */ 7097 /* Restore the foreground color of the GC if we changed it above. */
7071 if (f->output_data.x->scroll_bar_foreground_pixel != -1) 7098 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7072 XSetForeground (FRAME_X_DISPLAY (f), gc, 7099 XSetForeground (FRAME_X_DISPLAY (f), gc,
7073 FRAME_FOREGROUND_PIXEL (f)); 7100 FRAME_FOREGROUND_PIXEL (f));
7074 7101
7075 unblock_input (); 7102 unblock_input ();
7076 7103
@@ -7839,8 +7866,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7839 f = x_top_window_to_frame (dpyinfo, event->xreparent.window); 7866 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
7840 if (f) 7867 if (f)
7841 { 7868 {
7842 f->output_data.x->parent_desc = event->xreparent.parent; 7869 /* Maybe we shouldn't set this for child frames ?? */
7843 x_real_positions (f, &f->left_pos, &f->top_pos); 7870 f->output_data.x->parent_desc = event->xreparent.parent;
7871 if (!FRAME_PARENT_FRAME (f))
7872 x_real_positions (f, &f->left_pos, &f->top_pos);
7873 else
7874 {
7875 Window root;
7876 unsigned int dummy_uint;
7877
7878 block_input ();
7879 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7880 &root, &f->left_pos, &f->top_pos,
7881 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
7882 unblock_input ();
7883 }
7844 7884
7845 /* Perhaps reparented due to a WM restart. Reset this. */ 7885 /* Perhaps reparented due to a WM restart. Reset this. */
7846 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; 7886 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
@@ -8000,7 +8040,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8000 /* Check if fullscreen was specified before we where mapped the 8040 /* Check if fullscreen was specified before we where mapped the
8001 first time, i.e. from the command line. */ 8041 first time, i.e. from the command line. */
8002 if (!f->output_data.x->has_been_visible) 8042 if (!f->output_data.x->has_been_visible)
8003 x_check_fullscreen (f); 8043 {
8044
8045 x_check_fullscreen (f);
8046#ifndef USE_GTK
8047 /* For systems that cannot synthesize `skip_taskbar' for
8048 unmapped windows do the following. */
8049 if (FRAME_SKIP_TASKBAR (f))
8050 x_set_skip_taskbar (f, Qt, Qnil);
8051#endif /* Not USE_GTK */
8052 }
8053
8054 if (!iconified)
8055 {
8056 /* The `z-group' is reset every time a frame becomes
8057 invisible. Handle this here. */
8058 if (FRAME_Z_GROUP (f) == z_group_above)
8059 x_set_z_group (f, Qabove, Qnil);
8060 else if (FRAME_Z_GROUP (f) == z_group_below)
8061 x_set_z_group (f, Qbelow, Qnil);
8062 }
8004 8063
8005 SET_FRAME_VISIBLE (f, 1); 8064 SET_FRAME_VISIBLE (f, 1);
8006 SET_FRAME_ICONIFIED (f, false); 8065 SET_FRAME_ICONIFIED (f, false);
@@ -8444,34 +8503,46 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8444#endif 8503#endif
8445 if (f) 8504 if (f)
8446 { 8505 {
8447 8506 /* Maybe generate a SELECT_WINDOW_EVENT for
8448 /* Generate SELECT_WINDOW_EVENTs when needed. 8507 `mouse-autoselect-window' but don't let popup menus
8449 Don't let popup menus influence things (bug#1261). */ 8508 interfere with this (Bug#1261). */
8450 if (!NILP (Vmouse_autoselect_window) && !popup_activated ()) 8509 if (!NILP (Vmouse_autoselect_window)
8510 && !popup_activated ()
8511 /* Don't switch if we're currently in the minibuffer.
8512 This tries to work around problems where the
8513 minibuffer gets unselected unexpectedly, and where
8514 you then have to move your mouse all the way down to
8515 the minibuffer to select it. */
8516 && !MINI_WINDOW_P (XWINDOW (selected_window))
8517 /* With `focus-follows-mouse' non-nil create an event
8518 also when the target window is on another frame. */
8519 && (f == XFRAME (selected_frame)
8520 || !NILP (focus_follows_mouse)))
8451 { 8521 {
8452 static Lisp_Object last_mouse_window; 8522 static Lisp_Object last_mouse_window;
8453 Lisp_Object window = window_from_coordinates 8523 Lisp_Object window = window_from_coordinates
8454 (f, event->xmotion.x, event->xmotion.y, 0, false); 8524 (f, event->xmotion.x, event->xmotion.y, 0, false);
8455 8525
8456 /* Window will be selected only when it is not selected now and 8526 /* A window will be autoselected only when it is not
8457 last mouse movement event was not in it. Minibuffer window 8527 selected now and the last mouse movement event was
8458 will be selected only when it is active. */ 8528 not in it. The remainder of the code is a bit vague
8529 wrt what a "window" is. For immediate autoselection,
8530 the window is usually the entire window but for GTK
8531 where the scroll bars don't count. For delayed
8532 autoselection the window is usually the window's text
8533 area including the margins. */
8459 if (WINDOWP (window) 8534 if (WINDOWP (window)
8460 && !EQ (window, last_mouse_window) 8535 && !EQ (window, last_mouse_window)
8461 && !EQ (window, selected_window) 8536 && !EQ (window, selected_window))
8462 /* For click-to-focus window managers
8463 create event iff we don't leave the
8464 selected frame. */
8465 && (focus_follows_mouse
8466 || (EQ (XWINDOW (window)->frame,
8467 XWINDOW (selected_window)->frame))))
8468 { 8537 {
8469 inev.ie.kind = SELECT_WINDOW_EVENT; 8538 inev.ie.kind = SELECT_WINDOW_EVENT;
8470 inev.ie.frame_or_window = window; 8539 inev.ie.frame_or_window = window;
8471 } 8540 }
8541
8472 /* Remember the last window where we saw the mouse. */ 8542 /* Remember the last window where we saw the mouse. */
8473 last_mouse_window = window; 8543 last_mouse_window = window;
8474 } 8544 }
8545
8475 if (!note_mouse_movement (f, &event->xmotion)) 8546 if (!note_mouse_movement (f, &event->xmotion))
8476 help_echo_string = previous_help_echo_string; 8547 help_echo_string = previous_help_echo_string;
8477 } 8548 }
@@ -8621,7 +8692,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8621 8692
8622 XSETFRAME (frame, f); 8693 XSETFRAME (frame, f);
8623 8694
8624 x_real_positions (f, &f->left_pos, &f->top_pos); 8695 if (!FRAME_PARENT_FRAME (f))
8696 x_real_positions (f, &f->left_pos, &f->top_pos);
8697 else
8698 {
8699 Window root;
8700 unsigned int dummy_uint;
8701
8702 block_input ();
8703 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8704 &root, &f->left_pos, &f->top_pos,
8705 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
8706 unblock_input ();
8707 }
8625 8708
8626 if (old_left != f->left_pos || old_top != f->top_pos) 8709 if (old_left != f->left_pos || old_top != f->top_pos)
8627 { 8710 {
@@ -8650,8 +8733,35 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8650 dpyinfo->last_mouse_glyph_frame = NULL; 8733 dpyinfo->last_mouse_glyph_frame = NULL;
8651 x_display_set_last_user_time (dpyinfo, event->xbutton.time); 8734 x_display_set_last_user_time (dpyinfo, event->xbutton.time);
8652 8735
8653 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame 8736 if (x_mouse_grabbed (dpyinfo))
8654 : x_window_to_frame (dpyinfo, event->xbutton.window)); 8737 f = dpyinfo->last_mouse_frame;
8738 else
8739 {
8740 f = x_window_to_frame (dpyinfo, event->xbutton.window);
8741
8742 if (f && event->xbutton.type == ButtonPress
8743 && !popup_activated ()
8744 && !x_window_to_scroll_bar (event->xbutton.display,
8745 event->xbutton.window, 2)
8746 && !FRAME_NO_ACCEPT_FOCUS (f))
8747 {
8748 /* When clicking into a child frame or when clicking
8749 into a parent frame with the child frame selected and
8750 `no-accept-focus' is not set, select the clicked
8751 frame. */
8752 struct frame *hf = dpyinfo->x_highlight_frame;
8753
8754 if (FRAME_PARENT_FRAME (f) || frame_ancestor_p (f, hf))
8755 {
8756 block_input ();
8757 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8758 RevertToParent, CurrentTime);
8759 if (FRAME_PARENT_FRAME (f))
8760 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8761 unblock_input ();
8762 }
8763 }
8764 }
8655 8765
8656#ifdef USE_GTK 8766#ifdef USE_GTK
8657 if (f && xg_event_is_for_scrollbar (f, event)) 8767 if (f && xg_event_is_for_scrollbar (f, event))
@@ -10007,6 +10117,7 @@ static void
10007x_calc_absolute_position (struct frame *f) 10117x_calc_absolute_position (struct frame *f)
10008{ 10118{
10009 int flags = f->size_hint_flags; 10119 int flags = f->size_hint_flags;
10120 struct frame *p = FRAME_PARENT_FRAME (f);
10010 10121
10011 /* We have nothing to do if the current position 10122 /* We have nothing to do if the current position
10012 is already for the top-left corner. */ 10123 is already for the top-left corner. */
@@ -10015,32 +10126,72 @@ x_calc_absolute_position (struct frame *f)
10015 10126
10016 /* Treat negative positions as relative to the leftmost bottommost 10127 /* Treat negative positions as relative to the leftmost bottommost
10017 position that fits on the screen. */ 10128 position that fits on the screen. */
10018 if (flags & XNegative) 10129 if ((flags & XNegative) && (f->left_pos <= 0))
10019 f->left_pos = x_display_pixel_width (FRAME_DISPLAY_INFO (f)) 10130 {
10020 - FRAME_PIXEL_WIDTH (f) + f->left_pos; 10131 int width = FRAME_PIXEL_WIDTH (f);
10021 10132
10022 { 10133 /* A frame that has been visible at least once should have outer
10023 int height = FRAME_PIXEL_HEIGHT (f); 10134 edges. */
10135 if (f->output_data.x->has_been_visible && !p)
10136 {
10137 Lisp_Object frame;
10138 Lisp_Object edges = Qnil;
10139
10140 XSETFRAME (frame, f);
10141 edges = Fx_frame_edges (frame, Qouter_edges);
10142 if (!NILP (edges))
10143 width = (XINT (Fnth (make_number (2), edges))
10144 - XINT (Fnth (make_number (0), edges)));
10145 }
10146
10147 if (p)
10148 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
10149 + f->left_pos);
10150 else
10151 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
10152 - width + f->left_pos);
10153
10154 }
10155
10156 if ((flags & YNegative) && (f->top_pos <= 0))
10157 {
10158 int height = FRAME_PIXEL_HEIGHT (f);
10024 10159
10025#if defined USE_X_TOOLKIT && defined USE_MOTIF 10160#if defined USE_X_TOOLKIT && defined USE_MOTIF
10026 /* Something is fishy here. When using Motif, starting Emacs with 10161 /* Something is fishy here. When using Motif, starting Emacs with
10027 `-g -0-0', the frame appears too low by a few pixels. 10162 `-g -0-0', the frame appears too low by a few pixels.
10028 10163
10029 This seems to be so because initially, while Emacs is starting, 10164 This seems to be so because initially, while Emacs is starting,
10030 the column widget's height and the frame's pixel height are 10165 the column widget's height and the frame's pixel height are
10031 different. The column widget's height is the right one. In 10166 different. The column widget's height is the right one. In
10032 later invocations, when Emacs is up, the frame's pixel height 10167 later invocations, when Emacs is up, the frame's pixel height
10033 is right, though. 10168 is right, though.
10034 10169
10035 It's not obvious where the initial small difference comes from. 10170 It's not obvious where the initial small difference comes from.
10036 2000-12-01, gerd. */ 10171 2000-12-01, gerd. */
10037 10172
10038 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL); 10173 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
10039#endif 10174#endif
10040 10175
10041 if (flags & YNegative) 10176 if (f->output_data.x->has_been_visible && !p)
10042 f->top_pos = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) 10177 {
10043 - height + f->top_pos; 10178 Lisp_Object frame;
10179 Lisp_Object edges = Qnil;
10180
10181 XSETFRAME (frame, f);
10182 if (NILP (edges))
10183 edges = Fx_frame_edges (frame, Qouter_edges);
10184 if (!NILP (edges))
10185 height = (XINT (Fnth (make_number (3), edges))
10186 - XINT (Fnth (make_number (1), edges)));
10187 }
10188
10189 if (p)
10190 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
10191 + f->top_pos);
10192 else
10193 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
10194 - height + f->top_pos);
10044 } 10195 }
10045 10196
10046 /* The left_pos and top_pos 10197 /* The left_pos and top_pos
@@ -10125,6 +10276,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
10125 need to compute the top/left offset adjustment for this frame. */ 10276 need to compute the top/left offset adjustment for this frame. */
10126 10277
10127 if (change_gravity != 0 10278 if (change_gravity != 0
10279 && !FRAME_PARENT_FRAME (f)
10128 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN 10280 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
10129 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A 10281 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
10130 && (FRAME_X_OUTPUT (f)->move_offset_left == 0 10282 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
@@ -10255,6 +10407,92 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10255 dpyinfo->Xatom_net_wm_state_sticky, None); 10407 dpyinfo->Xatom_net_wm_state_sticky, None);
10256} 10408}
10257 10409
10410/**
10411 * x_set_skip_taskbar:
10412 *
10413 * Set frame F's `skip-taskbar' parameter. If non-nil, this should
10414 * remove F's icon from the taskbar associated with the display of F's
10415 * window-system window and inhibit switching to F's window via
10416 * <Alt>-<TAB>. If nil, lift these restrictions.
10417 *
10418 * Some window managers may not honor this parameter.
10419 */
10420void
10421x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10422{
10423 if (!EQ (new_value, old_value))
10424 {
10425#ifdef USE_GTK
10426 xg_set_skip_taskbar (f, new_value);
10427#else
10428 Lisp_Object frame;
10429 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10430
10431 XSETFRAME (frame, f);
10432 set_wm_state (frame, !NILP (new_value),
10433 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
10434#endif /* USE_GTK */
10435 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
10436 }
10437}
10438
10439/**
10440 * x_set_z_group:
10441 *
10442 * Set frame F's `z-group' parameter. If `above', F's window-system
10443 * window is displayed above all windows that do not have the `above'
10444 * property set. If nil, F's window is shown below all windows that
10445 * have the `above' property set and above all windows that have the
10446 * `below' property set. If `below', F's window is displayed below all
10447 * windows that do not have the `below' property set.
10448 *
10449 * Some window managers may not honor this parameter.
10450 */
10451void
10452x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10453{
10454 /* We don't care about old_value. The window manager might have
10455 reset the value without telling us. */
10456 Lisp_Object frame;
10457 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10458
10459 XSETFRAME (frame, f);
10460
10461 if (NILP (new_value))
10462 {
10463 set_wm_state (frame, false,
10464 dpyinfo->Xatom_net_wm_state_above, None);
10465 set_wm_state (frame, false,
10466 dpyinfo->Xatom_net_wm_state_below, None);
10467 FRAME_Z_GROUP (f) = z_group_none;
10468 }
10469 else if (EQ (new_value, Qabove))
10470 {
10471 set_wm_state (frame, true,
10472 dpyinfo->Xatom_net_wm_state_above, None);
10473 set_wm_state (frame, false,
10474 dpyinfo->Xatom_net_wm_state_below, None);
10475 FRAME_Z_GROUP (f) = z_group_above;
10476 }
10477 else if (EQ (new_value, Qbelow))
10478 {
10479 set_wm_state (frame, false,
10480 dpyinfo->Xatom_net_wm_state_above, None);
10481 set_wm_state (frame, true,
10482 dpyinfo->Xatom_net_wm_state_below, None);
10483 FRAME_Z_GROUP (f) = z_group_below;
10484 }
10485 else if (EQ (new_value, Qabove_suspended))
10486 {
10487 set_wm_state (frame, false,
10488 dpyinfo->Xatom_net_wm_state_above, None);
10489 FRAME_Z_GROUP (f) = z_group_above_suspended;
10490 }
10491 else
10492 error ("Invalid z-group specification");
10493}
10494
10495
10258/* Return the current _NET_WM_STATE. 10496/* Return the current _NET_WM_STATE.
10259 SIZE_STATE is set to one of the FULLSCREEN_* values. 10497 SIZE_STATE is set to one of the FULLSCREEN_* values.
10260 Set *STICKY to the sticky state. 10498 Set *STICKY to the sticky state.
@@ -10758,7 +10996,8 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
10758 int old_height = FRAME_PIXEL_HEIGHT (f); 10996 int old_height = FRAME_PIXEL_HEIGHT (f);
10759 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 10997 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
10760 10998
10761 if (change_gravity) f->win_gravity = NorthWestGravity; 10999 if (change_gravity)
11000 f->win_gravity = NorthWestGravity;
10762 x_wm_set_size_hint (f, 0, false); 11001 x_wm_set_size_hint (f, 0, false);
10763 11002
10764 /* When the frame is fullheight and we only want to change the width 11003 /* When the frame is fullheight and we only want to change the width
@@ -11047,6 +11286,26 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
11047void 11286void
11048x_make_frame_visible (struct frame *f) 11287x_make_frame_visible (struct frame *f)
11049{ 11288{
11289 if (FRAME_PARENT_FRAME (f))
11290 {
11291 if (!FRAME_VISIBLE_P (f))
11292 {
11293 block_input ();
11294#ifdef USE_GTK
11295 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11296 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11297 f->left_pos, f->top_pos);
11298#else
11299 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11300#endif
11301 unblock_input ();
11302
11303 SET_FRAME_VISIBLE (f, true);
11304 SET_FRAME_ICONIFIED (f, false);
11305 }
11306 return;
11307 }
11308
11050 block_input (); 11309 block_input ();
11051 11310
11052 x_set_bitmap_icon (f); 11311 x_set_bitmap_icon (f);
@@ -11115,9 +11374,10 @@ x_make_frame_visible (struct frame *f)
11115 because the window manager may choose the position 11374 because the window manager may choose the position
11116 and we don't want to override it. */ 11375 and we don't want to override it. */
11117 11376
11118 if (! FRAME_VISIBLE_P (f) 11377 if (!FRAME_VISIBLE_P (f)
11119 && ! FRAME_ICONIFIED_P (f) 11378 && !FRAME_ICONIFIED_P (f)
11120 && ! FRAME_X_EMBEDDED_P (f) 11379 && !FRAME_X_EMBEDDED_P (f)
11380 && !FRAME_PARENT_FRAME (f)
11121 && f->win_gravity == NorthWestGravity 11381 && f->win_gravity == NorthWestGravity
11122 && previously_visible) 11382 && previously_visible)
11123 { 11383 {
@@ -11180,15 +11440,15 @@ x_make_frame_invisible (struct frame *f)
11180 xembed_set_info (f, 0); 11440 xembed_set_info (f, 0);
11181 else 11441 else
11182#endif 11442#endif
11183 {
11184 11443
11185 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window, 11444 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11186 DefaultScreen (FRAME_X_DISPLAY (f)))) 11445 DefaultScreen (FRAME_X_DISPLAY (f))))
11187 { 11446 {
11188 unblock_input (); 11447 unblock_input ();
11189 error ("Can't notify window manager of window withdrawal"); 11448 error ("Can't notify window manager of window withdrawal");
11190 } 11449 }
11191 } 11450
11451 x_sync (f);
11192 11452
11193 /* We can't distinguish this from iconification 11453 /* We can't distinguish this from iconification
11194 just by the event that we get from the server. 11454 just by the event that we get from the server.
@@ -11198,8 +11458,6 @@ x_make_frame_invisible (struct frame *f)
11198 SET_FRAME_VISIBLE (f, 0); 11458 SET_FRAME_VISIBLE (f, 0);
11199 SET_FRAME_ICONIFIED (f, false); 11459 SET_FRAME_ICONIFIED (f, false);
11200 11460
11201 x_sync (f);
11202
11203 unblock_input (); 11461 unblock_input ();
11204} 11462}
11205 11463
@@ -12355,6 +12613,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
12355 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) 12613 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
12356 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) 12614 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
12357 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) 12615 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
12616 ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
12617 ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
12618 ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
12358 }; 12619 };
12359 12620
12360 int i; 12621 int i;
diff --git a/src/xterm.h b/src/xterm.h
index 32c879bcdca..a75257006fd 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -447,9 +447,9 @@ struct x_display_info
447 /* Atoms dealing with EWMH (i.e. _NET_...) */ 447 /* Atoms dealing with EWMH (i.e. _NET_...) */
448 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen, 448 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen,
449 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert, 449 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
450 Xatom_net_wm_state_sticky, Xatom_net_wm_state_hidden, 450 Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, Xatom_net_wm_state_below,
451 Xatom_net_frame_extents, 451 Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
452 Xatom_net_current_desktop, Xatom_net_workarea; 452 Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea;
453 453
454 /* XSettings atoms and windows. */ 454 /* XSettings atoms and windows. */
455 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; 455 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -1168,6 +1168,8 @@ x_mutable_colormap (Visual *visual)
1168} 1168}
1169 1169
1170extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); 1170extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
1171extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object);
1172extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object);
1171extern bool x_wm_supports (struct frame *, Atom); 1173extern bool x_wm_supports (struct frame *, Atom);
1172extern void x_wait_for_event (struct frame *, int); 1174extern void x_wait_for_event (struct frame *, int);
1173extern void x_clear_under_internal_border (struct frame *f); 1175extern void x_clear_under_internal_border (struct frame *f);