Merge branch 'scratch/tty-child-frames'

Add support for child frames on tty

The redisplay part is complete.  The frame-handling part supports
use-cases like Posframe, Corfu, and child frames acting like tooltips.
Other use-cases of child frames are not currently supported.  In
particular, trying to create minibuffer-only child frames on ttys will
signal an error.

* src/xfaces.c (free_frame_faces): Change formatting slightly.

* src/xdisp.c (redisplay_trace, move_tracxe): Print to stderr because
stdout screws up terminal display.
(init_iterator): Remove a #ifdef HAVE_WINDOW_SYSTEM.
(clear_garbaged_frames): Return a bool telling if we cleared matrix.
(echo_area_display): Use combine_updates on tty frames.
(redisplay_internal): Changes for redisplay of tty child windows.
(deep_copy_glyph_row): Take a frame parameter.
(display_tty_menu_item): Changes because of function signature changes.

* src/w32term.c (w32_read_socket): Don't use FRAME_OBSCRURED_P,
which has been removed.

* src/w32inevt.c (do_mouse_event): Workaround for mouse events on
child frafmes.

* src/w32console.c (w32con_write_glyphs, w32con_update_end):
Use glyphs' frame for faces.

* src/treesit.c (treesit_load_language): Pacify a warning.

* src/w32console.c (w32con_clear_end_of_line): Set glyph's frame.

* src/terminal.c (cursor_to, raw_cursor_to): Handle case that
frame is a child frame.

* src/termhooks.h: Declare formerly static functions.

* src/term.c (tty_hide_cursor, tty_show_cursor): Make externally
visible.
(tty_write_glyphs): Determine faces based on a glyph's frame.
(tty_write_glyphs_with_face): Take a struct face argument instead
of a face id.  Callers changed.
(tty_insert_glyphs): Use faces, not face ids.
(append_glyph, append_composite_glyph, append_glyphless_glyph):
Set glyph's frame.
(turn_on_face, turn_off_face): Take face argument instead of face
id.  Callers adapted.
(Fresume_tty): Act on root frame.
(tty_draw_row_with_mouse_face): Handle child frames.
(restore_desired_matrix): Make sure glyphs' is live.
(set_tty_hooks): Set terminal's frame_raise_lower_hook.
(tty_frame_geometry, Ftty_frame_geometry, Ftty_frame_edges)
(Ftty_frame_list_z_order, Ftty_frame_restack)
(tty_display_dimension, Ftty_display_pixel_width)
(Ftty_display_pixel_height): New functions.
(syms_of_term): Defsubr new Lisp functions.

* src/minibuf.c (read_minibuf): Use combine_updates for tty
frames.

* src/frame.h (struct frame): Always define parent_frame.  Change
'visible' to be a boolean.  Always define 'undecorated' and
'no_accept_focus'.  Add 'z_order'.
(FRAME_OBSCURED_P): Removed.
(FRAME_PARENT_FRAME): Make it a function.
(SET_FRAME_VISIBLE): Take a bool parameter, not an int.
(FRAME_INTERNAL_BORDER_WIDTH): Don't special-base HAVE_WINDOW_SYSTEM.

* src/frame.c (decode_tty_frame): New function.
(set_menu_bar_lines): Set menu bar lines and height to 0 for tty
child frames.  Compute min height differently.
(adjust_frame_size): Set FrameCols/Rows only for root tty frames.
Mark tty root frame garbaged if child frame is adjusted.  Run some
code even if not HAVE_WINDOW_SYSTEM.
(make_frame): Run some code even if not HAVE_WINDOW_SYSTEM.
(make_terminal_frame): Implement child frame creation.
(tty_child_pos_param, tty_child_size_param)
(tty_child_frame_rect): New functions.
(Fmake_terminal_frame): Parts rewritten for child frames.
(do_switch_frame): Add child frame support.
(Fframe_ancestor_p): Define if not HAVE_WINDOW_SYSTEM.
(Fmake_frame_visible, Fmake_frame_invisible)
(Fframe_visible_p, Fraise_frame):
Handle tty frames differently.
(store_frame_param): Signal error if trying to re-parent a tty
child frame.
(Fframe_parameters): Report some additional tty frame parameters.
(Fmodify_frame_parameters): Handle tty child frames.
(Fset_frame_position): Ditto.
(frame_parms): Define index for additional frame parameters.
(handle_frame_param): New function.
(gui_set_frame_parameters_1): Use handle_frame_param.

* src/disptab.h (DISP_TABLE_EXTRA_SLOTS): Change to 12.
(enum box): New enumeration.

* src/dispnew.c (check_rows): New function, #if 0.
(frame_matrix_frame): Variable removed.
(line_hash_code): Take glyph's frame into account.
(build_frame_matrix_from_leaf_window): Do not copy glyphs from
rows that aren't enabled.
(fill_up_glyph_row_with_spaces): Add frame parameter, uses
changed.
(fill_up_glyph_row_area_with_spaces): Add frame parameter.  Set
glyph's frame to it.
(fill_up_frame_row_with_spaces): Ditto.
(set_frame_matrix_frame): Function removed.
(make_current): Change signature.  Callers changed.
(mirrored_line_dance): Take a frame argument, not a matrix.
(redraw_frame): Don't clear_frame a child frame.
(struct rect): New.
(rect_intersect, frame_pos_abs, frame_rect_abs, root_frame)
(max_child_z_order, is_frame_ancestor, frames_with_root)
(frames_with_parent, frame_z_order_cmp, Fframe__z_order_lessp)
(frames_in_reverse_z_order, tty_raise_lower_frame, is_tty_frame)
(is_tty_child_frame, is_tty_root_frame, first_enabled_row)
(make_matrix_current, prepare_desired_root_row)
(make_glyph_space, neutralize_wide_char, produce_box_glyphs)
(produce_box_sides, produce_box_line, copy_child_glyphs)
(update_window_frame, update_initial_frame, flush_terminal)
(abs_cursor_pos, is_in_matrix, is_cursor_obscured)
(terminal_cursor_magic, combine_updates_for_frame)
(combine_updates): New functions.
(update_frame): Rewritten.
(Fdisplay__update_for_mouse_movement): Take a MOUSE_FRAME param.
(syms_of_display): New symbol frame--z-order--lessp, tty-non-selected-cursor.
New subr Sframe__z_order_lessp.  Provide tty-child-frames.

* src/dispextern.h (struct glyph): Add member 'frame'.
(CHAR_GLYPH_SPACE_P): Add FRAME parameter.  All uses changed.
(GLYPH_EQUAL_P): Compare glyphs' frame.
(SET_CHAR_GLYPH): Add parameter FRAME.
(SET_CHAR_GLYPH_FROM_GLYPH): Ditto.

* src/chartab.c (Fmake_char_table): Allow more than 10 display
table slots.

* lisp/xt-mouse.el (xterm-mouse--handle-mouse-movement): Use new
terminal parameter xterm-mouse-frame.
(xterm-mouse-position-function): Ditto.
(xterm-mouse-event): Determine frame under mouse and compute
frame-relative coordinates.  Set terminal parameter
xterm-mouse-frame.

* lisp/tty-tip.el: New file implementing tooltip for ttys.

* lisp/paren.el (show-paren-function): Don't check if
display-graphics-p when using child frames.

* lisp/frame.el (frame-at): New function.
(tty-frame-geometry, tty-frame-edges, tty-frame-restack)
(tty-display-pixel-height, tty-frame-list-z-order)
(tty-display-pixel-width): Declare C function.
(frame-geometry): Use tty-frame-geometry.
(frame-edges): Use tty-frame-edges.
(frame-list-z-order): Use tty-frame-list-z-order.
(frame-restack): Use tty-frame-restack.
(display-pixel-height): Use tty-display-pixel-height.
(display-pixel-width): Use tty-display-pixel-width.

* lisp/disp-table.el (display-table): Increase size to 12.
(box-horizontal, box-vertical, box-down-right, box-down-left)
(box-up-right, box-up-left): New display table slot names for
box-drawing characters.
(display-table-slot, set-display-table-slot): Extend doc string.
(describe-display-table): Display new display table slots.
(standard-display-unicode-special-glyphs): New function setting
up Unicode characters for display table entries.

* .gitignore: Don't ignore patch files, they are useful to see in
Magit status buffer when applying patches (git am).
This commit is contained in:
Gerd Möllmann 2024-12-19 10:14:16 +01:00
commit 8aef5d224a
27 changed files with 2141 additions and 702 deletions

1
.gitignore vendored
View file

@ -323,7 +323,6 @@ gnustmp*
*~
\#*\#
ChangeLog
[0-9]*.patch
[0-9]*.txt
/vc-dwim-log-*

View file

