mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
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.
This commit is contained in:
parent
449bc49c76
commit
3fdd3bb56c
20 changed files with 2541 additions and 452 deletions
|
|
@ -286,7 +286,11 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
|
|||
;; fns.c
|
||||
(use-dialog-box menu boolean "21.1")
|
||||
(use-file-dialog menu boolean "22.1")
|
||||
(focus-follows-mouse frames boolean "20.3")
|
||||
(focus-follows-mouse
|
||||
frames (choice
|
||||
(const :tag "Off (nil)" :value nil)
|
||||
(const :tag "On (t)" :value t)
|
||||
(const :tag "Auto-raise" :value auto-raise)) "26.1")
|
||||
;; fontset.c
|
||||
;; FIXME nil is the initial value, fontset.el setqs it.
|
||||
(vertical-centering-font-regexp display
|
||||
|
|
|
|||
117
lisp/frame.el
117
lisp/frame.el
|
|
@ -115,15 +115,19 @@ appended when the minibuffer frame is created."
|
|||
(defun handle-delete-frame (event)
|
||||
"Handle delete-frame events from the X server."
|
||||
(interactive "e")
|
||||
(let ((frame (posn-window (event-start event)))
|
||||
(i 0)
|
||||
(tail (frame-list)))
|
||||
(while tail
|
||||
(and (frame-visible-p (car tail))
|
||||
(not (eq (car tail) frame))
|
||||
(setq i (1+ i)))
|
||||
(setq tail (cdr tail)))
|
||||
(if (> i 0)
|
||||
(let* ((frame (posn-window (event-start event))))
|
||||
(if (catch 'other-frame
|
||||
(dolist (frame-1 (frame-list))
|
||||
;; A valid "other" frame is visible, owns its minibuffer
|
||||
;; window, has its `delete-before' parameter unset and is
|
||||
;; not a child frame.
|
||||
(when (and (not (eq frame-1 frame))
|
||||
(frame-visible-p frame-1)
|
||||
(window-live-p (minibuffer-window frame-1))
|
||||
(eq (window-frame (minibuffer-window frame-1)) frame-1)
|
||||
(not (frame-parent frame-1))
|
||||
(not (frame-parameter frame-1 'delete-before)))
|
||||
(throw 'other-frame t))))
|
||||
(delete-frame frame t)
|
||||
;; Gildea@x.org says it is ok to ask questions before terminating.
|
||||
(save-buffers-kill-emacs))))
|
||||
|
|
@ -834,21 +838,24 @@ All frames are arranged in a cyclic order.
|
|||
This command selects the frame ARG steps away in that order.
|
||||
A negative ARG moves in the opposite order.
|
||||
|
||||
To make this command work properly, you must tell Emacs
|
||||
how the system (or the window manager) generally handles
|
||||
focus-switching between windows. If moving the mouse onto a window
|
||||
selects it (gives it focus), set `focus-follows-mouse' to t.
|
||||
Otherwise, that variable should be nil."
|
||||
To make this command work properly, you must tell Emacs how the
|
||||
system (or the window manager) generally handles focus-switching
|
||||
between windows. If moving the mouse onto a window selects
|
||||
it (gives it focus), set `focus-follows-mouse' to t. Otherwise,
|
||||
that variable should be nil."
|
||||
(interactive "p")
|
||||
(let ((frame (selected-frame)))
|
||||
(let ((sframe (selected-frame))
|
||||
(frame (selected-frame)))
|
||||
(while (> arg 0)
|
||||
(setq frame (next-frame frame))
|
||||
(while (not (eq (frame-visible-p frame) t))
|
||||
(while (and (not (eq frame sframe))
|
||||
(not (eq (frame-visible-p frame) t)))
|
||||
(setq frame (next-frame frame)))
|
||||
(setq arg (1- arg)))
|
||||
(while (< arg 0)
|
||||
(setq frame (previous-frame frame))
|
||||
(while (not (eq (frame-visible-p frame) t))
|
||||
(while (and (not (eq frame sframe))
|
||||
(not (eq (frame-visible-p frame) t)))
|
||||
(setq frame (previous-frame frame)))
|
||||
(setq arg (1+ arg)))
|
||||
(select-frame-set-input-focus frame)))
|
||||
|
|
@ -1380,6 +1387,7 @@ and width values are in pixels.
|
|||
'(outer-position 0 . 0)
|
||||
(cons 'outer-size (cons (frame-width frame) (frame-height frame)))
|
||||
'(external-border-size 0 . 0)
|
||||
'(outer-border-width . 0)
|
||||
'(title-bar-size 0 . 0)
|
||||
'(menu-bar-external . nil)
|
||||
(let ((menu-bar-lines (frame-parameter frame 'menu-bar-lines)))
|
||||
|
|
@ -1490,6 +1498,59 @@ keys and their meanings."
|
|||
for frames = (cdr (assq 'frames attributes))
|
||||
if (memq frame frames) return attributes))
|
||||
|
||||
(declare-function x-frame-list-z-order "xfns.c" (&optional display))
|
||||
(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
|
||||
|
||||
(defun frame-list-z-order (&optional display)
|
||||
"Return list of Emacs' frames, in Z (stacking) order.
|
||||
The optional argument DISPLAY specifies which display to poll.
|
||||
DISPLAY should be either a frame or a display name (a string).
|
||||
If omitted or nil, that stands for the selected frame's display.
|
||||
|
||||
Frames are listed from topmost (first) to bottommost (last). As
|
||||
a special case, if DISPLAY is non-nil and specifies a live frame,
|
||||
return the child frames of that frame in Z (stacking) order.
|
||||
|
||||
Return nil if DISPLAY contains no Emacs frame."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((eq frame-type 'x)
|
||||
(x-frame-list-z-order display))
|
||||
((eq frame-type 'w32)
|
||||
(w32-frame-list-z-order display)))))
|
||||
|
||||
(declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above))
|
||||
(declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above))
|
||||
|
||||
(defun frame-restack (frame1 frame2 &optional above)
|
||||
"Restack FRAME1 below FRAME2.
|
||||
This implies that if both frames are visible and the display
|
||||
areas of these frames overlap, FRAME2 will (partially) obscure
|
||||
FRAME1. If the optional third argument ABOVE is non-nil, restack
|
||||
FRAME1 above FRAME2. This means that if both frames are visible
|
||||
and the display areas of these frames overlap, FRAME1 will
|
||||
\(partially) obscure FRAME2.
|
||||
|
||||
This may be thought of as an atomic action performed in two
|
||||
steps: The first step removes FRAME1's window-system window from
|
||||
the display. The second step reinserts FRAME1's window
|
||||
below (above if ABOVE is true) that of FRAME2. Hence the
|
||||
position of FRAME2 in its display's Z (stacking) order relative
|
||||
to all other frames excluding FRAME1 remains unaltered.
|
||||
|
||||
Some window managers may refuse to restack windows. "
|
||||
(if (and (frame-live-p frame1)
|
||||
(frame-live-p frame2)
|
||||
(equal (frame-parameter frame1 'display)
|
||||
(frame-parameter frame2 'display)))
|
||||
(let ((frame-type (framep-on-display frame1)))
|
||||
(cond
|
||||
((eq frame-type 'x)
|
||||
(x-frame-restack frame1 frame2 above))
|
||||
((eq frame-type 'w32)
|
||||
(w32-frame-restack frame1 frame2 above))))
|
||||
(error "Cannot restack frames")))
|
||||
|
||||
(defun frame-size-changed-p (&optional frame)
|
||||
"Return non-nil when the size of FRAME has changed.
|
||||
More 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,
|
|||
where the value is a cons with car `+', not numeric.
|
||||
SPEC is a frame geometry spec: (left . VALUE) or (top . VALUE).
|
||||
If VALUE is a number, then it is converted to a cons value, perhaps
|
||||
relative to the opposite frame edge from that in the original spec.
|
||||
relative to the opposite frame edge from that in the original spec.
|
||||
FRAME defaults to the selected frame.
|
||||
|
||||
Examples (measures in pixels) -
|
||||
|
|
@ -1907,24 +1968,36 @@ the opposite frame edge from the edge indicated in the input spec."
|
|||
(defun delete-other-frames (&optional frame)
|
||||
"Delete all frames on FRAME's terminal, except FRAME.
|
||||
If FRAME uses another frame's minibuffer, the minibuffer frame is
|
||||
left untouched. FRAME must be a live frame and defaults to the
|
||||
selected one."
|
||||
left untouched. Do not delete any of FRAME's child frames. If
|
||||
FRAME is a child frame, delete its siblings only. FRAME must be
|
||||
a live frame and defaults to the selected one."
|
||||
(interactive)
|
||||
(setq frame (window-normalize-frame frame))
|
||||
(let ((minibuffer-frame (window-frame (minibuffer-window frame)))
|
||||
(this (next-frame frame t))
|
||||
(parent (frame-parent frame))
|
||||
next)
|
||||
;; In a first round consider minibuffer-less frames only.
|
||||
(while (not (eq this frame))
|
||||
(setq next (next-frame this t))
|
||||
(unless (eq (window-frame (minibuffer-window this)) this)
|
||||
(unless (or (eq (window-frame (minibuffer-window this)) this)
|
||||
;; When FRAME is a child frame, delete its siblings
|
||||
;; only.
|
||||
(and parent (not (eq (frame-parent this) parent)))
|
||||
;; Do not delete a child frame of FRAME.
|
||||
(eq (frame-parent this) frame))
|
||||
(delete-frame this))
|
||||
(setq this next))
|
||||
;; In a second round consider all remaining frames.
|
||||
(setq this (next-frame frame t))
|
||||
(while (not (eq this frame))
|
||||
(setq next (next-frame this t))
|
||||
(unless (eq this minibuffer-frame)
|
||||
(unless (or (eq this minibuffer-frame)
|
||||
;; When FRAME is a child frame, delete its siblings
|
||||
;; only.
|
||||
(and parent (not (eq (frame-parent this) parent)))
|
||||
;; Do not delete a child frame of FRAME.
|
||||
(eq (frame-parent this) frame))
|
||||
(delete-frame this))
|
||||
(setq this next))))
|
||||
|
||||
|
|
|
|||
100
lisp/frameset.el
100
lisp/frameset.el
|
|
@ -446,6 +446,7 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
|
|||
(buffer-list . :never)
|
||||
(buffer-predicate . :never)
|
||||
(buried-buffer-list . :never)
|
||||
(delete-before . :never)
|
||||
(font . frameset-filter-shelve-param)
|
||||
(foreground-color . frameset-filter-sanitize-color)
|
||||
(fullscreen . frameset-filter-shelve-param)
|
||||
|
|
@ -455,7 +456,9 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
|
|||
(GUI:width . frameset-filter-unshelve-param)
|
||||
(height . frameset-filter-shelve-param)
|
||||
(outer-window-id . :never)
|
||||
(parent-frame . :never)
|
||||
(parent-id . :never)
|
||||
(mouse-wheel-frame . :never)
|
||||
(tty . frameset-filter-tty-to-GUI)
|
||||
(tty-type . frameset-filter-tty-to-GUI)
|
||||
(width . frameset-filter-shelve-param)
|
||||
|
|
@ -717,9 +720,18 @@ If nil, check all live frames."
|
|||
|
||||
;; Saving framesets
|
||||
|
||||
(defun frameset--record-minibuffer-relationships (frame-list)
|
||||
"Process FRAME-LIST and record minibuffer relationships.
|
||||
FRAME-LIST is a list of frames. Internal use only."
|
||||
(defun frameset--record-relationships (frame-list)
|
||||
"Process FRAME-LIST and record relationships.
|
||||
FRAME-LIST is a list of frames.
|
||||
|
||||
The relationships recorded for each frame are
|
||||
|
||||
- `minibuffer' via `frameset--mini'
|
||||
- `delete-before' via `frameset--delete-before'
|
||||
- `parent-frame' via `frameset--parent-frame'
|
||||
- `mouse-wheel-frame' via `frameset--mouse-wheel-frame'
|
||||
|
||||
Internal use only."
|
||||
;; Record frames with their own minibuffer
|
||||
(dolist (frame (minibuffer-frame-list))
|
||||
(when (memq frame frame-list)
|
||||
|
|
@ -730,22 +742,41 @@ FRAME-LIST is a list of frames. Internal use only."
|
|||
(set-frame-parameter frame
|
||||
'frameset--mini
|
||||
(cons t (eq frame default-minibuffer-frame)))))
|
||||
;; Now link minibufferless frames with their minibuffer frames
|
||||
;; Now link minibufferless frames with their minibuffer frames and
|
||||
;; store `parent-frame', `delete-before' and `mouse-wheel-frame'
|
||||
;; relationships in a similar way.
|
||||
(dolist (frame frame-list)
|
||||
(unless (frame-parameter frame 'frameset--mini)
|
||||
(frameset--set-id frame)
|
||||
(let ((mb-frame (window-frame (minibuffer-window frame))))
|
||||
;; For minibufferless frames, frameset--mini is a cons
|
||||
;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of
|
||||
;; the frame containing its minibuffer window.
|
||||
;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain
|
||||
;; the minibuffer frame of a minibufferless frame; we allow
|
||||
;; it without trying to second-guess the user.
|
||||
(set-frame-parameter frame
|
||||
'frameset--mini
|
||||
(cons nil
|
||||
(and mb-frame
|
||||
(frameset-frame-id mb-frame))))))))
|
||||
(let ((parent-frame (frame-parent frame))
|
||||
(delete-before (frame-parameter frame 'delete-before))
|
||||
(mouse-wheel-frame (frame-parameter frame 'mouse-wheel-frame))
|
||||
(nomini (not (frame-parameter frame 'frameset--mini))))
|
||||
(when (or nomini parent-frame delete-before mouse-wheel-frame)
|
||||
(when nomini
|
||||
(frameset--set-id frame))
|
||||
(when parent-frame
|
||||
(set-frame-parameter
|
||||
frame 'frameset--parent-frame (frameset-frame-id parent-frame)))
|
||||
(when delete-before
|
||||
(set-frame-parameter
|
||||
frame 'frameset--delete-before (frameset-frame-id delete-before)))
|
||||
(when mouse-wheel-frame
|
||||
(set-frame-parameter
|
||||
frame 'frameset--mouse-wheel-frame
|
||||
(frameset-frame-id mouse-wheel-frame)))
|
||||
(when nomini
|
||||
(let ((mb-frame (window-frame (minibuffer-window frame))))
|
||||
;; For minibufferless frames, frameset--mini is a cons
|
||||
;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of
|
||||
;; the frame containing its minibuffer window.
|
||||
;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain
|
||||
;; the minibuffer frame of a minibufferless frame; we allow
|
||||
;; it without trying to second-guess the user.
|
||||
(set-frame-parameter
|
||||
frame
|
||||
'frameset--mini
|
||||
(cons nil
|
||||
(and mb-frame
|
||||
(frameset-frame-id mb-frame))))))))))
|
||||
|
||||
;;;###autoload
|
||||
(cl-defun frameset-save (frame-list
|
||||
|
|
@ -768,7 +799,7 @@ PROPERTIES is a user-defined property list to add to the frameset."
|
|||
(cl-delete-if-not predicate list)
|
||||
list)))
|
||||
fs)
|
||||
(frameset--record-minibuffer-relationships frames)
|
||||
(frameset--record-relationships frames)
|
||||
(setq fs (frameset--make
|
||||
:app app
|
||||
:name name
|
||||
|
|
@ -993,6 +1024,14 @@ Internal use only."
|
|||
(frameset--initial-params filtered-cfg))))
|
||||
(puthash frame :created frameset--action-map))
|
||||
|
||||
;; Try to assign parent-frame right here - it will improve things
|
||||
;; for minibuffer-less child frames.
|
||||
(let* ((frame-id (frame-parameter frame 'frameset--parent-frame))
|
||||
(parent-frame
|
||||
(and frame-id (frameset-frame-with-id frame-id))))
|
||||
(when (frame-live-p parent-frame)
|
||||
(set-frame-parameter frame 'parent-frame parent-frame)))
|
||||
|
||||
(modify-frame-parameters frame
|
||||
(if (eq (frame-parameter frame 'fullscreen) fullscreen)
|
||||
;; Workaround for bug#14949
|
||||
|
|
@ -1205,6 +1244,29 @@ All keyword parameters default to nil."
|
|||
(error
|
||||
(delay-warning 'frameset (error-message-string err) :error))))))
|
||||
|
||||
;; Setting the parent frame after the frame has been created is a
|
||||
;; pain because one can see the frame move on the screen. Ideally,
|
||||
;; we would restore minibuffer equipped child frames after their
|
||||
;; respective parents have been made but this might interfere with
|
||||
;; the reordering of minibuffer frames. Left to the experts ...
|
||||
(dolist (frame (frame-list))
|
||||
(let* ((frame-id (frame-parameter frame 'frameset--parent-frame))
|
||||
(parent-frame
|
||||
(and frame-id (frameset-frame-with-id frame-id))))
|
||||
(when (and (not (eq (frame-parameter frame 'parent-frame) parent-frame))
|
||||
(frame-live-p parent-frame))
|
||||
(set-frame-parameter frame 'parent-frame parent-frame)))
|
||||
(let* ((frame-id (frame-parameter frame 'frameset--delete-before))
|
||||
(delete-before
|
||||
(and frame-id (frameset-frame-with-id frame-id))))
|
||||
(when (frame-live-p delete-before)
|
||||
(set-frame-parameter frame 'delete-before delete-before)))
|
||||
(let* ((frame-id (frame-parameter frame 'frameset--mouse-wheel-frame))
|
||||
(mouse-wheel-frame
|
||||
(and frame-id (frameset-frame-with-id frame-id))))
|
||||
(when (frame-live-p mouse-wheel-frame)
|
||||
(set-frame-parameter frame 'mouse-wheel-frame mouse-wheel-frame))))
|
||||
|
||||
;; In case we try to delete the initial frame, we want to make sure that
|
||||
;; other frames are already visible (discussed in thread for bug#14841).
|
||||
(sit-for 0 t)
|
||||
|
|
|
|||
|
|
@ -190,14 +190,33 @@ This can be slightly disconcerting, but some people prefer it."
|
|||
This should be bound only to mouse buttons 4 and 5 on non-Windows
|
||||
systems."
|
||||
(interactive (list last-input-event))
|
||||
(let* ((curwin (if mouse-wheel-follow-mouse
|
||||
(prog1
|
||||
(selected-window)
|
||||
(select-window (mwheel-event-window event)))))
|
||||
(buffer (window-buffer curwin))
|
||||
(opoint (with-current-buffer buffer
|
||||
(when (eq (car-safe transient-mark-mode) 'only)
|
||||
(point))))
|
||||
(let* ((selected-window (selected-window))
|
||||
(scroll-window
|
||||
(or (catch 'found
|
||||
(let* ((window (if mouse-wheel-follow-mouse
|
||||
(mwheel-event-window event)
|
||||
(selected-window)))
|
||||
(frame (when (window-live-p window)
|
||||
(frame-parameter
|
||||
(window-frame window) 'mouse-wheel-frame))))
|
||||
(when (frame-live-p frame)
|
||||
(let* ((pos (mouse-absolute-pixel-position))
|
||||
(pos-x (car pos))
|
||||
(pos-y (cdr pos)))
|
||||
(walk-window-tree
|
||||
(lambda (window-1)
|
||||
(let ((edges (window-edges window-1 nil t t)))
|
||||
(when (and (<= (nth 0 edges) pos-x)
|
||||
(<= pos-x (nth 2 edges))
|
||||
(<= (nth 1 edges) pos-y)
|
||||
(<= pos-y (nth 3 edges)))
|
||||
(throw 'found window-1))))
|
||||
frame nil t)))))
|
||||
(mwheel-event-window event)))
|
||||
(old-point
|
||||
(and (eq scroll-window selected-window)
|
||||
(eq (car-safe transient-mark-mode) 'only)
|
||||
(window-point)))
|
||||
(mods
|
||||
(delq 'click (delq 'double (delq 'triple (event-modifiers event)))))
|
||||
(amt (assoc mods mouse-wheel-scroll-amount)))
|
||||
|
|
@ -232,18 +251,18 @@ systems."
|
|||
;; Make sure we do indeed scroll to the end of the buffer.
|
||||
(end-of-buffer (while t (funcall mwheel-scroll-up-function)))))
|
||||
(t (error "Bad binding in mwheel-scroll"))))
|
||||
(if curwin (select-window curwin)))
|
||||
;; If there is a temporarily active region, deactivate it if
|
||||
;; scrolling moves point.
|
||||
(when opoint
|
||||
(with-current-buffer buffer
|
||||
(when (/= opoint (point))
|
||||
;; Call `deactivate-mark' at the original position, so that
|
||||
;; the original region is saved to the X selection.
|
||||
(let ((newpoint (point)))
|
||||
(goto-char opoint)
|
||||
(deactivate-mark)
|
||||
(goto-char newpoint))))))
|
||||
(if (eq scroll-window selected-window)
|
||||
;; If there is a temporarily active region, deactivate it if
|
||||
;; scrolling moved point.
|
||||
(when (and old-point (/= old-point (window-point)))
|
||||
;; Call `deactivate-mark' at the original position, so that
|
||||
;; the original region is saved to the X selection.
|
||||
(let ((new-point (window-point)))
|
||||
(goto-char old-point)
|
||||
(deactivate-mark)
|
||||
(goto-char new-point)))
|
||||
(select-window selected-window t))))
|
||||
|
||||
(when (and mouse-wheel-click-event mouse-wheel-inhibit-click-time)
|
||||
(if mwheel-inhibit-click-event-timer
|
||||
(cancel-timer mwheel-inhibit-click-event-timer)
|
||||
|
|
|
|||
169
lisp/window.el
169
lisp/window.el
|
|
@ -1533,7 +1533,7 @@ return the minimum pixel-size of WINDOW."
|
|||
(window-normalize-window window) horizontal ignore pixelwise))
|
||||
|
||||
(defun window--min-size-ignore-p (window ignore)
|
||||
"Return non-nil if IGNORE says to ignore height restrictions for WINDOW."
|
||||
"Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
|
||||
(if (window-valid-p ignore)
|
||||
(eq window ignore)
|
||||
(not (memq ignore '(nil preserved)))))
|
||||
|
|
@ -8735,13 +8735,14 @@ means suspend autoselection."
|
|||
If the mouse position has stabilized in a non-selected window, select
|
||||
that window. The minibuffer window is selected only if the minibuffer
|
||||
is active. This function is run by `mouse-autoselect-window-timer'."
|
||||
(ignore-errors
|
||||
(let* ((mouse-position (mouse-position))
|
||||
(window
|
||||
(ignore-errors
|
||||
(window-at (cadr mouse-position) (cddr mouse-position)
|
||||
(car mouse-position)))))
|
||||
(cond
|
||||
(let* ((mouse-position (mouse-position))
|
||||
(mouse-x (and (numberp (cadr mouse-position))
|
||||
(cadr mouse-position)))
|
||||
(mouse-y (and (numberp (cddr mouse-position))
|
||||
(cddr mouse-position)))
|
||||
(frame (and mouse-x mouse-y (car mouse-position)))
|
||||
(window (and frame (window-at mouse-x mouse-y frame))))
|
||||
(cond
|
||||
((or (and (fboundp 'menu-or-popup-active-p) (menu-or-popup-active-p))
|
||||
(and window
|
||||
(let ((coords (coordinates-in-window-p
|
||||
|
|
@ -8752,72 +8753,63 @@ is active. This function is run by `mouse-autoselect-window-timer'."
|
|||
;; text region of WINDOW: Suspend autoselection temporarily.
|
||||
(mouse-autoselect-window-start mouse-position nil t))
|
||||
((or (eq mouse-autoselect-window-state 'suspend)
|
||||
;; When the mouse is at its first recorded position, restart
|
||||
;; delayed autoselection. This works around a scenario with
|
||||
;; two two-window frames with identical dimensions: select the
|
||||
;; first window of the first frame, switch to the second
|
||||
;; frame, move the mouse to its second window, minimize the
|
||||
;; second frame. Now the second window of the first frame
|
||||
;; gets selected although the mouse never really "moved" into
|
||||
;; that window.
|
||||
(and (numberp mouse-autoselect-window)
|
||||
(equal (mouse-position) mouse-autoselect-window-position-1)))
|
||||
;; Delayed autoselection was temporarily suspended, reenable it.
|
||||
(mouse-autoselect-window-start mouse-position))
|
||||
((and window (not (eq window (selected-window)))
|
||||
(or (not (numberp mouse-autoselect-window))
|
||||
(and (>= mouse-autoselect-window 0)
|
||||
;; If `mouse-autoselect-window' is non-negative,
|
||||
;; select window if it's the same as before.
|
||||
(eq window mouse-autoselect-window-window))
|
||||
;; Otherwise select window iff the mouse is at the same
|
||||
;; position as before. Observe that the first test
|
||||
;; after starting autoselection usually fails since the
|
||||
;; value of `mouse-autoselect-window-position' recorded
|
||||
;; there is the position where the mouse has entered the
|
||||
;; new window and not necessarily where the mouse has
|
||||
;; stopped moving.
|
||||
(equal mouse-position mouse-autoselect-window-position))
|
||||
;; The minibuffer is a candidate window if it's active.
|
||||
(or (not (window-minibuffer-p window))
|
||||
(eq window (active-minibuffer-window))))
|
||||
;; Mouse position has stabilized in non-selected window: Cancel
|
||||
;; delayed autoselection and try to select that window.
|
||||
(mouse-autoselect-window-cancel t)
|
||||
;; Select window where mouse appears unless the selected window is the
|
||||
;; minibuffer. Use `unread-command-events' in order to execute pre-
|
||||
;; and post-command hooks and trigger idle timers. To avoid delaying
|
||||
;; autoselection again, set `mouse-autoselect-window-state'."
|
||||
(unless (window-minibuffer-p)
|
||||
(setq mouse-autoselect-window-state 'select)
|
||||
(setq unread-command-events
|
||||
(cons (list 'select-window (list window))
|
||||
unread-command-events))))
|
||||
((or (and window (eq window (selected-window)))
|
||||
(not (numberp mouse-autoselect-window))
|
||||
(equal mouse-position mouse-autoselect-window-position))
|
||||
;; Mouse position has either stabilized in the selected window or at
|
||||
;; `mouse-autoselect-window-position': Cancel delayed autoselection.
|
||||
(mouse-autoselect-window-cancel t))
|
||||
(t
|
||||
;; Mouse position has not stabilized yet, resume delayed
|
||||
;; autoselection.
|
||||
(mouse-autoselect-window-start mouse-position window))))))
|
||||
;; When the mouse is at its first recorded position, restart
|
||||
;; delayed autoselection. This works around a scenario with
|
||||
;; two two-window frames with identical dimensions: select the
|
||||
;; first window of the first frame, switch to the second
|
||||
;; frame, move the mouse to its second window, minimize the
|
||||
;; second frame. Now the second window of the first frame
|
||||
;; gets selected although the mouse never really "moved" into
|
||||
;; that window.
|
||||
(and (numberp mouse-autoselect-window)
|
||||
(equal (mouse-position) mouse-autoselect-window-position-1)))
|
||||
;; Delayed autoselection was temporarily suspended, reenable it.
|
||||
(mouse-autoselect-window-start mouse-position))
|
||||
((and window
|
||||
(or (not (numberp mouse-autoselect-window))
|
||||
(and (>= mouse-autoselect-window 0)
|
||||
;; If `mouse-autoselect-window' is non-negative,
|
||||
;; select window if it's the same as before.
|
||||
(eq window mouse-autoselect-window-window))
|
||||
;; Otherwise select window iff the mouse is at the same
|
||||
;; position as before. Observe that the first test
|
||||
;; after starting autoselection usually fails since the
|
||||
;; value of `mouse-autoselect-window-position' recorded
|
||||
;; there is the position where the mouse has entered the
|
||||
;; new window and not necessarily where the mouse has
|
||||
;; stopped moving.
|
||||
(equal mouse-position mouse-autoselect-window-position))
|
||||
;; The minibuffer is a candidate window if it's active.
|
||||
(or (not (window-minibuffer-p window))
|
||||
(eq window (active-minibuffer-window))))
|
||||
;; Mouse position has stabilized in non-selected window: Cancel
|
||||
;; delayed autoselection and try to select that window.
|
||||
(mouse-autoselect-window-cancel t)
|
||||
;; Use `unread-command-events' in order to execute pre- and
|
||||
;; post-command hooks and trigger idle timers. To avoid delaying
|
||||
;; autoselection again, set `mouse-autoselect-window-state'."
|
||||
(setq mouse-autoselect-window-state 'select)
|
||||
(setq unread-command-events
|
||||
(cons (list 'select-window (list window))
|
||||
unread-command-events)))
|
||||
((or (not (numberp mouse-autoselect-window))
|
||||
(equal mouse-position mouse-autoselect-window-position))
|
||||
;; Mouse position has stabilized at
|
||||
;; `mouse-autoselect-window-position': Cancel delayed
|
||||
;; autoselection.
|
||||
(mouse-autoselect-window-cancel t))
|
||||
(window
|
||||
;; Mouse position has not stabilized yet, resume delayed
|
||||
;; autoselection.
|
||||
(mouse-autoselect-window-start mouse-position window)))))
|
||||
|
||||
(defun handle-select-window (event)
|
||||
"Handle select-window events."
|
||||
(interactive "^e")
|
||||
(let ((window (posn-window (event-start event))))
|
||||
(let* ((window (posn-window (event-start event)))
|
||||
(frame (and (window-live-p window) (window-frame window)))
|
||||
(old-frame (selected-frame)))
|
||||
(unless (or (not (window-live-p window))
|
||||
;; Don't switch if we're currently in the minibuffer.
|
||||
;; This tries to work around problems where the
|
||||
;; minibuffer gets unselected unexpectedly, and where
|
||||
;; you then have to move your mouse all the way down to
|
||||
;; the minibuffer to select it.
|
||||
(window-minibuffer-p)
|
||||
;; Don't switch to minibuffer window unless it's active.
|
||||
(and (window-minibuffer-p window)
|
||||
(not (minibuffer-window-active-p window)))
|
||||
;; Don't switch when autoselection shall be delayed.
|
||||
(and (numberp mouse-autoselect-window)
|
||||
(not (eq mouse-autoselect-window-state 'select))
|
||||
|
|
@ -8830,15 +8822,40 @@ is active. This function is run by `mouse-autoselect-window-timer'."
|
|||
(mouse-autoselect-window-start position window)
|
||||
;; Executing a command cancels delayed autoselection.
|
||||
(add-hook
|
||||
'pre-command-hook 'mouse-autoselect-window-cancel))))
|
||||
(when mouse-autoselect-window
|
||||
;; Reset state of delayed autoselection.
|
||||
(setq mouse-autoselect-window-state nil)
|
||||
;; Run `mouse-leave-buffer-hook' when autoselecting window.
|
||||
(run-hooks 'mouse-leave-buffer-hook))
|
||||
'pre-command-hook 'mouse-autoselect-window-cancel)))
|
||||
;; Don't switch to a `no-accept-focus' frame unless it's
|
||||
;; already selected.
|
||||
(and (not (eq frame (selected-frame)))
|
||||
(frame-parameter frame 'no-accept-focus))
|
||||
;; Don't switch to minibuffer window unless it's active.
|
||||
(and (window-minibuffer-p window)
|
||||
(not (minibuffer-window-active-p window))))
|
||||
;; Reset state of delayed autoselection.
|
||||
(setq mouse-autoselect-window-state nil)
|
||||
;; Run `mouse-leave-buffer-hook' when autoselecting window.
|
||||
(run-hooks 'mouse-leave-buffer-hook)
|
||||
;; Clear echo area.
|
||||
(message nil)
|
||||
(select-window window))))
|
||||
;; Select the window before giving the frame focus since otherwise
|
||||
;; we might get two windows with an active cursor.
|
||||
(select-window window)
|
||||
(cond
|
||||
((or (not (memq (window-system frame) '(x w32 ns)))
|
||||
(not focus-follows-mouse)
|
||||
;; Focus FRAME if it's either a child frame or an ancestor
|
||||
;; of the frame switched from.
|
||||
(and (not (frame-parameter frame 'parent-frame))
|
||||
(not (frame-ancestor-p frame old-frame)))))
|
||||
((eq focus-follows-mouse 'auto-raise)
|
||||
;; Focus and auto-raise frame.
|
||||
(x-focus-frame frame)
|
||||
;; This doesn't seem to work when we move from a normal frame
|
||||
;; right into the child frame of another frame - we should raise
|
||||
;; that child frame's ancestor frame first ...
|
||||
(raise-frame frame))
|
||||
(t
|
||||
;; Just focus frame.
|
||||
(x-focus-frame frame))))))
|
||||
|
||||
(defun truncated-partial-width-window-p (&optional window)
|
||||
"Return non-nil if lines in WINDOW are specifically truncated due to its width.
|
||||
|
|
|
|||
400
src/frame.c
400
src/frame.c
|
|
@ -324,11 +324,51 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
|
|||
return make_number (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* frame_windows_min_size:
|
||||
*
|
||||
* Return the minimum number of lines (columns if HORIZONTAL is non-nil)
|
||||
* of FRAME. If PIXELWISE is non-nil, return the minimum height (width)
|
||||
* in pixels.
|
||||
*
|
||||
* This value is calculated by the function `frame-windows-min-size' in
|
||||
* window.el unless the `min-height' (`min-width' if HORIZONTAL is
|
||||
* non-nil) parameter of FRAME is non-nil thus explicitly specifying the
|
||||
* value to be returned. In that latter case IGNORE is ignored.
|
||||
*
|
||||
* If `frame-windows-min-size' is called, it will make sure that the
|
||||
* return value accomodates all windows of FRAME respecting the values
|
||||
* of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
|
||||
* With IGNORE non-nil the values of these variables are ignored.
|
||||
*
|
||||
* In either case never return a value less than 1.
|
||||
*/
|
||||
static int
|
||||
frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
|
||||
Lisp_Object ignore, Lisp_Object pixelwise)
|
||||
{
|
||||
return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
|
||||
struct frame *f = XFRAME (frame);
|
||||
Lisp_Object par_size;
|
||||
|
||||
if ((!NILP (horizontal)
|
||||
&& NUMBERP (par_size = get_frame_param (f, Qmin_width)))
|
||||
|| (NILP (horizontal)
|
||||
&& NUMBERP (par_size = get_frame_param (f, Qmin_height))))
|
||||
{
|
||||
int min_size = XINT (par_size);
|
||||
|
||||
/* Don't allow phantom frames. */
|
||||
if (min_size < 1)
|
||||
min_size = 1;
|
||||
|
||||
return (NILP (pixelwise)
|
||||
? min_size
|
||||
: min_size * (NILP (horizontal)
|
||||
? FRAME_LINE_HEIGHT (f)
|
||||
: FRAME_COLUMN_WIDTH (f)));
|
||||
}
|
||||
else
|
||||
return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
|
||||
ignore, pixelwise));
|
||||
}
|
||||
|
||||
|
|
@ -643,6 +683,16 @@ make_frame (bool mini_p)
|
|||
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
|
||||
f->horizontal_scroll_bars = false;
|
||||
f->want_fullscreen = FULLSCREEN_NONE;
|
||||
#if ! defined (HAVE_NS)
|
||||
f->undecorated = false;
|
||||
#ifndef HAVE_NTGUI
|
||||
f->override_redirect = false;
|
||||
#endif
|
||||
f->skip_taskbar = false;
|
||||
f->no_focus_on_map = false;
|
||||
f->no_accept_focus = false;
|
||||
f->z_group = z_group_none;
|
||||
#endif
|
||||
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
|
||||
f->last_tool_bar_item = -1;
|
||||
#endif
|
||||
|
|
@ -1215,7 +1265,10 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
|
|||
(select-window (frame-root-window (new-frame))) doesn't end up
|
||||
with your typing being interpreted in the new frame instead of
|
||||
the one you're actually typing in. */
|
||||
internal_last_event_frame = Qnil;
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (!frame_ancestor_p (f, sf))
|
||||
#endif
|
||||
internal_last_event_frame = Qnil;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
|
@ -1283,6 +1336,72 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
|
|||
return frames;
|
||||
}
|
||||
|
||||
DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
|
||||
0, 1, 0,
|
||||
doc: /* Return the parent frame of FRAME.
|
||||
The parent frame of FRAME is the Emacs frame whose window-system window
|
||||
is the parent window of FRAME's window-system window. When such a frame
|
||||
exists, FRAME is considered a child frame of that frame.
|
||||
|
||||
Return nil if FRAME has no parent frame. This means that FRAME's
|
||||
window-system window is either a "top-level" window (a window whose
|
||||
parent window is the window-system's root window) or an embedded window
|
||||
\(a window whose parent window is owned by some other application). */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
struct frame *f = decode_live_frame (frame);
|
||||
struct frame *p = FRAME_PARENT_FRAME (f);
|
||||
Lisp_Object parent;
|
||||
|
||||
/* Can't return f->parent_frame directly since it might not be defined
|
||||
for this platform. */
|
||||
if (p)
|
||||
{
|
||||
XSETFRAME (parent, p);
|
||||
|
||||
return parent;
|
||||
}
|
||||
else
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
bool
|
||||
frame_ancestor_p (struct frame *af, struct frame *df)
|
||||
{
|
||||
struct frame *pf = FRAME_PARENT_FRAME (df);
|
||||
|
||||
while (pf)
|
||||
{
|
||||
if (pf == af)
|
||||
return true;
|
||||
else
|
||||
pf = FRAME_PARENT_FRAME (pf);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
|
||||
2, 2, 0,
|
||||
doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
|
||||
ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
|
||||
parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
|
||||
ANCESTOR and DESCENDANT must be live frames and default to the selected
|
||||
frame. */)
|
||||
(Lisp_Object ancestor, Lisp_Object descendant)
|
||||
{
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
struct frame *af = decode_live_frame (ancestor);
|
||||
struct frame *df = decode_live_frame (descendant);
|
||||
|
||||
return frame_ancestor_p (af, df) ? Qt : Qnil;
|
||||
#else
|
||||
return Qnil;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
|
||||
same tty (for tty frames) or among frames which uses FRAME's keyboard.
|
||||
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)
|
|||
|| (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
|
||||
&& FRAME_TTY (c) == FRAME_TTY (f)))
|
||||
{
|
||||
if (NILP (minibuf))
|
||||
if (!NILP (get_frame_param (c, Qno_other_frame)))
|
||||
return Qnil;
|
||||
else if (NILP (minibuf))
|
||||
{
|
||||
if (!FRAME_MINIBUF_ONLY_P (c))
|
||||
return candidate;
|
||||
|
|
@ -1441,35 +1562,65 @@ DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
|
|||
return frame;
|
||||
}
|
||||
|
||||
/* Return 1 if it is ok to delete frame F;
|
||||
0 if all frames aside from F are invisible.
|
||||
(Exception: if F is the terminal frame, and we are using X, return 1.) */
|
||||
/**
|
||||
* other_frames:
|
||||
*
|
||||
* Return true if there exists at least one visible or iconified frame
|
||||
* but F. Return false otherwise.
|
||||
*
|
||||
* Always return false when all remaining frames are either tooltip or
|
||||
* child frames or frames with a non-nil `delete-before' parameter. If
|
||||
* INVISIBLE is false, also return false when the minibuffer window of
|
||||
* all remaining frames is on F.
|
||||
|
||||
static int
|
||||
other_visible_frames (struct frame *f)
|
||||
* If F is the terminal frame and we are using X, return true if at
|
||||
* least one X frame exists. */
|
||||
static bool
|
||||
other_frames (struct frame *f, bool invisible)
|
||||
{
|
||||
Lisp_Object frames, this;
|
||||
Lisp_Object frames, frame, frame1;
|
||||
struct frame *f1;
|
||||
Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
|
||||
|
||||
FOR_EACH_FRAME (frames, this)
|
||||
XSETFRAME (frame, f);
|
||||
if (WINDOWP (minibuffer_window)
|
||||
&& !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
|
||||
minibuffer_window = Qnil;
|
||||
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
if (f == XFRAME (this))
|
||||
continue;
|
||||
|
||||
/* Verify that we can still talk to the frame's X window,
|
||||
and note any recent change in visibility. */
|
||||
f1 = XFRAME (frame1);
|
||||
if (f != f1)
|
||||
{
|
||||
/* Verify that we can still talk to the frame's X window, and
|
||||
note any recent change in visibility. */
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
if (FRAME_WINDOW_P (XFRAME (this)))
|
||||
x_sync (XFRAME (this));
|
||||
if (FRAME_WINDOW_P (f1))
|
||||
x_sync (f1);
|
||||
#endif
|
||||
|
||||
if (FRAME_VISIBLE_P (XFRAME (this))
|
||||
|| FRAME_ICONIFIED_P (XFRAME (this))
|
||||
/* Allow deleting the terminal frame when at least one X
|
||||
frame exists. */
|
||||
|| (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
|
||||
return 1;
|
||||
if (NILP (Fframe_parameter (frame1, Qtooltip))
|
||||
/* Tooltips and child frames don't count. */
|
||||
&& !FRAME_PARENT_FRAME (f1)
|
||||
/* Frames with a non-nil `delete-before' parameter don't
|
||||
count - either they depend on us or they depend on a
|
||||
frame that we will have to find right here. */
|
||||
&& NILP (get_frame_param (f1, Qdelete_before))
|
||||
/* Frames whose minibuffer window is on F don't count
|
||||
unless INVISIBLE is set - in that case F is either made
|
||||
invisible and may be autoraised from such a frame or
|
||||
the FORCE argument of delete_frame was non-nil. */
|
||||
&& (invisible || NILP (minibuffer_window)
|
||||
|| !EQ (FRAME_MINIBUF_WINDOW (f1), minibuffer_window))
|
||||
/* At least one visible/iconified frame must remain. */
|
||||
&& (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
|
||||
/* Allow deleting the terminal frame when at least one
|
||||
X frame exists. */
|
||||
|| (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
|
||||
|
|
@ -1518,53 +1669,65 @@ check_minibuf_window (Lisp_Object frame, int select)
|
|||
}
|
||||
|
||||
|
||||
/* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
|
||||
unconditionally. x_connection_closed and delete_terminal use
|
||||
this. Any other value of FORCE implements the semantics
|
||||
described for Fdelete_frame. */
|
||||
/**
|
||||
* delete_frame:
|
||||
*
|
||||
* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
|
||||
* unconditionally. x_connection_closed and delete_terminal use this.
|
||||
* Any other value of FORCE implements the semantics described for
|
||||
* Fdelete_frame. */
|
||||
Lisp_Object
|
||||
delete_frame (Lisp_Object frame, Lisp_Object force)
|
||||
{
|
||||
struct frame *f = decode_any_frame (frame);
|
||||
struct frame *sf;
|
||||
struct kboard *kb;
|
||||
|
||||
Lisp_Object frames, frame1;
|
||||
int minibuffer_selected, is_tooltip_frame;
|
||||
bool nochild = !FRAME_PARENT_FRAME (f);
|
||||
|
||||
if (! FRAME_LIVE_P (f))
|
||||
if (!FRAME_LIVE_P (f))
|
||||
return Qnil;
|
||||
|
||||
if (NILP (force) && !other_visible_frames (f))
|
||||
error ("Attempt to delete the sole visible or iconified frame");
|
||||
|
||||
/* x_connection_closed must have set FORCE to `noelisp' in order
|
||||
to delete the last frame, if it is gone. */
|
||||
if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
|
||||
error ("Attempt to delete the only frame");
|
||||
else if (!EQ (force, Qnoelisp) && !other_frames (f, !NILP (force)))
|
||||
{
|
||||
if (NILP (force))
|
||||
error ("Attempt to delete the sole visible or iconified frame");
|
||||
else
|
||||
error ("Attempt to delete the only frame");
|
||||
}
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
/* Softly delete all frames with this frame as their parent frame or
|
||||
as their `delete-before' frame parameter value. */
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
|
||||
/* Process `delete-before' parameter iff FRAME is not a child
|
||||
frame. This avoids that we enter an infinite chain of mixed
|
||||
dependencies. */
|
||||
|| (nochild
|
||||
&& EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
|
||||
delete_frame (frame1, Qnil);
|
||||
|
||||
/* Does this frame have a minibuffer, and is it the surrogate
|
||||
minibuffer for any other frame? */
|
||||
if (FRAME_HAS_MINIBUF_P (f))
|
||||
{
|
||||
Lisp_Object frames, this;
|
||||
|
||||
FOR_EACH_FRAME (frames, this)
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
Lisp_Object fminiw;
|
||||
|
||||
if (EQ (this, frame))
|
||||
if (EQ (frame1, frame))
|
||||
continue;
|
||||
|
||||
fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this));
|
||||
fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
|
||||
|
||||
if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
|
||||
{
|
||||
/* If we MUST delete this frame, delete the other first.
|
||||
But do this only if FORCE equals `noelisp'. */
|
||||
if (EQ (force, Qnoelisp))
|
||||
delete_frame (this, Qnoelisp);
|
||||
delete_frame (frame1, Qnoelisp);
|
||||
else
|
||||
error ("Attempt to delete a surrogate minibuffer frame");
|
||||
}
|
||||
|
|
@ -1593,20 +1756,26 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
|
||||
}
|
||||
|
||||
/* The hook may sometimes (indirectly) cause the frame to be deleted. */
|
||||
if (! FRAME_LIVE_P (f))
|
||||
/* delete_frame_functions may have deleted any frame, including this
|
||||
one. */
|
||||
if (!FRAME_LIVE_P (f))
|
||||
return Qnil;
|
||||
else if (!EQ (force, Qnoelisp) && !other_frames (f, !NILP (force)))
|
||||
{
|
||||
if (NILP (force))
|
||||
error ("Attempt to delete the sole visible or iconified frame");
|
||||
else
|
||||
error ("Attempt to delete the only frame");
|
||||
}
|
||||
|
||||
/* At this point, we are committed to deleting the frame.
|
||||
There is no more chance for errors to prevent it. */
|
||||
|
||||
minibuffer_selected = EQ (minibuf_window, selected_window);
|
||||
sf = SELECTED_FRAME ();
|
||||
/* Don't let the frame remain selected. */
|
||||
if (f == sf)
|
||||
{
|
||||
Lisp_Object tail;
|
||||
Lisp_Object frame1 = Qnil;
|
||||
|
||||
/* Look for another visible frame on the same terminal.
|
||||
Do not call next_frame here because it may loop forever.
|
||||
|
|
@ -1746,16 +1915,15 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
another one. */
|
||||
if (f == last_nonminibuf_frame)
|
||||
{
|
||||
Lisp_Object frames, this;
|
||||
|
||||
last_nonminibuf_frame = 0;
|
||||
|
||||
FOR_EACH_FRAME (frames, this)
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
f = XFRAME (this);
|
||||
if (!FRAME_MINIBUF_ONLY_P (f))
|
||||
struct frame *f1 = XFRAME (frame1);
|
||||
|
||||
if (!FRAME_MINIBUF_ONLY_P (f1))
|
||||
{
|
||||
last_nonminibuf_frame = f;
|
||||
last_nonminibuf_frame = f1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1765,13 +1933,12 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
single-kboard state if we're in it for this kboard. */
|
||||
if (kb != NULL)
|
||||
{
|
||||
Lisp_Object frames, this;
|
||||
/* Some frame we found on the same kboard, or nil if there are none. */
|
||||
Lisp_Object frame_on_same_kboard = Qnil;
|
||||
|
||||
FOR_EACH_FRAME (frames, this)
|
||||
if (kb == FRAME_KBOARD (XFRAME (this)))
|
||||
frame_on_same_kboard = this;
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
if (kb == FRAME_KBOARD (XFRAME (frame1)))
|
||||
frame_on_same_kboard = frame1;
|
||||
|
||||
if (NILP (frame_on_same_kboard))
|
||||
not_single_kboard_state (kb);
|
||||
|
|
@ -1783,29 +1950,27 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
frames with other windows. */
|
||||
if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
|
||||
{
|
||||
Lisp_Object frames, this;
|
||||
|
||||
/* The last frame we saw with a minibuffer, minibuffer-only or not. */
|
||||
Lisp_Object frame_with_minibuf = Qnil;
|
||||
/* Some frame we found on the same kboard, or nil if there are none. */
|
||||
Lisp_Object frame_on_same_kboard = Qnil;
|
||||
|
||||
FOR_EACH_FRAME (frames, this)
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
struct frame *f1 = XFRAME (this);
|
||||
struct frame *f1 = XFRAME (frame1);
|
||||
|
||||
/* Consider only frames on the same kboard
|
||||
and only those with minibuffers. */
|
||||
if (kb == FRAME_KBOARD (f1)
|
||||
&& FRAME_HAS_MINIBUF_P (f1))
|
||||
{
|
||||
frame_with_minibuf = this;
|
||||
frame_with_minibuf = frame1;
|
||||
if (FRAME_MINIBUF_ONLY_P (f1))
|
||||
break;
|
||||
}
|
||||
|
||||
if (kb == FRAME_KBOARD (f1))
|
||||
frame_on_same_kboard = this;
|
||||
frame_on_same_kboard = frame1;
|
||||
}
|
||||
|
||||
if (!NILP (frame_on_same_kboard))
|
||||
|
|
@ -2118,7 +2283,7 @@ displayed in the terminal. */)
|
|||
{
|
||||
struct frame *f = decode_live_frame (frame);
|
||||
|
||||
if (NILP (force) && !other_visible_frames (f))
|
||||
if (NILP (force) && !other_frames (f, true))
|
||||
error ("Attempt to make invisible the sole visible or iconified frame");
|
||||
|
||||
/* 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)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check these parameters for circular dependeny. This does not check
|
||||
for interdependencies between these properties. Hence you can
|
||||
still create circular dependencies with different properties, for
|
||||
example a chain of frames F1->F2->...Fn such that F1 is an ancestor
|
||||
frame of Fn and thus cannot be deleted before Fn and a second chain
|
||||
Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
|
||||
else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
|
||||
{
|
||||
Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
|
||||
|
||||
if (!EQ (oldval, val) && !NILP (val))
|
||||
{
|
||||
Lisp_Object frame;
|
||||
Lisp_Object frame1 = val;
|
||||
|
||||
if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
|
||||
error ("Invalid `%s' frame parameter",
|
||||
SSDATA (SYMBOL_NAME (prop)));
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
|
||||
if (EQ (frame1, frame))
|
||||
error ("Circular specification of `%s' frame parameter",
|
||||
SSDATA (SYMBOL_NAME (prop)));
|
||||
else
|
||||
frame1 = get_frame_param (XFRAME (frame1), prop);
|
||||
}
|
||||
}
|
||||
|
||||
/* The buffer-list parameters are stored in a special place and not
|
||||
in the alist. All buffers must be live. */
|
||||
if (EQ (prop, Qbuffer_list))
|
||||
else if (EQ (prop, Qbuffer_list))
|
||||
{
|
||||
Lisp_Object list = Qnil;
|
||||
for (; CONSP (val); val = XCDR (val))
|
||||
|
|
@ -2464,7 +2659,7 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
|
|||
fset_buffer_list (f, Fnreverse (list));
|
||||
return;
|
||||
}
|
||||
if (EQ (prop, Qburied_buffer_list))
|
||||
else if (EQ (prop, Qburied_buffer_list))
|
||||
{
|
||||
Lisp_Object list = Qnil;
|
||||
for (; CONSP (val); val = XCDR (val))
|
||||
|
|
@ -3095,6 +3290,13 @@ static const struct frame_parm_table frame_parms[] =
|
|||
{"sticky", SYMBOL_INDEX (Qsticky)},
|
||||
{"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
|
||||
{"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
|
||||
{"undecorated", SYMBOL_INDEX (Qundecorated)},
|
||||
{"parent-frame", SYMBOL_INDEX (Qparent_frame)},
|
||||
{"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
|
||||
{"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
|
||||
{"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
|
||||
{"z-group", SYMBOL_INDEX (Qz_group)},
|
||||
{"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
|
||||
};
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
|
@ -4882,6 +5084,14 @@ syms_of_frame (void)
|
|||
DEFSYM (Qheight, "height");
|
||||
DEFSYM (Qicon, "icon");
|
||||
DEFSYM (Qminibuffer, "minibuffer");
|
||||
DEFSYM (Qundecorated, "undecorated");
|
||||
DEFSYM (Qparent_frame, "parent-frame");
|
||||
DEFSYM (Qskip_taskbar, "skip-taskbar");
|
||||
DEFSYM (Qno_focus_on_map, "no-focus-on-map");
|
||||
DEFSYM (Qno_accept_focus, "no-accept-focus");
|
||||
DEFSYM (Qz_group, "z-group");
|
||||
DEFSYM (Qoverride_redirect, "override-redirect");
|
||||
DEFSYM (Qdelete_before, "delete-before");
|
||||
DEFSYM (Qmodeline, "modeline");
|
||||
DEFSYM (Qonly, "only");
|
||||
DEFSYM (Qnone, "none");
|
||||
|
|
@ -4978,6 +5188,7 @@ syms_of_frame (void)
|
|||
DEFSYM (Qauto_raise, "auto-raise");
|
||||
DEFSYM (Qborder_color, "border-color");
|
||||
DEFSYM (Qborder_width, "border-width");
|
||||
DEFSYM (Qouter_border_width, "outer-border-width");
|
||||
DEFSYM (Qbottom_divider_width, "bottom-divider-width");
|
||||
DEFSYM (Qcursor_color, "cursor-color");
|
||||
DEFSYM (Qcursor_type, "cursor-type");
|
||||
|
|
@ -5011,6 +5222,12 @@ syms_of_frame (void)
|
|||
DEFSYM (Qvisibility, "visibility");
|
||||
DEFSYM (Qwait_for_wm, "wait-for-wm");
|
||||
DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
|
||||
DEFSYM (Qno_other_frame, "no-other-frame");
|
||||
DEFSYM (Qbelow, "below");
|
||||
DEFSYM (Qabove_suspended, "above-suspended");
|
||||
DEFSYM (Qmin_width, "min-width");
|
||||
DEFSYM (Qmin_height, "min-height");
|
||||
DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
|
||||
|
||||
{
|
||||
int i;
|
||||
|
|
@ -5179,12 +5396,51 @@ displayed.
|
|||
|
||||
This variable is local to the current terminal and cannot be buffer-local. */);
|
||||
|
||||
DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
|
||||
DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
|
||||
doc: /* Non-nil if window system changes focus when you move the mouse.
|
||||
You should set this variable to tell Emacs how your window manager
|
||||
handles focus, since there is no way in general for Emacs to find out
|
||||
automatically. See also `mouse-autoselect-window'. */);
|
||||
focus_follows_mouse = 0;
|
||||
automatically.
|
||||
|
||||
There are three meaningful values:
|
||||
|
||||
- The default nil should be used when your window manager follows a
|
||||
"click-to-focus" policy where you have to click the mouse inside of a
|
||||
frame in order for that frame to get focus.
|
||||
|
||||
- The value t should be used when your window manager has the focus
|
||||
automatically follow the position of the mouse pointer but a window
|
||||
that gains focus is not raised automatically.
|
||||
|
||||
- The value `auto-raise' should be used when your window manager has the
|
||||
focus automatically follow the position of the mouse pointer and a
|
||||
window that gains focus is raised automatically.
|
||||
|
||||
If this option is non-nil, Emacs moves the mouse pointer to the frame
|
||||
selected by `select-frame-set-input-focus'. This function is used by a
|
||||
number of commands like, for example, `other-frame' and `pop-to-buffer'.
|
||||
If this option is nil and your focus follows mouse window manager does
|
||||
not autonomously move the mouse pointer to the newly selected frame, the
|
||||
previously selected window manager window might get reselected instead
|
||||
immediately.
|
||||
|
||||
The distinction between the values t and `auto-raise' is not needed for
|
||||
"normal" frames because the window manager takes care of raising them.
|
||||
Setting this to `auto-raise' will, however, override the standard
|
||||
behavior of a window manager that does not automatically raise the frame
|
||||
that gets focus. Setting this to `auto-raise' is also necessary to
|
||||
automatically raise child frames which are usually left alone by the
|
||||
window manager.
|
||||
|
||||
Note that this option does not distinguish "sloppy" focus (where the
|
||||
frame that previously had focus retains focus as long as the mouse
|
||||
pointer does not move into another window manager window) from "strict"
|
||||
focus (where a frame immediately loses focus when it's left by the mouse
|
||||
pointer).
|
||||
|
||||
In order to extend a "focus follows mouse" policy to individual Emacs
|
||||
windows, customize the variable `mouse-autoselect-window'. */);
|
||||
focus_follows_mouse = Qnil;
|
||||
|
||||
DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
|
||||
doc: /* Non-nil means resize frames pixelwise.
|
||||
|
|
@ -5286,6 +5542,8 @@ Gtk+ tooltips are not used) and on Windows. */);
|
|||
defsubr (&Sselect_frame);
|
||||
defsubr (&Sselected_frame);
|
||||
defsubr (&Sframe_list);
|
||||
defsubr (&Sframe_parent);
|
||||
defsubr (&Sframe_ancestor_p);
|
||||
defsubr (&Snext_frame);
|
||||
defsubr (&Sprevious_frame);
|
||||
defsubr (&Slast_nonminibuf_frame);
|
||||
|
|
|
|||
86
src/frame.h
86
src/frame.h
|
|
@ -45,6 +45,13 @@ enum fullscreen_type
|
|||
#endif
|
||||
};
|
||||
|
||||
enum z_group
|
||||
{
|
||||
z_group_none,
|
||||
z_group_above,
|
||||
z_group_below,
|
||||
z_group_above_suspended,
|
||||
};
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
/* The structure representing a frame. */
|
||||
|
|
@ -68,6 +75,11 @@ struct frame
|
|||
Usually it is nil. */
|
||||
Lisp_Object title;
|
||||
|
||||
#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
|
||||
/* This frame's parent frame, if it has one. */
|
||||
Lisp_Object parent_frame;
|
||||
#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
|
||||
|
||||
/* The frame which should receive keystrokes that occur in this
|
||||
frame, or nil if they should go to the frame itself. This is
|
||||
usually nil, but if the frame is minibufferless, we can use this
|
||||
|
|
@ -320,6 +332,30 @@ struct frame
|
|||
bool_bf horizontal_scroll_bars : 1;
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
|
||||
/* True if this is an undecorated frame. */
|
||||
bool_bf undecorated : 1;
|
||||
|
||||
#ifndef HAVE_NTGUI
|
||||
/* True if this is an override_redirect frame. */
|
||||
bool_bf override_redirect : 1;
|
||||
#endif
|
||||
|
||||
/* Nonzero if this frame's icon should not appear on its display's taskbar. */
|
||||
bool_bf skip_taskbar : 1;
|
||||
|
||||
/* Nonzero if this frame's window F's X window does not want to
|
||||
receive input focus when it is mapped. */
|
||||
bool_bf no_focus_on_map : 1;
|
||||
|
||||
/* Nonzero if this frame's window does not want to receive input focus
|
||||
via mouse clicks or by moving the mouse into it. */
|
||||
bool_bf no_accept_focus : 1;
|
||||
|
||||
/* The z-group this frame's window belongs to. */
|
||||
ENUM_BF (z_group) z_group : 2;
|
||||
#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
|
||||
|
||||
/* Whether new_height and new_width shall be interpreted
|
||||
in pixels. */
|
||||
bool_bf new_pixelwise : 1;
|
||||
|
|
@ -534,6 +570,13 @@ fset_face_alist (struct frame *f, Lisp_Object val)
|
|||
{
|
||||
f->face_alist = val;
|
||||
}
|
||||
#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
|
||||
INLINE void
|
||||
fset_parent_frame (struct frame *f, Lisp_Object val)
|
||||
{
|
||||
f->parent_frame = val;
|
||||
}
|
||||
#endif
|
||||
INLINE void
|
||||
fset_focus_frame (struct frame *f, Lisp_Object val)
|
||||
{
|
||||
|
|
@ -854,7 +897,6 @@ default_pixels_per_inch_y (void)
|
|||
#define FRAME_FOCUS_FRAME(f) f->focus_frame
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
||||
/* This frame slot says whether scroll bars are currently enabled for frame F,
|
||||
and which side they are on. */
|
||||
#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type)
|
||||
|
|
@ -864,17 +906,47 @@ default_pixels_per_inch_y (void)
|
|||
((f)->vertical_scroll_bar_type == vertical_scroll_bar_left)
|
||||
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \
|
||||
((f)->vertical_scroll_bar_type == vertical_scroll_bar_right)
|
||||
|
||||
#else /* not HAVE_WINDOW_SYSTEM */
|
||||
|
||||
/* If there is no window system, there are no scroll bars. */
|
||||
#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none)
|
||||
#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0)
|
||||
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0)
|
||||
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0)
|
||||
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
|
||||
#define FRAME_UNDECORATED(f) ((f)->undecorated)
|
||||
#ifdef HAVE_NTGUI
|
||||
#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0)
|
||||
#else
|
||||
#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect)
|
||||
#endif
|
||||
#define FRAME_PARENT_FRAME(f) \
|
||||
(NILP ((f)->parent_frame) \
|
||||
? NULL \
|
||||
: XFRAME ((f)->parent_frame))
|
||||
#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar)
|
||||
#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map)
|
||||
#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus)
|
||||
#define FRAME_Z_GROUP(f) ((f)->z_group)
|
||||
#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none)
|
||||
#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above)
|
||||
#define FRAME_Z_GROUP_ABOVE_SUSPENDED(f) \
|
||||
((f)->z_group == z_group_above_suspended)
|
||||
#define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below)
|
||||
#else /* not HAVE_WINDOW_SYSTEM or HAVE_NS */
|
||||
#define FRAME_UNDECORATED(f) ((void) f, 0)
|
||||
#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0)
|
||||
#define FRAME_PARENT_FRAME(f) ((void) f, NULL)
|
||||
#define FRAME_SKIP_TASKBAR(f) ((void) f, 0)
|
||||
#define FRAME_NO_FOCUS_ON_MAP(f) ((void) f, 0)
|
||||
#define FRAME_NO_ACCEPT_FOCUS(f) ((void) f, 0)
|
||||
#define FRAME_Z_GROUP(f) ((void) f, z_group_none)
|
||||
#define FRAME_Z_GROUP_NONE(f) ((void) f, true)
|
||||
#define FRAME_Z_GROUP_ABOVE(f) ((void) f, false)
|
||||
#define FRAME_Z_GROUP_BELOW(f) ((void) f, false)
|
||||
#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */
|
||||
|
||||
/* Whether horizontal scroll bars are currently enabled for frame F. */
|
||||
#if USE_HORIZONTAL_SCROLL_BARS
|
||||
#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
|
||||
|
|
@ -1041,7 +1113,8 @@ default_pixels_per_inch_y (void)
|
|||
loop will set FRAME_VAR, a Lisp_Object, to each frame in
|
||||
Vframe_list in succession and execute the statement. LIST_VAR
|
||||
should be a Lisp_Object too; it is used to iterate through the
|
||||
Vframe_list.
|
||||
Vframe_list. Note that this macro walks over child frames and
|
||||
the tooltip frame as well.
|
||||
|
||||
This macro is a holdover from a time when multiple frames weren't always
|
||||
supported. An alternate definition of the macro would expand to
|
||||
|
|
@ -1221,7 +1294,7 @@ FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
|
|||
return frame_dimension (f->internal_border_width);
|
||||
}
|
||||
|
||||
/* Pixel-size of window border lines */
|
||||
/* Pixel-size of window divider lines */
|
||||
INLINE int
|
||||
FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f)
|
||||
{
|
||||
|
|
@ -1446,6 +1519,7 @@ extern void x_activate_menubar (struct frame *);
|
|||
extern void x_real_positions (struct frame *, int *, int *);
|
||||
extern void free_frame_menubar (struct frame *);
|
||||
extern void x_free_frame_resources (struct frame *);
|
||||
extern bool frame_ancestor_p (struct frame *af, struct frame *df);
|
||||
|
||||
#if defined HAVE_X_WINDOWS
|
||||
extern void x_wm_set_icon_position (struct frame *, int, int);
|
||||
|
|
|
|||
135
src/gtkutil.c
135
src/gtkutil.c
|
|
@ -1200,7 +1200,14 @@ xg_create_frame_widgets (struct frame *f)
|
|||
else if (! NILP (f->name))
|
||||
title = SSDATA (ENCODE_UTF_8 (f->name));
|
||||
|
||||
if (title) gtk_window_set_title (GTK_WINDOW (wtop), title);
|
||||
if (title)
|
||||
gtk_window_set_title (GTK_WINDOW (wtop), title);
|
||||
|
||||
if (FRAME_UNDECORATED (f))
|
||||
{
|
||||
gtk_window_set_decorated (GTK_WINDOW (wtop), FALSE);
|
||||
store_frame_param (f, Qundecorated, Qt);
|
||||
}
|
||||
|
||||
FRAME_GTK_OUTER_WIDGET (f) = wtop;
|
||||
FRAME_GTK_WIDGET (f) = wfixed;
|
||||
|
|
@ -1275,6 +1282,14 @@ xg_create_frame_widgets (struct frame *f)
|
|||
gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE);
|
||||
#endif
|
||||
|
||||
if (FRAME_OVERRIDE_REDIRECT (f))
|
||||
{
|
||||
GdkWindow *gwin = gtk_widget_get_window (wtop);
|
||||
|
||||
if (gwin)
|
||||
gdk_window_set_override_redirect (gwin, TRUE);
|
||||
}
|
||||
|
||||
#ifdef USE_GTK_TOOLTIP
|
||||
/* Steal a tool tip window we can move ourselves. */
|
||||
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)
|
|||
/* Don't set size hints during initialization; that apparently leads
|
||||
to a race condition. See the thread at
|
||||
http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */
|
||||
if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
|
||||
if (NILP (Vafter_init_time)
|
||||
|| !FRAME_GTK_OUTER_WIDGET (f)
|
||||
|| FRAME_PARENT_FRAME (f))
|
||||
return;
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
|
@ -1489,6 +1506,100 @@ xg_set_background_color (struct frame *f, unsigned long bg)
|
|||
}
|
||||
}
|
||||
|
||||
/* Change the frame's decoration (title bar + resize borders). This
|
||||
might not work with all window managers. */
|
||||
void
|
||||
xg_set_undecorated (struct frame *f, Lisp_Object undecorated)
|
||||
{
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
{
|
||||
block_input ();
|
||||
gtk_window_set_decorated (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
NILP (undecorated) ? TRUE : FALSE);
|
||||
unblock_input ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Restack F1 below F2, above if ABOVE_FLAG is true. This might not
|
||||
work with all window managers. */
|
||||
void
|
||||
xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))
|
||||
{
|
||||
GdkWindow *gwin1 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f1));
|
||||
GdkWindow *gwin2 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f2));
|
||||
Lisp_Object frame1, frame2;
|
||||
|
||||
XSETFRAME (frame1, f1);
|
||||
XSETFRAME (frame2, f2);
|
||||
|
||||
gdk_window_restack (gwin1, gwin2, above_flag);
|
||||
x_sync (f1);
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
||||
/* Don't show frame in taskbar, don't ALT-TAB to it. */
|
||||
void
|
||||
xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
gdk_window_set_skip_taskbar_hint
|
||||
(gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
NILP (skip_taskbar) ? FALSE : TRUE);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
||||
/* Don't give frame focus. */
|
||||
void
|
||||
xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
{
|
||||
GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
|
||||
gboolean gno_focus_on_map = NILP (no_focus_on_map) ? TRUE : FALSE;
|
||||
|
||||
gtk_window_set_focus_on_map (gwin, gno_focus_on_map);
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
{
|
||||
GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
|
||||
gboolean gno_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE;
|
||||
|
||||
gtk_window_set_accept_focus (gwin, gno_accept_focus);
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
void
|
||||
xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect)
|
||||
{
|
||||
block_input ();
|
||||
|
||||
if (FRAME_GTK_OUTER_WIDGET (f))
|
||||
{
|
||||
GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
|
||||
|
||||
gdk_window_set_override_redirect (gwin, NILP (override_redirect) ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK
|
||||
functions so GTK does not overwrite the icon. */
|
||||
|
|
@ -3769,6 +3880,7 @@ xg_update_scrollbar_pos (struct frame *f,
|
|||
GtkWidget *wparent = gtk_widget_get_parent (wscroll);
|
||||
gint msl;
|
||||
int scale = xg_get_gdk_scale ();
|
||||
bool hidden;
|
||||
|
||||
top /= scale;
|
||||
left /= scale;
|
||||
|
|
@ -3793,6 +3905,7 @@ xg_update_scrollbar_pos (struct frame *f,
|
|||
the height is less than the min size. */
|
||||
gtk_widget_hide (wparent);
|
||||
gtk_widget_hide (wscroll);
|
||||
hidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3807,6 +3920,15 @@ xg_update_scrollbar_pos (struct frame *f,
|
|||
x_clear_area (f, oldx, oldy, oldw, oldh);
|
||||
}
|
||||
|
||||
if (!hidden)
|
||||
{
|
||||
GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id);
|
||||
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
|
||||
|
||||
/* Don't obscure any child frames. */
|
||||
XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
|
||||
}
|
||||
|
||||
/* GTK does not redraw until the main loop is entered again, but
|
||||
if there are no X events pending we will not enter it. So we sync
|
||||
here to get some events. */
|
||||
|
|
@ -3872,6 +3994,15 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
|
|||
if there are no X events pending we will not enter it. So we sync
|
||||
here to get some events. */
|
||||
|
||||
{
|
||||
GtkWidget *scrollbar =
|
||||
xg_get_widget_from_map (scrollbar_id);
|
||||
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
|
||||
|
||||
/* Don't obscure any child frames. */
|
||||
XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
|
||||
}
|
||||
|
||||
x_sync (f);
|
||||
SET_FRAME_GARBAGED (f);
|
||||
cancel_mouse_face (f);
|
||||
|
|
|
|||
|
|
@ -172,6 +172,13 @@ extern void xg_set_frame_icon (struct frame *f,
|
|||
Pixmap icon_pixmap,
|
||||
Pixmap icon_mask);
|
||||
|
||||
extern void xg_set_undecorated (struct frame *f, Lisp_Object undecorated);
|
||||
extern void xg_frame_restack (struct frame *f1, struct frame *f2, bool above);
|
||||
extern void xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar);
|
||||
extern void xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map);
|
||||
extern void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus);
|
||||
extern void xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect);
|
||||
|
||||
extern bool xg_prepare_tooltip (struct frame *f,
|
||||
Lisp_Object string,
|
||||
int *width,
|
||||
|
|
|
|||
13
src/nsfns.m
13
src/nsfns.m
|
|
@ -972,6 +972,13 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
|
|||
0, /* x_set_sticky */
|
||||
0, /* x_set_tool_bar_position */
|
||||
0, /* x_set_inhibit_double_buffering */
|
||||
0, /* x_set_undecorated */
|
||||
0, /* x_set_parent_frame */
|
||||
0, /* x_set_skip_taskbar */
|
||||
0, /* x_set_no_focus_on_map */
|
||||
0, /* x_set_no_accept_focus */
|
||||
0, /* x_set_z_group */
|
||||
0, /* x_set_override_redirect */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1248,6 +1255,12 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
|
|||
init_frame_faces (f);
|
||||
|
||||
/* Read comment about this code in corresponding place in xfns.c. */
|
||||
tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_width, tem);
|
||||
tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_height, tem);
|
||||
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
|
||||
FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
|
||||
Qx_create_frame_1);
|
||||
|
|
|
|||
|
|
@ -6288,7 +6288,7 @@ - (void)mouseMoved: (NSEvent *)e
|
|||
if (WINDOWP (window)
|
||||
&& !EQ (window, last_mouse_window)
|
||||
&& !EQ (window, selected_window)
|
||||
&& (focus_follows_mouse
|
||||
&& (!NILP (focus_follows_mouse)
|
||||
|| (EQ (XWINDOW (window)->frame,
|
||||
XWINDOW (selected_window)->frame))))
|
||||
{
|
||||
|
|
|
|||
659
src/w32fns.c
659
src/w32fns.c
|
|
@ -256,6 +256,10 @@ static unsigned int sound_type = 0xFFFFFFFF;
|
|||
# define WTS_SESSION_LOCK 0x7
|
||||
#endif
|
||||
|
||||
#ifndef WS_EX_NOACTIVATE
|
||||
#define WS_EX_NOACTIVATE 0x08000000L
|
||||
#endif
|
||||
|
||||
/* Keyboard hook state data. */
|
||||
static struct
|
||||
{
|
||||
|
|
@ -367,17 +371,20 @@ void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
|
|||
void
|
||||
x_real_positions (struct frame *f, int *xptr, int *yptr)
|
||||
{
|
||||
POINT pt;
|
||||
RECT rect;
|
||||
|
||||
/* Get the bounds of the WM window. */
|
||||
GetWindowRect (FRAME_W32_WINDOW (f), &rect);
|
||||
|
||||
pt.x = 0;
|
||||
pt.y = 0;
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
/* For a child window we have to get its coordinates wrt its
|
||||
parent. */
|
||||
HWND parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
|
||||
|
||||
/* Convert (0, 0) in the client area to screen co-ordinates. */
|
||||
ClientToScreen (FRAME_W32_WINDOW (f), &pt);
|
||||
if (parent_hwnd)
|
||||
MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
|
||||
}
|
||||
|
||||
*xptr = rect.left;
|
||||
*yptr = rect.top;
|
||||
|
|
@ -1682,7 +1689,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
|
|||
most of the commands try to apply themselves to the minibuffer
|
||||
frame itself, and get an error because you can't switch buffers
|
||||
in or split the minibuffer window. */
|
||||
if (FRAME_MINIBUF_ONLY_P (f))
|
||||
if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
|
||||
return;
|
||||
|
||||
if (INTEGERP (value))
|
||||
|
|
@ -1955,6 +1962,233 @@ x_set_scroll_bar_default_height (struct frame *f)
|
|||
FRAME_CONFIG_SCROLL_BAR_LINES (f)
|
||||
= (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_undecorated:
|
||||
*
|
||||
* Set frame F's `undecorated' parameter. If non-nil, F's window-system
|
||||
* window is drawn without decorations, title, minimize/maximize boxes
|
||||
* and external borders. This usually means that the window cannot be
|
||||
* dragged, resized, iconified, maximized or deleted with the mouse. If
|
||||
* nil, draw the frame with all the elements listed above unless these
|
||||
* have been suspended via window manager settings.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
HWND hwnd = FRAME_W32_WINDOW (f);
|
||||
DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
|
||||
Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
|
||||
|
||||
block_input ();
|
||||
if (!NILP (new_value) && !FRAME_UNDECORATED (f))
|
||||
{
|
||||
dwStyle = ((dwStyle & ~WS_THICKFRAME & ~WS_CAPTION)
|
||||
| ((NUMBERP (border_width) && (XINT (border_width) > 0))
|
||||
? WS_BORDER : false));
|
||||
SetWindowLong (hwnd, GWL_STYLE, dwStyle);
|
||||
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
|
||||
| SWP_FRAMECHANGED);
|
||||
FRAME_UNDECORATED (f) = true;
|
||||
}
|
||||
else if (NILP (new_value) && FRAME_UNDECORATED (f))
|
||||
{
|
||||
SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_CAPTION
|
||||
| WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU);
|
||||
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
|
||||
| SWP_FRAMECHANGED);
|
||||
FRAME_UNDECORATED (f) = false;
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_parent_frame:
|
||||
*
|
||||
* Set frame F's `parent-frame' parameter. If non-nil, make F a child
|
||||
* frame of the frame specified by that parameter. Technically, this
|
||||
* makes F's window-system window a child window of the parent frame's
|
||||
* window-system window. If nil, make F's window-system window a
|
||||
* top-level window--a child of its display's root window.
|
||||
*
|
||||
* A child frame is clipped at the native edges of its parent frame.
|
||||
* Its `left' and `top' parameters specify positions relative to the
|
||||
* top-left corner of its parent frame's native rectangle. Usually,
|
||||
* moving a parent frame moves all its child frames too, keeping their
|
||||
* position relative to the parent unaltered. When a parent frame is
|
||||
* iconified or made invisible, its child frames are made invisible.
|
||||
* When a parent frame is deleted, its child frames are deleted too.
|
||||
*
|
||||
* A visible child frame always appears on top of its parent frame thus
|
||||
* obscuring parts of it. When a frame has more than one child frame,
|
||||
* their stacking order is specified just as that of non-child frames
|
||||
* relative to their display.
|
||||
*
|
||||
* Whether a child frame has a menu or tool bar may be window-system or
|
||||
* window manager dependent. It's advisable to disable both via the
|
||||
* frame parameter settings.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
struct frame *p = NULL;
|
||||
|
||||
if (!NILP (new_value)
|
||||
&& (!FRAMEP (new_value)
|
||||
|| !FRAME_LIVE_P (p = XFRAME (new_value))
|
||||
|| !FRAME_W32_P (p)))
|
||||
{
|
||||
store_frame_param (f, Qparent_frame, old_value);
|
||||
error ("Invalid specification of `parent-frame'");
|
||||
}
|
||||
|
||||
if (p != FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
HWND hwnd = FRAME_W32_WINDOW (f);
|
||||
HWND hwnd_parent = p ? FRAME_W32_WINDOW (p) : NULL;
|
||||
HWND hwnd_value;
|
||||
|
||||
block_input ();
|
||||
hwnd_value = SetParent (hwnd, hwnd_parent);
|
||||
unblock_input ();
|
||||
|
||||
if (hwnd_value)
|
||||
fset_parent_frame (f, new_value);
|
||||
else
|
||||
{
|
||||
store_frame_param (f, Qparent_frame, old_value);
|
||||
error ("Reparenting frame failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_skip_taskbar:
|
||||
*
|
||||
* Set frame F's `skip-taskbar' parameter. If non-nil, this should
|
||||
* remove F's icon from the taskbar associated with the display of F's
|
||||
* window-system window and inhibit switching to F's window via
|
||||
* <Alt>-<TAB>. On Windows iconifying F will "roll in" its window at
|
||||
* the bottom of the desktop. If nil, lift these restrictions.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
HWND hwnd = FRAME_W32_WINDOW (f);
|
||||
DWORD exStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
|
||||
|
||||
block_input ();
|
||||
/* Temporarily hide the window while changing its WS_EX_NOACTIVATE
|
||||
setting. */
|
||||
ShowWindow (hwnd, SW_HIDE);
|
||||
if (!NILP (new_value))
|
||||
SetWindowLong (hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
|
||||
else
|
||||
SetWindowLong (hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
|
||||
ShowWindow (hwnd, SW_SHOWNOACTIVATE);
|
||||
unblock_input ();
|
||||
|
||||
FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_no_focus_on_map:
|
||||
*
|
||||
* Set frame F's `no-focus-on-map' parameter which, if non-nil, means
|
||||
* that F's window-system window does not want to receive input focus
|
||||
* when it is mapped. (A frame's window is mapped when the frame is
|
||||
* displayed for the first time and when the frame changes its state
|
||||
* from `iconified' or `invisible' to `visible'.)
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_no_accept_focus:
|
||||
*
|
||||
* Set frame F's `no-accept-focus' parameter which, if non-nil, hints
|
||||
* that F's window-system window does not want to receive input focus
|
||||
* via mouse clicks or by moving the mouse into it.
|
||||
*
|
||||
* If non-nil, this may have the unwanted side-effect that a user cannot
|
||||
* scroll a non-selected frame with the mouse.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_z_group:
|
||||
*
|
||||
* Set frame F's `z-group' parameter. If `above', F's window-system
|
||||
* window is displayed above all windows that do not have the `above'
|
||||
* property set. If nil, F's window is shown below all windows that
|
||||
* have the `above' property set and above all windows that have the
|
||||
* `below' property set. If `below', F's window is displayed below all
|
||||
* windows that do not have the `below' property set.
|
||||
*
|
||||
* Some window managers may not honor this parameter. The value `below'
|
||||
* is not supported on Windows.
|
||||
*/
|
||||
static void
|
||||
x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
HWND hwnd = FRAME_W32_WINDOW (f);
|
||||
|
||||
if (NILP (new_value))
|
||||
{
|
||||
block_input ();
|
||||
SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
|
||||
| SWP_NOOWNERZORDER);
|
||||
unblock_input ();
|
||||
FRAME_Z_GROUP (f) = z_group_none;
|
||||
}
|
||||
else if (EQ (new_value, Qabove))
|
||||
{
|
||||
block_input ();
|
||||
SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
|
||||
| SWP_NOOWNERZORDER);
|
||||
unblock_input ();
|
||||
FRAME_Z_GROUP (f) = z_group_above;
|
||||
}
|
||||
else if (EQ (new_value, Qabove_suspended))
|
||||
{
|
||||
block_input ();
|
||||
SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
|
||||
| SWP_NOOWNERZORDER);
|
||||
unblock_input ();
|
||||
FRAME_Z_GROUP (f) = z_group_above_suspended;
|
||||
}
|
||||
else if (EQ (new_value, Qbelow))
|
||||
error ("Value `below' for z-group is not supported on Windows");
|
||||
else
|
||||
error ("Invalid z-group specification");
|
||||
}
|
||||
|
||||
/* Subroutines for creating a frame. */
|
||||
|
||||
|
|
@ -2013,7 +2247,12 @@ w32_init_class (HINSTANCE hinst)
|
|||
static HWND
|
||||
w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
|
||||
{
|
||||
return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
|
||||
return CreateWindow ("SCROLLBAR", "",
|
||||
/* Clip siblings so we don't draw over child
|
||||
frames. Apparently this is not always
|
||||
sufficient so we also try to make bar windows
|
||||
bottommost. */
|
||||
SBS_VERT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
||||
/* Position and size of scroll bar. */
|
||||
bar->left, bar->top, bar->width, bar->height,
|
||||
FRAME_W32_WINDOW (f), NULL, hinst, NULL);
|
||||
|
|
@ -2022,7 +2261,12 @@ w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
|
|||
static HWND
|
||||
w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
|
||||
{
|
||||
return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE,
|
||||
return CreateWindow ("SCROLLBAR", "",
|
||||
/* Clip siblings so we don't draw over child
|
||||
frames. Apparently this is not always
|
||||
sufficient so we also try to make bar windows
|
||||
bottommost. */
|
||||
SBS_HORZ | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
||||
/* Position and size of scroll bar. */
|
||||
bar->left, bar->top, bar->width, bar->height,
|
||||
FRAME_W32_WINDOW (f), NULL, hinst, NULL);
|
||||
|
|
@ -2031,20 +2275,55 @@ w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
|
|||
static void
|
||||
w32_createwindow (struct frame *f, int *coords)
|
||||
{
|
||||
HWND hwnd;
|
||||
HWND hwnd = NULL, parent_hwnd = NULL;
|
||||
RECT rect;
|
||||
int top;
|
||||
int left;
|
||||
DWORD dwStyle;
|
||||
int top, left;
|
||||
Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
|
||||
|
||||
if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
|
||||
{
|
||||
parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
|
||||
f->output_data.w32->dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
|
||||
|
||||
if (FRAME_UNDECORATED (f))
|
||||
{
|
||||
/* If we want a thin border, specify it here. */
|
||||
if (NUMBERP (border_width) && (XINT (border_width) > 0))
|
||||
f->output_data.w32->dwStyle =
|
||||
f->output_data.w32->dwStyle | WS_BORDER;
|
||||
}
|
||||
else
|
||||
/* To decorate a child frame, list all needed elements. */
|
||||
f->output_data.w32->dwStyle =
|
||||
f->output_data.w32->dwStyle | WS_THICKFRAME | WS_CAPTION
|
||||
| WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU;
|
||||
}
|
||||
else if (FRAME_UNDECORATED (f))
|
||||
{
|
||||
/* All attempts to start with ~WS_OVERLAPPEDWINDOW or overlapped
|
||||
with all other style elements negated failed here. */
|
||||
f->output_data.w32->dwStyle = WS_POPUP;
|
||||
|
||||
/* If we want a thin border, specify it here. */
|
||||
if (NUMBERP (border_width) && (XINT (border_width) > 0))
|
||||
f->output_data.w32->dwStyle =
|
||||
f->output_data.w32->dwStyle | WS_BORDER;
|
||||
}
|
||||
else
|
||||
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
/* Always clip children. */
|
||||
f->output_data.w32->dwStyle = f->output_data.w32->dwStyle | WS_CLIPCHILDREN;
|
||||
|
||||
rect.left = rect.top = 0;
|
||||
rect.right = FRAME_PIXEL_WIDTH (f);
|
||||
rect.bottom = FRAME_PIXEL_HEIGHT (f);
|
||||
|
||||
AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
|
||||
FRAME_EXTERNAL_MENU_BAR (f));
|
||||
FRAME_EXTERNAL_MENU_BAR (f) && !parent_hwnd);
|
||||
|
||||
/* Do first time app init */
|
||||
|
||||
w32_init_class (hinst);
|
||||
|
||||
if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
|
||||
|
|
@ -2059,18 +2338,16 @@ w32_createwindow (struct frame *f, int *coords)
|
|||
}
|
||||
|
||||
FRAME_W32_WINDOW (f) = hwnd
|
||||
= CreateWindow (EMACS_CLASS,
|
||||
f->namebuf,
|
||||
f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
|
||||
left, top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
NULL,
|
||||
NULL,
|
||||
hinst,
|
||||
NULL);
|
||||
= CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
|
||||
left, top, rect.right - rect.left, rect.bottom - rect.top,
|
||||
parent_hwnd, NULL, hinst, NULL);
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
if (FRAME_SKIP_TASKBAR (f))
|
||||
SetWindowLong (hwnd, GWL_EXSTYLE,
|
||||
GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
|
||||
|
||||
SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
|
||||
SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
|
||||
SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
|
||||
|
|
@ -2086,6 +2363,12 @@ w32_createwindow (struct frame *f, int *coords)
|
|||
|
||||
/* Update frame positions. */
|
||||
GetWindowRect (hwnd, &rect);
|
||||
|
||||
if (parent_hwnd)
|
||||
/* For a child window we have to get its coordinates wrt its
|
||||
parent. */
|
||||
MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
|
||||
|
||||
f->left_pos = rect.left;
|
||||
f->top_pos = rect.top;
|
||||
}
|
||||
|
|
@ -4381,6 +4664,22 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
|
||||
if (f && (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN
|
||||
|| msg == WM_MBUTTONDOWN ||msg == WM_XBUTTONDOWN)
|
||||
&& !FRAME_NO_ACCEPT_FOCUS (f))
|
||||
/* When clicking into a child frame or when clicking into a
|
||||
parent frame with the child frame selected and
|
||||
`no-accept-focus' is not set, select the clicked frame. */
|
||||
{
|
||||
struct frame *p = FRAME_PARENT_FRAME (XFRAME (selected_frame));
|
||||
|
||||
if (FRAME_PARENT_FRAME (f) || f == p)
|
||||
{
|
||||
SetFocus (hwnd);
|
||||
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
wmsg.dwModifiers = w32_get_modifiers ();
|
||||
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
|
||||
signal_user_input ();
|
||||
|
|
@ -4486,6 +4785,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
if (w32_pass_multimedia_buttons_to_system)
|
||||
goto dflt;
|
||||
/* Otherwise, pass to lisp, the same way we do with mousehwheel. */
|
||||
|
||||
/* FIXME!!! This is never reached so what's the purpose? If the
|
||||
non-zero return remark below is right we're doing it wrong all
|
||||
the time. */
|
||||
case WM_MOUSEHWHEEL:
|
||||
wmsg.dwModifiers = w32_get_modifiers ();
|
||||
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
|
||||
|
|
@ -4712,19 +5015,34 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
case WM_MOUSEACTIVATE:
|
||||
/* WM_MOUSEACTIVATE is the only way on Windows to implement the
|
||||
`no-accept-focus' frame parameter. This means that one can't
|
||||
use the mouse to scroll a window on a non-selected frame. */
|
||||
|
||||
/* Still not right - can't distinguish between clicks in the
|
||||
client area of the frame from clicks forwarded from the scroll
|
||||
bars - may have to hook WM_NCHITTEST to remember the mouse
|
||||
position and then check if it is in the client area ourselves. */
|
||||
case WM_MOUSEACTIVATE:
|
||||
position and then check if it is in the client area
|
||||
ourselves. */
|
||||
|
||||
/* Discard the mouse click that activates a frame, allowing the
|
||||
user to click anywhere without changing point (or worse!).
|
||||
Don't eat mouse clicks on scrollbars though!! */
|
||||
if (LOWORD (lParam) == HTCLIENT )
|
||||
return MA_ACTIVATEANDEAT;
|
||||
|
||||
if ((f = x_window_to_frame (dpyinfo, hwnd))
|
||||
&& FRAME_NO_ACCEPT_FOCUS (f)
|
||||
/* Ignore child frames, they don't accept focus anyway. */
|
||||
&& !FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
Lisp_Object frame;
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
if (!EQ (selected_frame, frame))
|
||||
/* Don't discard the message, GTK doesn't either. */
|
||||
return MA_NOACTIVATE; /* ANDEAT; */
|
||||
}
|
||||
goto dflt;
|
||||
#endif
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
/* No longer tracking mouse. */
|
||||
|
|
@ -4903,6 +5221,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
AttachThreadInput (GetCurrentThreadId (),
|
||||
foreground_thread, FALSE);
|
||||
|
||||
/* SetFocus to give/remove focus to/from a child window. */
|
||||
if (msg == WM_EMACS_SETFOREGROUND)
|
||||
SetFocus ((HWND) wParam);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -5134,7 +5456,8 @@ w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
|
|||
|
||||
unblock_input ();
|
||||
|
||||
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
|
||||
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)
|
||||
&& !FRAME_PARENT_FRAME (f))
|
||||
initialize_frame_menubar (f);
|
||||
|
||||
if (FRAME_W32_WINDOW (f) == 0)
|
||||
|
|
@ -5322,7 +5645,7 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
Lisp_Object display;
|
||||
struct w32_display_info *dpyinfo = NULL;
|
||||
Lisp_Object parent;
|
||||
Lisp_Object parent, parent_frame;
|
||||
struct kboard *kb;
|
||||
int x_width = 0, x_height = 0;
|
||||
|
||||
|
|
@ -5359,10 +5682,11 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
Vx_resource_name = name;
|
||||
|
||||
/* See if parent window is specified. */
|
||||
parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
|
||||
parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
|
||||
RES_TYPE_NUMBER);
|
||||
if (EQ (parent, Qunbound))
|
||||
parent = Qnil;
|
||||
if (! NILP (parent))
|
||||
else if (!NILP (parent))
|
||||
CHECK_NUMBER (parent);
|
||||
|
||||
/* 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. */)
|
|||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
parent_frame = x_get_arg (dpyinfo, parameters, Qparent_frame, NULL, NULL,
|
||||
RES_TYPE_SYMBOL);
|
||||
/* Apply `parent-frame' parameter only when no `parent-id' was
|
||||
specified. */
|
||||
if (!NILP (parent_frame)
|
||||
&& (!NILP (parent)
|
||||
|| !FRAMEP (parent_frame)
|
||||
|| !FRAME_LIVE_P (XFRAME (parent_frame))
|
||||
|| !FRAME_W32_P (XFRAME (parent_frame))))
|
||||
parent_frame = Qnil;
|
||||
|
||||
fset_parent_frame (f, parent_frame);
|
||||
store_frame_param (f, Qparent_frame, parent_frame);
|
||||
|
||||
tem = x_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
|
||||
RES_TYPE_BOOLEAN);
|
||||
FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
|
||||
store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
|
||||
|
||||
tem = x_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
|
||||
RES_TYPE_BOOLEAN);
|
||||
FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
|
||||
store_frame_param (f, Qskip_taskbar,
|
||||
(NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
|
||||
|
||||
/* By default, make scrollbars the system standard width and height. */
|
||||
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
|
||||
FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
|
||||
|
|
@ -5412,7 +5761,9 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
dpyinfo_refcount = dpyinfo->reference_count;
|
||||
#endif /* GLYPH_DEBUG */
|
||||
|
||||
/* Specify the parent under which to make this window. */
|
||||
/* Specify the parent under which to make this window - this seems to
|
||||
have no effect on Windows because parent_desc is explicitly reset
|
||||
below. */
|
||||
if (!NILP (parent))
|
||||
{
|
||||
/* 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. */)
|
|||
"leftFringe", "LeftFringe", RES_TYPE_NUMBER);
|
||||
x_default_parameter (f, parameters, Qright_fringe, Qnil,
|
||||
"rightFringe", "RightFringe", RES_TYPE_NUMBER);
|
||||
/* Process alpha here (Bug#16619). */
|
||||
x_default_parameter (f, parameters, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
x_default_parameter (f, parameters, Qno_focus_on_map, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
x_default_parameter (f, parameters, Qno_accept_focus, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
|
||||
/* Process alpha here (Bug#16619). On XP this fails with child
|
||||
frames. For `no-focus-on-map' frames delay processing of alpha
|
||||
until the frame becomes visible. */
|
||||
if (!FRAME_NO_FOCUS_ON_MAP (f))
|
||||
x_default_parameter (f, parameters, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
|
||||
/* Init faces first since we need the frame's column width/line
|
||||
height in various occasions. */
|
||||
init_frame_faces (f);
|
||||
|
||||
/* The following call of change_frame_size is needed since otherwise
|
||||
/* We have to call adjust_frame_size here since otherwise
|
||||
x_set_tool_bar_lines will already work with the character sizes
|
||||
installed by init_frame_faces while the frame's pixel size is
|
||||
still calculated from a character size of 1 and we subsequently
|
||||
hit the (height >= 0) assertion in window_box_height.
|
||||
installed by init_frame_faces while the frame's pixel size is still
|
||||
calculated from a character size of 1 and we subsequently hit the
|
||||
(height >= 0) assertion in window_box_height.
|
||||
|
||||
The non-pixelwise code apparently worked around this because it
|
||||
had one frame line vs one toolbar line which left us with a zero
|
||||
root window height which was obviously wrong as well ... */
|
||||
root window height which was obviously wrong as well ...
|
||||
|
||||
Also process `min-width' and `min-height' parameters right here
|
||||
because `frame-windows-min-size' needs them. */
|
||||
tem = x_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
|
||||
RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_width, tem);
|
||||
tem = x_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
|
||||
RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_height, tem);
|
||||
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
|
||||
FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
|
||||
Qx_create_frame_1);
|
||||
|
|
@ -5520,10 +5890,17 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
/* The X resources controlling the menu-bar and tool-bar are
|
||||
processed specially at startup, and reflected in the mode
|
||||
variables; ignore them here. */
|
||||
x_default_parameter (f, parameters, Qmenu_bar_lines,
|
||||
NILP (Vmenu_bar_mode)
|
||||
? make_number (0) : make_number (1),
|
||||
NULL, NULL, RES_TYPE_NUMBER);
|
||||
if (NILP (parent_frame))
|
||||
{
|
||||
x_default_parameter (f, parameters, Qmenu_bar_lines,
|
||||
NILP (Vmenu_bar_mode)
|
||||
? make_number (0) : make_number (1),
|
||||
NULL, NULL, RES_TYPE_NUMBER);
|
||||
}
|
||||
else
|
||||
/* No menu bar for child frames. */
|
||||
store_frame_param (f, Qmenu_bar_lines, make_number (0));
|
||||
|
||||
x_default_parameter (f, parameters, Qtool_bar_lines,
|
||||
NILP (Vtool_bar_mode)
|
||||
? make_number (0) : make_number (1),
|
||||
|
|
@ -5534,9 +5911,7 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
x_default_parameter (f, parameters, Qtitle, Qnil,
|
||||
"title", "Title", RES_TYPE_STRING);
|
||||
|
||||
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
|
||||
|
||||
f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
|
||||
f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
|
||||
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. */)
|
|||
adjust_frame_size call. */
|
||||
x_default_parameter (f, parameters, Qfullscreen, Qnil,
|
||||
"fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
|
||||
x_default_parameter (f, parameters, Qz_group, Qnil,
|
||||
NULL, NULL, RES_TYPE_SYMBOL);
|
||||
|
||||
/* Make the window appear on the frame and enable display, unless
|
||||
the caller says not to. However, with explicit parent, Emacs
|
||||
cannot control visibility, so don't try. */
|
||||
if (! f->output_data.w32->explicit_parent)
|
||||
if (!f->output_data.w32->explicit_parent)
|
||||
{
|
||||
Lisp_Object visibility;
|
||||
|
||||
visibility = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
|
||||
if (EQ (visibility, Qunbound))
|
||||
visibility = Qt;
|
||||
Lisp_Object visibility
|
||||
= x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
|
||||
|
||||
if (EQ (visibility, Qicon))
|
||||
x_iconify_frame (f);
|
||||
else if (! NILP (visibility))
|
||||
x_make_frame_visible (f);
|
||||
else
|
||||
{
|
||||
/* Must have been Qnil. */
|
||||
;
|
||||
if (EQ (visibility, Qunbound))
|
||||
visibility = Qt;
|
||||
|
||||
if (!NILP (visibility))
|
||||
x_make_frame_visible (f);
|
||||
}
|
||||
|
||||
store_frame_param (f, Qvisibility, visibility);
|
||||
}
|
||||
|
||||
/* For `no-focus-on-map' frames set alpha here. */
|
||||
if (FRAME_NO_FOCUS_ON_MAP (f))
|
||||
x_default_parameter (f, parameters, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
|
||||
/* Initialize `default-minibuffer-frame' in case this is the first
|
||||
frame on this terminal. */
|
||||
if (FRAME_HAS_MINIBUF_P (f)
|
||||
|
|
@ -6572,8 +6954,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
|
|||
dpyinfo_refcount = dpyinfo->reference_count;
|
||||
#endif /* GLYPH_DEBUG */
|
||||
FRAME_KBOARD (f) = kb;
|
||||
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
|
||||
f->output_data.w32->explicit_parent = false;
|
||||
|
||||
/* Set the name; the functions to which we pass f expect the name to
|
||||
be set. */
|
||||
|
|
@ -6639,6 +7019,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
|
|||
|
||||
f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
|
||||
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
|
||||
f->output_data.w32->explicit_parent = false;
|
||||
|
||||
x_figure_window_size (f, parms, true, &x_width, &x_height);
|
||||
|
||||
|
|
@ -7282,6 +7663,23 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w32_dialog_in_progress (Lisp_Object in_progress)
|
||||
{
|
||||
Lisp_Object frames, frame;
|
||||
|
||||
/* Don't let frames in `above' z-group obscure popups. */
|
||||
FOR_EACH_FRAME (frames, frame)
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
|
||||
if (!NILP (in_progress) && FRAME_Z_GROUP_ABOVE (f))
|
||||
x_set_z_group (f, Qabove_suspended, Qabove);
|
||||
else if (NILP (in_progress) && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
|
||||
x_set_z_group (f, Qabove, Qabove_suspended);
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
|
||||
doc: /* Read file name, prompting with PROMPT in directory DIR.
|
||||
Use 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. */)
|
|||
|
||||
{
|
||||
int count = SPECPDL_INDEX ();
|
||||
|
||||
w32_dialog_in_progress (Qt);
|
||||
|
||||
/* Prevent redisplay. */
|
||||
specbind (Qinhibit_redisplay, Qt);
|
||||
record_unwind_protect (w32_dialog_in_progress, Qnil);
|
||||
block_input ();
|
||||
if (use_unicode)
|
||||
{
|
||||
|
|
@ -8559,6 +8961,136 @@ menu bar or tool bar of FRAME. */)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* w32_frame_list_z_order:
|
||||
*
|
||||
* Recursively add list of all frames on the display specified via
|
||||
* DPYINFO and whose window-system window's parent is specified by
|
||||
* WINDOW to FRAMES and return FRAMES.
|
||||
*/
|
||||
static Lisp_Object
|
||||
w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window)
|
||||
{
|
||||
Lisp_Object frame, frames = Qnil;
|
||||
|
||||
while (window)
|
||||
{
|
||||
struct frame *f = x_window_to_frame (dpyinfo, window);
|
||||
|
||||
if (f)
|
||||
{
|
||||
XSETFRAME (frame, f);
|
||||
frames = Fcons (frame, frames);
|
||||
}
|
||||
|
||||
block_input ();
|
||||
window = GetNextWindow (window, GW_HWNDNEXT);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
return Fnreverse (frames);
|
||||
}
|
||||
|
||||
DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
|
||||
Sw32_frame_list_z_order, 0, 1, 0,
|
||||
doc: /* Return list of Emacs' frames, in Z (stacking) order.
|
||||
The optional argument DISPLAY specifies which display to ask about.
|
||||
DISPLAY should be either a frame or a display name (a string). If
|
||||
omitted or nil, that stands for the selected frame's display.
|
||||
|
||||
As a special case, if DISPLAY is non-nil and specifies a live frame,
|
||||
return the child frames of that frame in Z (stacking) order.
|
||||
|
||||
Frames are listed from topmost (first) to bottommost (last). */)
|
||||
(Lisp_Object display)
|
||||
{
|
||||
struct w32_display_info *dpyinfo = check_x_display_info (display);
|
||||
HWND window;
|
||||
|
||||
block_input ();
|
||||
if (FRAMEP (display) && FRAME_LIVE_P (XFRAME (display)))
|
||||
window = GetWindow (FRAME_W32_WINDOW (XFRAME (display)), GW_CHILD);
|
||||
else
|
||||
window = GetTopWindow (NULL);
|
||||
unblock_input ();
|
||||
|
||||
return w32_frame_list_z_order (dpyinfo, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* w32_frame_restack:
|
||||
*
|
||||
* Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
|
||||
* practice this is a two-step action: The first step removes F1's
|
||||
* window-system window from the display. The second step reinserts
|
||||
* F1's window below (above if ABOVE_FLAG is true) that of F2.
|
||||
*/
|
||||
static void
|
||||
w32_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
|
||||
{
|
||||
HWND hwnd1 = FRAME_W32_WINDOW (f1);
|
||||
HWND hwnd2 = FRAME_W32_WINDOW (f2);
|
||||
|
||||
block_input ();
|
||||
if (above_flag)
|
||||
/* Put F1 above F2 in the z-order. */
|
||||
{
|
||||
if (GetNextWindow (hwnd1, GW_HWNDNEXT) != hwnd2)
|
||||
{
|
||||
/* Make sure F1 is below F2 first because we must not
|
||||
change the relative position of F2 wrt any other
|
||||
window but F1. */
|
||||
if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
|
||||
SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
|
||||
| SWP_FRAMECHANGED);
|
||||
/* Now put F1 above F2. */
|
||||
SetWindowPos (hwnd2, hwnd1, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
|
||||
| SWP_FRAMECHANGED);
|
||||
}
|
||||
}
|
||||
else if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
|
||||
/* Put F1 below F2 in the z-order. */
|
||||
SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
|
||||
| SWP_FRAMECHANGED);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
DEFUN ("w32-frame-restack", Fw32_frame_restack, Sw32_frame_restack, 2, 3, 0,
|
||||
doc: /* Restack FRAME1 below FRAME2.
|
||||
This means that if both frames are visible and the display areas of
|
||||
these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
|
||||
third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
|
||||
means that if both frames are visible and the display areas of these
|
||||
frames overlap, FRAME1 (partially) obscures FRAME2.
|
||||
|
||||
This may be thought of as an atomic action performed in two steps: The
|
||||
first step removes FRAME1's window-system window from the display. The
|
||||
second step reinserts FRAME1's window below (above if ABOVE is true)
|
||||
that of FRAME2. Hence the position of FRAME2 in its display's Z
|
||||
\(stacking) order relative to all other frames excluding FRAME1 remains
|
||||
unaltered.
|
||||
|
||||
Some window managers may refuse to restack windows. */)
|
||||
(Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
|
||||
{
|
||||
struct frame *f1 = decode_live_frame (frame1);
|
||||
struct frame *f2 = decode_live_frame (frame2);
|
||||
|
||||
if (FRAME_W32_P (f1) && FRAME_W32_P (f2))
|
||||
{
|
||||
w32_frame_restack (f1, f2, !NILP (above));
|
||||
return Qt;
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("Cannot restack frames");
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
|
||||
Sw32_mouse_absolute_pixel_position, 0, 0, 0,
|
||||
doc: /* Return absolute position of mouse cursor in pixels.
|
||||
|
|
@ -9753,6 +10285,13 @@ frame_parm_handler w32_frame_parm_handlers[] =
|
|||
0, /* x_set_sticky */
|
||||
0, /* x_set_tool_bar_position */
|
||||
0, /* x_set_inhibit_double_buffering */
|
||||
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,
|
||||
0, /* x_set_override_redirect */
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -10132,6 +10671,8 @@ tip frame. */);
|
|||
defsubr (&Sx_display_list);
|
||||
defsubr (&Sw32_frame_geometry);
|
||||
defsubr (&Sw32_frame_edges);
|
||||
defsubr (&Sw32_frame_list_z_order);
|
||||
defsubr (&Sw32_frame_restack);
|
||||
defsubr (&Sw32_mouse_absolute_pixel_position);
|
||||
defsubr (&Sw32_set_mouse_absolute_pixel_position);
|
||||
defsubr (&Sx_synchronize);
|
||||
|
|
|
|||
|
|
@ -2553,11 +2553,22 @@ in the font selection dialog. */)
|
|||
SelectObject (hdc, oldobj);
|
||||
ReleaseDC (FRAME_W32_WINDOW (f), hdc);
|
||||
|
||||
if (!ChooseFont (&cf)
|
||||
|| logfont_to_fcname (&lf, cf.iPointSize, buf, 100) < 0)
|
||||
return Qnil;
|
||||
{
|
||||
int count = SPECPDL_INDEX ();
|
||||
Lisp_Object value = Qnil;
|
||||
|
||||
return DECODE_SYSTEM (build_string (buf));
|
||||
w32_dialog_in_progress (Qt);
|
||||
specbind (Qinhibit_redisplay, Qt);
|
||||
record_unwind_protect (w32_dialog_in_progress, Qnil);
|
||||
|
||||
if (ChooseFont (&cf)
|
||||
&& logfont_to_fcname (&lf, cf.iPointSize, buf, 100) >= 0)
|
||||
value = DECODE_SYSTEM (build_string (buf));
|
||||
|
||||
unbind_to (count, Qnil);
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *const w32font_booleans [] = {
|
||||
|
|
|
|||
198
src/w32term.c
198
src/w32term.c
|
|
@ -3095,7 +3095,8 @@ construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
|
|||
coordinates, so cast to short to interpret them correctly. */
|
||||
p.x = (short) LOWORD (msg->msg.lParam);
|
||||
p.y = (short) HIWORD (msg->msg.lParam);
|
||||
ScreenToClient (msg->msg.hwnd, &p);
|
||||
/* For the case that F's w32 window is not msg->msg.hwnd. */
|
||||
ScreenToClient (FRAME_W32_WINDOW (f), &p);
|
||||
XSETINT (result->x, p.x);
|
||||
XSETINT (result->y, p.y);
|
||||
XSETFRAME (result->frame_or_window, f);
|
||||
|
|
@ -3446,8 +3447,22 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
/* If mouse was grabbed on a frame, give coords for that
|
||||
frame even if the mouse is now outside it. Otherwise
|
||||
check for window under mouse on one of our frames. */
|
||||
f1 = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: x_any_window_to_frame (dpyinfo, WindowFromPoint (pt)));
|
||||
if (x_mouse_grabbed (dpyinfo))
|
||||
f1 = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
{
|
||||
HWND wfp = WindowFromPoint (pt);
|
||||
|
||||
if (wfp && (f1 = x_any_window_to_frame (dpyinfo, wfp)))
|
||||
{
|
||||
HWND cwfp = ChildWindowFromPoint (wfp, pt);
|
||||
struct frame *f2;
|
||||
|
||||
/* If cwfp exists it should be one of our windows ... */
|
||||
if (cwfp && (f2 = x_any_window_to_frame (dpyinfo, cwfp)))
|
||||
f1 = f2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not, is it one of our scroll bars? */
|
||||
if (! f1)
|
||||
|
|
@ -3897,7 +3912,10 @@ w32_set_vertical_scroll_bar (struct window *w,
|
|||
/* Make sure scroll bar is "visible" before moving, to ensure the
|
||||
area of the parent window now exposed will be refreshed. */
|
||||
my_show_window (f, hwnd, SW_HIDE);
|
||||
MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
|
||||
/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
|
||||
/* Try to not draw over child frames. */
|
||||
SetWindowPos (hwnd, HWND_BOTTOM, left, top, width, max (height, 1),
|
||||
SWP_FRAMECHANGED);
|
||||
|
||||
si.cbSize = sizeof (si);
|
||||
si.fMask = SIF_RANGE;
|
||||
|
|
@ -3995,7 +4013,10 @@ w32_set_horizontal_scroll_bar (struct window *w,
|
|||
/* Make sure scroll bar is "visible" before moving, to ensure the
|
||||
area of the parent window now exposed will be refreshed. */
|
||||
my_show_window (f, hwnd, SW_HIDE);
|
||||
MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
|
||||
/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
|
||||
/* Try to not draw over child frames. */
|
||||
SetWindowPos (hwnd, HWND_BOTTOM, left, top, max (width, 1), height,
|
||||
SWP_FRAMECHANGED);
|
||||
|
||||
/* +++ SetScrollInfo +++ */
|
||||
si.cbSize = sizeof (si);
|
||||
|
|
@ -4649,7 +4670,7 @@ w32_read_socket (struct terminal *terminal,
|
|||
in that case expose_frame will do nothing, and if
|
||||
the various redisplay flags happen to be unset,
|
||||
we are left with a blank frame. */
|
||||
if (!FRAME_GARBAGED_P (f))
|
||||
if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
HDC hdc = get_frame_dc (f);
|
||||
|
||||
|
|
@ -4835,8 +4856,15 @@ w32_read_socket (struct terminal *terminal,
|
|||
|
||||
if (f)
|
||||
{
|
||||
/* Generate SELECT_WINDOW_EVENTs when needed. */
|
||||
if (!NILP (Vmouse_autoselect_window))
|
||||
/* Maybe generate SELECT_WINDOW_EVENTs for
|
||||
`mouse-autoselect-window'. */
|
||||
if (!NILP (Vmouse_autoselect_window)
|
||||
&& (f == XFRAME (selected_frame)
|
||||
/* Switch to f from another frame iff
|
||||
focus_follows_mouse is set and f accepts
|
||||
focus. */
|
||||
|| (!NILP (focus_follows_mouse)
|
||||
&& !FRAME_NO_ACCEPT_FOCUS (f))))
|
||||
{
|
||||
static Lisp_Object last_mouse_window;
|
||||
Lisp_Object window = window_from_coordinates
|
||||
|
|
@ -4848,20 +4876,16 @@ w32_read_socket (struct terminal *terminal,
|
|||
only when it is active. */
|
||||
if (WINDOWP (window)
|
||||
&& !EQ (window, last_mouse_window)
|
||||
&& !EQ (window, selected_window)
|
||||
/* For click-to-focus window managers
|
||||
create event iff we don't leave the
|
||||
selected frame. */
|
||||
&& (focus_follows_mouse
|
||||
|| (EQ (XWINDOW (window)->frame,
|
||||
XWINDOW (selected_window)->frame))))
|
||||
&& !EQ (window, selected_window))
|
||||
{
|
||||
inev.kind = SELECT_WINDOW_EVENT;
|
||||
inev.frame_or_window = window;
|
||||
}
|
||||
|
||||
/* Remember the last window where we saw the mouse. */
|
||||
last_mouse_window = window;
|
||||
}
|
||||
|
||||
if (!note_mouse_movement (f, &msg.msg))
|
||||
help_echo_string = previous_help_echo_string;
|
||||
}
|
||||
|
|
@ -4927,7 +4951,10 @@ w32_read_socket (struct terminal *terminal,
|
|||
|
||||
if (tool_bar_p
|
||||
|| (dpyinfo->w32_focus_frame
|
||||
&& f != dpyinfo->w32_focus_frame))
|
||||
&& f != dpyinfo->w32_focus_frame
|
||||
/* This does not help when the click happens in
|
||||
a grand-parent frame. */
|
||||
&& !frame_ancestor_p (f, dpyinfo->w32_focus_frame)))
|
||||
inev.kind = NO_EVENT;
|
||||
}
|
||||
|
||||
|
|
@ -4964,21 +4991,40 @@ w32_read_socket (struct terminal *terminal,
|
|||
|
||||
if (f)
|
||||
{
|
||||
|
||||
if (!dpyinfo->w32_focus_frame
|
||||
|| f == dpyinfo->w32_focus_frame)
|
||||
/* Emit an Emacs wheel-up/down event. */
|
||||
{
|
||||
/* Emit an Emacs wheel-up/down event. */
|
||||
construct_mouse_wheel (&inev, &msg, f);
|
||||
|
||||
/* Ignore any mouse motion that happened before this
|
||||
event; any subsequent mouse-movement Emacs events
|
||||
should reflect only motion after the ButtonPress. */
|
||||
f->mouse_moved = false;
|
||||
f->last_tool_bar_item = -1;
|
||||
dpyinfo->last_mouse_frame = f;
|
||||
}
|
||||
/* Ignore any mouse motion that happened before this
|
||||
event; any subsequent mouse-movement Emacs events
|
||||
should reflect only motion after the
|
||||
ButtonPress. */
|
||||
f->mouse_moved = false;
|
||||
f->last_tool_bar_item = -1;
|
||||
else if (FRAME_NO_ACCEPT_FOCUS (f)
|
||||
&& !x_mouse_grabbed (dpyinfo))
|
||||
{
|
||||
Lisp_Object frame1 = get_frame_param (f, Qmouse_wheel_frame);
|
||||
struct frame *f1 = FRAMEP (frame1) ? XFRAME (frame1) : NULL;
|
||||
|
||||
if (f1 && FRAME_LIVE_P (f1) && FRAME_W32_P (f1))
|
||||
{
|
||||
construct_mouse_wheel (&inev, &msg, f1);
|
||||
f1->mouse_moved = false;
|
||||
f1->last_tool_bar_item = -1;
|
||||
dpyinfo->last_mouse_frame = f1;
|
||||
}
|
||||
else
|
||||
dpyinfo->last_mouse_frame = f;
|
||||
}
|
||||
else
|
||||
dpyinfo->last_mouse_frame = f;
|
||||
}
|
||||
dpyinfo->last_mouse_frame = f;
|
||||
else
|
||||
dpyinfo->last_mouse_frame = f;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -5031,6 +5077,7 @@ w32_read_socket (struct terminal *terminal,
|
|||
w32fullscreen_hook (f);
|
||||
}
|
||||
}
|
||||
|
||||
check_visibility = 1;
|
||||
break;
|
||||
|
||||
|
|
@ -5969,6 +6016,8 @@ x_calc_absolute_position (struct frame *f)
|
|||
are computed correctly (Bug#21173). */
|
||||
int display_left = 0;
|
||||
int display_top = 0;
|
||||
struct frame *p = FRAME_PARENT_FRAME (f);
|
||||
|
||||
if (flags & (XNegative | YNegative))
|
||||
{
|
||||
Lisp_Object list;
|
||||
|
|
@ -5997,18 +6046,34 @@ x_calc_absolute_position (struct frame *f)
|
|||
/* Treat negative positions as relative to the rightmost bottommost
|
||||
position that fits on the screen. */
|
||||
if (flags & XNegative)
|
||||
f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
|
||||
+ display_left
|
||||
- FRAME_PIXEL_WIDTH (f)
|
||||
+ f->left_pos
|
||||
- (left_right_borders_width - 1));
|
||||
{
|
||||
if (p)
|
||||
f->left_pos = (FRAME_PIXEL_WIDTH (p)
|
||||
- FRAME_PIXEL_WIDTH (f)
|
||||
+ f->left_pos
|
||||
- (left_right_borders_width - 1));
|
||||
else
|
||||
f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
|
||||
+ display_left
|
||||
- FRAME_PIXEL_WIDTH (f)
|
||||
+ f->left_pos
|
||||
- (left_right_borders_width - 1));
|
||||
}
|
||||
|
||||
if (flags & YNegative)
|
||||
f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
|
||||
+ display_top
|
||||
- FRAME_PIXEL_HEIGHT (f)
|
||||
+ f->top_pos
|
||||
- (top_bottom_borders_height - 1));
|
||||
{
|
||||
if (p)
|
||||
f->top_pos = (FRAME_PIXEL_HEIGHT (p)
|
||||
- FRAME_PIXEL_HEIGHT (f)
|
||||
+ f->top_pos
|
||||
- (top_bottom_borders_height - 1));
|
||||
else
|
||||
f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
|
||||
+ display_top
|
||||
- FRAME_PIXEL_HEIGHT (f)
|
||||
+ f->top_pos
|
||||
- (top_bottom_borders_height - 1));
|
||||
}
|
||||
|
||||
/* The left_pos and top_pos are now relative to the top and left
|
||||
screen edges, so the flags should correspond. */
|
||||
|
|
@ -6046,11 +6111,16 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
|
|||
modified_left = f->left_pos;
|
||||
modified_top = f->top_pos;
|
||||
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f),
|
||||
NULL,
|
||||
modified_left, modified_top,
|
||||
0, 0,
|
||||
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
|
||||
modified_left, modified_top,
|
||||
0, 0,
|
||||
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
else
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
|
||||
modified_left, modified_top,
|
||||
0, 0,
|
||||
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
|
@ -6254,11 +6324,18 @@ x_set_window_size (struct frame *f, bool change_gravity,
|
|||
Fcons (make_number (rect.right - rect.left),
|
||||
make_number (rect.bottom - rect.top))));
|
||||
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
|
||||
0, 0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
|
||||
0, 0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
else
|
||||
my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
|
||||
0, 0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
|
||||
change_frame_size (f,
|
||||
((pixelwidth == 0)
|
||||
|
|
@ -6447,18 +6524,21 @@ x_make_frame_visible (struct frame *f)
|
|||
if (! FRAME_ICONIFIED_P (f)
|
||||
&& ! f->output_data.w32->asked_for_visible)
|
||||
{
|
||||
RECT workarea_rect;
|
||||
RECT window_rect;
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
RECT workarea_rect;
|
||||
RECT window_rect;
|
||||
|
||||
/* Adjust vertical window position in order to avoid being
|
||||
covered by a taskbar placed at the bottom of the desktop. */
|
||||
SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
|
||||
GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
|
||||
if (window_rect.bottom > workarea_rect.bottom
|
||||
&& window_rect.top > workarea_rect.top)
|
||||
f->top_pos = max (window_rect.top
|
||||
- window_rect.bottom + workarea_rect.bottom,
|
||||
workarea_rect.top);
|
||||
/* Adjust vertical window position in order to avoid being
|
||||
covered by a taskbar placed at the bottom of the desktop. */
|
||||
SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
|
||||
GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
|
||||
if (window_rect.bottom > workarea_rect.bottom
|
||||
&& window_rect.top > workarea_rect.top)
|
||||
f->top_pos = max (window_rect.top
|
||||
- window_rect.bottom + workarea_rect.bottom,
|
||||
workarea_rect.top);
|
||||
}
|
||||
|
||||
x_set_offset (f, f->left_pos, f->top_pos, 0);
|
||||
}
|
||||
|
|
@ -6473,7 +6553,11 @@ x_make_frame_visible (struct frame *f)
|
|||
set for minimized windows that are still visible, so use that to
|
||||
determine the appropriate flag to pass ShowWindow. */
|
||||
my_show_window (f, FRAME_W32_WINDOW (f),
|
||||
FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL);
|
||||
FRAME_ICONIFIED_P (f)
|
||||
? SW_RESTORE
|
||||
: FRAME_NO_FOCUS_ON_MAP (f)
|
||||
? SW_SHOWNOACTIVATE
|
||||
: SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
/* Synchronize to ensure Emacs knows the frame is visible
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ extern void x_set_internal_border_width (struct frame *f,
|
|||
Lisp_Object value,
|
||||
Lisp_Object oldval);
|
||||
extern void initialize_frame_menubar (struct frame *);
|
||||
extern void w32_dialog_in_progress (Lisp_Object in_progress);
|
||||
|
||||
/* w32inevt.c */
|
||||
extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId);
|
||||
|
|
|
|||
|
|
@ -11767,6 +11767,7 @@ x_consider_frame_title (Lisp_Object frame)
|
|||
&& FRAME_KBOARD (tf) == FRAME_KBOARD (f)
|
||||
&& !FRAME_MINIBUF_ONLY_P (tf)
|
||||
&& !EQ (other_frame, tip_frame)
|
||||
&& !FRAME_PARENT_FRAME (tf)
|
||||
&& (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
|
||||
break;
|
||||
}
|
||||
|
|
@ -11883,6 +11884,7 @@ prepare_menu_bars (void)
|
|||
continue;
|
||||
|
||||
if (!EQ (frame, tooltip_frame)
|
||||
&& !FRAME_PARENT_FRAME (f)
|
||||
&& (FRAME_ICONIFIED_P (f)
|
||||
|| FRAME_VISIBLE_P (f) == 1
|
||||
/* Exclude TTY frames that are obscured because they
|
||||
|
|
@ -11929,6 +11931,10 @@ prepare_menu_bars (void)
|
|||
continue;
|
||||
|
||||
run_window_size_change_functions (frame);
|
||||
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
continue;
|
||||
|
||||
menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
update_tool_bar (f, false);
|
||||
|
|
|
|||
605
src/xfns.c
605
src/xfns.c
|
|
@ -90,6 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <Xm/FileSB.h>
|
||||
#include <Xm/List.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/MwmUtil.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LUCID
|
||||
|
|
@ -117,6 +118,35 @@ static ptrdiff_t image_cache_refcount;
|
|||
static int dpyinfo_refcount;
|
||||
#endif
|
||||
|
||||
#ifndef USE_MOTIF
|
||||
#ifndef USE_GTK
|
||||
/** #define MWM_HINTS_FUNCTIONS (1L << 0) **/
|
||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||
/** #define MWM_HINTS_INPUT_MODE (1L << 2) **/
|
||||
/** #define MWM_HINTS_STATUS (1L << 3) **/
|
||||
|
||||
#define MWM_DECOR_ALL (1L << 0)
|
||||
/** #define MWM_DECOR_BORDER (1L << 1) **/
|
||||
/** #define MWM_DECOR_RESIZEH (1L << 2) **/
|
||||
/** #define MWM_DECOR_TITLE (1L << 3) **/
|
||||
/** #define MWM_DECOR_MENU (1L << 4) **/
|
||||
/** #define MWM_DECOR_MINIMIZE (1L << 5) **/
|
||||
/** #define MWM_DECOR_MAXIMIZE (1L << 6) **/
|
||||
|
||||
/** #define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS" **/
|
||||
|
||||
typedef struct {
|
||||
unsigned long flags;
|
||||
unsigned long functions;
|
||||
unsigned long decorations;
|
||||
long input_mode;
|
||||
unsigned long status;
|
||||
} PropMotifWmHints;
|
||||
|
||||
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
|
||||
#endif /* NOT USE_GTK */
|
||||
#endif /* NOT USE_MOTIF */
|
||||
|
||||
static struct x_display_info *x_display_info_for_name (Lisp_Object);
|
||||
static void set_up_x_back_buffer (struct frame *f);
|
||||
|
||||
|
|
@ -185,7 +215,9 @@ x_real_pos_and_offsets (struct frame *f,
|
|||
int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
|
||||
int real_x = 0, real_y = 0;
|
||||
bool had_errors = false;
|
||||
Window win = f->output_data.x->parent_desc;
|
||||
Window win = (FRAME_PARENT_FRAME (f)
|
||||
? FRAME_X_WINDOW (FRAME_PARENT_FRAME (f))
|
||||
: f->output_data.x->parent_desc);
|
||||
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
|
||||
long max_len = 400;
|
||||
Atom target_type = XA_CARDINAL;
|
||||
|
|
@ -323,7 +355,8 @@ x_real_pos_and_offsets (struct frame *f,
|
|||
outer_geom_cookie = xcb_get_geometry (xcb_conn,
|
||||
FRAME_OUTER_WINDOW (f));
|
||||
|
||||
if (dpyinfo->root_window == f->output_data.x->parent_desc)
|
||||
if ((dpyinfo->root_window == f->output_data.x->parent_desc)
|
||||
&& !FRAME_PARENT_FRAME (f))
|
||||
/* Try _NET_FRAME_EXTENTS if our parent is the root window. */
|
||||
prop_cookie = xcb_get_property (xcb_conn, 0, win,
|
||||
dpyinfo->Xatom_net_frame_extents,
|
||||
|
|
@ -437,7 +470,8 @@ x_real_pos_and_offsets (struct frame *f,
|
|||
#endif
|
||||
}
|
||||
|
||||
if (dpyinfo->root_window == f->output_data.x->parent_desc)
|
||||
if ((dpyinfo->root_window == f->output_data.x->parent_desc)
|
||||
&& !FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
/* Try _NET_FRAME_EXTENTS if our parent is the root window. */
|
||||
#ifdef USE_XCB
|
||||
|
|
@ -735,6 +769,204 @@ x_set_inhibit_double_buffering (struct frame *f,
|
|||
unblock_input ();
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_undecorated:
|
||||
*
|
||||
* Set frame F's `undecorated' parameter. If non-nil, F's window-system
|
||||
* window is drawn without decorations, title, minimize/maximize boxes
|
||||
* and external borders. This usually means that the window cannot be
|
||||
* dragged, resized, iconified, maximized or deleted with the mouse. If
|
||||
* nil, draw the frame with all the elements listed above unless these
|
||||
* have been suspended via window manager settings.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
|
||||
#ifdef USE_GTK
|
||||
xg_set_undecorated (f, new_value);
|
||||
#else
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
PropMotifWmHints hints;
|
||||
Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
|
||||
|
||||
memset (&hints, 0, sizeof(hints));
|
||||
hints.flags = MWM_HINTS_DECORATIONS;
|
||||
hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
|
||||
|
||||
block_input ();
|
||||
/* For some reason the third and fourth argument in the following
|
||||
call must be identic: In the corresponding XGetWindowProperty
|
||||
call in getMotifHints, xfwm has the third and seventh arg both
|
||||
display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
|
||||
XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
|
||||
PropModeReplace, (unsigned char *) &hints,
|
||||
PROP_MOTIF_WM_HINTS_ELEMENTS);
|
||||
unblock_input ();
|
||||
|
||||
#endif /* USE_GTK */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_parent_frame:
|
||||
*
|
||||
* Set frame F's `parent-frame' parameter. If non-nil, make F a child
|
||||
* frame of the frame specified by that parameter. Technically, this
|
||||
* makes F's window-system window a child window of the parent frame's
|
||||
* window-system window. If nil, make F's window-system window a
|
||||
* top-level window--a child of its display's root window.
|
||||
*
|
||||
* A child frame is clipped at the native edges of its parent frame.
|
||||
* Its `left' and `top' parameters specify positions relative to the
|
||||
* top-left corner of its parent frame's native rectangle. Usually,
|
||||
* moving a parent frame moves all its child frames too, keeping their
|
||||
* position relative to the parent unaltered. When a parent frame is
|
||||
* iconified or made invisible, its child frames are made invisible.
|
||||
* When a parent frame is deleted, its child frames are deleted too.
|
||||
*
|
||||
* A visible child frame always appears on top of its parent frame thus
|
||||
* obscuring parts of it. When a frame has more than one child frame,
|
||||
* their stacking order is specified just as that of non-child frames
|
||||
* relative to their display.
|
||||
*
|
||||
* Whether a child frame has a menu or tool bar may be window-system or
|
||||
* window manager dependent. It's advisable to disable both via the
|
||||
* frame parameter settings.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
struct frame *p = NULL;
|
||||
|
||||
if (!NILP (new_value)
|
||||
&& (!FRAMEP (new_value)
|
||||
|| !FRAME_LIVE_P (p = XFRAME (new_value))
|
||||
|| !FRAME_X_P (p)))
|
||||
{
|
||||
store_frame_param (f, Qparent_frame, old_value);
|
||||
error ("Invalid specification of `parent-frame'");
|
||||
}
|
||||
|
||||
if (p != FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
block_input ();
|
||||
XReparentWindow
|
||||
(FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
|
||||
f->left_pos, f->top_pos);
|
||||
unblock_input ();
|
||||
|
||||
fset_parent_frame (f, new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_no_focus_on_map:
|
||||
*
|
||||
* Set frame F's `no-focus-on-map' parameter which, if non-nil, means
|
||||
* that F's window-system window does not want to receive input focus
|
||||
* when it is mapped. (A frame's window is mapped when the frame is
|
||||
* displayed for the first time and when the frame changes its state
|
||||
* from `iconified' or `invisible' to `visible'.)
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
xg_set_no_focus_on_map (f, new_value);
|
||||
#else /* not USE_GTK */
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
|
||||
Time timestamp = NILP (new_value) ? CurrentTime : 0;
|
||||
|
||||
XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *) ×tamp, 1);
|
||||
#endif /* USE_GTK */
|
||||
FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_no_accept_focus:
|
||||
*
|
||||
* Set frame F's `no-accept-focus' parameter which, if non-nil, hints
|
||||
* that F's window-system window does not want to receive input focus
|
||||
* via mouse clicks or by moving the mouse into it.
|
||||
*
|
||||
* If non-nil, this may have the unwanted side-effect that a user cannot
|
||||
* scroll a non-selected frame with the mouse.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
xg_set_no_accept_focus (f, new_value);
|
||||
#else /* not USE_GTK */
|
||||
#ifdef USE_X_TOOLKIT
|
||||
Arg al[1];
|
||||
|
||||
XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
|
||||
XtSetValues (f->output_data.x->widget, al, 1);
|
||||
#else /* not USE_X_TOOLKIT */
|
||||
Window window = FRAME_X_WINDOW (f);
|
||||
|
||||
f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
|
||||
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
|
||||
#endif /* USE_X_TOOLKIT */
|
||||
#endif /* USE_GTK */
|
||||
FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_override_redirect:
|
||||
*
|
||||
* Set frame F's `override_redirect' parameter which, if non-nil, hints
|
||||
* that the window manager doesn't want to deal with F. Usually, such
|
||||
* frames have no decorations and always appear on top of all frames.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
static void
|
||||
x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
/* Here (xfwm) override_redirect can be changed for invisible
|
||||
frames only. */
|
||||
x_make_frame_invisible (f);
|
||||
|
||||
#ifdef USE_GTK
|
||||
xg_set_override_redirect (f, new_value);
|
||||
#else /* not USE_GTK */
|
||||
XSetWindowAttributes attributes;
|
||||
|
||||
attributes.override_redirect = NILP (new_value) ? False : True;
|
||||
XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
CWOverrideRedirect, &attributes);
|
||||
#endif
|
||||
x_make_frame_visible (f);
|
||||
FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_GTK
|
||||
|
||||
/* 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)
|
|||
most of the commands try to apply themselves to the minibuffer
|
||||
frame itself, and get an error because you can't switch buffers
|
||||
in or split the minibuffer window. */
|
||||
if (FRAME_MINIBUF_ONLY_P (f))
|
||||
if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
|
||||
return;
|
||||
|
||||
if (TYPE_RANGED_INTEGERP (int, value))
|
||||
|
|
@ -2693,7 +2925,7 @@ x_window (struct frame *f, long window_prompting)
|
|||
and specify it.
|
||||
Note that we do not specify here whether the position
|
||||
is a user-specified or program-specified one.
|
||||
We pass that information later, in x_wm_set_size_hints. */
|
||||
We pass that information later, in x_wm_set_size_hint. */
|
||||
{
|
||||
int left = f->left_pos;
|
||||
bool xneg = (window_prompting & XNegative) != 0;
|
||||
|
|
@ -2783,7 +3015,8 @@ x_window (struct frame *f, long window_prompting)
|
|||
}
|
||||
#endif /* HAVE_X_I18N */
|
||||
|
||||
attribute_mask = CWEventMask;
|
||||
attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
|
||||
attribute_mask = CWEventMask | CWOverrideRedirect;
|
||||
XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
|
||||
attribute_mask, &attributes);
|
||||
|
||||
|
|
@ -2803,6 +3036,25 @@ x_window (struct frame *f, long window_prompting)
|
|||
x_set_name (f, name, explicit);
|
||||
}
|
||||
|
||||
if (FRAME_UNDECORATED (f))
|
||||
{
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
PropMotifWmHints hints;
|
||||
Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
|
||||
|
||||
memset (&hints, 0, sizeof(hints));
|
||||
hints.flags = MWM_HINTS_DECORATIONS;
|
||||
hints.decorations = 0;
|
||||
|
||||
/* For some reason the third and fourth argument in the following
|
||||
call must be identic: In the corresponding XGetWindowProperty
|
||||
call in getMotifHints, xfwm has the third and seventh arg both
|
||||
display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
|
||||
XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
|
||||
PropModeReplace, (unsigned char *) &hints,
|
||||
PROP_MOTIF_WM_HINTS_ELEMENTS);
|
||||
}
|
||||
|
||||
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
f->output_data.x->current_cursor
|
||||
= f->output_data.x->text_cursor);
|
||||
|
|
@ -2870,8 +3122,9 @@ x_window (struct frame *f)
|
|||
attributes.save_under = True;
|
||||
attributes.event_mask = STANDARD_EVENT_SET;
|
||||
attributes.colormap = FRAME_X_COLORMAP (f);
|
||||
attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
|
||||
attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
|
||||
| CWColormap);
|
||||
| CWOverrideRedirect | CWColormap);
|
||||
|
||||
block_input ();
|
||||
FRAME_X_WINDOW (f)
|
||||
|
|
@ -2943,6 +3196,26 @@ x_window (struct frame *f)
|
|||
x_set_name (f, name, explicit);
|
||||
}
|
||||
|
||||
if (FRAME_UNDECORATED (f))
|
||||
{
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
PropMotifWmHints hints;
|
||||
Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
|
||||
|
||||
memset (&hints, 0, sizeof(hints));
|
||||
hints.flags = MWM_HINTS_DECORATIONS;
|
||||
hints.decorations = 0;
|
||||
|
||||
/* For some reason the third and fourth argument in the following
|
||||
call must be identic: In the corresponding XGetWindowProperty
|
||||
call in getMotifHints, xfwm has the third and seventh arg both
|
||||
display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
|
||||
XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
|
||||
PropModeReplace, (unsigned char *) &hints,
|
||||
PROP_MOTIF_WM_HINTS_ELEMENTS);
|
||||
}
|
||||
|
||||
|
||||
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
f->output_data.x->current_cursor
|
||||
= f->output_data.x->text_cursor);
|
||||
|
|
@ -3285,11 +3558,12 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
Lisp_Object frame, tem;
|
||||
Lisp_Object name;
|
||||
bool minibuffer_only = false;
|
||||
bool undecorated = false, override_redirect = false;
|
||||
long window_prompting = 0;
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
Lisp_Object display;
|
||||
struct x_display_info *dpyinfo = NULL;
|
||||
Lisp_Object parent;
|
||||
Lisp_Object parent, parent_frame;
|
||||
struct kboard *kb;
|
||||
int x_width = 0, x_height = 0;
|
||||
|
||||
|
|
@ -3341,6 +3615,36 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
else
|
||||
f = make_frame (true);
|
||||
|
||||
parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
|
||||
RES_TYPE_SYMBOL);
|
||||
/* Accept parent-frame iff parent-id was not specified. */
|
||||
if (!NILP (parent)
|
||||
|| EQ (parent_frame, Qunbound)
|
||||
|| NILP (parent_frame)
|
||||
|| !FRAMEP (parent_frame)
|
||||
|| !FRAME_LIVE_P (XFRAME (parent_frame))
|
||||
|| !FRAME_X_P (XFRAME (parent_frame)))
|
||||
parent_frame = Qnil;
|
||||
|
||||
fset_parent_frame (f, parent_frame);
|
||||
store_frame_param (f, Qparent_frame, parent_frame);
|
||||
|
||||
if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
|
||||
RES_TYPE_BOOLEAN)))
|
||||
&& !(EQ (tem, Qunbound)))
|
||||
undecorated = true;
|
||||
|
||||
FRAME_UNDECORATED (f) = undecorated;
|
||||
store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
|
||||
|
||||
if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
|
||||
RES_TYPE_BOOLEAN)))
|
||||
&& !(EQ (tem, Qunbound)))
|
||||
override_redirect = true;
|
||||
|
||||
FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
|
||||
store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
f->terminal = dpyinfo->terminal;
|
||||
|
|
@ -3528,15 +3832,24 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
init_iterator with a null face cache, which should not happen. */
|
||||
init_frame_faces (f);
|
||||
|
||||
/* The following call of change_frame_size is needed since otherwise
|
||||
/* We have to call adjust_frame_size here since otherwise
|
||||
x_set_tool_bar_lines will already work with the character sizes
|
||||
installed by init_frame_faces while the frame's pixel size is
|
||||
still calculated from a character size of 1 and we subsequently
|
||||
hit the (height >= 0) assertion in window_box_height.
|
||||
installed by init_frame_faces while the frame's pixel size is still
|
||||
calculated from a character size of 1 and we subsequently hit the
|
||||
(height >= 0) assertion in window_box_height.
|
||||
|
||||
The non-pixelwise code apparently worked around this because it
|
||||
had one frame line vs one toolbar line which left us with a zero
|
||||
root window height which was obviously wrong as well ... */
|
||||
root window height which was obviously wrong as well ...
|
||||
|
||||
Also process `min-width' and `min-height' parameters right here
|
||||
because `frame-windows-min-size' needs them. */
|
||||
tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_width, tem);
|
||||
tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
|
||||
if (NUMBERP (tem))
|
||||
store_frame_param (f, Qmin_height, tem);
|
||||
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
|
||||
FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
|
||||
Qx_create_frame_1);
|
||||
|
|
@ -3611,6 +3924,21 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
x_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
|
||||
if (!NILP (parent_frame))
|
||||
{
|
||||
struct frame *p = XFRAME (parent_frame);
|
||||
|
||||
block_input ();
|
||||
XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
x_default_parameter (f, parms, Qno_accept_focus, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
|
||||
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
|
||||
/* Create the menu bar. */
|
||||
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
|
||||
|
|
@ -3656,23 +3984,23 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
/* Make the window appear on the frame and enable display, unless
|
||||
the caller says not to. However, with explicit parent, Emacs
|
||||
cannot control visibility, so don't try. */
|
||||
if (! f->output_data.x->explicit_parent)
|
||||
if (!f->output_data.x->explicit_parent)
|
||||
{
|
||||
Lisp_Object visibility;
|
||||
|
||||
visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
|
||||
RES_TYPE_SYMBOL);
|
||||
if (EQ (visibility, Qunbound))
|
||||
visibility = Qt;
|
||||
Lisp_Object visibility
|
||||
= x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
|
||||
|
||||
if (EQ (visibility, Qicon))
|
||||
x_iconify_frame (f);
|
||||
else if (! NILP (visibility))
|
||||
x_make_frame_visible (f);
|
||||
else
|
||||
{
|
||||
/* Must have been Qnil. */
|
||||
if (EQ (visibility, Qunbound))
|
||||
visibility = Qt;
|
||||
|
||||
if (!NILP (visibility))
|
||||
x_make_frame_visible (f);
|
||||
}
|
||||
|
||||
store_frame_param (f, Qvisibility, visibility);
|
||||
}
|
||||
|
||||
block_input ();
|
||||
|
|
@ -3685,14 +4013,21 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
if (dpyinfo->client_leader_window != 0)
|
||||
{
|
||||
XChangeProperty (FRAME_X_DISPLAY (f),
|
||||
FRAME_OUTER_WINDOW (f),
|
||||
dpyinfo->Xatom_wm_client_leader,
|
||||
XA_WINDOW, 32, PropModeReplace,
|
||||
(unsigned char *) &dpyinfo->client_leader_window, 1);
|
||||
FRAME_OUTER_WINDOW (f),
|
||||
dpyinfo->Xatom_wm_client_leader,
|
||||
XA_WINDOW, 32, PropModeReplace,
|
||||
(unsigned char *) &dpyinfo->client_leader_window, 1);
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
|
||||
/* Works iff frame has been already mapped. */
|
||||
x_default_parameter (f, parms, Qskip_taskbar, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
/* The `z-group' parameter works only for visible frames. */
|
||||
x_default_parameter (f, parms, Qz_group, Qnil,
|
||||
NULL, NULL, RES_TYPE_SYMBOL);
|
||||
|
||||
/* Initialize `default-minibuffer-frame' in case this is the first
|
||||
frame on this terminal. */
|
||||
if (FRAME_HAS_MINIBUF_P (f)
|
||||
|
|
@ -3710,7 +4045,7 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
and similar functions. */
|
||||
Vwindow_list = Qnil;
|
||||
|
||||
return unbind_to (count, frame);
|
||||
return unbind_to (count, frame);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4644,9 +4979,9 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
|
|||
struct frame *f = decode_live_frame (frame);
|
||||
/** XWindowAttributes atts; **/
|
||||
Window rootw;
|
||||
unsigned int ign, native_width, native_height;
|
||||
int xy_ign, xptr, yptr;
|
||||
int left_off, right_off, top_off, bottom_off;
|
||||
unsigned int ign, native_width, native_height, x_border_width = 0;
|
||||
int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
|
||||
int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
|
||||
int outer_left, outer_top, outer_right, outer_bottom;
|
||||
int native_left, native_top, native_right, native_bottom;
|
||||
int inner_left, inner_top, inner_right, inner_bottom;
|
||||
|
|
@ -4660,25 +4995,51 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
|
|||
|
||||
block_input ();
|
||||
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
&rootw, &xy_ign, &xy_ign, &native_width, &native_height,
|
||||
&ign, &ign);
|
||||
&rootw, &x_native, &y_native, &native_width, &native_height,
|
||||
&x_border_width, &ign);
|
||||
/** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
|
||||
x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
|
||||
NULL, NULL, &xptr, &yptr, NULL);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
|
||||
NULL, NULL, &xptr, &yptr, NULL);
|
||||
unblock_input ();
|
||||
|
||||
/** native_width = atts.width; **/
|
||||
/** native_height = atts.height; **/
|
||||
|
||||
outer_left = xptr;
|
||||
outer_top = yptr;
|
||||
outer_right = outer_left + left_off + native_width + right_off;
|
||||
outer_bottom = outer_top + top_off + native_height + bottom_off;
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
Lisp_Object parent, edges;
|
||||
|
||||
native_left = outer_left + left_off;
|
||||
native_top = outer_top + top_off;
|
||||
native_right = native_left + native_width;
|
||||
native_bottom = native_top + native_height;
|
||||
XSETFRAME (parent, FRAME_PARENT_FRAME (f));
|
||||
edges = Fx_frame_edges (parent, Qnative_edges);
|
||||
if (!NILP (edges))
|
||||
{
|
||||
x_native += XINT (Fnth (make_number (0), edges));
|
||||
y_native += XINT (Fnth (make_number (1), edges));
|
||||
}
|
||||
|
||||
outer_left = x_native;
|
||||
outer_top = y_native;
|
||||
outer_right = outer_left + native_width + 2 * x_border_width;
|
||||
outer_bottom = outer_top + native_height + 2 * x_border_width;
|
||||
|
||||
native_left = x_native + x_border_width;
|
||||
native_top = y_native + x_border_width;
|
||||
native_right = native_left + native_width;
|
||||
native_bottom = native_top + native_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
outer_left = xptr;
|
||||
outer_top = yptr;
|
||||
outer_right = outer_left + left_off + native_width + right_off;
|
||||
outer_bottom = outer_top + top_off + native_height + bottom_off;
|
||||
|
||||
native_left = outer_left + left_off;
|
||||
native_top = outer_top + top_off;
|
||||
native_right = native_left + native_width;
|
||||
native_bottom = native_top + native_height;
|
||||
}
|
||||
|
||||
internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
|
||||
inner_left = native_left + internal_border_width;
|
||||
|
|
@ -4749,7 +5110,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
|
|||
make_number (inner_right), make_number (inner_bottom));
|
||||
else
|
||||
return
|
||||
listn (CONSTYPE_HEAP, 10,
|
||||
listn (CONSTYPE_HEAP, 11,
|
||||
Fcons (Qouter_position,
|
||||
Fcons (make_number (outer_left),
|
||||
make_number (outer_top))),
|
||||
|
|
@ -4760,6 +5121,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
|
|||
Fcons (Qexternal_border_size,
|
||||
Fcons (make_number (right_off),
|
||||
make_number (bottom_off))),
|
||||
Fcons (Qouter_border_width, make_number (x_border_width)),
|
||||
/* Approximate. */
|
||||
Fcons (Qtitle_bar_size,
|
||||
Fcons (make_number (0),
|
||||
|
|
@ -4788,7 +5150,8 @@ and width values are in pixels.
|
|||
|
||||
`outer-size' is a cons of the outer width and height of FRAME. The
|
||||
outer size includes the title bar and the external borders as well as
|
||||
any menu and/or tool bar of frame.
|
||||
any menu and/or tool bar of frame. For a child frame the value
|
||||
includes FRAME's X borders, if any.
|
||||
|
||||
`external-border-size' is a cons of the horizontal and vertical width of
|
||||
FRAME's external borders as supplied by the window manager.
|
||||
|
|
@ -4815,7 +5178,11 @@ and width values are in pixels.
|
|||
FRAME.
|
||||
|
||||
`internal-border-width' is the width of the internal border of
|
||||
FRAME. */)
|
||||
FRAME.
|
||||
|
||||
`outer-border-width' is the width of the X border of FRAME. The X
|
||||
border is usually only shown for frames without window manager
|
||||
decorations like child and tooltip frames. */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
return frame_geometry (frame, Qnil);
|
||||
|
|
@ -4845,6 +5212,139 @@ menu bar or tool bar of FRAME. */)
|
|||
: Qnative_edges));
|
||||
}
|
||||
|
||||
/**
|
||||
* x_frame_list_z_order:
|
||||
*
|
||||
* Recursively add list of all frames on the display specified via
|
||||
* DPYINFO and whose window-system window's parent is specified by
|
||||
* WINDOW to FRAMES and return FRAMES.
|
||||
*/
|
||||
static Lisp_Object
|
||||
x_frame_list_z_order (Display* dpy, Window window)
|
||||
{
|
||||
Window root, parent, *children;
|
||||
unsigned int nchildren;
|
||||
int i;
|
||||
Lisp_Object frames = Qnil;
|
||||
|
||||
block_input ();
|
||||
if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
|
||||
{
|
||||
unblock_input ();
|
||||
for (i = 0; i < nchildren; i++)
|
||||
{
|
||||
Lisp_Object frame, tail;
|
||||
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
/* With a reparenting window manager the parent_desc field
|
||||
usually specifies the topmost windows of our frames.
|
||||
Otherwise FRAME_OUTER_WINDOW should do. */
|
||||
if (XFRAME (frame)->output_data.x->parent_desc == children[i]
|
||||
|| FRAME_OUTER_WINDOW (XFRAME (frame)) == children[i])
|
||||
frames = Fcons (frame, frames);
|
||||
}
|
||||
|
||||
if (children) XFree ((char *)children);
|
||||
}
|
||||
else
|
||||
unblock_input ();
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
|
||||
Sx_frame_list_z_order, 0, 1, 0,
|
||||
doc: /* Return list of Emacs' frames, in Z (stacking) order.
|
||||
The optional argument TERMINAL specifies which display to ask about.
|
||||
TERMINAL should be either a frame or a display name (a string). If
|
||||
omitted or nil, that stands for the selected frame's display. Return
|
||||
nil if TERMINAL contains no Emacs frame.
|
||||
|
||||
As a special case, if TERMINAL is non-nil and specifies a live frame,
|
||||
return the child frames of that frame in Z (stacking) order.
|
||||
|
||||
Frames are listed from topmost (first) to bottommost (last). */)
|
||||
(Lisp_Object terminal)
|
||||
{
|
||||
struct x_display_info *dpyinfo = check_x_display_info (terminal);
|
||||
Display *dpy = dpyinfo->display;
|
||||
Window window;
|
||||
|
||||
if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
|
||||
window = FRAME_X_WINDOW (XFRAME (terminal));
|
||||
else
|
||||
window = dpyinfo->root_window;
|
||||
|
||||
return x_frame_list_z_order (dpy, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* x_frame_restack:
|
||||
*
|
||||
* Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
|
||||
* practice this is a two-step action: The first step removes F1's
|
||||
* window-system window from the display. The second step reinserts
|
||||
* F1's window below (above if ABOVE_FLAG is true) that of F2.
|
||||
*/
|
||||
static void
|
||||
x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
block_input ();
|
||||
xg_frame_restack (f1, f2, above_flag);
|
||||
unblock_input ();
|
||||
#else
|
||||
Display *dpy = FRAME_X_DISPLAY (f1);
|
||||
Window window1 = FRAME_OUTER_WINDOW (f1);
|
||||
XWindowChanges wc;
|
||||
unsigned long mask = (CWSibling | CWStackMode);
|
||||
|
||||
wc.sibling = FRAME_OUTER_WINDOW (f2);
|
||||
wc.stack_mode = above_flag ? Above : Below;
|
||||
block_input ();
|
||||
/* Configure the window manager window (a normal XConfigureWindow
|
||||
won't cut it). This should also work for child frames. */
|
||||
XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
|
||||
unblock_input ();
|
||||
#endif /* USE_GTK */
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
|
||||
doc: /* Restack FRAME1 below FRAME2.
|
||||
This means that if both frames are visible and the display areas of
|
||||
these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
|
||||
third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
|
||||
means that if both frames are visible and the display areas of these
|
||||
frames overlap, FRAME1 (partially) obscures FRAME2.
|
||||
|
||||
This may be thought of as an atomic action performed in two steps: The
|
||||
first step removes FRAME1's window-step window from the display. The
|
||||
second step reinserts FRAME1's window below (above if ABOVE is true)
|
||||
that of FRAME2. Hence the position of FRAME2 in its display's Z
|
||||
\(stacking) order relative to all other frames excluding FRAME1 remains
|
||||
unaltered.
|
||||
|
||||
Some window managers may refuse to restack windows. */)
|
||||
(Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
|
||||
{
|
||||
struct frame *f1 = decode_live_frame (frame1);
|
||||
struct frame *f2 = decode_live_frame (frame2);
|
||||
|
||||
if (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2))
|
||||
{
|
||||
x_frame_restack (f1, f2, !NILP (above));
|
||||
return Qt;
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("Cannot restack frames");
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
|
||||
Sx_mouse_absolute_pixel_position, 0, 0, 0,
|
||||
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. */)
|
|||
|
||||
if (popup_activated ())
|
||||
error ("Trying to use a menu from within a menu-entry");
|
||||
else
|
||||
x_menu_set_in_use (true);
|
||||
|
||||
CHECK_STRING (prompt);
|
||||
CHECK_STRING (dir);
|
||||
|
|
@ -6641,6 +7143,8 @@ nil, it defaults to the selected frame. */)
|
|||
|
||||
if (popup_activated ())
|
||||
error ("Trying to use a menu from within a menu-entry");
|
||||
else
|
||||
x_menu_set_in_use (true);
|
||||
|
||||
/* Prevent redisplay. */
|
||||
specbind (Qinhibit_redisplay, Qt);
|
||||
|
|
@ -6979,6 +7483,13 @@ frame_parm_handler x_frame_parm_handlers[] =
|
|||
x_set_sticky,
|
||||
x_set_tool_bar_position,
|
||||
x_set_inhibit_double_buffering,
|
||||
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,
|
||||
x_set_override_redirect,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -7183,6 +7694,8 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
|
|||
defsubr (&Sx_display_monitor_attributes_list);
|
||||
defsubr (&Sx_frame_geometry);
|
||||
defsubr (&Sx_frame_edges);
|
||||
defsubr (&Sx_frame_list_z_order);
|
||||
defsubr (&Sx_frame_restack);
|
||||
defsubr (&Sx_mouse_absolute_pixel_position);
|
||||
defsubr (&Sx_set_mouse_absolute_pixel_position);
|
||||
defsubr (&Sx_wm_set_size_hint);
|
||||
|
|
|
|||
14
src/xmenu.c
14
src/xmenu.c
|
|
@ -140,14 +140,26 @@ menubar_id_to_frame (LWLIB_ID id)
|
|||
void
|
||||
x_menu_set_in_use (bool in_use)
|
||||
{
|
||||
Lisp_Object frames, frame;
|
||||
|
||||
menu_items_inuse = in_use ? Qt : Qnil;
|
||||
popup_activated_flag = in_use;
|
||||
#ifdef USE_X_TOOLKIT
|
||||
if (popup_activated_flag)
|
||||
x_activate_timeout_atimer ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Don't let frames in `above' z-group obscure popups. */
|
||||
FOR_EACH_FRAME (frames, frame)
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
|
||||
if (in_use && FRAME_Z_GROUP_ABOVE (f))
|
||||
x_set_z_group (f, Qabove_suspended, Qabove);
|
||||
else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
|
||||
x_set_z_group (f, Qabove, Qabove_suspended);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Wait for an X event to arrive or for a timer to expire. */
|
||||
|
|
|
|||
389
src/xterm.c
389
src/xterm.c
|
|
@ -945,11 +945,14 @@ x_set_frame_alpha (struct frame *f)
|
|||
Do this unconditionally as this function is called on reparent when
|
||||
alpha has not changed on the frame. */
|
||||
|
||||
parent = x_find_topmost_parent (f);
|
||||
if (parent != None)
|
||||
XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *) &opac, 1);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
parent = x_find_topmost_parent (f);
|
||||
if (parent != None)
|
||||
XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *) &opac, 1);
|
||||
}
|
||||
|
||||
/* return unless necessary */
|
||||
{
|
||||
|
|
@ -4964,6 +4967,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
containing the pointer. */
|
||||
{
|
||||
Window win, child;
|
||||
#ifdef USE_GTK
|
||||
Window first_win = 0;
|
||||
#endif
|
||||
int win_x, win_y;
|
||||
int parent_x = 0, parent_y = 0;
|
||||
|
||||
|
|
@ -5010,20 +5016,37 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
&child);
|
||||
|
||||
if (child == None || child == win)
|
||||
break;
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
/* On GTK we have not inspected WIN yet. If it has
|
||||
a frame and that frame has a parent, use it. */
|
||||
struct frame *f = x_window_to_frame (dpyinfo, win);
|
||||
|
||||
if (f && FRAME_PARENT_FRAME (f))
|
||||
first_win = win;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#ifdef USE_GTK
|
||||
/* We don't wan't to know the innermost window. We
|
||||
want the edit window. For non-Gtk+ the innermost
|
||||
window is the edit window. For Gtk+ it might not
|
||||
be. It might be the tool bar for example. */
|
||||
if (x_window_to_frame (dpyinfo, win))
|
||||
break;
|
||||
/* But don't hurry. We might find a child frame
|
||||
beneath. */
|
||||
first_win = win;
|
||||
#endif
|
||||
win = child;
|
||||
parent_x = win_x;
|
||||
parent_y = win_y;
|
||||
}
|
||||
|
||||
#ifdef USE_GTK
|
||||
if (first_win)
|
||||
win = first_win;
|
||||
#endif
|
||||
|
||||
/* Now we know that:
|
||||
win is the innermost window containing the pointer
|
||||
(XTC says it has no child containing the pointer),
|
||||
|
|
@ -6496,10 +6519,14 @@ x_scroll_bar_create (struct window *w, int top, int left,
|
|||
Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
|
||||
XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
|
||||
XtMapWidget (scroll_bar);
|
||||
/* Don't obscure any child frames. */
|
||||
XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
|
||||
#endif /* not USE_GTK */
|
||||
}
|
||||
#else /* not USE_TOOLKIT_SCROLL_BARS */
|
||||
XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
|
||||
XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
|
||||
/* Don't obscure any child frames. */
|
||||
XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
|
||||
#endif /* not USE_TOOLKIT_SCROLL_BARS */
|
||||
|
||||
unblock_input ();
|
||||
|
|
@ -7067,10 +7094,10 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
|
|||
/* x, y, width, height */
|
||||
0, 0, bar->width - 1, bar->height - 1);
|
||||
|
||||
/* Restore the foreground color of the GC if we changed it above. */
|
||||
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
|
||||
XSetForeground (FRAME_X_DISPLAY (f), gc,
|
||||
FRAME_FOREGROUND_PIXEL (f));
|
||||
/* Restore the foreground color of the GC if we changed it above. */
|
||||
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
|
||||
XSetForeground (FRAME_X_DISPLAY (f), gc,
|
||||
FRAME_FOREGROUND_PIXEL (f));
|
||||
|
||||
unblock_input ();
|
||||
|
||||
|
|
@ -7839,8 +7866,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
|
||||
if (f)
|
||||
{
|
||||
f->output_data.x->parent_desc = event->xreparent.parent;
|
||||
x_real_positions (f, &f->left_pos, &f->top_pos);
|
||||
/* Maybe we shouldn't set this for child frames ?? */
|
||||
f->output_data.x->parent_desc = event->xreparent.parent;
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
x_real_positions (f, &f->left_pos, &f->top_pos);
|
||||
else
|
||||
{
|
||||
Window root;
|
||||
unsigned int dummy_uint;
|
||||
|
||||
block_input ();
|
||||
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
&root, &f->left_pos, &f->top_pos,
|
||||
&dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/* Perhaps reparented due to a WM restart. Reset this. */
|
||||
FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
|
||||
|
|
@ -8000,7 +8040,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
/* Check if fullscreen was specified before we where mapped the
|
||||
first time, i.e. from the command line. */
|
||||
if (!f->output_data.x->has_been_visible)
|
||||
x_check_fullscreen (f);
|
||||
{
|
||||
|
||||
x_check_fullscreen (f);
|
||||
#ifndef USE_GTK
|
||||
/* For systems that cannot synthesize `skip_taskbar' for
|
||||
unmapped windows do the following. */
|
||||
if (FRAME_SKIP_TASKBAR (f))
|
||||
x_set_skip_taskbar (f, Qt, Qnil);
|
||||
#endif /* Not USE_GTK */
|
||||
}
|
||||
|
||||
if (!iconified)
|
||||
{
|
||||
/* The `z-group' is reset every time a frame becomes
|
||||
invisible. Handle this here. */
|
||||
if (FRAME_Z_GROUP (f) == z_group_above)
|
||||
x_set_z_group (f, Qabove, Qnil);
|
||||
else if (FRAME_Z_GROUP (f) == z_group_below)
|
||||
x_set_z_group (f, Qbelow, Qnil);
|
||||
}
|
||||
|
||||
SET_FRAME_VISIBLE (f, 1);
|
||||
SET_FRAME_ICONIFIED (f, false);
|
||||
|
|
@ -8444,34 +8503,46 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
#endif
|
||||
if (f)
|
||||
{
|
||||
|
||||
/* Generate SELECT_WINDOW_EVENTs when needed.
|
||||
Don't let popup menus influence things (bug#1261). */
|
||||
if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
|
||||
/* Maybe generate a SELECT_WINDOW_EVENT for
|
||||
`mouse-autoselect-window' but don't let popup menus
|
||||
interfere with this (Bug#1261). */
|
||||
if (!NILP (Vmouse_autoselect_window)
|
||||
&& !popup_activated ()
|
||||
/* Don't switch if we're currently in the minibuffer.
|
||||
This tries to work around problems where the
|
||||
minibuffer gets unselected unexpectedly, and where
|
||||
you then have to move your mouse all the way down to
|
||||
the minibuffer to select it. */
|
||||
&& !MINI_WINDOW_P (XWINDOW (selected_window))
|
||||
/* With `focus-follows-mouse' non-nil create an event
|
||||
also when the target window is on another frame. */
|
||||
&& (f == XFRAME (selected_frame)
|
||||
|| !NILP (focus_follows_mouse)))
|
||||
{
|
||||
static Lisp_Object last_mouse_window;
|
||||
Lisp_Object window = window_from_coordinates
|
||||
(f, event->xmotion.x, event->xmotion.y, 0, false);
|
||||
|
||||
/* Window will be selected only when it is not selected now and
|
||||
last mouse movement event was not in it. Minibuffer window
|
||||
will be selected only when it is active. */
|
||||
/* A window will be autoselected only when it is not
|
||||
selected now and the last mouse movement event was
|
||||
not in it. The remainder of the code is a bit vague
|
||||
wrt what a "window" is. For immediate autoselection,
|
||||
the window is usually the entire window but for GTK
|
||||
where the scroll bars don't count. For delayed
|
||||
autoselection the window is usually the window's text
|
||||
area including the margins. */
|
||||
if (WINDOWP (window)
|
||||
&& !EQ (window, last_mouse_window)
|
||||
&& !EQ (window, selected_window)
|
||||
/* For click-to-focus window managers
|
||||
create event iff we don't leave the
|
||||
selected frame. */
|
||||
&& (focus_follows_mouse
|
||||
|| (EQ (XWINDOW (window)->frame,
|
||||
XWINDOW (selected_window)->frame))))
|
||||
&& !EQ (window, selected_window))
|
||||
{
|
||||
inev.ie.kind = SELECT_WINDOW_EVENT;
|
||||
inev.ie.frame_or_window = window;
|
||||
}
|
||||
|
||||
/* Remember the last window where we saw the mouse. */
|
||||
last_mouse_window = window;
|
||||
}
|
||||
|
||||
if (!note_mouse_movement (f, &event->xmotion))
|
||||
help_echo_string = previous_help_echo_string;
|
||||
}
|
||||
|
|
@ -8621,7 +8692,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
x_real_positions (f, &f->left_pos, &f->top_pos);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
x_real_positions (f, &f->left_pos, &f->top_pos);
|
||||
else
|
||||
{
|
||||
Window root;
|
||||
unsigned int dummy_uint;
|
||||
|
||||
block_input ();
|
||||
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
&root, &f->left_pos, &f->top_pos,
|
||||
&dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
if (old_left != f->left_pos || old_top != f->top_pos)
|
||||
{
|
||||
|
|
@ -8650,8 +8733,35 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
dpyinfo->last_mouse_glyph_frame = NULL;
|
||||
x_display_set_last_user_time (dpyinfo, event->xbutton.time);
|
||||
|
||||
f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: x_window_to_frame (dpyinfo, event->xbutton.window));
|
||||
if (x_mouse_grabbed (dpyinfo))
|
||||
f = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
{
|
||||
f = x_window_to_frame (dpyinfo, event->xbutton.window);
|
||||
|
||||
if (f && event->xbutton.type == ButtonPress
|
||||
&& !popup_activated ()
|
||||
&& !x_window_to_scroll_bar (event->xbutton.display,
|
||||
event->xbutton.window, 2)
|
||||
&& !FRAME_NO_ACCEPT_FOCUS (f))
|
||||
{
|
||||
/* When clicking into a child frame or when clicking
|
||||
into a parent frame with the child frame selected and
|
||||
`no-accept-focus' is not set, select the clicked
|
||||
frame. */
|
||||
struct frame *hf = dpyinfo->x_highlight_frame;
|
||||
|
||||
if (FRAME_PARENT_FRAME (f) || frame_ancestor_p (f, hf))
|
||||
{
|
||||
block_input ();
|
||||
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
RevertToParent, CurrentTime);
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
|
||||
unblock_input ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_GTK
|
||||
if (f && xg_event_is_for_scrollbar (f, event))
|
||||
|
|
@ -10007,6 +10117,7 @@ static void
|
|||
x_calc_absolute_position (struct frame *f)
|
||||
{
|
||||
int flags = f->size_hint_flags;
|
||||
struct frame *p = FRAME_PARENT_FRAME (f);
|
||||
|
||||
/* We have nothing to do if the current position
|
||||
is already for the top-left corner. */
|
||||
|
|
@ -10015,32 +10126,72 @@ x_calc_absolute_position (struct frame *f)
|
|||
|
||||
/* Treat negative positions as relative to the leftmost bottommost
|
||||
position that fits on the screen. */
|
||||
if (flags & XNegative)
|
||||
f->left_pos = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
|
||||
- FRAME_PIXEL_WIDTH (f) + f->left_pos;
|
||||
if ((flags & XNegative) && (f->left_pos <= 0))
|
||||
{
|
||||
int width = FRAME_PIXEL_WIDTH (f);
|
||||
|
||||
{
|
||||
int height = FRAME_PIXEL_HEIGHT (f);
|
||||
/* A frame that has been visible at least once should have outer
|
||||
edges. */
|
||||
if (f->output_data.x->has_been_visible && !p)
|
||||
{
|
||||
Lisp_Object frame;
|
||||
Lisp_Object edges = Qnil;
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
edges = Fx_frame_edges (frame, Qouter_edges);
|
||||
if (!NILP (edges))
|
||||
width = (XINT (Fnth (make_number (2), edges))
|
||||
- XINT (Fnth (make_number (0), edges)));
|
||||
}
|
||||
|
||||
if (p)
|
||||
f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
|
||||
+ f->left_pos);
|
||||
else
|
||||
f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
|
||||
- width + f->left_pos);
|
||||
|
||||
}
|
||||
|
||||
if ((flags & YNegative) && (f->top_pos <= 0))
|
||||
{
|
||||
int height = FRAME_PIXEL_HEIGHT (f);
|
||||
|
||||
#if defined USE_X_TOOLKIT && defined USE_MOTIF
|
||||
/* Something is fishy here. When using Motif, starting Emacs with
|
||||
`-g -0-0', the frame appears too low by a few pixels.
|
||||
/* Something is fishy here. When using Motif, starting Emacs with
|
||||
`-g -0-0', the frame appears too low by a few pixels.
|
||||
|
||||
This seems to be so because initially, while Emacs is starting,
|
||||
the column widget's height and the frame's pixel height are
|
||||
different. The column widget's height is the right one. In
|
||||
later invocations, when Emacs is up, the frame's pixel height
|
||||
is right, though.
|
||||
This seems to be so because initially, while Emacs is starting,
|
||||
the column widget's height and the frame's pixel height are
|
||||
different. The column widget's height is the right one. In
|
||||
later invocations, when Emacs is up, the frame's pixel height
|
||||
is right, though.
|
||||
|
||||
It's not obvious where the initial small difference comes from.
|
||||
2000-12-01, gerd. */
|
||||
It's not obvious where the initial small difference comes from.
|
||||
2000-12-01, gerd. */
|
||||
|
||||
XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
|
||||
XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
|
||||
#endif
|
||||
|
||||
if (flags & YNegative)
|
||||
f->top_pos = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
|
||||
- height + f->top_pos;
|
||||
if (f->output_data.x->has_been_visible && !p)
|
||||
{
|
||||
Lisp_Object frame;
|
||||
Lisp_Object edges = Qnil;
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
if (NILP (edges))
|
||||
edges = Fx_frame_edges (frame, Qouter_edges);
|
||||
if (!NILP (edges))
|
||||
height = (XINT (Fnth (make_number (3), edges))
|
||||
- XINT (Fnth (make_number (1), edges)));
|
||||
}
|
||||
|
||||
if (p)
|
||||
f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
|
||||
+ f->top_pos);
|
||||
else
|
||||
f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
|
||||
- height + f->top_pos);
|
||||
}
|
||||
|
||||
/* The left_pos and top_pos
|
||||
|
|
@ -10125,6 +10276,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
|
|||
need to compute the top/left offset adjustment for this frame. */
|
||||
|
||||
if (change_gravity != 0
|
||||
&& !FRAME_PARENT_FRAME (f)
|
||||
&& (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
|
||||
|| (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
|
||||
&& (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)
|
|||
dpyinfo->Xatom_net_wm_state_sticky, None);
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_skip_taskbar:
|
||||
*
|
||||
* Set frame F's `skip-taskbar' parameter. If non-nil, this should
|
||||
* remove F's icon from the taskbar associated with the display of F's
|
||||
* window-system window and inhibit switching to F's window via
|
||||
* <Alt>-<TAB>. If nil, lift these restrictions.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
void
|
||||
x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
if (!EQ (new_value, old_value))
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
xg_set_skip_taskbar (f, new_value);
|
||||
#else
|
||||
Lisp_Object frame;
|
||||
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
set_wm_state (frame, !NILP (new_value),
|
||||
dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
|
||||
#endif /* USE_GTK */
|
||||
FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* x_set_z_group:
|
||||
*
|
||||
* Set frame F's `z-group' parameter. If `above', F's window-system
|
||||
* window is displayed above all windows that do not have the `above'
|
||||
* property set. If nil, F's window is shown below all windows that
|
||||
* have the `above' property set and above all windows that have the
|
||||
* `below' property set. If `below', F's window is displayed below all
|
||||
* windows that do not have the `below' property set.
|
||||
*
|
||||
* Some window managers may not honor this parameter.
|
||||
*/
|
||||
void
|
||||
x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
|
||||
{
|
||||
/* We don't care about old_value. The window manager might have
|
||||
reset the value without telling us. */
|
||||
Lisp_Object frame;
|
||||
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
if (NILP (new_value))
|
||||
{
|
||||
set_wm_state (frame, false,
|
||||
dpyinfo->Xatom_net_wm_state_above, None);
|
||||
set_wm_state (frame, false,
|
||||
dpyinfo->Xatom_net_wm_state_below, None);
|
||||
FRAME_Z_GROUP (f) = z_group_none;
|
||||
}
|
||||
else if (EQ (new_value, Qabove))
|
||||
{
|
||||
set_wm_state (frame, true,
|
||||
dpyinfo->Xatom_net_wm_state_above, None);
|
||||
set_wm_state (frame, false,
|
||||
dpyinfo->Xatom_net_wm_state_below, None);
|
||||
FRAME_Z_GROUP (f) = z_group_above;
|
||||
}
|
||||
else if (EQ (new_value, Qbelow))
|
||||
{
|
||||
set_wm_state (frame, false,
|
||||
dpyinfo->Xatom_net_wm_state_above, None);
|
||||
set_wm_state (frame, true,
|
||||
dpyinfo->Xatom_net_wm_state_below, None);
|
||||
FRAME_Z_GROUP (f) = z_group_below;
|
||||
}
|
||||
else if (EQ (new_value, Qabove_suspended))
|
||||
{
|
||||
set_wm_state (frame, false,
|
||||
dpyinfo->Xatom_net_wm_state_above, None);
|
||||
FRAME_Z_GROUP (f) = z_group_above_suspended;
|
||||
}
|
||||
else
|
||||
error ("Invalid z-group specification");
|
||||
}
|
||||
|
||||
|
||||
/* Return the current _NET_WM_STATE.
|
||||
SIZE_STATE is set to one of the FULLSCREEN_* values.
|
||||
Set *STICKY to the sticky state.
|
||||
|
|
@ -10758,7 +10996,8 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
|
|||
int old_height = FRAME_PIXEL_HEIGHT (f);
|
||||
Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
|
||||
|
||||
if (change_gravity) f->win_gravity = NorthWestGravity;
|
||||
if (change_gravity)
|
||||
f->win_gravity = NorthWestGravity;
|
||||
x_wm_set_size_hint (f, 0, false);
|
||||
|
||||
/* 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,
|
|||
void
|
||||
x_make_frame_visible (struct frame *f)
|
||||
{
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
if (!FRAME_VISIBLE_P (f))
|
||||
{
|
||||
block_input ();
|
||||
#ifdef USE_GTK
|
||||
gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
|
||||
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
f->left_pos, f->top_pos);
|
||||
#else
|
||||
XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
|
||||
#endif
|
||||
unblock_input ();
|
||||
|
||||
SET_FRAME_VISIBLE (f, true);
|
||||
SET_FRAME_ICONIFIED (f, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
block_input ();
|
||||
|
||||
x_set_bitmap_icon (f);
|
||||
|
|
@ -11115,9 +11374,10 @@ x_make_frame_visible (struct frame *f)
|
|||
because the window manager may choose the position
|
||||
and we don't want to override it. */
|
||||
|
||||
if (! FRAME_VISIBLE_P (f)
|
||||
&& ! FRAME_ICONIFIED_P (f)
|
||||
&& ! FRAME_X_EMBEDDED_P (f)
|
||||
if (!FRAME_VISIBLE_P (f)
|
||||
&& !FRAME_ICONIFIED_P (f)
|
||||
&& !FRAME_X_EMBEDDED_P (f)
|
||||
&& !FRAME_PARENT_FRAME (f)
|
||||
&& f->win_gravity == NorthWestGravity
|
||||
&& previously_visible)
|
||||
{
|
||||
|
|
@ -11180,15 +11440,15 @@ x_make_frame_invisible (struct frame *f)
|
|||
xembed_set_info (f, 0);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
|
||||
DefaultScreen (FRAME_X_DISPLAY (f))))
|
||||
{
|
||||
unblock_input ();
|
||||
error ("Can't notify window manager of window withdrawal");
|
||||
}
|
||||
}
|
||||
if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
|
||||
DefaultScreen (FRAME_X_DISPLAY (f))))
|
||||
{
|
||||
unblock_input ();
|
||||
error ("Can't notify window manager of window withdrawal");
|
||||
}
|
||||
|
||||
x_sync (f);
|
||||
|
||||
/* We can't distinguish this from iconification
|
||||
just by the event that we get from the server.
|
||||
|
|
@ -11198,8 +11458,6 @@ x_make_frame_invisible (struct frame *f)
|
|||
SET_FRAME_VISIBLE (f, 0);
|
||||
SET_FRAME_ICONIFIED (f, false);
|
||||
|
||||
x_sync (f);
|
||||
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
|
@ -12355,6 +12613,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
|
|||
ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
|
||||
ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
|
||||
ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
|
||||
ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
|
||||
ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
|
||||
ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
|
||||
};
|
||||
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -447,9 +447,9 @@ struct x_display_info
|
|||
/* Atoms dealing with EWMH (i.e. _NET_...) */
|
||||
Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen,
|
||||
Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
|
||||
Xatom_net_wm_state_sticky, Xatom_net_wm_state_hidden,
|
||||
Xatom_net_frame_extents,
|
||||
Xatom_net_current_desktop, Xatom_net_workarea;
|
||||
Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, Xatom_net_wm_state_below,
|
||||
Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
|
||||
Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea;
|
||||
|
||||
/* XSettings atoms and windows. */
|
||||
Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
|
||||
|
|
@ -1168,6 +1168,8 @@ x_mutable_colormap (Visual *visual)
|
|||
}
|
||||
|
||||
extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern bool x_wm_supports (struct frame *, Atom);
|
||||
extern void x_wait_for_event (struct frame *, int);
|
||||
extern void x_clear_under_internal_border (struct frame *f);
|
||||
|
|
|
|||
Loading…
Reference in a new issue