@ -28,7 +28,7 @@
;;; Code:
(put 'display-table 'char-table-extra-slots 6)
(put 'display-table 'char-table-extra-slots 12)
;;;###autoload
(defun make-display-table ()
@ -46,13 +46,21 @@
(put 'control 'display-table-slot 3)
(put 'selective-display 'display-table-slot 4)
(put 'vertical-border 'display-table-slot 5)
(put 'box-vertical 'display-table-slot 6)
(put 'box-horizontal 'display-table-slot 7)
(put 'box-down-right 'display-table-slot 8)
(put 'box-down-left 'display-table-slot 9)
(put 'box-up-right 'display-table-slot 10)
(put 'box-up-left 'display-table-slot 11)
;;;###autoload
(defun display-table-slot (display-table slot)
"Return the value of the extra slot in DISPLAY-TABLE named SLOT.
SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol).
SLOT may be a number from 0 to 11 inclusive, or a slot name (symbol).
Valid symbols are `truncation', `wrap', `escape', `control',
`selective-display', and `vertical-border'."
`selective-display', `vertical-border', `box-vertical',
`box-horizontal', `box-down-right', `box-down-left', `box-up-right',
and `box-up-left'."
(let ((slot-number
(if (numberp slot) slot
(or (get slot 'display-table-slot)
@ -62,9 +70,11 @@ Valid symbols are `truncation', `wrap', `escape', `control',
;;;###autoload
(defun set-display-table-slot (display-table slot value)
"Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE.
SLOT may be a number from 0 to 5 inclusive, or a name (symbol).
SLOT may be a number from 0 to 11 inclusive, or a name (symbol).
Valid symbols are `truncation', `wrap', `escape', `control',
`selective-display', and `vertical-border'."
`selective-display', `vertical-border', `box-vertical',
`box-horizontal', `box-down-right', `box-down-left', `box-up-right',
and `box-up-left'."
(let ((slot-number
(if (numberp slot) slot
(or (get slot 'display-table-slot)
@ -87,6 +97,18 @@ Valid symbols are `truncation', `wrap', `escape', `control',
(prin1 (display-table-slot dt 'selective-display))
(princ "\nVertical window border glyph: ")
(prin1 (display-table-slot dt 'vertical-border))
(princ "\nBox vertical line glyph: ")
(prin1 (display-table-slot dt 'box-vertical))
(princ "\nBox horizonal line glyph: ")
(prin1 (display-table-slot dt 'box-horizontal))
(princ "\nBox upper left corner glyph: ")
(prin1 (display-table-slot dt 'box-down-right))
(princ "\nBox upper right corner glyph: ")
(prin1 (display-table-slot dt 'box-down-left))
(princ "\nBox lower left corner glyph: ")
(prin1 (display-table-slot dt 'box-up-right))
(princ "\nBox lower right corner glyph: ")
(prin1 (display-table-slot dt 'box-up-left))
(princ "\nCharacter display glyph sequences:\n")
(with-current-buffer standard-output
(let ((vector (make-vector 256 nil))
@ -126,6 +148,28 @@ Valid symbols are `truncation', `wrap', `escape', `control',
(describe-display-table disptab)
(message "No display table"))))
;;;###autoload
(defun standard-display-unicode-special-glyphs ()
"Display some glyps using Unicode characters.
The glyphs being changed by this function are `vertical-border',
`box-vertical', `box-horizontal', `box-down-right', `box-down-left',
`box-up-right', and `box-up-left'."
(interactive)
(set-display-table-slot standard-display-table
'vertical-border (make-glyph-code #x2502))
(set-display-table-slot standard-display-table
'box-vertical (make-glyph-code #x2502))
(set-display-table-slot standard-display-table
'box-horizontal (make-glyph-code #x2500))
(set-display-table-slot standard-display-table
'box-down-right (make-glyph-code #x250c))
(set-display-table-slot standard-display-table
'box-down-left (make-glyph-code #x2510))
(set-display-table-slot standard-display-table
'box-up-right (make-glyph-code #x2514))
(set-display-table-slot standard-display-table
'box-up-left (make-glyph-code #x2518)))
;;;###autoload
(defun standard-display-8bit (l h)
"Display characters representing raw bytes in the range L to H literally.

View file

@ -1506,6 +1506,13 @@ FRAME defaults to the selected frame."
(let ((edges (frame-edges frame 'outer-edges)))
(- (nth 3 edges) (nth 1 edges))))
(defun frame-at (x y)
"Return frame containing pixel position X, Y."
(cl-loop for frame in (frame-list-z-order)
as (x0 y0 x1 y1) = (frame-edges frame)
when (and (<= x0 x (1- x1)) (<= y0 y (1- y1)))
return frame))
(declare-function x-list-fonts "xfaces.c"
(pattern &optional face frame maximum width))
@ -1733,6 +1740,7 @@ live frame and defaults to the selected one."
(declare-function pgtk-frame-geometry "pgtkfns.c" (&optional frame))
(declare-function haiku-frame-geometry "haikufns.c" (&optional frame))
(declare-function android-frame-geometry "androidfns.c" (&optional frame))
(declare-function tty-frame-geometry "term.c" (&optional frame))
(defun frame-geometry (&optional frame)
"Return geometric attributes of FRAME.
@ -1789,24 +1797,7 @@ and width values are in pixels.
((eq frame-type 'android)
(android-frame-geometry frame))
(t
(list
'(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)))
(cons 'menu-bar-size
(if menu-bar-lines
(cons (frame-width frame) 1)
1 0)))
'(tool-bar-external . nil)
'(tool-bar-position . nil)
'(tool-bar-size 0 . 0)
'(tab-bar-size 0 . 0)
(cons 'internal-border-width
(frame-parameter frame 'internal-border-width)))))))
(tty-frame-geometry frame)))))
(defun frame--size-history (&optional frame)
"Print history of resize operations for FRAME.
@ -1915,6 +1906,7 @@ of frames like calls to map a frame or change its visibility."
(declare-function pgtk-frame-edges "pgtkfns.c" (&optional frame type))
(declare-function haiku-frame-edges "haikufns.c" (&optional frame type))
(declare-function android-frame-edges "androidfns.c" (&optional frame type))
(declare-function tty-frame-edges "term.c" (&optional frame type))
(defun frame-edges (&optional frame type)
"Return coordinates of FRAME's edges.
@ -1945,7 +1937,7 @@ FRAME."
((eq frame-type 'android)
(android-frame-edges frame type))
(t
(list 0 0 (frame-width frame) (frame-height frame))))))
(tty-frame-edges frame type)))))
(declare-function w32-mouse-absolute-pixel-position "w32fns.c")
(declare-function x-mouse-absolute-pixel-position "xfns.c")
@ -2098,6 +2090,7 @@ workarea attribute."
;; (declare-function pgtk-frame-list-z-order "pgtkfns.c" (&optional display))
(declare-function haiku-frame-list-z-order "haikufns.c" (&optional display))
(declare-function android-frame-list-z-order "androidfns.c" (&optional display))
(declare-function tty-frame-list-z-order "term.c" (&optional display))
(defun frame-list-z-order (&optional display)
"Return list of Emacs's frames, in Z (stacking) order.
@ -2125,7 +2118,9 @@ Return nil if DISPLAY contains no Emacs frame."
((eq frame-type 'haiku)
(haiku-frame-list-z-order display))
((eq frame-type 'android)
(android-frame-list-z-order display)))))
(android-frame-list-z-order display))
(t
(tty-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))
@ -2134,6 +2129,7 @@ Return nil if DISPLAY contains no Emacs frame."
(declare-function haiku-frame-restack "haikufns.c" (frame1 frame2 &optional above))
(declare-function android-frame-restack "androidfns.c" (frame1 frame2
&optional above))
(declare-function tty-frame-restack "term.c" (frame1 frame2 &optional above))
(defun frame-restack (frame1 frame2 &optional above)
"Restack FRAME1 below FRAME2.
@ -2169,7 +2165,9 @@ Some window managers may refuse to restack windows."
((eq frame-type 'pgtk)
(pgtk-frame-restack frame1 frame2 above))
((eq frame-type 'android)
(android-frame-restack frame1 frame2 above))))
(android-frame-restack frame1 frame2 above))
(t
(tty-frame-restack frame1 frame2 above))))
(error "Cannot restack frames")))
(defun frame-size-changed-p (&optional frame)
@ -2322,6 +2320,7 @@ If DISPLAY is omitted or nil, it defaults to the selected frame's display."
1))))
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function tty-display-pixel-height "term.c" (&optional terminal))
(defun display-pixel-height (&optional display)
"Return the height of DISPLAY's screen in pixels.
@ -2339,9 +2338,10 @@ with DISPLAY. To get information for each physical monitor, use
((memq frame-type '(x w32 ns haiku pgtk android))
(x-display-pixel-height display))
(t
(frame-height (if (framep display) display (selected-frame)))))))
(tty-display-pixel-height display)))))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
(declare-function tty-display-pixel-width "term.c" (&optional terminal))
(defun display-pixel-width (&optional display)
"Return the width of DISPLAY's screen in pixels.
@ -2359,7 +2359,7 @@ with DISPLAY. To get information for each physical monitor, use
((memq frame-type '(x w32 ns haiku pgtk android))
(x-display-pixel-width display))
(t
(frame-width (if (framep display) display (selected-frame)))))))
(tty-display-pixel-width display)))))
(defcustom display-mm-dimensions-alist nil
"Alist for specifying screen dimensions in millimeters.

View file

@ -522,9 +522,7 @@ It is the default value of `show-paren-data-function'."
openparen))
(message-log-max nil))
(cond
((and
(eq show-paren-context-when-offscreen 'child-frame)
(display-graphic-p))
((eq show-paren-context-when-offscreen 'child-frame)
(show-paren--show-context-in-child-frame context))
((eq show-paren-context-when-offscreen 'overlay)
(show-paren--show-context-in-overlay context))

208
lisp/tty-tip.el Normal file
View file

@ -0,0 +1,208 @@
;;; -*- lexical-binding: t; symbol-packages: t; -*-
;;; tty-tip.el --- Display help in kind of tooltips on ttys
;; Copyright (C) 2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; This uses tty child frames to display help which looks and feels much
;; like using tooltips (but they really aren't).
;; Use `tty-tip-mode' to activate or toggle this feature.
;;
;; You can customize face `tooltip', `tooltip-short-delay',
;; `tooltip-delay', `tooltip-recent-seconds'.
(require 'tooltip)
(defvar tty-tip--frame nil)
(defun tty-tip--make-buffer (text)
(with-current-buffer
(get-buffer-create " *tty-tip*")
;; Redirect focus to parent.
(add-hook 'pre-command-hook #'tty-tip--delete-frame nil t)
;; Use an empty keymap.
(use-local-map (make-keymap))
(dolist (var '((mode-line-format . nil)
(header-line-format . nil)
(tab-line-format . nil)
(tab-bar-format . nil) ;; Emacs 28 tab-bar-format
(frame-title-format . "")
(truncate-lines . t)
(cursor-in-non-selected-windows . nil)
(cursor-type . nil)
(show-trailing-whitespace . nil)
(display-line-numbers . nil)
(left-fringe-width . nil)
(right-fringe-width . nil)
(left-margin-width . 0)
(right-margin-width . 0)
(fringes-outside-margins . 0)
(buffer-read-only . t)))
(set (make-local-variable (car var)) (cdr var)))
(let ((inhibit-modification-hooks t)
(inhibit-read-only t))
(erase-buffer)
(insert text)
(goto-char (point-min)))
(current-buffer)))
(defvar tty-tip-frame-parameters
`((visibility . nil)
(background-color . "lightyellow")
(foreground-color . "black")
(width . 0) (height . 0)
(min-width . t) (min-height . t)
(no-accept-focus . t)
(no-focus-on-map . t)
(border-width . 0)
(child-frame-border-width . 1)
(left-fringe . 0)
(right-fringe . 0)
(vertical-scroll-bars . nil)
(horizontal-scroll-bars . nil)
(menu-bar-lines . 0)
(tool-bar-lines . 0)
(tab-bar-lines . 0)
(no-other-frame . t)
(no-other-window . t)
(no-delete-other-windows . t)
(unsplittable . t)
(undecorated . t)
(cursor-type . nil)
(no-special-glyphs . t)
(desktop-dont-save . t)))
(defun tty-tip--frame-parameters ()
(let ((params (copy-sequence tty-tip-frame-parameters))
(fg (face-attribute 'tooltip :foreground))
(bg (face-attribute 'tooltip :background)))
(when (stringp fg)
(setf (alist-get 'foreground-color params) fg))
(when (stringp bg)
(setf (alist-get 'background-color params) bg))
params))
(defvar tty-tip--help-message nil)
(defvar tty-tip--hide-time nil)
(defvar tty-tip--show-timer nil)
(defvar tty-tip--hide-timer nil)
(defun tty-tip--delete-frame ()
(when tty-tip--frame
(when tty-tip--hide-timer
(cancel-timer tty-tip--hide-timer)
(setq tty-tip--hide-timer nil))
(delete-frame tty-tip--frame)
(setq tty-tip--frame nil)
t))
(defun tty-tip--compute-position ()
(let* ((pos (mouse-position))
(mouse-x (car (cdr pos)))
(mouse-y (cdr (cdr pos)))
(x (+ mouse-x 1))
(y (+ mouse-y 1))
(tip-width (frame-width tty-tip--frame))
(tip-height (frame-height tty-tip--frame))
(tty-width (display-pixel-width))
(tty-height (display-pixel-height)))
(when (> (+ x tip-width) tty-width)
(setq x (max 0 (- x tip-width 1))))
(when (> (+ y tip-height) tty-height)
(setq y (max 0 (- y tip-height 1))))
(cons x y)))
(defun tty-tip--create-frame (text)
(let* ((minibuffer (minibuffer-window (window-frame)))
(buffer (tty-tip--make-buffer text))
(window-min-height 1)
(window-min-width 1)
after-make-frame-functions
(text-lines (string-lines text)))
(setq tty-tip--frame
(make-frame
`((parent-frame . ,(car (mouse-position)))
(minibuffer . ,minibuffer)
,@(tty-tip--frame-parameters))))
(let ((win (frame-root-window tty-tip--frame)))
(set-window-buffer win buffer)
(set-window-dedicated-p win t)
(set-frame-size tty-tip--frame
(apply #'max (mapcar #'string-width text-lines))
(length text-lines))
(let* ((pos (tty-tip--compute-position))
(x (car pos))
(y (cdr pos)))
(set-frame-position tty-tip--frame x y))
(make-frame-visible tty-tip--frame)
(setq tty-tip--hide-timer
(run-with-timer tooltip-hide-delay nil
#'tty-tip--delete-frame)))))
(defun tty-tip--delay ()
(if (and tty-tip--hide-time
(time-less-p (time-since tty-tip--hide-time)
tooltip-recent-seconds))
tooltip-short-delay
tooltip-delay))
(defun tty-tip--cancel-delayed-tip ()
(when tty-tip--show-timer
(cancel-timer tty-tip--show-timer)
(setq tty-tip--show-timer nil)))
(defun tty-tip--start-delayed-tip ()
(setq tty-tip--show-timer
(run-with-timer (tty-tip--delay) nil
(lambda ()
(tty-tip--create-frame
tty-tip--help-message)))))
(defun tty-tip--hide (&optional _ignored-arg)
(tty-tip--cancel-delayed-tip)
(when (tty-tip--delete-frame)
(setq tty-tip--hide-time (float-time))))
(defun tty-tip--show-help (msg)
(let ((previous-help tty-tip--help-message))
(setq tty-tip--help-message msg)
(cond ((null msg)
(tty-tip--hide))
((equal previous-help msg)
nil)
(t
(tty-tip--hide)
(tty-tip--start-delayed-tip)))))
;;;###autoload
(define-minor-mode tty-tip-mode
"Global minor mode for displaying help in tty child frames."
:global t :group 'help
(unless (display-graphic-p)
(cond (tty-tip-mode
(setq show-help-function #'tty-tip--show-help)
(add-hook 'pre-command-hook #'tty-tip--hide))
(t
(setq show-help-function nil)
(remove-hook 'pre-command-hook #'tty-tip--hide)))))
(provide 'tty-tip)
;;; End

View file

@ -133,7 +133,8 @@ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)."
(defun xterm-mouse--handle-mouse-movement ()
"Handle mouse motion that was just generated for XTerm mouse."
(display--update-for-mouse-movement (terminal-parameter nil 'xterm-mouse-x)
(display--update-for-mouse-movement (terminal-parameter nil 'xterm-mouse-frame)
(terminal-parameter nil 'xterm-mouse-x)
(terminal-parameter nil 'xterm-mouse-y)))
;; These two variables have been converted to terminal parameters.
@ -150,10 +151,11 @@ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)."
(defun xterm-mouse-position-function (pos)
"Bound to `mouse-position-function' in XTerm mouse mode."
(when (terminal-parameter nil 'xterm-mouse-x)
(setcdr pos (cons (terminal-parameter nil 'xterm-mouse-x)
(terminal-parameter nil 'xterm-mouse-y))))
pos)
(if (terminal-parameter nil 'xterm-mouse-x)
(cons (terminal-parameter nil 'xterm-mouse-frame)
(cons (terminal-parameter nil 'xterm-mouse-x)
(terminal-parameter nil 'xterm-mouse-y)))
pos))
(define-obsolete-function-alias 'xterm-mouse-truncate-wrap 'truncate "27.1")
@ -293,7 +295,16 @@ which is the \"1006\" extension implemented in Xterm >= 277."
(progn (setq xt-mouse-epoch (float-time)) 0)
(car (time-convert (time-since xt-mouse-epoch)
1000))))
(w (window-at x y))
(frame (frame-at x y))
;;(_ (message (format "*** %S" frame)))
(frame-pos (frame-position frame))
;;(_ (message (format "*** %S" frame-pos)))
(x (- x (car frame-pos)))
(y (- y (cdr frame-pos)))
;;(_ (message (format "*** %S %S" x y)))
(w (window-at x y frame))
;;(_ (message (format "*** %S" w)))
(ltrb (window-edges w))
(left (nth 0 ltrb))
(top (nth 1 ltrb))
@ -345,6 +356,7 @@ which is the \"1006\" extension implemented in Xterm >= 277."
(set-terminal-parameter nil 'xterm-mouse-x x)
(set-terminal-parameter nil 'xterm-mouse-y y)
(set-terminal-parameter nil 'xterm-mouse-frame frame)
(setq last-input-event event)))))
;;;###autoload

View file

@ -6853,9 +6853,11 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
struct glyph *end_glyph = glyph + row->used[area];
for (; glyph < end_glyph; ++glyph)
if (STRINGP (glyph->object)
&& !string_marked_p (XSTRING (glyph->object)))
mark_object (glyph->object);
{
if (STRINGP (glyph->object)
&& !string_marked_p (XSTRING (glyph->object)))
mark_object (glyph->object);
}
}
}
}

View file

@ -122,8 +122,6 @@ the char-table has no extra slot. */)
else
{
CHECK_FIXNAT (n);
if (XFIXNUM (n) > 10)
args_out_of_range (n, Qnil);
n_extras = XFIXNUM (n);
}

View file

@ -482,6 +482,11 @@ struct glyph
continuation glyphs, or the overlay-arrow glyphs on TTYs. */
Lisp_Object object;
/* Frame on which the glyph was produced. The face_id of this glyph
refers to the face_cache of this frame. This is used on tty
frames only. */
struct frame *frame;
/* Width in pixels. */
short pixel_width;
@ -626,10 +631,12 @@ struct glyph
#define FONT_TYPE_UNKNOWN 0
/* Is GLYPH a space? */
/* Is GLYPH a space in default face on frame FRAME? */
#define CHAR_GLYPH_SPACE_P(GLYPH) \
((GLYPH).u.ch == SPACEGLYPH && (GLYPH).face_id == DEFAULT_FACE_ID)
# define CHAR_GLYPH_SPACE_P(FRAME, GLYPH) \
((GLYPH).u.ch == SPACEGLYPH \
&& (GLYPH).face_id == DEFAULT_FACE_ID \
&& (GLYPH).frame == (FRAME))
/* Are glyph slices of glyphs *X and *Y equal? It assumes that both
glyphs have the same type.
@ -654,6 +661,7 @@ struct glyph
&& (X)->u.val == (Y)->u.val \
&& GLYPH_SLICE_EQUAL_P (X, Y) \
&& (X)->face_id == (Y)->face_id \
&& (X)->frame == (Y)->frame \
&& (X)->padding_p == (Y)->padding_p \
&& (X)->left_box_line_p == (Y)->left_box_line_p \
&& (X)->right_box_line_p == (Y)->right_box_line_p \
@ -665,16 +673,18 @@ struct glyph
#define GLYPH_CHAR_AND_FACE_EQUAL_P(X, Y) \
((X)->u.ch == (Y)->u.ch \
&& (X)->face_id == (Y)->face_id \
&& (X)->frame == (Y)->frame \
&& (X)->padding_p == (Y)->padding_p)
/* Fill a character glyph GLYPH. CODE, FACE_ID, PADDING_P correspond
to the bits defined for the typedef `GLYPH' in lisp.h. */
#define SET_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P) \
#define SET_CHAR_GLYPH(FRAME, GLYPH, CODE, FACE_ID, PADDING_P) \
do \
{ \
(GLYPH).u.ch = (CODE); \
(GLYPH).face_id = (FACE_ID); \
(GLYPH).frame = (FRAME); \
(GLYPH).padding_p = (PADDING_P); \
} \
while (false)
@ -682,11 +692,9 @@ struct glyph
/* Fill a character type glyph GLYPH from a glyph typedef FROM as
defined in lisp.h. */
#define SET_CHAR_GLYPH_FROM_GLYPH(GLYPH, FROM) \
SET_CHAR_GLYPH (GLYPH, \
GLYPH_CHAR (FROM), \
GLYPH_FACE (FROM), \
false)
#define SET_CHAR_GLYPH_FROM_GLYPH(FRAME, GLYPH, FROM) \
SET_CHAR_GLYPH (FRAME, GLYPH, GLYPH_CHAR (FROM), \
GLYPH_FACE (FROM), false)
/* Construct a glyph code from a character glyph GLYPH. If the
character is multibyte, return -1 as we can't use glyph table for a
@ -3835,7 +3843,7 @@ extern void adjust_frame_glyphs (struct frame *);
void free_glyphs (struct frame *);
void free_window_matrices (struct window *);
void check_glyph_memory (void);
void mirrored_line_dance (struct glyph_matrix *, int, int, int *, char *);
void mirrored_line_dance (struct frame *f, int, int, int *, char *);
void clear_glyph_matrix (struct glyph_matrix *);
void clear_current_matrices (struct frame *f);
void clear_desired_matrices (struct frame *);
@ -3859,7 +3867,7 @@ extern bool frame_size_change_delayed (struct frame *);
void init_display (void);
void syms_of_display (void);
extern void spec_glyph_lookup_face (struct window *, GLYPH *);
extern void fill_up_frame_row_with_spaces (struct glyph_row *, int);
extern void fill_up_frame_row_with_spaces (struct frame *, struct glyph_row *, int);
/* Defined in terminal.c. */
@ -3941,6 +3949,16 @@ extern void gui_redo_mouse_highlight (Display_Info *);
#endif /* HAVE_WINDOW_SYSTEM */
struct frame *root_frame (struct frame *f);
Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible);
bool is_tty_frame (struct frame *f);
bool is_tty_child_frame (struct frame *f);
bool is_tty_root_frame (struct frame *f);
bool combine_updates (Lisp_Object root_frames, bool force_p, bool inhibit_id_p);
bool combine_updates_for_frame (struct frame *f, bool force_p, bool inhibit_id_p);
void tty_raise_lower_frame (struct frame *f, bool raise);
int max_child_z_order (struct frame *parent);
INLINE_HEADER_END
#endif /* not DISPEXTERN_H_INCLUDED */

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
&& EQ (XCHAR_TABLE (obj)->purpose, Qdisplay_table) \
&& CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (obj)) == DISP_TABLE_EXTRA_SLOTS)
#define DISP_TABLE_EXTRA_SLOTS 6
#define DISP_TABLE_EXTRA_SLOTS 12
#define DISP_TRUNC_GLYPH(dp) ((dp)->extras[0])
#define DISP_CONTINUE_GLYPH(dp) ((dp)->extras[1])
#define DISP_ESCAPE_GLYPH(dp) ((dp)->extras[2])
@ -36,6 +36,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define DISP_INVIS_VECTOR(dp) ((dp)->extras[4])
#define DISP_BORDER_GLYPH(dp) ((dp)->extras[5])
enum box
{
BOX_VERTICAL = 6,
BOX_HORIZONTAL,
BOX_DOWN_RIGHT,
BOX_DOWN_LEFT,
BOX_UP_RIGHT,
BOX_UP_LEFT
};
extern Lisp_Object disp_char_vector (struct Lisp_Char_Table *, int);
#define DISP_CHAR_VECTOR(dp, c) \

View file

@ -130,6 +130,14 @@ decode_window_system_frame (Lisp_Object frame)
#endif
}
struct frame *
decode_tty_frame (Lisp_Object frame)
{
struct frame *f = decode_live_frame (frame);
check_tty (f);
return f;
}
void
check_window_system (struct frame *f)
{
@ -141,6 +149,13 @@ check_window_system (struct frame *f)
: "Window system is not in use or not initialized");
}
void
check_tty (struct frame *f)
{
if (!f || !FRAME_TERMCAP_P (f))
error ("tty frame should be used");
}
/* Return the value of frame parameter PROP in frame FRAME. */
Lisp_Object
@ -178,6 +193,17 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
int olines = FRAME_MENU_BAR_LINES (f);
int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0;
/* Menu bars on child frames don't work on all platforms, which is
the reason why prepare_menu_bar does not update_menu_bar for
child frames (info from Martin Rudalics). This could be
implemented in ttys, but it's probaly not worth it. */
if (is_tty_child_frame (f))
{
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_MENU_BAR_HEIGHT (f) = 0;
return;
}
/* Right now, menu bars don't work properly in minibuf-only frames;
most of the commands try to apply themselves to the minibuffer
frame itself, and get an error because you can't switch buffers
@ -366,17 +392,17 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
}
else
retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal,
ignore, pixelwise));
ignore, pixelwise));
/* Don't allow too small height of text-mode frames, or else cm.c
might abort in cmcheckmagic. */
if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
{
int min_height = (FRAME_MENU_BAR_LINES (f)
+ FRAME_TAB_BAR_LINES (f)
int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)
+ FRAME_WANTS_MODELINE_P (f)
+ 2); /* one text line and one echo-area line */
+ FRAME_HAS_MINIBUF_P (f));
if (min_height == 0)
min_height = 1;
if (retval < min_height)
retval = min_height;
}
@ -385,7 +411,6 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
}
#ifdef HAVE_WINDOW_SYSTEM
/**
* keep_ratio:
*
@ -504,7 +529,6 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
}
}
}
#endif
static void
@ -829,8 +853,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
/* MSDOS frames cannot PRETEND, as they change frame size by
manipulating video hardware. */
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameCols (FRAME_TTY (f)) = new_text_cols;
if (is_tty_root_frame (f))
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameCols (FRAME_TTY (f)) = new_text_cols;
#if defined (HAVE_WINDOW_SYSTEM)
if (WINDOWP (f->tab_bar_window))
@ -862,9 +887,10 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
resize_frame_windows (f, new_inner_height, false);
/* MSDOS frames cannot PRETEND, as they change frame size by
manipulating video hardware. */
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
manipulating video hardware. */
if (is_tty_root_frame (f))
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
}
else if (new_text_lines != old_text_lines)
call2 (Qwindow__pixel_to_total, frame, Qnil);
@ -894,6 +920,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
adjust_frame_glyphs (f);
calculate_costs (f);
SET_FRAME_GARBAGED (f);
if (is_tty_child_frame (f))
SET_FRAME_GARBAGED (root_frame (f));
/* We now say here that F was resized instead of using the old
condition below. Some resizing must have taken place and if it was
only shifting the root window's position (paranoia?). */
@ -906,7 +935,6 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
unblock_input ();
#ifdef HAVE_WINDOW_SYSTEM
{
/* Adjust size of F's child frames. */
Lisp_Object frames, frame1;
@ -916,7 +944,6 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height,
new_native_width, new_native_height);
}
#endif
}
/* Allocate basically initialized frame. */
@ -961,12 +988,12 @@ make_frame (bool mini_p)
f->line_height = 1; /* !FRAME_WINDOW_P value. */
f->new_width = -1;
f->new_height = -1;
f->no_special_glyphs = false;
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
f->horizontal_scroll_bars = false;
f->want_fullscreen = FULLSCREEN_NONE;
f->undecorated = false;
f->no_special_glyphs = false;
#ifndef HAVE_NTGUI
f->override_redirect = false;
#endif
@ -1083,7 +1110,6 @@ make_frame (bool mini_p)
return f;
}
#ifdef HAVE_WINDOW_SYSTEM
/* Make a frame using a separate minibuffer window on another frame.
MINI_WINDOW is the minibuffer window to use. nil means use the
default (the global minibuffer). */
@ -1177,7 +1203,7 @@ make_minibuffer_frame (void)
: Fcar (Vminibuffer_list)), 0, 0);
return f;
}
#endif /* HAVE_WINDOW_SYSTEM */
/* Construct a frame that refers to a terminal. */
@ -1203,7 +1229,7 @@ make_initial_frame (void)
tty_frame_count = 1;
fset_name (f, build_pure_c_string ("F1"));
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_VISIBLE (f, true);
f->output_method = terminal->type;
f->terminal = terminal;
@ -1240,23 +1266,48 @@ make_initial_frame (void)
#ifndef HAVE_ANDROID
static struct frame *
make_terminal_frame (struct terminal *terminal)
make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
Lisp_Object params)
{
register struct frame *f;
Lisp_Object frame;
char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
if (!terminal->name)
error ("Terminal is not live, can't create new frames on it");
f = make_frame (1);
struct frame *f;
if (NILP (parent))
f = make_frame (true);
else
{
CHECK_LIVE_FRAME (parent);
f = NULL;
Lisp_Object mini = Fassq (Qminibuffer, params);
if (CONSP (mini))
{
mini = Fcdr (mini);
struct kboard *kb = FRAME_KBOARD (XFRAME (parent));
if (EQ (mini, Qnone) || NILP (mini))
f = make_frame_without_minibuffer (Qnil, kb, Qnil);
else if (EQ (mini, Qonly))
error ("minibuffer-only child frames are not implemented");
else if (WINDOWP (mini))
f = make_frame_without_minibuffer (mini, kb, Qnil);
}
if (f == NULL)
f = make_frame (true);
f->parent_frame = parent;
f->z_order = 1 + max_child_z_order (XFRAME (parent));
}
Lisp_Object frame;
XSETFRAME (frame, f);
Vframe_list = Fcons (frame, Vframe_list);
fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count));
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_VISIBLE (f, true);
f->terminal = terminal;
f->terminal->reference_count++;
@ -1281,7 +1332,15 @@ make_terminal_frame (struct terminal *terminal)
f->horizontal_scroll_bars = false;
#endif
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
/* Menu bars on child frames don't work on all platforms, which is
the reason why prepare_menu_bar does not update_menu_bar for
child frames (info from Martin Rudalics). This could be
implemented in ttys, but it's unclear if it is worth it. */
if (NILP (parent))
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
else
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_TAB_BAR_LINES (f) = NILP (Vtab_bar_mode) ? 0 : 1;
FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f)
- FRAME_TAB_BAR_LINES (f);
@ -1290,16 +1349,18 @@ make_terminal_frame (struct terminal *terminal)
FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f)
- FRAME_TAB_BAR_HEIGHT (f);
/* Mark current topmost frame obscured if we make a new root frame.
Child frames don't completely obscure other frames. */
if (NILP (parent) && FRAMEP (FRAME_TTY (f)->top_frame))
{
struct frame *top = XFRAME (FRAME_TTY (f)->top_frame);
struct frame *root = root_frame (top);
if (FRAME_LIVE_P (root))
SET_FRAME_VISIBLE (root, false);
}
/* Set the top frame to the newly created frame. */
if (FRAMEP (FRAME_TTY (f)->top_frame)
&& FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
FRAME_TTY (f)->top_frame = frame;
if (!noninteractive)
init_frame_faces (f);
return f;
}
@ -1329,6 +1390,68 @@ get_future_frame_param (Lisp_Object parameter,
#endif
static int
tty_child_pos_param (struct frame *child, Lisp_Object key,
Lisp_Object params, int dflt)
{
Lisp_Object val = Fassq (key, params);
if (CONSP (val))
{
val = XCDR (val);
if (FIXNUMP (val))
return XFIXNUM (val);
}
return dflt;
}
static int
tty_child_size_param (struct frame *child, Lisp_Object key,
Lisp_Object params, int dflt)
{
Lisp_Object val = Fassq (key, params);
if (CONSP (val))
{
val = XCDR (val);
if (CONSP (val))
{
/* Width and height may look like (width text-pixels . PIXELS)
on window systems. Mimic that. */
val = XCDR (val);
if (EQ (val, Qtext_pixels))
val = XCDR (val);
}
else if (FLOATP (val))
{
/* Width and height may be a float, in which case
it's a multiple of the parent's value. */
struct frame *parent = FRAME_PARENT_FRAME (child);
eassert (parent); /* the caller ensures this, but... */
if (parent)
{
int sz = (EQ (key, Qwidth) ? FRAME_TOTAL_COLS (parent)
: FRAME_TOTAL_LINES (parent));
val = make_fixnum (XFLOAT_DATA (val) * sz);
}
else
val = Qnil;
}
if (FIXNATP (val))
return XFIXNUM (val);
}
return dflt;
}
static void
tty_child_frame_rect (struct frame *f, Lisp_Object params,
int *x, int *y, int *w, int *h)
{
*x = tty_child_pos_param (f, Qleft, params, 0);
*y = tty_child_pos_param (f, Qtop, params, 0);
*w = tty_child_size_param (f, Qwidth, params, FRAME_TOTAL_COLS (f));
*h = tty_child_size_param (f, Qheight, params, FRAME_TOTAL_LINES (f));
}
DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1, 1, 0,
doc: /* Create an additional terminal frame, possibly on another terminal.
@ -1352,9 +1475,7 @@ affects all frames on the same terminal device. */)
error ("Text terminals are not supported on this platform");
return Qnil;
#else
struct frame *f;
struct terminal *t = NULL;
Lisp_Object frame;
struct frame *sf = SELECTED_FRAME ();
#ifdef MSDOS
@ -1384,7 +1505,7 @@ affects all frames on the same terminal device. */)
error ("Multiple terminals are not supported on this platform");
if (!t)
t = the_only_display_info.terminal;
#endif
# endif
}
if (!t)
@ -1411,19 +1532,64 @@ affects all frames on the same terminal device. */)
SAFE_FREE ();
}
f = make_terminal_frame (t);
/* Make a new frame. We need to know up front if a parent frame is
specified because we behave differently in this case, e.g., child
frames don't obscure other frames. */
Lisp_Object parent = Fcdr (Fassq (Qparent_frame, parms));
struct frame *f = make_terminal_frame (t, parent, parms);
{
int width, height;
if (!noninteractive)
init_frame_faces (f);
/* Visibility of root frames cannot be set with a frame parameter.
Their visibility solely depends on whether or not they are the
top_frame on the terminal. */
if (FRAME_PARENT_FRAME (f))
{
Lisp_Object visible = Fassq (Qvisibility, parms);
if (CONSP (visible))
SET_FRAME_VISIBLE (f, !NILP (visible));
/* FIXME/tty: The only way, for now, to get borders on a tty is
to allow decorations. */
Lisp_Object undecorated = Fassq (Qundecorated, parms);
if (CONSP (undecorated) && !NILP (XCDR (undecorated)))
f->undecorated = true;
/* Unused at present. */
Lisp_Object no_focus = Fassq (Qno_accept_focus, parms);
if (CONSP (no_focus) && !NILP (XCDR (no_focus)))
f->no_accept_focus = true;
Lisp_Object no_split = Fassq (Qunsplittable, parms);
if (CONSP (no_split) && !NILP (XCDR (no_split)))
f->no_split = true;
}
/* Determine width and height of the frame. For root frames use the
width/height of the terminal. For child frames, take it from frame
parameters. Note that a default (80x25) has been set in
make_frame. We handle root frames in this way because otherwise we
would end up needing glyph matrices for the terminal, which is both
more work and has its downsides (think of clipping frames to the
terminal size). */
int x = 0, y = 0, width, height;
if (FRAME_PARENT_FRAME (f))
tty_child_frame_rect (f, parms, &x, &y, &width, &height);
else
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
/* With INHIBIT 5 pass correct text height to adjust_frame_size. */
adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f),
5, 0, Qterminal_frame);
}
adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 5, 0,
Qterminal_frame);
adjust_frame_glyphs (f);
calculate_costs (f);
XSETFRAME (frame, f);
f->left_pos = x;
f->top_pos = y;
store_in_alist (&parms, Qleft, make_fixnum (x));
store_in_alist (&parms, Qtop, make_fixnum (y));
store_in_alist (&parms, Qwidth, make_fixnum (width));
store_in_alist (&parms, Qheight, make_fixnum (height));
store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
store_in_alist (&parms, Qtty,
@ -1445,7 +1611,11 @@ affects all frames on the same terminal device. */)
/* On terminal frames the `minibuffer' frame parameter is always
virtually t. Avoid that a different value in parms causes
complaints, see Bug#24758. */
store_in_alist (&parms, Qminibuffer, Qt);
if (!FRAME_PARENT_FRAME (f))
store_in_alist (&parms, Qminibuffer, Qt);
Lisp_Object frame;
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame, parms);
f->can_set_window_size = true;
@ -1474,8 +1644,6 @@ affects all frames on the same terminal device. */)
Lisp_Object
do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
{
struct frame *sf = SELECTED_FRAME (), *f;
/* If FRAME is a switch-frame event, extract the frame we should
switch to. */
if (CONSP (frame)
@ -1487,7 +1655,9 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
a switch-frame event to arrive after a frame is no longer live,
especially when deleting the initial frame during startup. */
CHECK_FRAME (frame);
f = XFRAME (frame);
struct frame *f = XFRAME (frame);
struct frame *sf = SELECTED_FRAME ();
/* Silently ignore dead and tooltip frames (Bug#47207). */
if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f))
return Qnil;
@ -1540,24 +1710,37 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
struct tty_display_info *tty = FRAME_TTY (f);
Lisp_Object top_frame = tty->top_frame;
/* Don't mark the frame garbaged and/or obscured if we are
switching to the frame that is already the top frame of that
TTY. */
/* Don't mark the frame garbaged if we are switching to the frame
that is already the top frame of that TTY. */
if (!EQ (frame, top_frame))
{
struct frame *new_root = root_frame (f);
SET_FRAME_VISIBLE (new_root, true);
SET_FRAME_VISIBLE (f, true);
/* Mark previously displayed frame as no longer visible. */
if (FRAMEP (top_frame))
/* Mark previously displayed frame as now obscured. */
SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
SET_FRAME_VISIBLE (f, 1);
/* If the new TTY frame changed dimensions, we need to
resync term.c's idea of the frame size with the new
frame's data. */
if (FRAME_COLS (f) != FrameCols (tty))
FrameCols (tty) = FRAME_COLS (f);
if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
FrameRows (tty) = FRAME_TOTAL_LINES (f);
{
struct frame *top = XFRAME (top_frame);
struct frame *old_root = root_frame (top);
if (old_root != new_root)
SET_FRAME_VISIBLE (old_root, false);
}
tty->top_frame = frame;
/* FIXME: Why is it correct to set FrameCols/Rows? */
if (!FRAME_PARENT_FRAME (f))
{
/* If the new TTY frame changed dimensions, we need to
resync term.c's idea of the frame size with the new
frame's data. */
if (FRAME_COLS (f) != FrameCols (tty))
FrameCols (tty) = FRAME_COLS (f);
if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
FrameRows (tty) = FRAME_TOTAL_LINES (f);
}
}
tty->top_frame = frame;
}
sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window));
@ -1599,10 +1782,36 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
(select-window (frame-root-window (make-frame))) doesn't end up
with your typing being interpreted in the new frame instead of
the one you're actually typing in. */
#ifdef HAVE_WINDOW_SYSTEM
if (!frame_ancestor_p (f, sf))
#endif
internal_last_event_frame = Qnil;
/* FIXME/tty: I don't understand this. (The comment above is from
Jim BLandy 1993 BTW, and the frame_ancestor_p from 2017.)
Setting the last event frame to nil leads to switch-frame events
being generated even if they normally wouldn't be because the frame
in question equals selected-frame. See the places in keyboard.c
where make_lispy_switch_frame is called.
This leads to problems at least on ttys.
Imagine that we have functions in post-command-hook that use
select-frame in some way (e.g., with-selected-window). Let these
functions select different frames during the execution of
post-command-hook in command_loop_1. Setting
internal_last_event_frame to nil here makes these select-frame
calls (potentially and in reality) generate switch-frame events.
(But only in one direction (frame_ancestor_p), which I also don't
understand).
These switch-frame events form an endless loop in
command_loop_1. It runs post-command-hook, which generates
switch-frame events, which command_loop_1 finds (bound to '#ignore)
and executes, which again runs post-command-hook etc., ad
infinitum.
Let's not do that for now on ttys. */
if (!is_tty_frame (f))
if (!frame_ancestor_p (f, sf))
internal_last_event_frame = Qnil;
return frame;
}
@ -1719,7 +1928,6 @@ parent window is the window-system's root window) or an embedded window
return Qnil;
}
#ifdef HAVE_WINDOW_SYSTEM
bool
frame_ancestor_p (struct frame *af, struct frame *df)
{
@ -1735,7 +1943,6 @@ frame_ancestor_p (struct frame *af, struct frame *df)
return false;
}
#endif
DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
2, 2, 0,
@ -1746,15 +1953,10 @@ 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.
@ -2015,7 +2217,9 @@ other_frames (struct frame *f, bool invisible, bool force)
&& (invisible || NILP (get_frame_param (f1, Qdelete_before)))
/* For invisibility and normal deletions, at least one
visible or iconified frame must remain (Bug#26682). */
&& (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
&& (FRAME_VISIBLE_P (f1)
|| is_tty_frame (f1)
|| FRAME_ICONIFIED_P (f1)
|| (!invisible
&& (force
/* Allow deleting the terminal frame when at
@ -2276,7 +2480,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
fset_root_window (f, Qnil);
Vframe_list = Fdelq (frame, Vframe_list);
SET_FRAME_VISIBLE (f, 0);
SET_FRAME_VISIBLE (f, false);
/* Allow the vector of menu bar contents to be freed in the next
garbage collection. The frame object itself may not be garbage
@ -2862,6 +3066,12 @@ If omitted, FRAME defaults to the currently selected frame. */)
if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, true);
if (is_tty_frame (f))
{
SET_FRAME_VISIBLE (f, true);
tty_raise_lower_frame (f, true);
}
make_frame_visible_1 (f->root_window);
/* Make menu bar update for the Buffers and Frames menus. */
@ -2912,6 +3122,12 @@ displayed in the terminal. */)
if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false);
/* The ELisp manual says that this "usually" makes child frames
invisible, too, but without saying when not. Since users can't
rely on this, it's not implemented. */
if (is_tty_frame (f))
SET_FRAME_VISIBLE (f, false);
/* Make menu bar update for the Buffers and Frames menus. */
windows_or_buffers_changed = 16;
@ -2971,10 +3187,13 @@ currently being displayed on the terminal. */)
(Lisp_Object frame)
{
CHECK_LIVE_FRAME (frame);
struct frame *f = XFRAME (frame);
if (FRAME_VISIBLE_P (XFRAME (frame)))
if (FRAME_VISIBLE_P (f))
return Qt;
if (FRAME_ICONIFIED_P (XFRAME (frame)))
else if (is_tty_root_frame (f))
return Qt;
if (FRAME_ICONIFIED_P (f))
return Qicon;
return Qnil;
}
@ -3006,12 +3225,7 @@ doesn't support multiple overlapping frames, this function selects FRAME. */)
XSETFRAME (frame, f);
if (FRAME_TERMCAP_P (f))
/* On a text terminal select FRAME. */
Fselect_frame (frame, Qnil);
else
/* Do like the documentation says. */
Fmake_frame_visible (frame);
Fmake_frame_visible (frame);
if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
(*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, true);
@ -3310,6 +3524,15 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
val = old_val;
}
/* Re-parenting is currently not implemented when changing a root
frame to a child frame or vice versa. */
if (is_tty_frame (f) && EQ (prop, Qparent_frame))
{
if (NILP (f->parent_frame) != NILP (val))
error ("Making a root frame a child or vice versa is not supported");
f->parent_frame = val;
}
/* The tty color needed to be set before the frame's parameter
alist was updated with the new value. This is not true any more,
but we still do this test early on. */
@ -3433,13 +3656,10 @@ If FRAME is omitted or nil, return information on the currently selected frame.
else
#endif
{
/* This ought to be correct in f->param_alist for an X frame. */
Lisp_Object lines;
XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
store_in_alist (&alist, Qmenu_bar_lines, lines);
XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f));
store_in_alist (&alist, Qtab_bar_lines, lines);
store_in_alist (&alist, Qmenu_bar_lines, make_fixnum (FRAME_MENU_BAR_LINES (f)));
store_in_alist (&alist, Qtab_bar_lines, make_fixnum (FRAME_TAB_BAR_LINES (f)));
store_in_alist (&alist, Qvisibility, FRAME_VISIBLE_P (f) ? Qt : Qnil);
store_in_alist (&alist, Qno_accept_focus, FRAME_NO_ACCEPT_FOCUS (f) ? Qt : Qnil);
}
return alist;
@ -3517,7 +3737,6 @@ If FRAME is nil, describe the currently selected frame. */)
return value;
}
DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
Smodify_frame_parameters, 2, 2, 0,
doc: /* Modify FRAME according to new values of its parameters in ALIST.
@ -3555,6 +3774,7 @@ list, but are otherwise ignored. */)
USE_SAFE_ALLOCA;
SAFE_ALLOCA_LISP (parms, 2 * length);
values = parms + length;
Lisp_Object params = alist;
/* Extract parm names and values into those vectors. */
@ -3580,6 +3800,31 @@ list, but are otherwise ignored. */)
update_face_from_frame_parameter (f, prop, val);
}
if (is_tty_child_frame (f))
{
int x = tty_child_pos_param (f, Qleft, params, f->left_pos);
int y = tty_child_pos_param (f, Qtop, params, f->top_pos);
if (x != f->left_pos || y != f->top_pos)
{
f->left_pos = x;
f->top_pos = y;
SET_FRAME_GARBAGED (root_frame (f));
}
int w = tty_child_size_param (f, Qwidth, params, f->total_cols);
int h = tty_child_size_param (f, Qheight, params, f->total_lines);
if (w != f->total_cols || h != f->total_lines)
change_frame_size (f, w, h, false, false, false);
Lisp_Object visible = Fassq (Qvisibility, params);
if (CONSP (visible))
SET_FRAME_VISIBLE (f, !NILP (Fcdr (visible)));
Lisp_Object no_special = Fassq (Qno_special_glyphs, params);
if (CONSP (no_special))
FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (Fcdr (no_special));
}
SAFE_FREE ();
}
return Qnil;
@ -3927,6 +4172,11 @@ bottom edge of FRAME's display. */)
(void) yval;
#endif
}
else if (is_tty_child_frame (f))
{
f->left_pos = xval;
f->top_pos = yval;
}
return Qt;
}
@ -3984,9 +4234,9 @@ multiplied to find the real number of pixels. */)
/* Connect the frame-parameter names for frames to the ways of passing
the parameter values to the window system.
The name of a parameter, as a Lisp symbol, has a
`frame-parameter-pos' property which is an integer in Lisp that is
an index in this table. */
The name of a parameter, a Lisp symbol, has an `x-frame-parameter'
property which is its index in this table. This is initialized in
syms_of_frame. */
struct frame_parm_table {
const char *name;
@ -3997,13 +4247,13 @@ static const struct frame_parm_table frame_parms[] =
{
{"auto-raise", SYMBOL_INDEX (Qauto_raise)},
{"auto-lower", SYMBOL_INDEX (Qauto_lower)},
{"background-color", -1},
{"background-color", SYMBOL_INDEX (Qbackground_color)},
{"border-color", SYMBOL_INDEX (Qborder_color)},
{"border-width", SYMBOL_INDEX (Qborder_width)},
{"cursor-color", SYMBOL_INDEX (Qcursor_color)},
{"cursor-type", SYMBOL_INDEX (Qcursor_type)},
{"font", -1},
{"foreground-color", -1},
{"font", SYMBOL_INDEX (Qfont)},
{"foreground-color", SYMBOL_INDEX (Qforeground_color)},
{"icon-name", SYMBOL_INDEX (Qicon_name)},
{"icon-type", SYMBOL_INDEX (Qicon_type)},
{"child-frame-border-width", SYMBOL_INDEX (Qchild_frame_border_width)},
@ -4238,6 +4488,29 @@ frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
}
}
/* Handle frame parameter change with frame parameter handler.
F is the frame whose frame parameter was changed.
PROP is the name of the frame parameter.
VAL and OLD_VALUE are the current and the old value of the
frame parameter. */
static void
handle_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val,
Lisp_Object old_value)
{
Lisp_Object param_index = Fget (prop, Qx_frame_parameter);
if (FIXNATP (param_index) && XFIXNAT (param_index) < ARRAYELTS (frame_parms))
{
if (FRAME_RIF (f))
{
frame_parm_handler handler
= FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (param_index)];
if (handler)
handler (f, val, old_value);
}
}
}
/* Change the parameters of frame F as specified by ALIST.
If a parameter is not specially recognized, do nothing special;
otherwise call the `gui_set_...' function for that parameter.
@ -4379,17 +4652,9 @@ gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
}
else
{
Lisp_Object param_index, old_value;
old_value = get_frame_param (f, prop);
Lisp_Object old_value = get_frame_param (f, prop);
store_frame_param (f, prop, val);
param_index = Fget (prop, Qx_frame_parameter);
if (FIXNATP (param_index)
&& XFIXNAT (param_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
(*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value);
handle_frame_param (f, prop, val, old_value);
if (!default_parameter && EQ (prop, Qfont))
/* The user manually specified the `font' frame parameter.
@ -4708,14 +4973,7 @@ gui_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_va
/* Apply the new gamma value to the frame background. */
bgcolor = Fassq (Qbackground_color, f->param_alist);
if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
{
Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
if (FIXNATP (parm_index)
&& XFIXNAT (parm_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
(*FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
(f, bgcolor, Qnil);
}
handle_frame_param (f, Qbackground_color, bgcolor, Qnil);
clear_face_cache (true); /* FIXME: Why of all frames? */
fset_redisplay (f);
@ -6453,17 +6711,13 @@ syms_of_frame (void)
DEFSYM (Quse_frame_synchronization, "use-frame-synchronization");
DEFSYM (Qfont_parameter, "font-parameter");
{
int i;
for (i = 0; i < ARRAYELTS (frame_parms); i++)
{
Lisp_Object v = (frame_parms[i].sym < 0
? intern_c_string (frame_parms[i].name)
: builtin_lisp_symbol (frame_parms[i].sym));
Fput (v, Qx_frame_parameter, make_fixnum (i));
}
}
for (int i = 0; i < ARRAYELTS (frame_parms); i++)
{
int sym = frame_parms[i].sym;
eassert (sym >= 0 && sym < ARRAYELTS (lispsym));
Lisp_Object v = builtin_lisp_symbol (sym);
Fput (v, Qx_frame_parameter, make_fixnum (i));
}
#ifdef HAVE_WINDOW_SYSTEM
DEFVAR_LISP ("x-resource-name", Vx_resource_name,

View file

@ -161,10 +161,8 @@ struct frame
Usually it is nil. */
Lisp_Object title;
#if defined (HAVE_WINDOW_SYSTEM)
/* This frame's parent frame, if it has one. */
Lisp_Object parent_frame;
#endif /* HAVE_WINDOW_SYSTEM */
/* Last device to move over this frame. Any value that isn't a
string means the "Virtual core pointer". */
@ -385,15 +383,8 @@ struct frame
zero if the frame has been made invisible without an icon. */
/* Nonzero if the frame is currently displayed; we check
it to see if we should bother updating the frame's contents.
On ttys and on Windows NT/9X, to avoid wasting effort updating
visible frames that are actually completely obscured by other
windows on the display, we bend the meaning of visible slightly:
if equal to 2, then the frame is obscured - we still consider
it to be "visible" as seen from lisp, but we don't bother
updating it. */
unsigned visible : 2;
it to see if we should bother updating the frame's contents. */
unsigned visible : 1;
/* True if the frame is currently iconified. Do not
set this directly, use SET_FRAME_ICONIFIED instead. */
@ -451,6 +442,13 @@ struct frame
This must be the same as the terminal->type. */
ENUM_BF (output_method) output_method : 4;
/* True if this is an undecorated frame. */
bool_bf undecorated : 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;
#ifdef HAVE_WINDOW_SYSTEM
/* True if this frame is a tooltip frame. */
bool_bf tooltip : 1;
@ -465,10 +463,7 @@ struct frame
/* Nonzero if we should actually display horizontal scroll bars on this frame. */
bool_bf horizontal_scroll_bars : 1;
/* True if this is an undecorated frame. */
bool_bf undecorated : 1;
#ifndef HAVE_NTGUI
# ifndef HAVE_NTGUI
/* True if this is an override_redirect frame. */
bool_bf override_redirect : 1;
#endif
@ -480,17 +475,13 @@ struct frame
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 */
/* Non-zero if display of truncation and continuation glyphs outside
the fringes is suppressed. */
bool_bf no_special_glyphs : 1;
#endif /* HAVE_WINDOW_SYSTEM */
/* True means set_window_size_hook requests can be processed for
this frame. */
@ -736,7 +727,10 @@ struct frame
#ifdef HAVE_TEXT_CONVERSION
/* Text conversion state used by certain input methods. */
struct text_conversion_state conversion;
#endif
# endif
/* Z-order of child frames. */
int z_order;
} GCALIGNED_STRUCT;
/* Most code should use these functions to set Lisp fields in struct frame. */
@ -1017,9 +1011,9 @@ default_pixels_per_inch_y (void)
does not have FRAME_DISPLAY_INFO. */
#ifdef HAVE_WINDOW_SYSTEM
#ifndef HAVE_ANDROID
# define MOUSE_HL_INFO(F) \
# define MOUSE_HL_INFO(F) \
(FRAME_WINDOW_P (F) \
? &FRAME_DISPLAY_INFO(F)->mouse_highlight \
? &FRAME_DISPLAY_INFO (F)->mouse_highlight \
: &(F)->output_data.tty->display_info->mouse_highlight)
#else
/* There is no "struct tty_output" on Android at all. */
@ -1172,9 +1166,6 @@ default_pixels_per_inch_y (void)
&& FRAME_X_VISIBLE (f)))
#endif
/* True if frame F is currently visible but hidden. */
#define FRAME_OBSCURED_P(f) ((f)->visible > 1)
/* True if frame F is currently iconified. */
#define FRAME_ICONIFIED_P(f) (f)->iconified
@ -1239,21 +1230,23 @@ default_pixels_per_inch_y (void)
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) (f), 0)
#endif /* HAVE_WINDOW_SYSTEM */
#if defined (HAVE_WINDOW_SYSTEM)
INLINE struct frame *
FRAME_PARENT_FRAME (struct frame *f)
{
return NILP (f->parent_frame) ? NULL : XFRAME (f->parent_frame);
}
#define FRAME_UNDECORATED(f) ((f)->undecorated)
#if defined (HAVE_WINDOW_SYSTEM)
#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_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
#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)
@ -1266,13 +1259,10 @@ default_pixels_per_inch_y (void)
#define FRAME_NS_TRANSPARENT_TITLEBAR(f) ((f)->ns_transparent_titlebar)
#endif
#else /* not HAVE_WINDOW_SYSTEM */
#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_NO_SPECIAL_GLYPHS(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)
@ -1280,6 +1270,8 @@ default_pixels_per_inch_y (void)
#define FRAME_TOOLTIP_P(f) ((void) f, false)
#endif /* HAVE_WINDOW_SYSTEM */
#define FRAME_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
/* Whether horizontal scroll bars are currently enabled for frame F. */
#if USE_HORIZONTAL_SCROLL_BARS
#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
@ -1441,9 +1433,8 @@ extern bool frame_garbaged;
if some changes were applied to it while it wasn't visible (and hence
wasn't redisplayed). */
INLINE void
SET_FRAME_VISIBLE (struct frame *f, int v)
SET_FRAME_VISIBLE (struct frame *f, bool v)
{
eassert (0 <= v && v <= 2);
if (v)
{
if (v == 1 && f->visible != 1)
@ -1500,13 +1491,14 @@ extern struct frame *decode_any_frame (Lisp_Object);
extern struct frame *make_initial_frame (void);
extern struct frame *make_frame (bool);
#ifdef HAVE_WINDOW_SYSTEM
extern struct frame *make_minibuffer_frame (void);
extern struct frame *make_frame_without_minibuffer (Lisp_Object,
struct kboard *,
Lisp_Object);
extern bool display_available (void);
#endif
struct frame *make_minibuffer_frame (void);
struct frame *
make_frame_without_minibuffer (Lisp_Object mini_window,
KBOARD *kb, Lisp_Object display);
INLINE bool
window_system_available (struct frame *f)
{
@ -1518,6 +1510,8 @@ window_system_available (struct frame *f)
}
extern WINDOW_SYSTEM_RETURN void check_window_system (struct frame *);
void check_tty (struct frame *f);
struct frame *decode_tty_frame (Lisp_Object frame);
extern void frame_make_pointer_invisible (struct frame *);
extern void frame_make_pointer_visible (struct frame *);
extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
@ -1613,15 +1607,11 @@ FRAME_CHILD_FRAME_BORDER_WIDTH (struct frame *f)
INLINE int
FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
{
#ifdef HAVE_WINDOW_SYSTEM
return (FRAME_PARENT_FRAME(f)
? (FRAME_CHILD_FRAME_BORDER_WIDTH(f) >= 0
? FRAME_CHILD_FRAME_BORDER_WIDTH(f)
: frame_dimension (f->internal_border_width))
: frame_dimension (f->internal_border_width));
#else
return frame_dimension (f->internal_border_width);
#endif
}
/* Pixel-size of window divider lines. */
@ -1876,7 +1866,6 @@ extern Lisp_Object gui_display_get_resource (Display_Info *,
extern void set_frame_menubar (struct frame *f, bool deep_p);
extern void frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
extern void free_frame_menubar (struct frame *);
extern bool frame_ancestor_p (struct frame *af, struct frame *df);
extern enum internal_border_part frame_internal_border_part (struct frame *f, int x, int y);
#if defined HAVE_X_WINDOWS
@ -1903,6 +1892,8 @@ gui_set_bitmap_icon (struct frame *f)
#endif /* !HAVE_NS */
#endif /* HAVE_WINDOW_SYSTEM */
extern bool frame_ancestor_p (struct frame *af, struct frame *df);
INLINE void
flush_frame (struct frame *f)
{

View file

@ -5415,7 +5415,7 @@ static const char *const lispy_kana_keys[] =
/* You'll notice that this table is arranged to be conveniently
indexed by X Windows keysym values. */
#ifdef HAVE_NS
#if defined HAVE_NS || !defined HAVE_WINDOW_SYSTEM
/* FIXME: Why are we using X11 keysym values for NS? */
static
#endif

View file

@ -913,7 +913,11 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
XWINDOW (minibuf_window)->cursor.hpos = 0;
XWINDOW (minibuf_window)->cursor.x = 0;
XWINDOW (minibuf_window)->must_be_updated_p = true;
update_frame (XFRAME (selected_frame), true, true);
struct frame *sf = XFRAME (selected_frame);
update_frame (sf, true, true);
if (is_tty_frame (sf))
combine_updates_for_frame (sf, true, true);
#ifndef HAVE_NTGUI
flush_frame (XFRAME (XWINDOW (minibuf_window)->frame));
#else

View file

@ -3351,7 +3351,7 @@ internalBorderWidth or internalBorder (which is what xterm calls
[nswindow orderFront: NSApp];
[nswindow display];
SET_FRAME_VISIBLE (tip_f, 1);
SET_FRAME_VISIBLE (tip_f, true);
unblock_input ();
goto start_timer;
@ -3534,7 +3534,7 @@ internalBorderWidth or internalBorder (which is what xterm calls
[nswindow orderFront: NSApp];
[nswindow display];
SET_FRAME_VISIBLE (tip_f, YES);
SET_FRAME_VISIBLE (tip_f, true);
FRAME_PIXEL_WIDTH (tip_f) = width;
FRAME_PIXEL_HEIGHT (tip_f) = height;
unblock_input ();

View file

@ -1505,7 +1505,7 @@ -(void)remove
EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
EmacsWindow *window = (EmacsWindow *)[view window];
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_VISIBLE (f, true);
ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f));
/* Making a new frame from a fullscreen frame will make the new frame
@ -1550,7 +1550,7 @@ Hide the window (X11 semantics)
check_window_system (f);
view = FRAME_NS_VIEW (f);
[[view window] orderOut: NSApp];
SET_FRAME_VISIBLE (f, 0);
SET_FRAME_VISIBLE (f, false);
SET_FRAME_ICONIFIED (f, 0);
}

View file

@ -366,7 +366,7 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
eassert (copy_from[k] >= 0 && copy_from[k] < window_size);
/* Perform the row swizzling. */
mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
mirrored_line_dance (frame, unchanged_at_top, window_size,
copy_from, retained_p);
/* Some sanity checks if GLYPH_DEBUG is defined. */
@ -780,7 +780,7 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
copy_from[i] gives the original line to copy to I, and
retained_p[copy_from[i]] is zero if line I in the new display is
empty. */
mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
mirrored_line_dance (frame, unchanged_at_top, window_size,
copy_from, retained_p);
if (terminal_window_p)

View file

@ -65,11 +65,9 @@ static int been_here = -1;
#ifndef HAVE_ANDROID
static void tty_set_scroll_region (struct frame *f, int start, int stop);
static void turn_on_face (struct frame *, int face_id);
static void turn_off_face (struct frame *, int face_id);
static void turn_on_face (struct frame *f, struct face *face);
static void turn_off_face (struct frame *f, struct face *face);
static void tty_turn_off_highlight (struct tty_display_info *);
static void tty_show_cursor (struct tty_display_info *);
static void tty_hide_cursor (struct tty_display_info *);
static void tty_background_highlight (struct tty_display_info *tty);
static void clear_tty_hooks (struct terminal *terminal);
static void set_tty_hooks (struct terminal *terminal);
@ -336,7 +334,7 @@ tty_toggle_highlight (struct tty_display_info *tty)
/* Make cursor invisible. */
static void
void
tty_hide_cursor (struct tty_display_info *tty)
{
if (tty->cursor_hidden == 0)
@ -353,7 +351,7 @@ tty_hide_cursor (struct tty_display_info *tty)
/* Ensure that cursor is visible. */
static void
void
tty_show_cursor (struct tty_display_info *tty)
{
if (tty->cursor_hidden)
@ -753,18 +751,12 @@ encode_terminal_code (struct glyph *src, int src_len,
static void
tty_write_glyphs (struct frame *f, struct glyph *string, int len)
{
unsigned char *conversion_buffer;
struct coding_system *coding;
int n, stringlen;
struct tty_display_info *tty = FRAME_TTY (f);
tty_turn_off_insert (tty);
tty_hide_cursor (tty);
/* Don't dare write in last column of bottom line, if Auto-Wrap,
since that would scroll the whole frame on some terminals. */
if (AutoWrap (tty)
&& curY (tty) + 1 == FRAME_TOTAL_LINES (f)
&& (curX (tty) + len) == FRAME_COLS (f))
@ -777,29 +769,34 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
/* If terminal_coding does any conversion, use it, otherwise use
safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
because it always return 1 if the member src_multibyte is 1. */
coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
struct coding_system *coding
= (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
/* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
for (stringlen = len; stringlen != 0; stringlen -= n)
for (int stringlen = len, n; stringlen; stringlen -= n, string += n)
{
/* Identify a run of glyphs with the same face. */
int face_id = string->face_id;
struct frame *face_id_frame = string->frame;
for (n = 1; n < stringlen; ++n)
if (string[n].face_id != face_id)
if (string[n].face_id != face_id || string[n].frame != face_id_frame)
break;
/* Turn appearance modes of the face of the run on. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
struct face *face = FACE_FROM_ID (face_id_frame, face_id);
turn_on_face (f, face);
if (n == stringlen)
/* This is the last run. */
coding->mode |= CODING_MODE_LAST_BLOCK;
conversion_buffer = encode_terminal_code (string, n, coding);
unsigned char *conversion_buffer
= encode_terminal_code (string, n, coding);
if (coding->produced > 0)
{
block_input ();
@ -809,10 +806,9 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
unblock_input ();
}
string += n;
/* Turn appearance modes off. */
turn_off_face (f, face_id);
turn_off_face (f, face);
tty_turn_off_highlight (tty);
}
@ -822,8 +818,8 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
#ifndef DOS_NT
static void
tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
register int len, register int face_id)
tty_write_glyphs_with_face (struct frame *f, struct glyph *string,
int len, struct face *face)
{
unsigned char *conversion_buffer;
struct coding_system *coding;
@ -856,7 +852,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
/* Turn appearance modes of the face. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
turn_on_face (f, face);
coding->mode |= CODING_MODE_LAST_BLOCK;
conversion_buffer = encode_terminal_code (string, len, coding);
@ -871,7 +867,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
}
/* Turn appearance modes off. */
turn_off_face (f, face_id);
turn_off_face (f, face);
tty_turn_off_highlight (tty);
cmcheckmagic (tty);
@ -919,6 +915,7 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
while (len-- > 0)
{
struct face *face = NULL;
OUTPUT1_IF (tty, tty->TS_ins_char);
if (!start)
{
@ -928,7 +925,10 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
else
{
tty_highlight_if_desired (tty);
turn_on_face (f, start->face_id);
int face_id = start->face_id;
struct frame *face_id_frame = start->frame;
face = FACE_FROM_ID (face_id_frame, face_id);
turn_on_face (f, face);
glyph = start;
++start;
/* We must open sufficient space for a character which
@ -957,9 +957,9 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
}
OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
if (start)
if (face)
{
turn_off_face (f, glyph->face_id);
turn_off_face (f, face);
tty_turn_off_highlight (tty);
}
}
@ -1542,6 +1542,7 @@ append_glyph (struct it *it)
glyph->type = CHAR_GLYPH;
glyph->pixel_width = 1;
glyph->u.ch = it->char_to_display;
glyph->frame = it->f;
glyph->face_id = it->face_id;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
@ -1769,6 +1770,7 @@ append_composite_glyph (struct it *it)
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
glyph->frame = it->f;
glyph->face_id = it->face_id;
glyph->padding_p = false;
glyph->charpos = CHARPOS (it->position);
@ -1855,6 +1857,7 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str)
glyph->pixel_width = 1;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
glyph->frame = it->f;
glyph->face_id = face_id;
glyph->padding_p = false;
glyph->charpos = CHARPOS (it->position);
@ -1981,9 +1984,8 @@ produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
FACE_ID is a realized face ID number, in the face cache. */
static void
turn_on_face (struct frame *f, int face_id)
turn_on_face (struct frame *f, struct face *face)
{
struct face *face = FACE_FROM_ID (f, face_id);
unsigned long fg = face->foreground;
unsigned long bg = face->background;
struct tty_display_info *tty = FRAME_TTY (f);
@ -2064,9 +2066,8 @@ turn_on_face (struct frame *f, int face_id)
/* Turn off appearances of face FACE_ID on tty frame F. */
static void
turn_off_face (struct frame *f, int face_id)
turn_off_face (struct frame *f, struct face *face)
{
struct face *face = FACE_FROM_ID (f, face_id);
struct tty_display_info *tty = FRAME_TTY (f);
if (tty->TS_exit_attribute_mode)
@ -2399,8 +2400,10 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
t->display_info.tty->output = 0;
if (FRAMEP (t->display_info.tty->top_frame))
SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
{
struct frame *top = XFRAME (t->display_info.tty->top_frame);
SET_FRAME_VISIBLE (root_frame (top), false);
}
}
/* Clear display hooks to prevent further output. */
@ -2472,7 +2475,8 @@ frame's terminal). */)
if (FRAMEP (t->display_info.tty->top_frame))
{
struct frame *f = XFRAME (t->display_info.tty->top_frame);
struct frame *top = XFRAME (t->display_info.tty->top_frame);
struct frame *f = root_frame (top);
int width, height;
int old_height = FRAME_COLS (f);
int old_width = FRAME_TOTAL_LINES (f);
@ -2482,7 +2486,7 @@ frame's terminal). */)
get_tty_size (fileno (t->display_info.tty->input), &width, &height);
if (width != old_width || height != old_height)
change_frame_size (f, width, height, false, false, false);
SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
SET_FRAME_VISIBLE (f, true);
}
set_tty_hooks (t);
@ -2563,22 +2567,24 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct tty_display_info *tty = FRAME_TTY (f);
int face_id = tty->mouse_highlight.mouse_face_face_id;
int save_x, save_y, pos_x, pos_y;
if (end_hpos >= row->used[TEXT_AREA])
nglyphs = row->used[TEXT_AREA] - start_hpos;
pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
int pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
int pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
/* Save current cursor coordinates. */
save_y = curY (tty);
save_x = curX (tty);
int save_y = curY (tty);
int save_x = curX (tty);
cursor_to (f, pos_y, pos_x);
if (draw == DRAW_MOUSE_FACE)
tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
nglyphs, face_id);
{
struct glyph *glyph = row->glyphs[TEXT_AREA] + start_hpos;
struct face *face = FACE_FROM_ID (f, face_id);
tty_write_glyphs_with_face (f, glyph, nglyphs, face);
}
else if (draw == DRAW_NORMAL_TEXT)
write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
@ -3115,9 +3121,7 @@ save_and_enable_current_matrix (struct frame *f)
static void
restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
{
int i;
for (i = 0; i < saved->nrows; ++i)
for (int i = 0; i < saved->nrows; ++i)
{
struct glyph_row *from = saved->rows + i;
struct glyph_row *to = f->desired_matrix->rows + i;
@ -3127,7 +3131,23 @@ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
to->used[TEXT_AREA] = from->used[TEXT_AREA];
to->enabled_p = from->enabled_p;
to->hash = from->hash;
bool need_new_hash = false;
for (int x = 0; x < f->desired_matrix->matrix_w; ++x)
{
struct glyph *glyph = to->glyphs[0] + x;
if (!FRAME_LIVE_P (glyph->frame))
{
glyph->frame = f;
glyph->face_id = DEFAULT_FACE_ID;
need_new_hash = true;
}
}
if (need_new_hash)
to->hash = row_hash (to);
else
to->hash = from->hash;
}
}
@ -3969,7 +3989,7 @@ tty_free_frame_resources (struct frame *f)
#endif
#ifndef HAVE_ANDROID
@ -4044,6 +4064,8 @@ set_tty_hooks (struct terminal *terminal)
terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
terminal->delete_frame_hook = &tty_free_frame_resources;
terminal->delete_terminal_hook = &delete_tty;
terminal->frame_raise_lower_hook = tty_raise_lower_frame;
/* Other hooks are NULL by default. */
}
@ -4714,6 +4736,186 @@ delete_tty (struct terminal *terminal)
#endif
/* Return geometric attributes of FRAME. According to the value of
ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the
native edges of FRAME (Qnative_edges), or the inner edges of frame
(Qinner_edges). Any other value means to return the geometry as
returned by Fx_frame_geometry. */
static Lisp_Object
tty_frame_geometry (Lisp_Object frame, Lisp_Object attribute)
{
struct frame *f = decode_live_frame (frame);
if (FRAME_INITIAL_P (f) || !FRAME_TTY (f))
return Qnil;
int native_width = f->pixel_width;
int native_height = f->pixel_height;
eassert (FRAME_PARENT_FRAME (f) || (f->left_pos == 0 && f->top_pos == 0));
int outer_left = f->left_pos;
int outer_top = f->top_pos;
int outer_right = outer_left + native_width;
int outer_bottom = outer_top + native_height;
int native_left = outer_left;
int native_top = outer_top;
int native_right = outer_right;
int native_bottom = outer_bottom;
int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
int inner_left = native_left + internal_border_width;
int inner_top = native_top + internal_border_width;
int inner_right = native_right - internal_border_width;
int inner_bottom = native_bottom - internal_border_width;
int menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
inner_top += menu_bar_height;
int menu_bar_width = menu_bar_height ? native_width : 0;
int tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
int tab_bar_width = (tab_bar_height
? native_width - 2 * internal_border_width
: 0);
inner_top += tab_bar_height;
int tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
int tool_bar_width = (tool_bar_height
? native_width - 2 * internal_border_width
: 0);
/* Subtract or add to the inner dimensions based on the tool bar
position. */
if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
inner_top += tool_bar_height;
else
inner_bottom -= tool_bar_height;
/* Construct list. */
if (EQ (attribute, Qouter_edges))
return list4i (outer_left, outer_top, outer_right, outer_bottom);
else if (EQ (attribute, Qnative_edges))
return list4i (native_left, native_top, native_right, native_bottom);
else if (EQ (attribute, Qinner_edges))
return list4i (inner_left, inner_top, inner_right, inner_bottom);
else
return list (Fcons (Qouter_position, Fcons (make_fixnum (outer_left),
make_fixnum (outer_top))),
Fcons (Qouter_size,
Fcons (make_fixnum (outer_right - outer_left),
make_fixnum (outer_bottom - outer_top))),
Fcons (Qouter_border_width, make_fixnum (0)),
Fcons (Qexternal_border_size,
Fcons (make_fixnum (0), make_fixnum (0))),
Fcons (Qtitle_bar_size,
Fcons (make_fixnum (0), make_fixnum (0))),
Fcons (Qmenu_bar_external, Qnil),
Fcons (Qmenu_bar_size,
Fcons (make_fixnum (menu_bar_width),
make_fixnum (menu_bar_height))),
Fcons (Qtab_bar_size,
Fcons (make_fixnum (tab_bar_width),
make_fixnum (tab_bar_height))),
Fcons (Qtool_bar_external, Qnil),
Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
Fcons (Qtool_bar_size,
Fcons (make_fixnum (tool_bar_width),
make_fixnum (tool_bar_height))),
Fcons (Qinternal_border_width,
make_fixnum (internal_border_width)));
}
DEFUN ("tty-frame-geometry", Ftty_frame_geometry, Stty_frame_geometry, 0, 1, 0,
doc: /* Return geometric attributes of terminal frame FRAME.
See also `frame-geometry'. */)
(Lisp_Object frame)
{
return tty_frame_geometry (frame, Qnil);
}
DEFUN ("tty-frame-edges", Ftty_frame_edges, Stty_frame_edges, 0, 2, 0,
doc: /* Return coordinates of FRAME's edges.
See also `frame-edges'. */)
(Lisp_Object frame, Lisp_Object type)
{
if (!EQ (type, Qouter_edges) && !EQ (type, Qinner_edges))
type = Qnative_edges;
return tty_frame_geometry (frame, type);
}
DEFUN ("tty-frame-list-z-order", Ftty_frame_list_z_order,
Stty_frame_list_z_order, 0, 1, 0,
doc: /* Return list of Emacs's frames, in Z (stacking) order.
See also `frame-list-z-order'. */)
(Lisp_Object frame)
{
struct frame *f = decode_tty_frame (frame);
Lisp_Object frames = frames_in_reverse_z_order (f, true);
return Fnreverse (frames);
}
DEFUN ("tty-frame-restack", Ftty_frame_restack,
Stty_frame_restack, 2, 3, 0,
doc: /* Restack FRAME1 below FRAME2 on terminals.
. See also `frame-restack'. */)
(Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
{
/* FIXME/tty: tty-frame-restack implementation. */
error ("tty-frame-restack is not implemented");
return Qnil;
}
static void
tty_display_dimension (Lisp_Object frame, int *width, int *height)
{
if (!FRAMEP (frame))
frame = Fselected_frame ();
struct frame *f = XFRAME (frame);
switch (f->output_method)
{
case output_initial:
*width = 80;
*height = 25;
break;
case output_termcap:
*width = FrameCols (FRAME_TTY (f));
*height = FrameRows (FRAME_TTY (f));
break;
case output_x_window:
case output_msdos_raw:
case output_w32:
case output_ns:
case output_pgtk:
case output_haiku:
case output_android:
default:
emacs_abort ();
break;
}
}
DEFUN ("tty-display-pixel-width", Ftty_display_pixel_width,
Stty_display_pixel_width, 0, 1, 0,
doc: /* Return the width of DISPLAY's screen in pixels.
. See also `display-pixel-width'. */)
(Lisp_Object display)
{
int width, height;
tty_display_dimension (display, &width, &height);
return make_fixnum (width);
}
DEFUN ("tty-display-pixel-height", Ftty_display_pixel_height,
Stty_display_pixel_height, 0, 1, 0,
doc: /* Return the height of DISPLAY's screen in pixels.
See also `display-pixel-height'. */)
(Lisp_Object display)
{
int width, height;
tty_display_dimension (display, &width, &height);
return make_fixnum (height);
}
void
syms_of_term (void)
{
@ -4770,6 +4972,13 @@ trigger redisplay. */);
defsubr (&Sgpm_mouse_stop);
#endif /* HAVE_GPM */
defsubr (&Stty_frame_geometry);
defsubr (&Stty_frame_edges);
defsubr (&Stty_frame_list_z_order);
defsubr (&Stty_frame_restack);
defsubr (&Stty_display_pixel_width);
defsubr (&Stty_display_pixel_height);
#if !defined DOS_NT && !defined HAVE_ANDROID
default_orig_pair = NULL;
default_set_foreground = NULL;

View file

@ -974,6 +974,9 @@ extern int cursorY (struct tty_display_info *);
#define cursorY(t) curY(t)
#endif
void tty_hide_cursor (struct tty_display_info *tty);
void tty_show_cursor (struct tty_display_info *tty);
INLINE_HEADER_END
#endif /* EMACS_TERMHOOKS_H */

View file

@ -111,7 +111,8 @@ void
cursor_to (struct frame *f, int vpos, int hpos)
{
if (FRAME_TERMINAL (f)->cursor_to_hook)
(*FRAME_TERMINAL (f)->cursor_to_hook) (f, vpos, hpos);
(*FRAME_TERMINAL (f)->cursor_to_hook) (f, vpos + f->top_pos,
hpos + f->left_pos);
}
/* Similar but don't take any account of the wasted characters. */
@ -120,7 +121,8 @@ void
raw_cursor_to (struct frame *f, int row, int col)
{
if (FRAME_TERMINAL (f)->raw_cursor_to_hook)
(*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row, col);
(*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row + f->top_pos,
col + f->left_pos);
}
/* Erase operations. */

View file

@ -651,7 +651,7 @@ treesit_load_language (Lisp_Object language_symbol,
/* Override the library name and C name, if appropriate. */
Lisp_Object override_name;
Lisp_Object override_c_name;
Lisp_Object override_c_name UNINIT;
bool found_override = treesit_find_override_name (language_symbol,
&override_name,
&override_c_name);

View file

@ -167,6 +167,7 @@ w32con_clear_end_of_line (struct frame *f, int end)
for (i = 0; i < glyphs_len; i++)
{
memcpy (&glyphs[i], &space_glyph, sizeof (struct glyph));
glyphs[i].frame = f;
}
ceol_initialized = TRUE;
}
@ -327,14 +328,19 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
{
/* Identify a run of glyphs with the same face. */
int face_id = string->face_id;
/* Since this is called to deliver the frame glyph matrix to the
glass, some of the glyphs might be from a child frame, which
affects the interpretation of face ID. */
struct frame *face_id_frame = string->frame;
int n;
for (n = 1; n < len; ++n)
if (string[n].face_id != face_id)
if (!(string[n].face_id == face_id
&& string[n].frame == face_id_frame))
break;
/* Turn appearance modes of the face of the run on. */
char_attr = w32_face_attributes (f, face_id);
char_attr = w32_face_attributes (face_id_frame, face_id);
if (n == len)
/* This is the last run. */
@ -530,6 +536,11 @@ static void
w32con_update_end (struct frame * f)
{
SetConsoleCursorPosition (cur_screen, cursor_coords);
if (!XWINDOW (selected_window)->cursor_off_p
&& cursor_coords.X < FRAME_COLS (f))
w32con_show_cursor ();
else
w32con_hide_cursor ();
}
/***********************************************************************

View file

@ -471,8 +471,13 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
DWORD but_change, mask, flags = event->dwEventFlags;
int i;
/* Mouse didn't move unless MOUSE_MOVED says it did. */
struct frame *f = get_frame ();
/* For now, mouse events on child frames are ignored, because the
coordinate conversion is not in place; FIXME. */
if (FRAMEP (f->parent_frame))
return 0;
/* Mouse didn't move unless MOUSE_MOVED says it did. */
f->mouse_moved = 0;
switch (flags)
@ -619,6 +624,10 @@ maybe_generate_resize_event (void)
CONSOLE_SCREEN_BUFFER_INFO info;
struct frame *f = get_frame ();
/* Only resize the root frame. */
if (FRAMEP (f->parent_frame))
return;
GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
/* It is okay to call this unconditionally, since it will do nothing

View file

@ -6405,14 +6405,13 @@ w32_read_socket (struct terminal *terminal,
if (FRAME_TOOLTIP_P (f))
continue;
/* Check "visible" frames and mark each as obscured or not.
/* Check "visible" frames and mark each as visible or not.
Note that visible is nonzero for unobscured and obscured
frames, but zero for hidden and iconified frames. */
if (FRAME_W32_P (f) && FRAME_VISIBLE_P (f))
{
RECT clipbox;
HDC hdc;
bool obscured;
enter_crit ();
/* Query clipping rectangle for the entire window area
@ -6426,29 +6425,11 @@ w32_read_socket (struct terminal *terminal,
ReleaseDC (FRAME_W32_WINDOW (f), hdc);
leave_crit ();
obscured = FRAME_OBSCURED_P (f);
if (clipbox.right == clipbox.left || clipbox.bottom == clipbox.top)
{
/* Frame has become completely obscured so mark as such (we
do this by setting visible to 2 so that FRAME_VISIBLE_P
is still true, but redisplay will skip it). */
SET_FRAME_VISIBLE (f, 2);
if (!obscured)
DebPrint (("frame %p (%s) obscured\n", f, SDATA (f->name)));
}
else
if (!(clipbox.right == clipbox.left
|| clipbox.bottom == clipbox.top))
{
/* Frame is not obscured, so mark it as such. */
SET_FRAME_VISIBLE (f, 1);
if (obscured)
{
SET_FRAME_GARBAGED (f);
DebPrint (("obscured frame %p (%s) found to be visible\n",
f, SDATA (f->name)));
}
}
}
}

View file

@ -943,7 +943,7 @@ redisplay_trace (char const *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vprintf (fmt, ap);
vfprintf (stderr, fmt, ap);
va_end (ap);
}
}
@ -961,7 +961,7 @@ move_trace (char const *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vprintf (fmt, ap);
vfprintf (stderr, fmt, ap);
va_end (ap);
}
}
@ -3350,9 +3350,7 @@ init_iterator (struct it *it, struct window *w,
of the iterator's frame, when set, suppresses their display - by
default for tooltip frames and when set via the 'no-special-glyphs'
frame parameter. */
#ifdef HAVE_WINDOW_SYSTEM
if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
#endif
if (!it->f->no_special_glyphs)
{
if (it->line_wrap == TRUNCATE)
{
@ -13417,18 +13415,22 @@ clear_message (bool current_p, bool last_displayed_p)
message_buf_print = false;
}
/* Clear garbaged frames.
/* Clear garbaged frames. Value is true if current matrices have been
cleared on at least one tty frame. This information is needed to
determine if more than one window has to be updated on ttys, whose
update requires building a frame matrix from window matrices.
This function is used where the old redisplay called
redraw_garbaged_frames which in turn called redraw_frame which in
turn called clear_frame. The call to clear_frame was a source of
flickering. I believe a clear_frame is not necessary. It should
suffice in the new redisplay to invalidate all current matrices,
and ensure a complete redisplay of all windows. */
and ensure a complete redisplay of all windows. */
static void
static bool
clear_garbaged_frames (void)
{
bool current_matrices_cleared = false;
if (frame_garbaged)
{
Lisp_Object tail, frame;
@ -13450,6 +13452,8 @@ clear_garbaged_frames (void)
redraw_frame (f);
else
clear_current_matrices (f);
if (is_tty_frame (f))
current_matrices_cleared = true;
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f)
@ -13464,6 +13468,8 @@ clear_garbaged_frames (void)
frame_garbaged = false;
}
return current_matrices_cleared;
}
@ -13556,7 +13562,11 @@ echo_area_display (bool update_frame_p)
flush_frame (f);
}
else
update_frame (f, true, true);
{
update_frame (f, true, true);
if (is_tty_frame (f))
combine_updates_for_frame (f, true, true);
}
/* If cursor is in the echo area, make sure that the next
redisplay displays the minibuffer, so that the cursor will
@ -17035,16 +17045,22 @@ redisplay_internal (void)
if (face_change)
windows_or_buffers_changed = 47;
struct frame *previous_frame;
if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
&& FRAME_TTY (sf)->previous_frame != sf)
&& (previous_frame = FRAME_TTY (sf)->previous_frame,
previous_frame != sf))
{
/* Since frames on a single ASCII terminal share the same
display area, displaying a different frame means redisplay
the whole thing. */
SET_FRAME_GARBAGED (sf);
if (previous_frame == NULL
|| root_frame (previous_frame) != root_frame (sf))
{
/* Since frames on a single terminal share the same display
area, displaying a different frame means redisplay the
whole thing. */
SET_FRAME_GARBAGED (sf);
#if !defined DOS_NT && !defined HAVE_ANDROID
set_tty_color_mode (FRAME_TTY (sf), sf);
set_tty_color_mode (FRAME_TTY (sf), sf);
#endif
}
FRAME_TTY (sf)->previous_frame = sf;
}
@ -17057,6 +17073,7 @@ redisplay_internal (void)
{
struct frame *f = XFRAME (frame);
/* FRAME_REDISPLAY_P true basically means the frame is visible. */
if (FRAME_REDISPLAY_P (f))
{
++number_of_visible_frames;
@ -17085,7 +17102,7 @@ redisplay_internal (void)
do_pending_window_change (true);
/* Clear frames marked as garbaged. */
clear_garbaged_frames ();
bool current_matrices_cleared = clear_garbaged_frames ();
/* Build menubar and tool-bar items. */
if (NILP (Vmemory_full))
@ -17176,7 +17193,8 @@ redisplay_internal (void)
overlay_arrows_changed_p (true);
consider_all_windows_p = (update_mode_lines
|| windows_or_buffers_changed);
|| windows_or_buffers_changed
|| current_matrices_cleared);
#define AINC(a,i) \
{ \
@ -17200,7 +17218,6 @@ redisplay_internal (void)
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
&& FRAME_REDISPLAY_P (XFRAME (w->frame))
&& !FRAME_OBSCURED_P (XFRAME (w->frame))
&& !XFRAME (w->frame)->cursor_type_changed
&& !XFRAME (w->frame)->face_change
/* Make sure recorded data applies to current buffer, etc. */
@ -17449,22 +17466,28 @@ redisplay_internal (void)
propagate_buffer_redisplay ();
Lisp_Object tty_root_frames = Qnil;
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
/* We don't have to do anything for unselected terminal
frames. */
if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
&& !EQ (FRAME_TTY (f)->top_frame, frame))
continue;
if (is_tty_frame (f))
{
/* Ignore all invisble tty frames, children or root. */
if (!FRAME_VISIBLE_P (root_frame (f)))
continue;
/* Remember tty root frames which we've seen. */
if (!FRAME_PARENT_FRAME (f)
&& NILP (assq_no_quit (frame, tty_root_frames)))
tty_root_frames = Fcons (frame, tty_root_frames);
}
retry_frame:
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
bool gcscrollbars
/* Only GC scrollbars when we redisplay the whole frame. */
= f->redisplay || !REDISPLAY_SOME_P ();
/* Only GC scrollbars when we redisplay the whole frame. */
bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P ();
bool f_redisplay_flag = f->redisplay;
/* The X error handler may have deleted that frame before
@ -17481,7 +17504,7 @@ redisplay_internal (void)
if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
if (FRAME_REDISPLAY_P (f))
{
/* Don't allow freeing images and faces for this
frame as long as the frame's update wasn't
@ -17507,7 +17530,7 @@ redisplay_internal (void)
if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
if (FRAME_REDISPLAY_P (f))
{
/* If fonts changed on visible frame, display again. */
if (f->fonts_changed)
@ -17592,6 +17615,9 @@ redisplay_internal (void)
}
}
if (CONSP (tty_root_frames))
pending |= combine_updates (tty_root_frames, false, false);
eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
if (!pending)
@ -17613,7 +17639,7 @@ redisplay_internal (void)
}
}
}
else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
else if (FRAME_REDISPLAY_P (sf))
{
sf->inhibit_clear_image_cache = true;
displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
@ -17664,7 +17690,7 @@ redisplay_internal (void)
unrequest_sigio ();
STOP_POLLING;
if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
if (FRAME_REDISPLAY_P (sf))
{
if (hscroll_retries <= MAX_HSCROLL_RETRIES
&& hscroll_windows (selected_window))
@ -17675,6 +17701,10 @@ redisplay_internal (void)
XWINDOW (selected_window)->must_be_updated_p = true;
pending = update_frame (sf, false, false);
if (is_tty_frame (sf))
pending |= combine_updates_for_frame (sf, false, false);
sf->cursor_type_changed = false;
sf->inhibit_clear_image_cache = false;
}
@ -17687,10 +17717,12 @@ redisplay_internal (void)
Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
if (mini_frame != sf)
{
XWINDOW (mini_window)->must_be_updated_p = true;
pending |= update_frame (mini_frame, false, false);
if (is_tty_frame (mini_frame))
pending |= combine_updates_for_frame (mini_frame, false, false);
mini_frame->cursor_type_changed = false;
if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
&& hscroll_windows (mini_window))
@ -23977,6 +24009,7 @@ extend_face_to_end_of_line (struct it *it)
{
it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
it->glyph_row->glyphs[TEXT_AREA][0].frame = f;
it->glyph_row->used[TEXT_AREA] = 1;
}
/* Mode line and the header line don't have margins, and
@ -23996,6 +24029,7 @@ extend_face_to_end_of_line (struct it *it)
it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
default_face->id;
it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].frame = f;
it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
}
if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
@ -24004,6 +24038,7 @@ extend_face_to_end_of_line (struct it *it)
it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
default_face->id;
it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].frame = f;
it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
}
@ -24368,9 +24403,11 @@ highlight_trailing_whitespace (struct it *it)
while (glyph >= start
&& BUFFERP (glyph->object)
&& (glyph->type == STRETCH_GLYPH
|| (glyph->type == CHAR_GLYPH
&& glyph->u.ch == ' ')))
(glyph--)->face_id = face_id;
|| (glyph->type == CHAR_GLYPH && glyph->u.ch == ' ')))
{
glyph->frame = it->f;
(glyph--)->face_id = face_id;
}
}
else
{
@ -24379,7 +24416,10 @@ highlight_trailing_whitespace (struct it *it)
&& (glyph->type == STRETCH_GLYPH
|| (glyph->type == CHAR_GLYPH
&& glyph->u.ch == ' ')))
(glyph++)->face_id = face_id;
{
glyph->frame = it->f;
(glyph++)->face_id = face_id;
}
}
}
}
@ -27232,7 +27272,7 @@ display_menu_bar (struct window *w)
/* Deep copy of a glyph row, including the glyphs. */
static void
deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
deep_copy_glyph_row (struct frame *f, struct glyph_row *to, struct glyph_row *from)
{
struct glyph *pointers[1 + LAST_AREA];
int to_used = to->used[TEXT_AREA];
@ -27253,7 +27293,7 @@ deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
/* If we filled only part of the TO row, fill the rest with
space_glyph (which will display as empty space). */
if (to_used > from->used[TEXT_AREA])
fill_up_frame_row_with_spaces (to, to_used);
fill_up_frame_row_with_spaces (f, to, to_used);
}
/* Produce glyphs for a menu separator on a tty.
@ -27331,7 +27371,7 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
it.last_visible_x = FRAME_COLS (f) - 1;
row = it.glyph_row;
/* Start with the row contents from the current matrix. */
deep_copy_glyph_row (row, f->current_matrix->rows + y);
deep_copy_glyph_row (f, row, f->current_matrix->rows + y);
bool saved_width = row->full_width_p;
row->full_width_p = true;
bool saved_reversed = row->reversed_p;

View file

@ -696,7 +696,6 @@ void
free_frame_faces (struct frame *f)
{
struct face_cache *face_cache = FRAME_FACE_CACHE (f);
if (face_cache)
{
free_face_cache (face_cache);