+2014-07-27 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.el (frame-notice-user-settings): Rewrite using
+ frame-initial-frame-tool-bar-height.
+ * menu-bar.el (menu-bar-horizontal-scroll-bar)
+ (menu-bar-no-horizontal-scroll-bar): New functions.
+ (menu-bar-showhide-scroll-bar-menu): Add bindings for horizontal
+ scroll bars.
+ * scroll-bar.el (scroll-bar-lines)
+ (set-horizontal-scroll-bar-mode)
+ (get-horizontal-scroll-bar-mode, horizontal-scroll-bar-mode)
+ (scroll-bar-horizontal-drag-1, scroll-bar-horizontal-drag)
+ (scroll-bar-toolkit-horizontal-scroll): New functions.
+ (horizontal-scroll-bar-mode)
+ (previous-horizontal-scroll-bar-mode)
+ (horizontal-scroll-bar-mode-explicit): New variables.
+ (horizontal-scroll-bar-mode): New option.
+ (toggle-horizontal-scroll-bar): Do something.
+ (top-level): Bind horizontal-scroll-bar mouse-1.
+ * startup.el (tool-bar-originally-present): Remove variable.
+ (command-line): Don't set tool-bar-originally-present.
+ * window.el (window-min-height): Update doc-string.
+ (window--dump-frame): Dump horizontal scroll bar values.
+ (window--min-size-1): Handle minibuffer window separately.
+ Count in margins and horizontal scroll bar. Return safe value
+ iff IGNORE equals 'safe.
+ (frame-windows-min-size): New function (used by frame resizing
+ routines).
+ (fit-frame-to-buffer, fit-window-to-buffer): Count in horizontal
+ scroll bars.
+ (window--sanitize-window-sizes): New function.
+ (window-split-min-size): Remove.
+ (split-window): Count divider-width. Don't use
+ `window-split-min-size' any more. Reword error messages.
+ Sanitize windows sizes after splitting.
+
2014-07-27 Thien-Thi Nguyen <ttn@gnu.org>
Use `defvar-local' more.
;; If the initial frame is still around, apply initial-frame-alist
;; and default-frame-alist to it.
(when (frame-live-p frame-initial-frame)
-
;; When tool-bar has been switched off, correct the frame size
;; by the lines added in x-create-frame for the tool-bar and
;; switch `tool-bar-mode' off.
(when (display-graphic-p)
- (let ((tool-bar-lines (or (assq 'tool-bar-lines initial-frame-alist)
- (assq 'tool-bar-lines window-system-frame-alist)
- (assq 'tool-bar-lines default-frame-alist))))
- (when (and tool-bar-originally-present
- (or (null tool-bar-lines)
- (null (cdr tool-bar-lines))
- (eq 0 (cdr tool-bar-lines))))
- (let* ((char-height (frame-char-height frame-initial-frame))
- (image-height tool-bar-images-pixel-height)
- (margin (cond ((and (consp tool-bar-button-margin)
- (integerp (cdr tool-bar-button-margin))
- (> tool-bar-button-margin 0))
- (cdr tool-bar-button-margin))
- ((and (integerp tool-bar-button-margin)
- (> tool-bar-button-margin 0))
- tool-bar-button-margin)
- (t 0)))
- (relief (if (and (integerp tool-bar-button-relief)
- (> tool-bar-button-relief 0))
- tool-bar-button-relief 3))
- (lines (/ (+ image-height
- (* 2 margin)
- (* 2 relief)
- (1- char-height))
- char-height))
- (height (frame-parameter frame-initial-frame 'height))
- (newparms (list (cons 'height (- height lines))))
- (initial-top (cdr (assq 'top
- frame-initial-geometry-arguments)))
+ (let ((tool-bar-lines
+ (or (assq 'tool-bar-lines initial-frame-alist)
+ (assq 'tool-bar-lines window-system-frame-alist)
+ (assq 'tool-bar-lines default-frame-alist))))
+ ;; Shrink frame by its initial tool bar height iff either zero
+ ;; tool bar lines have been requested in one of the frame's
+ ;; alists or tool bar mode has been turned off explicitly in
+ ;; the user's init file.
+ (when (and tool-bar-lines
+ (> frame-initial-frame-tool-bar-height 0)
+ (or (not tool-bar-mode)
+ (null (cdr tool-bar-lines))
+ (eq 0 (cdr tool-bar-lines))))
+ (set-frame-height
+ frame-initial-frame (- (frame-text-height frame-initial-frame)
+ frame-initial-frame-tool-bar-height)
+ nil t)
+ (let* ((initial-top
+ (cdr (assq 'top frame-initial-geometry-arguments)))
(top (frame-parameter frame-initial-frame 'top)))
(when (and (consp initial-top) (eq '- (car initial-top)))
(let ((adjusted-top
- (cond ((and (consp top)
- (eq '+ (car top)))
- (list '+
- (+ (cadr top)
- (* lines char-height))))
- ((and (consp top)
- (eq '- (car top)))
- (list '-
- (- (cadr top)
- (* lines char-height))))
- (t (+ top (* lines char-height))))))
- (setq newparms
- (append newparms
- `((top . ,adjusted-top))
- nil))))
- (modify-frame-parameters frame-initial-frame newparms)
- (tool-bar-mode -1)))))
+ (cond
+ ((and (consp top) (eq '+ (car top)))
+ (list '+ (+ (cadr top)
+ frame-initial-frame-tool-bar-height)))
+ ((and (consp top) (eq '- (car top)))
+ (list '- (- (cadr top)
+ frame-initial-frame-tool-bar-height)))
+ (t (+ top frame-initial-frame-tool-bar-height)))))
+ (modify-frame-parameters
+ frame-initial-frame '((top . adjusted-top))))))
+ (tool-bar-mode -1))))
;; The initial frame we create above always has a minibuffer.
;; If the user wants to remove it, or make it a minibuffer-only
(interactive)
(customize-set-variable 'scroll-bar-mode nil))
+(defun menu-bar-horizontal-scroll-bar ()
+ "Display horizontal scroll bars on each window."
+ (interactive)
+ (customize-set-variable 'horizontal-scroll-bar-mode t))
+
+(defun menu-bar-no-horizontal-scroll-bar ()
+ "Turn off horizontal scroll bars."
+ (interactive)
+ (customize-set-variable 'horizontal-scroll-bar-mode nil))
+
(defvar menu-bar-showhide-scroll-bar-menu
(let ((menu (make-sparse-keymap "Scroll-bar")))
+ (bindings--define-key menu [horizontal]
+ '(menu-item "Horizontal"
+ menu-bar-horizontal-scroll-bar
+ :help "Horizontal scroll bar"
+ :visible (display-graphic-p)
+ :button (:radio . (eq (cdr (assq 'horizontal-scroll-bars
+ (frame-parameters)))
+ t))))
+
+ (bindings--define-key menu [none-horizontal]
+ '(menu-item "None-horizontal"
+ menu-bar-no-horizontal-scroll-bar
+ :help "Turn off horizontal scroll bars"
+ :visible (display-graphic-p)
+ :button (:radio . (eq (cdr (assq 'horizontal-scroll-bars
+ (frame-parameters)))
+ nil))))
(bindings--define-key menu [right]
'(menu-item "On the Right"
:help "Scroll-bar on the right side"
:visible (display-graphic-p)
:button (:radio . (eq (cdr (assq 'vertical-scroll-bars
- (frame-parameters))) 'right))))
+ (frame-parameters)))
+ 'right))))
(bindings--define-key menu [left]
'(menu-item "On the Left"
:help "Scroll-bar on the left side"
:visible (display-graphic-p)
:button (:radio . (eq (cdr (assq 'vertical-scroll-bars
- (frame-parameters))) 'left))))
+ (frame-parameters)))
+ 'left))))
(bindings--define-key menu [none]
'(menu-item "None"
:help "Turn off scroll-bar"
:visible (display-graphic-p)
:button (:radio . (eq (cdr (assq 'vertical-scroll-bars
- (frame-parameters))) nil))))
+ (frame-parameters)))
+ nil))))
menu))
(defun menu-bar-frame-for-menubar ()
(frame-char-width)))
(0))))
+(defun scroll-bar-lines ()
+ "Return the height, measured in lines, of the horizontal scrollbar."
+ (let* ((wsb (window-scroll-bars))
+ (htype (nth 5 wsb))
+ (lines (nth 4 wsb)))
+ (cond
+ (htype lines)
+ ((frame-parameter nil 'horizontal-scroll-bars)
+ ;; nil means it's a non-toolkit scroll bar (which is currently
+ ;; impossible), and its width in columns is 14 pixels rounded up.
+ (ceiling (or (frame-parameter nil 'scroll-bar-height) 14)
+ (frame-char-width)))
+ (0))))
+
\f
;;;; Helpful functions for enabling and disabling scroll bars.
(defvar scroll-bar-mode)
+(defvar horizontal-scroll-bar-mode)
(defvar previous-scroll-bar-mode nil)
+(defvar previous-horizontal-scroll-bar-mode nil)
(defvar scroll-bar-mode-explicit nil
"Non-nil means `set-scroll-bar-mode' should really do something.
This is nil while loading `scroll-bar.el', and t afterward.")
+(defvar horizontal-scroll-bar-mode-explicit nil
+ "Non-nil means `set-horizontal-scroll-bar-mode' should really do something.
+This is nil while loading `scroll-bar.el', and t afterward.")
+
(defun set-scroll-bar-mode (value)
"Set the scroll bar mode to VALUE and put the new value into effect.
See the `scroll-bar-mode' variable for possible values to use."
(modify-all-frames-parameters (list (cons 'vertical-scroll-bars
scroll-bar-mode)))))
+(defun set-horizontal-scroll-bar-mode (value)
+ "Set the horizontal scroll bar mode to VALUE and put the new value into effect.
+See the `horizontal-scroll-bar-mode' variable for possible values to use."
+ (if horizontal-scroll-bar-mode
+ (setq previous-horizontal-scroll-bar-mode horizontal-scroll-bar-mode))
+
+ (setq horizontal-scroll-bar-mode value)
+
+ (when horizontal-scroll-bar-mode-explicit
+ (modify-all-frames-parameters (list (cons 'horizontal-scroll-bars
+ horizontal-scroll-bar-mode)))))
+
(defcustom scroll-bar-mode default-frame-scroll-bars
"Specify whether to have vertical scroll bars, and on which side.
Possible values are nil (no scroll bars), `left' (scroll bars on left)
:initialize 'custom-initialize-default
:set (lambda (_sym val) (set-scroll-bar-mode val)))
+(defcustom horizontal-scroll-bar-mode default-frame-horizontal-scroll-bars
+ "Specify whether to have horizontal scroll bars, and on which side.
+To set this variable in a Lisp program, use `set-horizontal-scroll-bar-mode'
+to make it take real effect.
+Setting the variable with a customization buffer also takes effect."
+ :type '(choice (const :tag "none (nil)" nil)
+ (const t))
+ :group 'frames
+ ;; The default value for :initialize would try to use :set
+ ;; when processing the file in cus-dep.el.
+ :initialize 'custom-initialize-default
+ :set (lambda (_sym val) (set-horizontal-scroll-bar-mode val)))
+
;; We just set scroll-bar-mode, but that was the default.
;; If it is set again, that is for real.
(setq scroll-bar-mode-explicit t)
+(setq horizontal-scroll-bar-mode-explicit t)
(defun get-scroll-bar-mode ()
(declare (gv-setter set-scroll-bar-mode))
scroll-bar-mode)
+(defun get-horizontal-scroll-bar-mode ()
+ (declare (gv-setter set-horizontal-scroll-bar-mode))
+ horizontal-scroll-bar-mode)
+
(define-minor-mode scroll-bar-mode
"Toggle vertical scroll bars on all frames (Scroll Bar mode).
With a prefix argument ARG, enable Scroll Bar mode if ARG is
created in the future."
:variable ((get-scroll-bar-mode)
. (lambda (v) (set-scroll-bar-mode
- (if v (or previous-scroll-bar-mode
- default-frame-scroll-bars))))))
+ (if v (or previous-scroll-bar-mode
+ default-frame-scroll-bars))))))
+
+(define-minor-mode horizontal-scroll-bar-mode
+ "Toggle horizontal scroll bars on all frames (Horizontal Scroll Bar mode).
+With a prefix argument ARG, enable Horizontal Scroll Bar mode if
+ARG is positive, and disable it otherwise. If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+This command applies to all frames that exist and frames to be
+created in the future."
+ :variable ((get-horizontal-scroll-bar-mode)
+ . (lambda (v) (set-horizontal-scroll-bar-mode
+ (if v (or previous-scroll-bar-mode
+ default-frame-horizontal-scroll-bars))))))
(defun toggle-scroll-bar (arg)
"Toggle whether or not the selected frame has vertical scroll bars.
(if (> arg 0)
(or scroll-bar-mode default-frame-scroll-bars))))))
-(defun toggle-horizontal-scroll-bar (_arg)
+(defun toggle-horizontal-scroll-bar (arg)
"Toggle whether or not the selected frame has horizontal scroll bars.
-With arg, turn horizontal scroll bars on if and only if arg is positive.
-Horizontal scroll bars aren't implemented yet."
+With arg, turn horizontal scroll bars on if and only if arg is positive."
(interactive "P")
- (error "Horizontal scroll bars aren't implemented yet"))
+ (if (null arg)
+ (setq arg
+ (if (cdr (assq 'horizontal-scroll-bars
+ (frame-parameters (selected-frame))))
+ -1 1))
+ (setq arg (prefix-numeric-value arg)))
+ (modify-frame-parameters
+ (selected-frame)
+ (list (cons 'horizontal-scroll-bars
+ (if (> arg 0)
+ (or horizontal-scroll-bar-mode default-frame-horizontal-scroll-bars))))))
\f
;;;; Buffer navigation using the scroll bar.
(with-current-buffer (window-buffer window)
(setq point-before-scroll before-scroll))))
+;; Scroll the window to the proper position for EVENT.
+(defun scroll-bar-horizontal-drag-1 (event)
+ (let* ((start-position (event-start event))
+ (window (nth 0 start-position))
+ (portion-whole (nth 2 start-position))
+ (unit (frame-char-width (window-frame window))))
+ (set-window-hscroll
+ window (/ (1- (+ (car portion-whole) unit)) unit))))
+
+(defun scroll-bar-horizontal-drag (event)
+ "Scroll the window horizontally by dragging the scroll bar slider.
+If you click outside the slider, the window scrolls to bring the slider there."
+ (interactive "e")
+ (let* (done
+ (echo-keystrokes 0)
+ (end-position (event-end event))
+ (window (nth 0 end-position))
+ (before-scroll))
+ (with-current-buffer (window-buffer window)
+ (setq before-scroll point-before-scroll))
+ (save-selected-window
+ (select-window window)
+ (setq before-scroll
+ (or before-scroll (point))))
+ (scroll-bar-horizontal-drag-1 event)
+ (track-mouse
+ (while (not done)
+ (setq event (read-event))
+ (if (eq (car-safe event) 'mouse-movement)
+ (setq event (read-event)))
+ (cond ((eq (car-safe event) 'scroll-bar-movement)
+ (scroll-bar-horizontal-drag-1 event))
+ (t
+ ;; Exit when we get the drag event; ignore that event.
+ (setq done t)))))
+ (sit-for 0)
+ (with-current-buffer (window-buffer window)
+ (setq point-before-scroll before-scroll))))
+
(defun scroll-bar-scroll-down (event)
"Scroll the window's top line down to the location of the scroll bar click.
EVENT should be a scroll bar click."
(window (nth 0 end-position))
(part (nth 4 end-position))
before-scroll)
- (cond ((eq part 'end-scroll))
- (t
- (with-current-buffer (window-buffer window)
- (setq before-scroll point-before-scroll))
- (save-selected-window
- (select-window window)
- (setq before-scroll (or before-scroll (point)))
- (cond ((eq part 'above-handle)
- (scroll-up '-))
- ((eq part 'below-handle)
- (scroll-up nil))
- ((eq part 'ratio)
- (let* ((portion-whole (nth 2 end-position))
- (lines (scroll-bar-scale portion-whole
- (1- (window-height)))))
- (scroll-up (cond ((not (zerop lines)) lines)
- ((< (car portion-whole) 0) -1)
- (t 1)))))
- ((eq part 'up)
- (scroll-up -1))
- ((eq part 'down)
- (scroll-up 1))
- ((eq part 'top)
- (set-window-start window (point-min)))
- ((eq part 'bottom)
- (goto-char (point-max))
- (recenter))
- ((eq part 'handle)
- (scroll-bar-drag-1 event))))
- (sit-for 0)
- (with-current-buffer (window-buffer window)
- (setq point-before-scroll before-scroll))))))
-
+ (cond
+ ((eq part 'end-scroll))
+ (t
+ (with-current-buffer (window-buffer window)
+ (setq before-scroll point-before-scroll))
+ (save-selected-window
+ (select-window window)
+ (setq before-scroll (or before-scroll (point)))
+ (cond
+ ((eq part 'above-handle)
+ (scroll-up '-))
+ ((eq part 'below-handle)
+ (scroll-up nil))
+ ((eq part 'ratio)
+ (let* ((portion-whole (nth 2 end-position))
+ (lines (scroll-bar-scale portion-whole
+ (1- (window-height)))))
+ (scroll-up (cond ((not (zerop lines)) lines)
+ ((< (car portion-whole) 0) -1)
+ (t 1)))))
+ ((eq part 'up)
+ (scroll-up -1))
+ ((eq part 'down)
+ (scroll-up 1))
+ ((eq part 'top)
+ (set-window-start window (point-min)))
+ ((eq part 'bottom)
+ (goto-char (point-max))
+ (recenter))
+ ((eq part 'handle)
+ (scroll-bar-drag-1 event))))
+ (sit-for 0)
+ (with-current-buffer (window-buffer window)
+ (setq point-before-scroll before-scroll))))))
+(defun scroll-bar-toolkit-horizontal-scroll (event)
+ (interactive "e")
+ (let* ((end-position (event-end event))
+ (window (nth 0 end-position))
+ (part (nth 4 end-position))
+ before-scroll)
+ (cond
+ ((eq part 'end-scroll))
+ (t
+ (with-current-buffer (window-buffer window)
+ (setq before-scroll point-before-scroll))
+ (save-selected-window
+ (select-window window)
+ (setq before-scroll (or before-scroll (point)))
+ (cond
+ ((eq part 'before-handle)
+ (scroll-right 4))
+ ((eq part 'after-handle)
+ (scroll-left 4))
+ ((eq part 'ratio)
+ (let* ((portion-whole (nth 2 end-position))
+ (columns (scroll-bar-scale portion-whole
+ (1- (window-width)))))
+ (scroll-right
+ (cond
+ ((not (zerop columns))
+ columns)
+ ((< (car portion-whole) 0) -1)
+ (t 1)))))
+ ((eq part 'left)
+ (scroll-right 1))
+ ((eq part 'right)
+ (scroll-left 1))
+ ((eq part 'leftmost)
+ (goto-char (line-beginning-position)))
+ ((eq part 'rightmost)
+ (goto-char (line-end-position)))
+ ((eq part 'horizontal-handle)
+ (scroll-bar-horizontal-drag-1 event))))
+ (sit-for 0)
+ (with-current-buffer (window-buffer window)
+ (setq point-before-scroll before-scroll))))))
\f
;;;; Bindings.
;; For now, we'll set things up to work like xterm.
(cond ((and (boundp 'x-toolkit-scroll-bars) x-toolkit-scroll-bars)
(global-set-key [vertical-scroll-bar mouse-1]
- 'scroll-bar-toolkit-scroll))
+ 'scroll-bar-toolkit-scroll)
+ (global-set-key [horizontal-scroll-bar mouse-1]
+ 'scroll-bar-toolkit-horizontal-scroll))
(t
(global-set-key [vertical-scroll-bar mouse-1]
'scroll-bar-scroll-up)
(defconst tool-bar-images-pixel-height 24
"Height in pixels of images in the tool-bar.")
-(defvar tool-bar-originally-present nil
- "Non-nil if tool-bars are present before user and site init files are read.")
-
(defvar handle-args-function-alist '((nil . tty-handle-args))
"Functions for processing window-system dependent command-line arguments.
Window system startup files should add their own function to this
(or (eq initial-window-system 'pc)
(tty-register-default-colors))
- ;; Record whether the tool-bar is present before the user and site
- ;; init files are processed. frame-notice-user-settings uses this
- ;; to determine if the tool-bar has been disabled by the init files,
- ;; and the frame needs to be resized.
- (when (fboundp 'frame-notice-user-settings)
- (let ((tool-bar-lines (or (assq 'tool-bar-lines initial-frame-alist)
- (assq 'tool-bar-lines default-frame-alist))))
- (setq tool-bar-originally-present
- (and tool-bar-lines
- (cdr tool-bar-lines)
- (not (eq 0 (cdr tool-bar-lines)))))))
-
(let ((old-scalable-fonts-allowed scalable-fonts-allowed)
(old-face-ignored-fonts face-ignored-fonts))
(defcustom window-min-height 4
"The minimum total height, in lines, of any window.
The value has to accommodate one text line, a mode and header
-line, and a bottom divider, if present. A value less than
-`window-safe-min-height' is ignored. The value of this variable
-is honored when windows are resized or split.
+line, a horizontal scroll bar and a bottom divider, if present.
+A value less than `window-safe-min-height' is ignored. The value
+of this variable is honored when windows are resized or split.
Applications should never rebind this variable. To resize a
window to a height less than the one specified here, an
(format "frame text pixel: %s x %s cols/lines: %s x %s\n"
(frame-text-width frame) (frame-text-height frame)
(frame-text-cols frame) (frame-text-lines frame))
- (format "tool: %s scroll: %s fringe: %s border: %s right: %s bottom: %s\n\n"
+ (format "tool: %s scroll: %s/%s fringe: %s border: %s right: %s bottom: %s\n\n"
(if (fboundp 'tool-bar-height)
(tool-bar-height frame t)
"0")
(frame-scroll-bar-width frame)
+ (frame-scroll-bar-height frame)
(frame-fringe-width frame)
(frame-border-width frame)
(frame-right-divider-width frame)
value)
(with-current-buffer (window-buffer window)
(cond
+ ((window-minibuffer-p window)
+ (if pixelwise (frame-char-height (window-frame window)) 1))
((and (not (window--size-ignore-p window ignore))
(window-size-fixed-p window horizontal))
;; The minimum size of a fixed size window is its size.
(window-size window horizontal pixelwise))
- ((or (eq ignore 'safe) (eq ignore window))
- ;; If IGNORE equals `safe' or WINDOW return the safe values.
+ ((eq ignore 'safe)
+ ;; If IGNORE equals `safe' return the safe value.
(window-safe-min-size window horizontal pixelwise))
(horizontal
;; For the minimum width of a window take fringes and
;; `window-min-width'.
(let* ((char-size (frame-char-size window t))
(fringes (window-fringes window))
+ (margins (window-margins window))
(pixel-width
(+ (window-safe-min-size window t t)
+ (* (or (car margins) 0) char-size)
+ (* (or (cdr margins) 0) char-size)
(car fringes) (cadr fringes)
(window-scroll-bar-width window)
(window-right-divider-width window))))
(pixel-height
(+ (window-safe-min-size window nil t)
(window-header-line-height window)
+ (window-scroll-bar-height window)
(window-mode-line-height window)
(window-bottom-divider-width window))))
(if pixelwise
(window--min-delta-1
window (- size minimum) horizontal ignore trail noup pixelwise)))))
+(defun frame-windows-min-size (&optional frame horizontal pixelwise)
+ "Return minimum number of lines of FRAME's windows.
+HORIZONTAL non-nil means return number of columns of FRAME's
+windows. PIXELWISE non-nil means return sizes in pixels."
+ (setq frame (window-normalize-frame frame))
+ (let* ((root (frame-root-window frame))
+ (mini (window-next-sibling root)))
+ (+ (window-min-size root horizontal nil pixelwise)
+ (if (and mini (not horizontal))
+ (window-min-size mini horizontal nil pixelwise)
+ 0))))
+
(defun window--max-delta-1 (window delta &optional horizontal ignore trail noup pixelwise)
"Internal function of `window-max-delta'."
(if (not (window-parent window))
pixel-delta
(/ pixel-delta (frame-char-height frame)))))
+(defun window--sanitize-window-sizes (frame horizontal)
+ "Assert that all windows on FRAME are large enough.
+If necessary and possible, make sure that every window on frame
+FRAME has its minimum height. Optional argument HORIZONTAL
+non-nil means to make sure that every window on frame FRAME has
+its minimum width. The minimumm height/width of a window is the
+respective value returned by `window-min-size' for that window.
+
+Return t if all windows were resized appropriately. Return nil
+if at least one window could not be resized as requested, which
+may happen when the FRAME is not large enough to accomodate it."
+ (let ((value t))
+ (walk-window-tree
+ (lambda (window)
+ (let ((delta (- (window-min-size window horizontal nil t)
+ (window-size window horizontal t))))
+ (when (> delta 0)
+ (if (window-resizable-p window delta horizontal nil t)
+ (window-resize window delta horizontal nil t)
+ (setq value nil))))))
+ value))
+
(defun adjust-window-trailing-edge (window delta &optional horizontal pixelwise)
"Move WINDOW's bottom edge by DELTA lines.
Optional argument HORIZONTAL non-nil means move WINDOW's right
;; If a window doesn't show BUFFER, unrecord BUFFER in it.
(unrecord-window-buffer window buffer)))))
\f
-;;; Splitting windows.
-(defun window-split-min-size (&optional horizontal pixelwise)
- "Return minimum height of any window when splitting windows.
-Optional argument HORIZONTAL non-nil means return minimum width."
- (cond
- (pixelwise
- (if horizontal
- (window-min-pixel-width)
- (window-min-pixel-height)))
- (horizontal
- (max window-min-width window-safe-min-width))
- (t
- (max window-min-height window-safe-min-height))))
-
(defun split-window (&optional window size side pixelwise)
"Make a new window adjacent to WINDOW.
WINDOW must be a valid window and defaults to the selected one.
(pixel-size
(when (numberp size)
(window--size-to-pixel window size horizontal pixelwise t)))
+ (divider-width (if horizontal
+ (frame-right-divider-width frame)
+ (frame-bottom-divider-width frame)))
atom-root)
(window--check frame)
(catch 'done
(cond
(resize
;; SIZE unspecified, resizing.
- (when (and (not (window-sizable-p
- parent (- new-pixel-size) horizontal nil t))
- ;; Try again with minimum split size.
- (setq new-pixel-size
- (max new-pixel-size
- (window-split-min-size horizontal t)))
- (not (window-sizable-p
- parent (- new-pixel-size) horizontal nil t)))
- (error "Window %s too small for splitting 1" parent)))
- ((> (+ new-pixel-size (window-min-size window horizontal nil t))
+ (unless (window-sizable-p
+ parent (- new-pixel-size divider-width) horizontal nil t)
+ (error "Window %s too small for splitting (1)" parent)))
+ ((> (+ new-pixel-size divider-width
+ (window-min-size window horizontal nil t))
old-pixel-size)
;; SIZE unspecified, no resizing.
- (error "Window %s too small for splitting 2" window))))
+ (error "Window %s too small for splitting (2)" window))))
((and (>= pixel-size 0)
(or (>= pixel-size old-pixel-size)
(< new-pixel-size
;; SIZE specified as new size of old window. If the new size
;; is larger than the old size or the size of the new window
;; would be less than the safe minimum, signal an error.
- (error "Window %s too small for splitting 3" window))
+ (error "Window %s too small for splitting (3)" window))
(resize
;; SIZE specified, resizing.
(unless (window-sizable-p
- parent (- new-pixel-size) horizontal nil t)
+ parent (- new-pixel-size divider-width) horizontal nil t)
;; If we cannot resize the parent give up.
- (error "Window %s too small for splitting 4" parent)))
+ (error "Window %s too small for splitting (4)" parent)))
((or (< new-pixel-size
(window-safe-min-pixel-size window horizontal))
(< (- old-pixel-size new-pixel-size)
(window-safe-min-pixel-size window horizontal)))
;; SIZE specification violates minimum size restrictions.
- (error "Window %s too small for splitting 5" window)))
+ (error "Window %s too small for splitting (5)" window)))
(window--resize-reset frame horizontal)
(set-window-parameter (window-parent new) 'window-atom t))
(set-window-parameter new 'window-atom t)))
+ ;; Sanitize sizes.
+ (window--sanitize-window-sizes frame horizontal)
+
(run-window-configuration-change-hook frame)
(run-window-scroll-functions new)
(window--check frame)
(value (window-text-pixel-size
nil t t workarea-width workarea-height t))
(width (+ (car value) (window-right-divider-width)))
- (height (+ (cdr value) (window-bottom-divider-width))))
+ (height
+ (+ (cdr value)
+ (window-bottom-divider-width)
+ (nth 3 (window-scroll-bars)))))
;; Don't change height or width when the window's size is fixed
;; in either direction or ONLY forbids it.
(cond
;; height. Its width remains fixed.
(setq height (+ (cdr (window-text-pixel-size
nil nil t nil (frame-pixel-height) t))
+ (nth 3 (window-scroll-bars window))
(window-bottom-divider-width)))
;; Round height.
(unless pixelwise
+2014-07-27 Martin Rudalics <rudalics@gmx.at>
+
+ * buffer.h (struct buffer): New fields scroll_bar_height and
+ horizontal_scroll_bar_type.
+ * buffer.c (bset_scroll_bar_height)
+ (bset_horizontal_scroll_bar_type): New functions.
+ (Fbuffer_swap_text): Handle old_pointm field.
+ (init_buffer_once): Set defaults for scroll_bar_height and
+ horizontal_scroll_bar_type.
+ (syms_of_buffer): New variables scroll_bar_height and
+ horizontal_scroll_bar_type.
+ * dispextern.h (window_part): Rename ON_SCROLL_BAR to
+ ON_VERTICAL_SCROLL_BAR. Add ON_HORIZONTAL_SCROLL_BAR.
+ (set_vertical_scroll_bar): Remove prototype.
+ (x_change_tool_bar_height): Add prototype.
+ * dispnew.c (adjust_frame_glyphs_for_frame_redisplay)
+ (window_to_frame_vpos, update_frame_1, scrolling, init_display):
+ Use FRAME_TOTAL_COLS and FRAME_TOTAL_LINES instead of FRAME_COLS
+ and FRAME_LINES.
+ (adjust_frame_glyphs_for_window_redisplay): Rearrange lines.
+ (update_window): Start mode_line_row->y after horizontal scroll
+ bar.
+ (change_frame_size_1): Call adjust_frame_size.
+ (init_display): When changing the size of a tty frame do not
+ pass height of menu bar.
+ (Qframe_windows_min_size): New symbol.
+ * frame.h (struct frame): List tool bar fields after menu bar
+ fields. Add official, total_lines, horizontal_scroll_bars,
+ config_scroll_bar_height and config_scroll_bar_lines fields.
+ (FRAME_HAS_HORIZONTAL_SCROLL_BARS)
+ (FRAME_CONFIG_SCROLL_BAR_HEIGHT, FRAME_CONFIG_SCROLL_BAR_LINES)
+ (FRAME_SCROLL_BAR_AREA_HEIGHT, FRAME_SCROLL_BAR_COLS)
+ (FRAME_SCROLL_BAR_LINES, FRAME_TOTAL_LINES, SET_FRAME_LINES)
+ (FRAME_WINDOWS_HEIGHT): New macros.
+ (SET_FRAME_HEIGHT, FRAME_TEXT_LINES_TO_PIXEL_HEIGHT)
+ (FRAME_PIXEL_Y_TO_LINE, FRAME_PIXEL_HEIGHT_TO_TEXT_LINES)
+ (FRAME_TEXT_TO_PIXEL_HEIGHT): Separately count top margin and
+ horizontal scroll bar.
+ (frame_inhibit_resize, adjust_frame_size)
+ (frame_windows_min_size): Add declarations.
+ (Qscroll_bar_height, Qhorizontal_scroll_bars)
+ (x_set_scroll_bar_default_height, x_set_left_fringe)
+ (x_set_right_fringe, x_set_vertical_scroll_bars)
+ (x_set_horizontal_scroll_bars, x_set_scroll_bar_width)
+ (x_set_scroll_bar_height): Add external declarations.
+ * frame.c: (frame_inhibit_resize, frame_windows_min_size)
+ (adjust_frame_size): New functions.
+ (make_frame): Initial horizontal_scroll_bars field. Use
+ SET_FRAME_LINES. Don't allow horizontal scroll bar in
+ minibuffer window.
+ (make_initial_frame, make_terminal_frame): No horizontal scroll
+ bar in initial and terminal frames. Use adjust_frame_size.
+ (Fframe_total_cols): Fix doc-string.
+ (Fframe_total_lines, Fscroll_bar_height): New Lisp functions.
+ (Fset_frame_height, Fset_frame_width, Fset_frame_size): Rewrite
+ using adjust_frame_size.
+ (Qscroll_bar_height, Qhorizontal_scroll_bars)
+ (Qframe_windows_min_size): New symbols.
+ (x_set_frame_parameters): Remove call of check_frame_size.
+ (x_report_frame_params): Return scroll_bar_height value.
+ (x_set_left_fringe, x_set_right_fringe): New functions.
+ (adjust_frame_height, x_set_internal_border_width)
+ (x_set_fringe_width): Remove.
+ (x_set_internal_border_width, x_set_vertical_scroll_bars)
+ (x_set_scroll_bar_width, x_set_right_divider_width)
+ (x_set_bottom_divider_width): Rewrite using adjust_frame_size.
+ (x_set_horizontal_scroll_bars, x_set_scroll_bar_height): New
+ functions.
+ (x_figure_window_size): Rewrite to make frame display the
+ expected number of lines.
+ (Vdefault_frame_scroll_bars): Rewrite doc-string.
+ (Vdefault_frame_horizontal_scroll_bars)
+ (Vframe_initial_frame_tool_bar_height)
+ (frame_inhibit_implied_resize): New variables.
+ * fringe.c (compute_fringe_widths): Remove.
+ * gtkutil.h (YG_SB_MIN, YG_SB_MAX, YG_SB_RANGE): Define.
+ (xg_create_horizontal_scroll_bar)
+ (xg_update_horizontal_scrollbar_pos)
+ (xg_set_toolkit_horizontal_scroll_bar_thumb)
+ (xg_get_default_scrollbar_height)
+ (xg_clear_under_internal_border): Extern.
+ * gtkutil.c (xg_frame_resized): Don't call
+ do_pending_window_change.
+ (xg_frame_set_char_size): Use adjust_frame_size.
+ (style_changed_cb): Call update_theme_scrollbar_height and
+ x_set_scroll_bar_default_height.
+ (x_wm_set_size_hint): Don't call check_frame_size.
+ (update_theme_scrollbar_height)
+ (xg_get_default_scrollbar_height)
+ (xg_create_horizontal_scroll_bar)
+ (xg_update_horizontal_scrollbar_pos)
+ (xg_set_toolkit_horizontal_scroll_bar_thumb): New functions.
+ (xg_create_scroll_bar): Set horizontal slot of bar.
+ (xg_initialize): Call update_theme_scrollbar_height.
+ (xg_clear_under_internal_border): No more static.
+ * insdel.c (adjust_suspend_auto_hscroll): New function.
+ (adjust_markers_for_delete, adjust_markers_for_insert)
+ (adjust_markers_for_replace): Call adjust_suspend_auto_hscroll.
+ * keyboard.c (readable_events, discard_mouse_events)
+ (make_lispy_event): Handle horizontal scroll bar click events.
+ (Fsuspend_emacs): When changing the size of a tty frame do not
+ pass height of menu bar.
+ (Qbefore_handle, Qhorizontal_handle, Qafter_handle, Qleft)
+ (Qright, Qleftmost, Qrightmost): New symbols.
+ * menu.c (Fx_popup_dialog): Use FRAME_TOTAL_LINES instead of
+ FRAME_LINES.
+ * minibuf.c (read_minibuf): Initialize suspend_auto_hscroll.
+ * nsfns.m (x_set_internal_border_width): New function.
+ * nsterm.m (ns_draw_fringe_bitmap, ns_set_vertical_scroll_bar):
+ Remove extended fringe code.
+ (x_set_window_size, x_new_font): Don't call
+ compute_fringe_widths.
+ * term.c (Fresume_tty): When changing the size of a tty frame do
+ not pass height of menu bar.
+ (clear_tty_hooks, set_tty_hooks): Clear
+ horizontal_scroll_bar_hook.
+ (init_tty): Frame has no horizontal scroll bars.
+ * termhooks.h (enum scroll_bar_part): Add scroll_bar_move_ratio,
+ scroll_bar_before_handle, scroll_bar_horizontal_handle,
+ scroll_bar_after_handle, scroll_bar_left_arrow,
+ scroll_bar_right_arrow, scroll_bar_to_leftmost and
+ scroll_bar_to_rightmost entries.
+ (enum event_kind): Add HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+ (struct terminal): Add set_horizontal_scroll_bar_hook.
+ * w32console.c (initialize_w32_display): Clear
+ horizontal_scroll_bar_hook.
+ * w32fns.c (x_set_mouse_color): Use FRAME_W32_DISPLAY instead of
+ FRAME_X_DISPLAY.
+ (x_clear_under_internal_border, x_set_internal_border_width):
+ New functions.
+ (x_set_menu_bar_lines): Rewrite using frame_inhibit_resize. Set
+ windows_or_buffers_changed when adding the menu bar.
+ (x_set_tool_bar_lines): Rewrite using adjust_frame_size.
+ (x_change_tool_bar_height, x_set_scroll_bar_default_height)
+ (w32_createhscrollbar): New functions.
+ (w32_createscrollbar): Rename to w32_createvscrollbar.
+ (w32_createwindow): Init WND_HSCROLLBAR_INDEX.
+ (w32_name_of_message): Replace WM_EMACS_CREATESCROLLBAR by
+ WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR. Add
+ WM_EMACS_SHOWCURSOR.
+ (w32_wnd_proc): Handle WM_HSCROLL case. In WM_WINDOWPOSCHANGING
+ case do not artificially impose WM size hints. Handle
+ WM_EMACS_SHOWCURSOR case. Replace WM_EMACS_CREATESCROLLBAR case
+ by WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR
+ cases.
+ (my_create_tip_window): Replace WND_SCROLLBAR_INDEX by
+ WND_VSCROLLBAR_INDEX and WND_HSCROLLBAR_INDEX.
+ (unwind_create_frame_1): Remove.
+ (Fx_create_frame): Make both scrollbars the system standard
+ width and height. Use official field of frame structure to
+ inhibit running window-configuration-change-hook.
+ (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size
+ pixelwise. Handle frame's official field.
+ (w32_frame_parm_handlers): Remove x_set_fringe_width
+ entries. Add x_set_scroll_bar_height,
+ x_set_horizontal_scroll_bars, x_set_left_fringe and
+ x_set_right_fringe.
+ * w32inevt.c (resize_event, maybe_generate_resize_event): Do not
+ pass height of menu bar to change_frame_size.
+ * w32menu.c (set_frame_menubar): Rewrite using
+ frame_inhibit_resize.
+ * w32term.h (struct w32_display_info): Add
+ horizontal_scroll_bar_cursor and cursor_display_counter.
+ (struct scroll_bar): Add horizontal.
+ (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT)
+ (HORIZONTAL_SCROLL_BAR_LEFT_RANGE)
+ (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH)
+ (HORIZONTAL_SCROLL_BAR_LEFT_BORDER)
+ (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER)
+ (HORIZONTAL_SCROLL_BAR_TOP_BORDER)
+ (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER)
+ (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): New macros.
+ (WM_EMACS_CREATEVSCROLLBAR, WM_EMACS_CREATEHSCROLLBAR): Define
+ instead of WM_EMACS_CREATESCROLLBAR.
+ (WND_VSCROLLBAR_INDEX, WND_HSCROLLBAR_INDEX): Define instead of
+ WND_SCROLLBAR_INDEX.
+ * w32term.c (horizontal_scroll_bar_min_handle)
+ (horizontal_scroll_bar_left_border)
+ (horizontal_scroll_bar_right_border): New integers.
+ (x_set_frame_alpha): Replace x_highlight_frame by
+ w32_focus_frame.
+ (x_window_to_scroll_bar): New argument "type". Update callers
+ accordingly.
+ (w32_set_horizontal_scroll_bar_thumb)
+ (x_horizontal_scroll_bar_report_motion)
+ (w32_set_horizontal_scroll_bar)
+ (w32_horizontal_scroll_bar_handle_click)
+ (x_horizontal_scroll_bar_report_motion): New functions.
+ (w32_mouse_position): Discriminate horizontal and vertical
+ scrollbar cases.
+ (my_create_scrollbar): Replace with two new functions
+ my_create_vscrollbar and my_create_hscrollbar.
+ (x_scroll_bar_create): New argument "horizontal". Update
+ callers accordingly.
+ (x_scroll_bar_remove, w32_condemn_scroll_bars)
+ (w32_redeem_scroll_bar, x_scroll_bar_clear): Handle horizontal
+ scroll bar case.
+ (w32_read_socket): Handle WM_HSCROLL cae.
+ (x_new_font): Don't recompute fringe widths. Use
+ frame_inhibit_resize. Calculate new menu bar height iff we
+ build without toolkit. Always clear under internal border.
+ (x_set_window_size): Don't check frame size or recompute
+ fringes. Reset fullscreen status before applying sizes. Always
+ resize as requested by pixelwise argument. Don't call
+ do_pending_window_change.
+ (x_wm_set_size_hint): Add call for FRAME_SCROLL_BAR_AREA_HEIGHT.
+ (w32_initialize_display_info): Initialize dpyinfo's
+ horizontal_scroll_bar_cursor entry.
+ (w32_create_terminal): Add set_horizontal_scroll_bar_hook.
+ (w32_initialize): Init horizontal_scroll_bar_min_handle and
+ horizontal_scroll_bar_left_border.
+ (w32fullscreen_hook): Intermittently resize window to normal
+ when switching from fullscreen to maximized state.
+ (run_window_configuration_change_hook): Don't run it if frame is
+ not official yet.
+ (unwind_change_frame): Remove.
+ (Fset_window_configuration): Rewrite using frame's official field.
+ * widget.c (set_frame_size): Don't call compute_fringe_widths.
+ (EmacsFrameSetCharSize): Obey frame_inhibit_resize.
+ * window.h (struct window): New fields old_pointm,
+ horizontal_scroll_bar, horizontal_scroll_bar_type, hscroll_whole,
+ scroll_bar_height and suspend_auto_hscroll.
+ (wset_horizontal_scroll_bar, wset_horizontal_scroll_bar_type):
+ New functions.
+ (sanitize_window_sizes): Extern.
+ (MINI_NON_ONLY_WINDOW_P, MINI_ONLY_WINDOW_P, WINDOW_PSEUDO_P)
+ (WINDOW_TOPMOST_P, WINDOW_HAS_HORIZONTAL_SCROLL_BAR)
+ (WINDOW_CONFIG_SCROLL_BAR_HEIGHT)
+ (WINDOW_CONFIG_SCROLL_BAR_LINES)
+ (WINDOW_SCROLL_BAR_LINES, WINDOW_SCROLL_BAR_AREA_HEIGHT): New
+ macros.
+ (WINDOW_LEFT_FRINGE_COLS, WINDOW_RIGHT_FRINGE_COLS)
+ (WINDOW_FRINGE_COLS, WINDOW_FRINGE_EXTENDED_P): Remove macros.
+ (WINDOW_VERTICAL_SCROLL_BAR_TYPE)
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT)
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT)
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR): Minor rewrite.
+ (WINDOW_BOX_HEIGHT_NO_MODE_LINE, WINDOW_BOX_TEXT_HEIGHT)
+ (WINDOW_SCROLL_BAR_AREA_Y): Count in scroll bar height.
+ * window.c (wset_old_pointm, Fwindow_scroll_bar_height)
+ (Fwindow_old_point, sanitize_window_sizes): New functions.
+ (Qwindow_sanitize_window_sizes): New symbol.
+ (window_body_height): Count in horizontal scroll bar.
+ (set_window_hscroll, Fscroll_left, Fscroll_right): Set
+ suspend_auto_hscroll slot.
+ (Fwindow_inside_edges): Count fringes pixelwise.
+ (coordinates_in_window, Fcoordinates_in_window_p): Consider
+ horizontal scroll bar.
+ (check_frame_size, adjust_window_margins): Remove functions and
+ corresponding calls.
+ (set_window_buffer): Initialize old_pointm and horizontal scroll
+ bars.
+ (temp_output_buffer_show): Reset hscroll related fields.
+ Initialize old_pointm.
+ (make_parent_window): Initialize old_pointm.
+ (make_window): Initialize old_pointm, horizontal scroll bar type,
+ and scroll bar height.
+ (resize_frame_windows): Don't count top margin in new sizes.
+ Don't use safe sizes when shrinking a frame; let the window
+ manager do the clipping.
+ (Fsplit_window_internal): Inherit horizontal scroll bar type and
+ height.
+ (Fdelete_window_internal): Unchain old_pointm marker.
+ (window_scroll_pixel_based, Fscroll_other_window): Adjust
+ old_pointm.
+ (Fwindow_text_width, Fwindow_text_height): New argument
+ "pixelwise".
+ (struct saved_window): New fields, old_pointm, hscroll_whole,
+ suspend_auto_hscroll, scroll_bar_height and
+ horizontal_scroll_bar_type.
+ (Fset_window_configuration, save_window_save): Set new fields of
+ saved_window.
+ (apply_window_adjustment): Don't call adjust_window_margins.
+ (set_window_margins): Don't change margins if new sizes don't
+ fit into window.
+ (set_window_scroll_bars): New argument "horizontal_type".
+ Handle horizontal scroll bars. Don't change scroll bars if they
+ don't fit into window.
+ (Fset_window_scroll_bars): New argument "horizontal_type".
+ (Fwindow_scroll_bars): Return values for horizontal scroll bars.
+ (compare_window_configurations): Compare horizontal scroll bar
+ settings.
+ * xdisp.c (window_text_bottom_y, window_box_height): Count in
+ horizontal scroll bar height.
+ (pixel_to_glyph_coords, init_xdisp): Use FRAME_TOTAL_LINES
+ instead of FRAME_LINES.
+ (remember_mouse_glyph): Case ON_SCROLL_BAR changed to
+ ON_VERTICAL_SCROLL_BAR.
+ (with_echo_area_buffer): Initialize old_pointm.
+ (with_echo_area_buffer_unwind_data): Store old_pointm values in
+ vector.
+ (unwind_with_echo_area_buffer): Handle old_pointm.
+ (update_tool_bar): Set do_update when the tool bar window has at
+ least one line (since this is what the user sets).
+ (MAX_FRAME_TOOL_BAR_HEIGHT): Remove macro.
+ (redisplay_tool_bar): Return early when toolbar has zero lines.
+ Call x_change_tool_bar_height. Don't use max_tool_bar_height.
+ (hscroll_window_tree): Handle suspension of auto_hscroll and
+ old_pointm.
+ (set_horizontal_scroll_bar): New function.
+ (redisplay_window): Set ignore_mouse_drag_p when tool bar has
+ more than one line. Handle horizontal scroll bars.
+ (note_mouse_highlight): Handle horizontal scrol bars.
+ (expose_frame): Set dimensions of XRectangle from frame's text
+ sizes.
+ (Vvoid_text_area_pointer): Update doc-string.
+ * xfns.c (x_set_menu_bar_lines): Use adjust_frame_size.
+ (x_change_tool_bar_height, x_set_scroll_bar_default_height)
+ (x_set_internal_border_width): New functions.
+ (x_set_tool_bar_lines): Call x_change_tool_bar_height.
+ (unwind_create_frame_1): Remove.
+ (Fx_create_frame): Handle horizontal scroll bars. Use official
+ field of frame structure to inhibit running
+ window-configuration-change-hook.
+ (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size
+ pixelwise. Handle frame's official field.
+ (x_frame_parm_handlers): Add x_set_scroll_bar_height,
+ x_set_horizontal_scroll_bars, x_set_left_fringe,
+ x_set_right_fringe.
+ * xmenu.c (update_frame_menubar, free_frame_menubar): Use
+ adjust_frame_size.
+ * xterm.h (struct x_display_info): Add
+ horizontal_scroll_bar_cursor and Xatom_Horizontal_Scrollbar
+ slots.
+ (struct scroll_bar): Add horizontal slot.
+ (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT)
+ (HORIZONTAL_SCROLL_BAR_LEFT_RANGE)
+ (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH): New macros.
+ (HORIZONTAL_SCROLL_BAR_LEFT_BORDER)
+ (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER)
+ (HORIZONTAL_SCROLL_BAR_TOP_BORDER)
+ (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER)
+ (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): Define.
+ (x_clear_under_internal_border): Remove.
+ * xterm.c (XTmouse_position): Handle horizontal scroll bars.
+ (x_window_to_scroll_bar): New argument TYPE. Update callers.
+ (x_send_scroll_bar_event, x_scroll_bar_create): New arguments
+ HORIZONTAL. Update callers.
+ (horizontal_action_hook_id): New action hook id.
+ (x_horizontal_scroll_bar_to_input_event)
+ (x_create_horizontal_toolkit_scroll_bar)
+ (xt_horizontal_action_hook)
+ (x_set_toolkit_horizontal_scroll_bar_thumb)
+ (XTset_horizontal_scroll_bar, x_net_wm_state)
+ (x_horizontal_scroll_bar_report_motion): New functions.
+ (xg_scroll_callback, x_scroll_bar_handle_click): Handle
+ horizontal scroll bars.
+ (SCROLL_BAR_HORIZONTAL_NAME): Define.
+ (XTset_vertical_scroll_bar): Attempt to clear areas not covered
+ by scroll bar.
+ (XTcondemn_scroll_bars, XTredeem_scroll_bar): Rewrite. Handle
+ horizontal scroll bars.
+ (handle_one_xevent): Handle horizontal scroll bar events. Call
+ x_net_wm_state.
+ (x_set_window_size_1, x_wm_set_size_hint): Don't call
+ check_frame_size.
+ (x_set_window_size): Don't call check_frame_size and
+ do_pending_window_change.
+ (x_term_init): Init horizontal_scroll_bar_cursor display info.
+ (x_create_terminal): Add set_horizontal_scroll_bar_hook.
+ (x_scroll_bar_set_handle): Add some checks when calling
+ x_clear_area.
+
2014-07-26 Paul Eggert <eggert@cs.ucla.edu>
Revert previous change.
Lisp_Object Qinsert_in_front_hooks;
Lisp_Object Qinsert_behind_hooks;
-Lisp_Object Qchoice, Qrange, Qleft, Qright, Qvertical_scroll_bar;
+Lisp_Object Qchoice, Qrange, Qleft, Qright;
+Lisp_Object Qvertical_scroll_bar, Qhorizontal_scroll_bar;
static Lisp_Object Qoverwrite_mode, Qfraction;
static void alloc_buffer_text (struct buffer *, ptrdiff_t);
b->INTERNAL_FIELD (scroll_bar_width) = val;
}
static void
+bset_scroll_bar_height (struct buffer *b, Lisp_Object val)
+{
+ b->INTERNAL_FIELD (scroll_bar_height) = val;
+}
+static void
bset_scroll_down_aggressively (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_down_aggressively) = val;
b->INTERNAL_FIELD (vertical_scroll_bar_type) = val;
}
static void
+bset_horizontal_scroll_bar_type (struct buffer *b, Lisp_Object val)
+{
+ b->INTERNAL_FIELD (horizontal_scroll_bar_type) = val;
+}
+static void
bset_word_wrap (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (word_wrap) = val;
make_number
(BUF_BEGV (XBUFFER (XWINDOW (w)->contents))),
XWINDOW (w)->contents);
+ /* Blindly copied from pointm part. */
+ if (MARKERP (XWINDOW (w)->old_pointm)
+ && (EQ (XWINDOW (w)->contents, buf1)
+ || EQ (XWINDOW (w)->contents, buf2)))
+ Fset_marker (XWINDOW (w)->old_pointm,
+ make_number
+ (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))),
+ XWINDOW (w)->contents);
if (MARKERP (XWINDOW (w)->start)
&& (EQ (XWINDOW (w)->contents, buf1)
|| EQ (XWINDOW (w)->contents, buf2)))
bset_right_fringe_width (&buffer_defaults, Qnil);
bset_fringes_outside_margins (&buffer_defaults, Qnil);
bset_scroll_bar_width (&buffer_defaults, Qnil);
+ bset_scroll_bar_height (&buffer_defaults, Qnil);
bset_vertical_scroll_bar_type (&buffer_defaults, Qt);
+ bset_horizontal_scroll_bar_type (&buffer_defaults, Qt);
bset_indicate_empty_lines (&buffer_defaults, Qnil);
bset_indicate_buffer_boundaries (&buffer_defaults, Qnil);
bset_fringe_indicator_alist (&buffer_defaults, Qnil);
XSETFASTINT (BVAR (&buffer_local_flags, right_fringe_width), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, fringes_outside_margins), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, scroll_bar_width), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, scroll_bar_height), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, vertical_scroll_bar_type), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, horizontal_scroll_bar_type), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, indicate_empty_lines), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, indicate_buffer_boundaries), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, fringe_indicator_alist), idx); ++idx;
DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar");
Fput (Qvertical_scroll_bar, Qchoice, list4 (Qnil, Qt, Qleft, Qright));
+ DEFSYM (Qhorizontal_scroll_bar, "horizontal-scroll-bar");
DEFSYM (Qfraction, "fraction");
Fput (Qfraction, Qrange, Fcons (make_float (0.0), make_float (1.0)));
doc: /* Width of this buffer's scroll bars in pixels.
A value of nil means to use the scroll bar width from the window's frame. */);
+ DEFVAR_PER_BUFFER ("scroll-bar-height", &BVAR (current_buffer, scroll_bar_height),
+ Qintegerp,
+ doc: /* Height of this buffer's scroll bars in pixels.
+A value of nil means to use the scroll bar heiht from the window's frame. */);
+
DEFVAR_PER_BUFFER ("vertical-scroll-bar", &BVAR (current_buffer, vertical_scroll_bar_type),
Qvertical_scroll_bar,
doc: /* Position of this buffer's vertical scroll bar.
of the window; a value of nil means don't show any vertical scroll bars.
A value of t (the default) means do whatever the window's frame specifies. */);
+ DEFVAR_PER_BUFFER ("horizontal-scroll-bar", &BVAR (current_buffer, horizontal_scroll_bar_type),
+ Qnil,
+ doc: /* Position of this buffer's horizontal scroll bar.
+The value takes effect whenever you tell a window to display this buffer;
+for instance, with `set-window-buffer' or when `display-buffer' displays it.
+
+A value of `bottom' means put the horizontal scroll bar at the bottom of
+the window; a value of nil means don't show any horizonal scroll bars.
+A value of t (the default) means do whatever the window's frame
+specifies. */);
+
DEFVAR_PER_BUFFER ("indicate-empty-lines",
&BVAR (current_buffer, indicate_empty_lines), Qnil,
doc: /* Visually indicate empty lines after the buffer end.
othersize draw them between margin areas and text. */
Lisp_Object INTERNAL_FIELD (fringes_outside_margins);
- /* Width and type of scroll bar areas for windows displaying
+ /* Width, height and types of scroll bar areas for windows displaying
this buffer. */
Lisp_Object INTERNAL_FIELD (scroll_bar_width);
+ Lisp_Object INTERNAL_FIELD (scroll_bar_height);
Lisp_Object INTERNAL_FIELD (vertical_scroll_bar_type);
+ Lisp_Object INTERNAL_FIELD (horizontal_scroll_bar_type);
/* Non-nil means indicate lines not displaying text (in a style
like vi). */
extern Lisp_Object Qafter_change_functions;
extern Lisp_Object Qfirst_change_hook;
extern Lisp_Object Qpriority, Qbefore_string, Qafter_string;
-extern Lisp_Object Qchoice, Qrange, Qleft, Qright, Qvertical_scroll_bar;
+extern Lisp_Object Qchoice, Qrange, Qleft, Qright;
+extern Lisp_Object Qvertical_scroll_bar, Qhorizontal_scroll_bar;
/* FOR_EACH_LIVE_BUFFER (LIST_VAR, BUF_VAR) followed by a statement is
a `for' loop which iterates over the buffers from Vbuffer_alist. */
ON_RIGHT_FRINGE,
ON_LEFT_MARGIN,
ON_RIGHT_MARGIN,
- ON_SCROLL_BAR,
+ ON_VERTICAL_SCROLL_BAR,
+ ON_HORIZONTAL_SCROLL_BAR,
ON_RIGHT_DIVIDER,
ON_BOTTOM_DIVIDER
};
void resize_echo_area_exactly (void);
int resize_mini_window (struct window *, int);
void set_vertical_scroll_bar (struct window *);
+void set_horizontal_scroll_bar (struct window *);
int try_window (Lisp_Object, struct text_pos, int);
void window_box (struct window *, enum glyph_row_area,
int *, int *, int *, int *);
extern Lisp_Object help_echo_string, help_echo_window;
extern Lisp_Object help_echo_object, previous_help_echo_string;
extern ptrdiff_t help_echo_pos;
+extern int last_tool_bar_item;
extern void reseat_at_previous_visible_line_start (struct it *);
extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
extern ptrdiff_t compute_display_string_pos (struct text_pos *,
void draw_row_fringe_bitmaps (struct window *, struct glyph_row *);
bool draw_window_fringes (struct window *, bool);
bool update_window_fringes (struct window *, bool);
-void compute_fringe_widths (struct frame *, bool);
#ifdef HAVE_NTGUI
void w32_init_fringe (struct redisplay_interface *);
#ifdef HAVE_WINDOW_SYSTEM
void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
+void x_change_tool_bar_height (struct frame *f, int);
extern Lisp_Object tip_frame;
extern Window tip_window;
static void update_frame_line (struct frame *, int);
static int required_matrix_height (struct window *);
static int required_matrix_width (struct window *);
-static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool);
static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
struct window *);
/* Size of frame matrices must equal size of frame. Note
that we are called for X frames with window widths NOT equal
to the frame width (from CHANGE_FRAME_SIZE_1). */
- if (matrix_dim.width != FRAME_COLS (f)
- || matrix_dim.height != FRAME_LINES (f))
+ if (matrix_dim.width != FRAME_TOTAL_COLS (f)
+ || matrix_dim.height != FRAME_TOTAL_LINES (f))
return;
- eassert (matrix_dim.width == FRAME_COLS (f)
- && matrix_dim.height == FRAME_LINES (f));
+ eassert (matrix_dim.width == FRAME_TOTAL_COLS (f)
+ && matrix_dim.height == FRAME_TOTAL_LINES (f));
/* Pointers to glyph memory in glyph rows are exchanged during
the update phase of redisplay, which means in general that a
w->left_col = 0;
w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
w->top_line = FRAME_MENU_BAR_LINES (f);
+ w->total_cols = FRAME_TOTAL_COLS (f);
w->pixel_width = (FRAME_PIXEL_WIDTH (f)
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
- w->total_cols = FRAME_TOTAL_COLS (f);
- w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
w->total_lines = FRAME_TOOL_BAR_LINES (f);
+ w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
allocate_matrices_for_window_redisplay (w);
}
#endif
eassert (!FRAME_WINDOW_P (XFRAME (w->frame)));
eassert (vpos >= 0 && vpos <= w->desired_matrix->nrows);
vpos += WINDOW_TOP_EDGE_LINE (w);
- eassert (vpos >= 0 && vpos <= FRAME_LINES (XFRAME (w->frame)));
+ eassert (vpos >= 0 && vpos <= FRAME_TOTAL_LINES (XFRAME (w->frame)));
return vpos;
}
mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
if (mode_line_row->mode_line_p && mode_line_row->enabled_p)
{
- mode_line_row->y = yb;
+ mode_line_row->y = yb + WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
desired_matrix),
&mouse_face_overwritten_p);
}
}
- pause_p = 0 < i && i < FRAME_LINES (f) - 1;
+ pause_p = 0 < i && i < FRAME_TOTAL_LINES (f) - 1;
/* Now just clean up termcap drivers and set cursor, etc. */
if (!pause_p && set_cursor_p)
cursor at the end of the prompt. If the mini-buffer
is several lines high, find the last line that has
any text on it. */
- row = FRAME_LINES (f);
+ row = FRAME_TOTAL_LINES (f);
do
{
--row;
if (col >= FRAME_CURSOR_X_LIMIT (f))
{
/* If we have another row, advance cursor into it. */
- if (row < FRAME_LINES (f) - 1)
+ if (row < FRAME_TOTAL_LINES (f) - 1)
{
col = FRAME_LEFT_SCROLL_BAR_COLS (f);
row++;
int unchanged_at_top, unchanged_at_bottom;
int window_size;
int changed_lines;
- int *old_hash = alloca (FRAME_LINES (frame) * sizeof (int));
- int *new_hash = alloca (FRAME_LINES (frame) * sizeof (int));
- int *draw_cost = alloca (FRAME_LINES (frame) * sizeof (int));
- int *old_draw_cost = alloca (FRAME_LINES (frame) * sizeof (int));
+ int *old_hash = alloca (FRAME_TOTAL_LINES (frame) * sizeof (int));
+ int *new_hash = alloca (FRAME_TOTAL_LINES (frame) * sizeof (int));
+ int *draw_cost = alloca (FRAME_TOTAL_LINES (frame) * sizeof (int));
+ int *old_draw_cost = alloca (FRAME_TOTAL_LINES (frame) * sizeof (int));
register int i;
- int free_at_end_vpos = FRAME_LINES (frame);
+ int free_at_end_vpos = FRAME_TOTAL_LINES (frame);
struct glyph_matrix *current_matrix = frame->current_matrix;
struct glyph_matrix *desired_matrix = frame->desired_matrix;
number of unchanged lines at the end. */
changed_lines = 0;
unchanged_at_top = 0;
- unchanged_at_bottom = FRAME_LINES (frame);
- for (i = 0; i < FRAME_LINES (frame); i++)
+ unchanged_at_bottom = FRAME_TOTAL_LINES (frame);
+ for (i = 0; i < FRAME_TOTAL_LINES (frame); i++)
{
/* Give up on this scrolling if some old lines are not enabled. */
if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
if (old_hash[i] != new_hash[i])
{
changed_lines++;
- unchanged_at_bottom = FRAME_LINES (frame) - i - 1;
+ unchanged_at_bottom = FRAME_TOTAL_LINES (frame) - i - 1;
}
else if (i == unchanged_at_top)
unchanged_at_top++;
/* If changed lines are few, don't allow preemption, don't scroll. */
if ((!FRAME_SCROLL_REGION_OK (frame)
&& changed_lines < baud_rate / 2400)
- || unchanged_at_bottom == FRAME_LINES (frame))
+ || unchanged_at_bottom == FRAME_TOTAL_LINES (frame))
return 1;
- window_size = (FRAME_LINES (frame) - unchanged_at_top
+ window_size = (FRAME_TOTAL_LINES (frame) - unchanged_at_top
- unchanged_at_bottom);
if (FRAME_SCROLL_REGION_OK (frame))
&& window_size >= 18 && baud_rate > 2400
&& (window_size >=
10 * scrolling_max_lines_saved (unchanged_at_top,
- FRAME_LINES (frame) - unchanged_at_bottom,
+ FRAME_TOTAL_LINES (frame) - unchanged_at_bottom,
old_hash, new_hash, draw_cost)))
return 0;
}
}
-/* Change the frame height and/or width. Values may be given as zero to
- indicate no change is to take place.
-
- new_height and new_width refer to the text portion of the frame. It
- doesn't matter for new_height, since text and total portion are the
- same in that case. But new_width must be enlarged to get the total
- width of the frame.
-
- If DELAY, assume we're being called from a signal handler, and
- queue the change for later - perhaps the next redisplay.
- Since this tries to resize windows, we can't call it
- from a signal handler.
-
- SAFE means this function is called from a place where it's
- safe to change frame sizes while a redisplay is in progress. */
-
-void
-change_frame_size (struct frame *f, int new_width, int new_height,
- bool pretend, bool delay, bool safe, bool pixelwise)
-{
- Lisp_Object tail, frame;
-
- if (FRAME_MSDOS_P (f))
- {
- /* On MS-DOS, all frames use the same screen, so a change in
- size affects all frames. Termcap now supports multiple
- ttys. */
- FOR_EACH_FRAME (tail, frame)
- if (! FRAME_WINDOW_P (XFRAME (frame)))
- change_frame_size_1 (XFRAME (frame), new_width, new_height,
- pretend, delay, safe, pixelwise);
- }
- else
- change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
- pixelwise);
-}
static void
change_frame_size_1 (struct frame *f, int new_width, int new_height,
bool pretend, bool delay, bool safe, bool pixelwise)
{
- int new_text_width, new_text_height, new_root_width;
- int old_root_width = WINDOW_PIXEL_WIDTH (XWINDOW (FRAME_ROOT_WINDOW (f)));
- int new_cols, new_lines;
- ptrdiff_t count = SPECPDL_INDEX ();
-
/* If we can't deal with the change now, queue it for later. */
if (delay || (redisplaying_p && !safe))
{
f->new_height = new_height;
f->new_pixelwise = pixelwise;
delayed_size_change = 1;
- return;
- }
-
- /* This size-change overrides any pending one for this frame. */
- f->new_height = 0;
- f->new_width = 0;
- f->new_pixelwise = 0;
-
- /* If an argument is zero, set it to the current value. */
- if (pixelwise)
- {
- new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width;
- new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
- /* Consider rounding here: Currently, the root window can be
- larger than the frame in terms of columns/lines. */
- new_cols = new_text_width / FRAME_COLUMN_WIDTH (f);
- new_lines = new_text_height / FRAME_LINE_HEIGHT (f);
}
else
{
- new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width;
- new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height;
- new_text_width = new_cols * FRAME_COLUMN_WIDTH (f);
- new_text_height = new_lines * FRAME_LINE_HEIGHT (f);
- }
-
- /* Compute width of windows in F. */
- /* Round up to the smallest acceptable size. */
- check_frame_size (f, &new_text_width, &new_text_height, 1);
-
- /* This is the width of the frame without vertical scroll bars and
- fringe columns. Do this after rounding - see discussion of
- bug#9723. */
- new_root_width = (new_text_width
- + FRAME_SCROLL_BAR_AREA_WIDTH (f)
- + FRAME_TOTAL_FRINGE_WIDTH (f));
- /* If we're not changing the frame size, quit now. */
- /* Frame width may be unchanged but the text portion may change, for
- example, fullscreen and remove/add scroll bar. */
- if (new_text_height == FRAME_TEXT_HEIGHT (f)
- && new_text_width == FRAME_TEXT_WIDTH (f)
- && new_root_width == old_root_width
- && (FRAME_PIXEL_HEIGHT (f) ==
- FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height))
- && (FRAME_PIXEL_WIDTH (f) ==
- FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width)))
- return;
-
- block_input ();
-
-#ifdef MSDOS
- /* We only can set screen dimensions to certain values supported
- by our video hardware. Try to find the smallest size greater
- or equal to the requested dimensions. */
- dos_set_window_size (&new_lines, &new_cols);
-#endif
-
- if (new_text_height != FRAME_TEXT_HEIGHT (f))
- {
- resize_frame_windows (f, new_text_height, 0, 1);
-
- /* 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_lines;
- }
-
- if (new_text_width != FRAME_TEXT_WIDTH (f)
- || new_root_width != old_root_width)
- {
- resize_frame_windows (f, new_root_width, 1, 1);
-
- /* 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_cols;
+ /* This size-change overrides any pending one for this frame. */
+ f->new_height = 0;
+ f->new_width = 0;
+ f->new_pixelwise = 0;
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
- if (WINDOWP (f->tool_bar_window))
+ /* If an argument is zero, set it to the current value. */
+ if (pixelwise)
{
- XWINDOW (f->tool_bar_window)->total_cols = new_cols;
- XWINDOW (f->tool_bar_window)->pixel_width = new_root_width;
+ new_width = (new_width <= 0) ? FRAME_TEXT_WIDTH (f) : new_width;
+ new_height = (new_height <= 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
+ }
+ else
+ {
+ new_width = (((new_width <= 0) ? FRAME_COLS (f) : new_width)
+ * FRAME_COLUMN_WIDTH (f));
+ new_height = (((new_height <= 0) ? FRAME_LINES (f) : new_height)
+ * FRAME_LINE_HEIGHT (f));
}
-#endif
- }
-
- SET_FRAME_COLS (f, new_cols);
- FRAME_LINES (f) = new_lines;
- FRAME_TEXT_WIDTH (f) = new_text_width;
- FRAME_TEXT_HEIGHT (f) = new_text_height;
- FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width);
- FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height);
- {
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
- int text_area_x, text_area_y, text_area_width, text_area_height;
-
- window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
- &text_area_height);
- if (w->cursor.x >= text_area_x + text_area_width)
- w->cursor.hpos = w->cursor.x = 0;
- if (w->cursor.y >= text_area_y + text_area_height)
- w->cursor.vpos = w->cursor.y = 0;
- }
+ /* Adjust frame size but make sure x_set_window_size does not
+ get called. */
+ adjust_frame_size (f, new_width, new_height, 5, pretend);
+ }
+}
- adjust_frame_glyphs (f);
- calculate_costs (f);
- SET_FRAME_GARBAGED (f);
- f->resized_p = 1;
- unblock_input ();
+/* Change text height/width of frame F. Values may be given as zero to
+ indicate that no change is needed.
- record_unwind_current_buffer ();
+ If DELAY, assume we're being called from a signal handler, and queue
+ the change for later - perhaps the next redisplay. Since this tries
+ to resize windows, we can't call it from a signal handler.
- run_window_configuration_change_hook (f);
+ SAFE means this function is called from a place where it's safe to
+ change frame sizes while a redisplay is in progress. */
+void
+change_frame_size (struct frame *f, int new_width, int new_height,
+ bool pretend, bool delay, bool safe, bool pixelwise)
+{
+ Lisp_Object tail, frame;
- unbind_to (count, Qnil);
+ if (FRAME_MSDOS_P (f))
+ {
+ /* On MS-DOS, all frames use the same screen, so a change in
+ size affects all frames. Termcap now supports multiple
+ ttys. */
+ FOR_EACH_FRAME (tail, frame)
+ if (! FRAME_WINDOW_P (XFRAME (frame)))
+ change_frame_size_1 (XFRAME (frame), new_width, new_height,
+ pretend, delay, safe, pixelwise);
+ }
+ else
+ change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
+ pixelwise);
}
\f
/***********************************************************************
t->display_info.tty->top_frame = selected_frame;
change_frame_size (XFRAME (selected_frame),
FrameCols (t->display_info.tty),
- FrameRows (t->display_info.tty), 0, 0, 1, 0);
+ FrameRows (t->display_info.tty)
+ - FRAME_MENU_BAR_LINES (f), 0, 0, 1, 0);
/* Delete the initial terminal. */
if (--initial_terminal->reference_count == 0
{
struct frame *sf = SELECTED_FRAME ();
int width = FRAME_TOTAL_COLS (sf);
- int height = FRAME_LINES (sf);
+ int height = FRAME_TOTAL_LINES (sf);
/* If these sizes are so big they cause overflow, just ignore the
change. It's not clear what better we could do. The rest of
/* FIXME: We should probably get rid of this! */
Lisp_Object Vsignaling_function;
-/* If non-nil, Lisp code must not be run since some part of Emacs is
- in an inconsistent state. Currently, x-create-frame uses this to
- avoid triggering window-configuration-change-hook while the new
- frame is half-initialized. */
+/* If non-nil, Lisp code must not be run since some part of Emacs is in
+ an inconsistent state. Currently unused. */
Lisp_Object inhibit_lisp_code;
/* These would ordinarily be static, but they need to be visible to GDB. */
Lisp_Object Qmouse_color;
Lisp_Object Qminibuffer;
Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
+Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars;
Lisp_Object Qvisibility;
Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
Lisp_Object Qscreen_gamma;
static Lisp_Object Qfocus_in_hook;
static Lisp_Object Qfocus_out_hook;
static Lisp_Object Qdelete_frame_functions;
-
+static Lisp_Object Qframe_windows_min_size;
static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
/* The currently selected frame. */
: "Window system is not in use or not initialized");
}
+
+/* Return the value of frame parameter PROP in frame FRAME. */
+#ifdef HAVE_WINDOW_SYSTEM
+Lisp_Object
+get_frame_param (register struct frame *frame, Lisp_Object prop)
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (prop, frame->param_alist);
+ if (EQ (tem, Qnil))
+ return tem;
+ return Fcdr (tem);
+}
+#endif
+
+
+/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
+ state of frame F would be affected by a vertical (horizontal if
+ HORIZONTAL is true) resize. */
+bool
+frame_inhibit_resize (struct frame *f, bool horizontal)
+{
+
+ return (frame_inhibit_implied_resize
+ || !NILP (get_frame_param (f, Qfullscreen)));
+}
+
+#if 0
+bool
+frame_inhibit_resize (struct frame *f, bool horizontal)
+{
+ Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+
+ return (frame_inhibit_implied_resize
+ || EQ (fullscreen, Qfullboth)
+ || EQ (fullscreen, Qfullscreen)
+ || EQ (fullscreen, Qmaximized)
+ || (horizontal && EQ (fullscreen, Qfullwidth))
+ || (!horizontal && EQ (fullscreen, Qfullheight)));
+}
+#endif
+
static void
set_menu_bar_lines_1 (Lisp_Object window, int n)
{
return type;
}
+int
+frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object pixelwise)
+{
+ return XINT (call3 (Qframe_windows_min_size, frame, horizontal, pixelwise));
+}
+
+
+/* Make sure windows sizes of frame F are OK. new_width and new_height
+ are in pixels. A value of -1 means no change is requested for that
+ size (but the frame may still have to be resized to accomodate
+ windows with their minimum sizes.
+
+ The argument INHIBIT can assume the following values:
+
+ 0 means to unconditionally call x_set_window_size even if sizes
+ apparently do not change. Fx_create_frame uses this to pass the
+ initial size to the window manager.
+
+ 1 means to call x_set_window_size iff the pixel size really changes.
+ Fset_frame_size, Fset_frame_height, ... use this.
+
+ 2 means to unconditionally call x_set_window_size provided
+ frame_inhibit_resize allows it. The menu bar code uses this.
+
+ 3 means call x_set_window_size iff window minimum sizes must be
+ preserved or frame_inhibit_resize allows it, x_set_left_fringe,
+ x_set_scroll_bar_width, ... use this.
+
+ 4 means call x_set_window_size iff window minimum sizes must be
+ preserved. x_set_tool_bar_lines, x_set_right_divider_width, ... use
+ this. BUT maybe the toolbar code shouldn't ....
+
+ 5 means to never call x_set_window_size. change_frame_size uses
+ this.
+
+ For 2 and 3 note that if frame_inhibit_resize inhibits resizing and
+ minimum sizes are not violated no internal resizing takes place
+ either. For 2, 3, 4 and 5 note that even if no x_set_window_size
+ call is issued, window sizes may have to be adjusted in order to
+ support minimum size constraints for the frame's windows.
+
+ PRETEND is as for change_frame_size. */
+void
+adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, bool pretend)
+{
+ int unit_width = FRAME_COLUMN_WIDTH (f);
+ int unit_height = FRAME_LINE_HEIGHT (f);
+ int old_pixel_width = FRAME_PIXEL_WIDTH (f);
+ int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
+ int new_pixel_width, new_pixel_height;
+ /* The following two values are calculated from the old frame pixel
+ sizes and any "new" settings for tool bar, menu bar and internal
+ borders. We do it this way to detect whether we have to call
+ x_set_window_size as consequence of the new settings. */
+ int windows_width = FRAME_WINDOWS_WIDTH (f);
+ int windows_height = FRAME_WINDOWS_HEIGHT (f);
+ int min_windows_width, min_windows_height;
+ /* These are a bit tedious, maybe we should use a macro. */
+ struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
+ int old_windows_width = WINDOW_PIXEL_WIDTH (r);
+ int old_windows_height
+ = (WINDOW_PIXEL_HEIGHT (r)
+ + (FRAME_HAS_MINIBUF_P (f)
+ ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
+ : 0));
+ int new_windows_width, new_windows_height;
+ int old_text_width = FRAME_TEXT_WIDTH (f);
+ int old_text_height = FRAME_TEXT_HEIGHT (f);
+ /* If a size is < 0 use the old value. */
+ int new_text_width = (new_width >= 0) ? new_width : old_text_width;
+ int new_text_height = (new_height >= 0) ? new_height : old_text_height;
+ int new_cols, new_lines;
+ bool inhibit_horizontal, inhibit_vertical;
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+ /* The following two values are calculated from the old window body
+ sizes and any "new" settings for scroll bars, dividers, fringes and
+ margins (though the latter should have been processed already). */
+ min_windows_width = frame_windows_min_size (frame, Qt, Qt);
+ min_windows_height = frame_windows_min_size (frame, Qnil, Qt);
+
+ if (inhibit >= 2 && inhibit <= 4)
+ /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
+ within the limits and either frame_inhibit_resize tells us to do
+ so or INHIBIT equals 4. */
+ {
+ inhibit_horizontal = ((windows_width >= min_windows_width
+ && (inhibit == 4 || frame_inhibit_resize (f, true)))
+ ? true : false);
+ inhibit_vertical = ((windows_height >= min_windows_height
+ && (inhibit == 4 || frame_inhibit_resize (f, false)))
+ ? true : false);
+ }
+ else
+ /* Otherwise inhibit if INHIBIT equals 5. */
+ inhibit_horizontal = inhibit_vertical = inhibit == 5;
+
+ new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
+ ? old_pixel_width
+ : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
+ min_windows_width
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
+ new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+ new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
+ new_cols = new_text_width / unit_width;
+
+ new_pixel_height = ((inhibit_vertical && (inhibit < 5))
+ ? old_pixel_height
+ : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
+ min_windows_height
+ + FRAME_TOP_MARGIN_HEIGHT (f)
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
+ new_windows_height = (new_pixel_height
+ - FRAME_TOP_MARGIN_HEIGHT (f)
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
+ new_lines = new_text_height / unit_height;
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_X_WINDOW (f)
+ && f->official
+ && ((!inhibit_horizontal
+ && (new_pixel_width != old_pixel_width
+ || inhibit == 0 || inhibit == 2))
+ || (!inhibit_vertical
+ && (new_pixel_height != old_pixel_height
+ || inhibit == 0 || inhibit == 2))))
+ /* We are either allowed to change the frame size or the minimum
+ sizes request such a change. Do not care for fixing minimum
+ sizes here, we do that eventually when we're called from
+ change_frame_size. */
+ {
+ /* Make sure we respect fullheight and fullwidth. */
+ if (inhibit_horizontal)
+ new_text_width = old_text_width;
+ else if (inhibit_vertical)
+ new_text_height = old_text_height;
+
+ x_set_window_size (f, 0, new_text_width, new_text_height, 1);
+ f->resized_p = true;
+
+ return;
+ }
+#endif
+
+ if (new_text_width == old_text_width
+ && new_text_height == old_text_height
+ && new_windows_width == old_windows_width
+ && new_windows_height == old_windows_height
+ && new_pixel_width == old_pixel_width
+ && new_pixel_height == old_pixel_height)
+ /* No change. Sanitize window sizes and return. */
+ {
+ sanitize_window_sizes (frame, Qt);
+ sanitize_window_sizes (frame, Qnil);
+
+ return;
+ }
+
+ block_input ();
+
+#ifdef MSDOS
+ /* We only can set screen dimensions to certain values supported
+ by our video hardware. Try to find the smallest size greater
+ or equal to the requested dimensions. */
+ dos_set_window_size (&new_lines, &new_cols);
+#endif
+
+ if (new_windows_width != old_windows_width)
+ {
+ resize_frame_windows (f, new_windows_width, 1, 1);
+
+ /* 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_cols;
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+ if (WINDOWP (f->tool_bar_window))
+ {
+ XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
+ XWINDOW (f->tool_bar_window)->total_cols
+ = new_windows_width / unit_width;
+ }
+#endif
+ }
+
+ if (new_windows_height != old_windows_height
+ /* When the top margin has changed we have to recalculate the top
+ edges of all windows. No such calculation is necessary for the
+ left edges. */
+ || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
+ {
+ resize_frame_windows (f, new_windows_height, 0, 1);
+
+ /* 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_lines;
+ }
+
+ /* Assign new sizes. */
+ FRAME_TEXT_WIDTH (f) = new_text_width;
+ FRAME_TEXT_HEIGHT (f) = new_text_height;
+ FRAME_PIXEL_WIDTH (f) = new_pixel_width;
+ FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
+ SET_FRAME_COLS (f, new_cols);
+ SET_FRAME_LINES (f, new_lines);
+
+ {
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+ int text_area_x, text_area_y, text_area_width, text_area_height;
+
+ window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
+ &text_area_height);
+ if (w->cursor.x >= text_area_x + text_area_width)
+ w->cursor.hpos = w->cursor.x = 0;
+ if (w->cursor.y >= text_area_y + text_area_height)
+ w->cursor.vpos = w->cursor.y = 0;
+ }
+
+ /* Sanitize window sizes. */
+ sanitize_window_sizes (frame, Qt);
+ sanitize_window_sizes (frame, Qnil);
+
+ adjust_frame_glyphs (f);
+ calculate_costs (f);
+ SET_FRAME_GARBAGED (f);
+
+ /* A frame was "resized" if one of its pixelsizes changed, even if its
+ X window wasn't resized at all. */
+ f->resized_p = (new_pixel_width != old_pixel_width
+ || new_pixel_height != old_pixel_height);
+
+ unblock_input ();
+
+ run_window_configuration_change_hook (f);
+}
+
+
struct frame *
make_frame (bool mini_p)
{
f->wants_modeline = true;
f->redisplay = true;
f->garbaged = true;
+ f->official = false;
f->column_width = 1; /* !FRAME_WINDOW_P value. */
f->line_height = 1; /* !FRAME_WINDOW_P value. */
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ f->horizontal_scroll_bars = false;
f->want_fullscreen = FULLSCREEN_NONE;
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
f->last_tool_bar_item = -1;
/* 10 is arbitrary,
just so that there is "something there."
- Correct size will be set up later with change_frame_size. */
+ Correct size will be set up later with adjust_frame_size. */
SET_FRAME_COLS (f, 10);
- FRAME_LINES (f) = 10;
+ SET_FRAME_LINES (f, 10);
SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
}
if (mini_p)
- set_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)),
- 0, 0);
+ {
+ set_window_buffer (mini_window,
+ (NILP (Vminibuffer_list)
+ ? get_minibuffer (0)
+ : Fcar (Vminibuffer_list)),
+ 0, 0);
+ /* No horizontal scroll bars in minibuffers. */
+ wset_horizontal_scroll_bar (mw, Qnil);
+ }
fset_root_window (f, root_window);
fset_selected_window (f, root_window);
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = false;
#endif
/* The default value of menu-bar-mode is t. */
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = false;
#endif
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
{
int width, height;
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
- change_frame_size (f, width, height, 0, 0, 0, 0);
+ adjust_frame_size (f, width, height, 5, 0);
}
adjust_frame_glyphs (f);
}
\f
-/* Return the value of frame parameter PROP in frame FRAME. */
-
-#ifdef HAVE_WINDOW_SYSTEM
-Lisp_Object
-get_frame_param (register struct frame *frame, Lisp_Object prop)
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, frame->param_alist);
- if (EQ (tem, Qnil))
- return tem;
- return Fcdr (tem);
-}
-#endif
-
/* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
void
? (f->new_pixelwise
? (f->new_height / FRAME_LINE_HEIGHT (f))
: f->new_height)
- : FRAME_LINES (f)) - FRAME_TOP_MARGIN (f);
+ : FRAME_LINES (f));
store_in_alist (&alist, Qheight, make_number (height));
width = (f->new_width
? (f->new_pixelwise
}
DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
- doc: /* Return total columns of FRAME. */)
+ doc: /* Return number of total columns of FRAME. */)
(Lisp_Object frame)
{
return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
}
+DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
+ doc: /* Return number of total lines of FRAME. */)
+ (Lisp_Object frame)
+{
+ return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
+}
+
DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
doc: /* Return text area width of FRAME in pixels. */)
(Lisp_Object frame)
return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
}
+DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
+ doc: /* Return scroll bar height of FRAME in pixels. */)
+ (Lisp_Object frame)
+{
+ return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
+}
+
DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
doc: /* Return fringe width of FRAME in pixels. */)
(Lisp_Object frame)
return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
}
-/* For requested height in *HEIGHTP, calculate new height of frame F in
- character units and return true if actual height should be changed. */
-
-static bool
-adjust_frame_height (struct frame *f, int *heightp)
-{
- if (FRAME_LINES (f) - FRAME_TOP_MARGIN (f) != *heightp)
- {
- *heightp += FRAME_TOP_MARGIN (f);
- return 1;
- }
- return 0;
-}
-
DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
doc: /* Specify that the frame FRAME has HEIGHT text lines.
Optional third arg PRETEND non-nil means that redisplay should use
FRAME should be HEIGHT pixels high. */)
(Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_height;
CHECK_TYPE_RANGED_INTEGER (int, height);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (NILP (pixelwise))
- {
- int h = XINT (height);
-
- if (adjust_frame_height (f, &h))
- x_set_window_size (f, 1, FRAME_COLS (f), h, 0);
+ pixel_height = (!NILP (pixelwise)
+ ? XINT (height)
+ : XINT (height) * FRAME_LINE_HEIGHT (f));
+ if (pixel_height != FRAME_TEXT_HEIGHT (f))
+ adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend));
- do_pending_window_change (0);
- }
- else if (XINT (height) != FRAME_TEXT_HEIGHT (f))
- {
- x_set_window_size (f, 1, FRAME_TEXT_WIDTH (f), XINT (height), 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, 0, XINT (height), !NILP (pretend), 0, 0,
- NILP (pixelwise) ? 0 : 1);
return Qnil;
}
should be WIDTH pixels wide. */)
(Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_width;
CHECK_TYPE_RANGED_INTEGER (int, width);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (NILP (pixelwise))
- {
- if (XINT (width) != FRAME_COLS (f))
- x_set_window_size (f, 1, XINT (width), FRAME_LINES (f), 0);
+ pixel_width = (!NILP (pixelwise)
+ ? XINT (width)
+ : XINT (width) * FRAME_COLUMN_WIDTH (f));
+ if (pixel_width != FRAME_TEXT_WIDTH (f))
+ adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend));
- do_pending_window_change (0);
- }
- else if (XINT (width) != FRAME_TEXT_WIDTH (f))
- {
- x_set_window_size (f, 1, XINT (width), FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, XINT (width), 0, !NILP (pretend), 0, 0,
- NILP (pixelwise) ? 0 : 1);
return Qnil;
}
Optional argument PIXELWISE non-nil means to measure in pixels. */)
(Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_width, pixel_height;
CHECK_TYPE_RANGED_INTEGER (int, width);
CHECK_TYPE_RANGED_INTEGER (int, height);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- int h = XINT (height);
-
- if (!NILP (pixelwise)
- ? (XINT (width) != FRAME_TEXT_WIDTH (f)
- || h != FRAME_TEXT_HEIGHT (f)
- || f->new_height || f->new_width)
- : (adjust_frame_height (f, &h)
- || XINT (width) != FRAME_COLS (f)
- || f->new_height || f->new_width))
- {
- x_set_window_size (f, 1, XINT (width), h,
- NILP (pixelwise) ? 0 : 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, XINT (width), XINT (height), 0, 0, 0,
- NILP (pixelwise) ? 0 : 1);
+ pixel_width = (!NILP (pixelwise)
+ ? XINT (width)
+ : XINT (width) * FRAME_COLUMN_WIDTH (f));
+ pixel_height = (!NILP (pixelwise)
+ ? XINT (height)
+ : XINT (height) * FRAME_LINE_HEIGHT (f));
+
+ if (pixel_width != FRAME_TEXT_WIDTH (f)
+ || pixel_height != FRAME_TEXT_HEIGHT (f))
+ adjust_frame_size (f, pixel_width, pixel_height, 1, 0);
return Qnil;
}
{"mouse-color", &Qmouse_color},
{"name", &Qname},
{"scroll-bar-width", &Qscroll_bar_width},
+ {"scroll-bar-height", &Qscroll_bar_height},
{"title", &Qtitle},
{"unsplittable", &Qunsplittable},
{"vertical-scroll-bars", &Qvertical_scroll_bars},
+ {"horizontal-scroll-bars", &Qhorizontal_scroll_bars},
{"visibility", &Qvisibility},
{"tool-bar-lines", &Qtool_bar_lines},
{"scroll-bar-foreground", &Qscroll_bar_foreground},
/* If both of these parameters are present, it's more efficient to
set them both at once. So we wait until we've looked at the
entire list before we set them. */
- int width = 0, height = 0;
+ int width, height;
bool width_change = 0, height_change = 0;
/* Same here. */
{
Lisp_Object frame;
- /* Make this 1, eventually. */
- check_frame_size (f, &width, &height, 1);
-
XSETFRAME (frame, f);
if ((width_change || height_change)
for non-toolkit scroll bar.
ruler-mode.el depends on this. */
: Qnil));
+ store_in_alist (alistptr, Qscroll_bar_height,
+ (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
+ ? make_number (0)
+ : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
+ ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
+ /* nil means "use default height"
+ for non-toolkit scroll bar. */
+ : Qnil));
/* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
MS-Windows it returns a value whose type is HANDLE, which is
actually a pointer. Explicit casting avoids compiler
}
}
-
void
-x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
+x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- compute_fringe_widths (f, 1);
-#ifdef HAVE_X_WINDOWS
- /* Must adjust this so window managers report correct number of columns. */
- if (FRAME_X_WINDOW (f) != 0)
- x_wm_set_size_hint (f, 0, 0);
-#endif
+ int unit = FRAME_COLUMN_WIDTH (f);
+ int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
+ int new_width;
+
+ new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
+ ? eabs (XINT (new_value)) : 8);
+
+ if (new_width != old_width)
+ {
+ FRAME_LEFT_FRINGE_WIDTH (f) = new_width;
+ FRAME_FRINGE_COLS (f) /* Round up. */
+ = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
+
+ if (FRAME_X_WINDOW (f) != 0)
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+ }
}
+
void
-x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- CHECK_TYPE_RANGED_INTEGER (int, arg);
+ int unit = FRAME_COLUMN_WIDTH (f);
+ int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
+ int new_width;
- if (XINT (arg) == f->border_width)
- return;
+ new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
+ ? eabs (XINT (new_value)) : 8);
- if (FRAME_X_WINDOW (f) != 0)
- error ("Cannot change the border width of a frame");
+ if (new_width != old_width)
+ {
+ FRAME_RIGHT_FRINGE_WIDTH (f) = new_width;
+ FRAME_FRINGE_COLS (f) /* Round up. */
+ = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
- f->border_width = XINT (arg);
+ if (FRAME_X_WINDOW (f) != 0)
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+ }
}
+
void
-x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int old = FRAME_INTERNAL_BORDER_WIDTH (f);
-
CHECK_TYPE_RANGED_INTEGER (int, arg);
- FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
- if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
- FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
-#ifdef USE_X_TOOLKIT
- if (FRAME_X_OUTPUT (f)->edit_widget)
- widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
-#endif
-
- if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
+ if (XINT (arg) == f->border_width)
return;
if (FRAME_X_WINDOW (f) != 0)
- {
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
- SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
- }
- else
- SET_FRAME_GARBAGED (f);
+ error ("Cannot change the border width of a frame");
+
+ f->border_width = XINT (arg);
}
void
FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
-
- if (FRAME_RIGHT_DIVIDER_WIDTH (f) == old)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
+ if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
{
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, -1, -1, 4, 0);
+ adjust_frame_glyphs (f);
SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
}
- else
- SET_FRAME_GARBAGED (f);
+
}
void
FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
-
- if (FRAME_BOTTOM_DIVIDER_WIDTH (f) == old)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
+ if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
{
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, -1, -1, 4, 0);
+ adjust_frame_glyphs (f);
SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
}
- else
- SET_FRAME_GARBAGED (f);
}
void
if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
|| (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
|| (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
+ || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
{
FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
= (NILP (arg)
However, if the window hasn't been created yet, we shouldn't
call x_set_window_size. */
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
}
}
+void
+x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
+ if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
+ || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
+ {
+ FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
+ = NILP (arg) ? false : true;
+
+ /* We set this parameter before creating the X window for the
+ frame, so we can get the geometry right from the start.
+ However, if the window hasn't been created yet, we shouldn't
+ call x_set_window_size. */
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+ }
+#endif
+}
+
void
x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
x_set_scroll_bar_default_width (f);
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
}
else if (RANGED_INTEGERP (1, arg, INT_MAX)
&& XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
}
- /* Eventually remove the following call. It should have been done by
- x_set_window_size already. */
- change_frame_size (f, 0, 0, 0, 0, 0, 1);
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
}
+void
+x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
+ int unit = FRAME_LINE_HEIGHT (f);
+
+ if (NILP (arg))
+ {
+ x_set_scroll_bar_default_height (f);
+
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+ }
+ else if (RANGED_INTEGERP (1, arg, INT_MAX)
+ && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
+ {
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+ }
+
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
+#endif
+}
+
void
x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
long
x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
{
- register Lisp_Object tem0, tem1, tem2;
+ Lisp_Object height, width, user_size, top, left, user_position;
long window_prompting = 0;
Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
SET_FRAME_COLS (f, DEFAULT_COLS);
SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
- FRAME_LINES (f) = DEFAULT_ROWS;
+ SET_FRAME_LINES (f, DEFAULT_ROWS);
/* Window managers expect that if program-specified
positions are not (0,0), they're intentional, not defaults. */
f->top_pos = 0;
f->left_pos = 0;
- /* Ensure that old new_width and new_height will not override the
- values set here. */
- /* ++KFS: This was specific to W32, but seems ok for all platforms */
- f->new_width = f->new_height = f->new_pixelwise = 0;
+ /* Ensure that earlier new_width and new_height settings won't
+ override what we specify below. */
+ f->new_width = f->new_height = 0;
- tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
- tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
- tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+ if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
{
- if (!EQ (tem0, Qunbound))
+ if (!EQ (width, Qunbound))
{
- CHECK_NUMBER (tem0);
- if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX))
- xsignal1 (Qargs_out_of_range, tem0);
- FRAME_LINES (f) = XINT (tem0);
+ CHECK_NUMBER (width);
+ if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
+ xsignal1 (Qargs_out_of_range, width);
+
+ SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
}
- if (!EQ (tem1, Qunbound))
+
+ if (!EQ (height, Qunbound))
{
- CHECK_NUMBER (tem1);
- if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX))
- xsignal1 (Qargs_out_of_range, tem1);
- SET_FRAME_COLS (f, XINT (tem1));
+ CHECK_NUMBER (height);
+ if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
+ xsignal1 (Qargs_out_of_range, height);
+
+ SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
}
- if (!NILP (tem2) && !EQ (tem2, Qunbound))
+
+ user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+ if (!NILP (user_size) && !EQ (user_size, Qunbound))
window_prompting |= USSize;
else
window_prompting |= PSize;
}
-
- /* This used to be done _before_ calling x_figure_window_size, but
- since the height is reset here, this was really a no-op. I
- assume that moving it here does what Gerd intended (although he
- no longer can remember what that was... ++KFS, 2003-03-25. */
-
- /* Add the tool-bar height to the initial frame height so that the
- user gets a text display area of the size he specified with -g or
- via .Xdefaults. Later changes of the tool-bar height don't
- change the frame size. This is done so that users can create
- tall Emacs frames without having to guess how tall the tool-bar
- will get. */
- if (toolbar_p && FRAME_TOOL_BAR_HEIGHT (f))
+ /* Add a tool bar height to the initial frame height so that the user
+ gets a text display area of the size he specified with -g or via
+ .Xdefaults. Later changes of the tool bar height don't change the
+ frame size. This is done so that users can create tall Emacs
+ frames without having to guess how tall the tool bar will get. */
+ if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
{
- int margin, relief, bar_height;
+ int margin, relief;
relief = (tool_bar_button_relief >= 0
? tool_bar_button_relief
else
margin = 0;
- /* PXW: We should be able to not round here. */
- bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
- FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
+ FRAME_TOOL_BAR_HEIGHT (f)
+ = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+ Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f));
}
- compute_fringe_widths (f, 0);
-
- SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
- SET_FRAME_HEIGHT(f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
-
- tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
- tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
- tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+ left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+ user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+ if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
{
- if (EQ (tem0, Qminus))
+ if (EQ (top, Qminus))
{
f->top_pos = 0;
window_prompting |= YNegative;
}
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
- && CONSP (XCDR (tem0))
- && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX))
+ else if (CONSP (top) && EQ (XCAR (top), Qminus)
+ && CONSP (XCDR (top))
+ && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
{
- f->top_pos = - XINT (XCAR (XCDR (tem0)));
+ f->top_pos = - XINT (XCAR (XCDR (top)));
window_prompting |= YNegative;
}
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
- && CONSP (XCDR (tem0))
- && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0))))
+ else if (CONSP (top) && EQ (XCAR (top), Qplus)
+ && CONSP (XCDR (top))
+ && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
{
- f->top_pos = XINT (XCAR (XCDR (tem0)));
+ f->top_pos = XINT (XCAR (XCDR (top)));
}
- else if (EQ (tem0, Qunbound))
+ else if (EQ (top, Qunbound))
f->top_pos = 0;
else
{
- CHECK_TYPE_RANGED_INTEGER (int, tem0);
- f->top_pos = XINT (tem0);
+ CHECK_TYPE_RANGED_INTEGER (int, top);
+ f->top_pos = XINT (top);
if (f->top_pos < 0)
window_prompting |= YNegative;
}
- if (EQ (tem1, Qminus))
+ if (EQ (left, Qminus))
{
f->left_pos = 0;
window_prompting |= XNegative;
}
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
- && CONSP (XCDR (tem1))
- && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX))
+ else if (CONSP (left) && EQ (XCAR (left), Qminus)
+ && CONSP (XCDR (left))
+ && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
{
- f->left_pos = - XINT (XCAR (XCDR (tem1)));
+ f->left_pos = - XINT (XCAR (XCDR (left)));
window_prompting |= XNegative;
}
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
- && CONSP (XCDR (tem1))
- && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1))))
+ else if (CONSP (left) && EQ (XCAR (left), Qplus)
+ && CONSP (XCDR (left))
+ && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
{
- f->left_pos = XINT (XCAR (XCDR (tem1)));
+ f->left_pos = XINT (XCAR (XCDR (left)));
}
- else if (EQ (tem1, Qunbound))
+ else if (EQ (left, Qunbound))
f->left_pos = 0;
else
{
- CHECK_TYPE_RANGED_INTEGER (int, tem1);
- f->left_pos = XINT (tem1);
+ CHECK_TYPE_RANGED_INTEGER (int, left);
+ f->left_pos = XINT (left);
if (f->left_pos < 0)
window_prompting |= XNegative;
}
- if (!NILP (tem2) && ! EQ (tem2, Qunbound))
+ if (!NILP (user_position) && ! EQ (user_position, Qunbound))
window_prompting |= USPosition;
else
window_prompting |= PPosition;
{
DEFSYM (Qframep, "framep");
DEFSYM (Qframe_live_p, "frame-live-p");
+ DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
DEFSYM (Qexplicit_name, "explicit-name");
DEFSYM (Qheight, "height");
DEFSYM (Qicon, "icon");
Vdefault_frame_alist = Qnil;
DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
- doc: /* Default position of scroll bars on this window-system. */);
+ doc: /* Default position of vertical scroll bars on this window-system. */);
#ifdef HAVE_WINDOW_SYSTEM
#if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
/* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
Vdefault_frame_scroll_bars = Qnil;
#endif
+ DEFVAR_LISP ("default-frame-horizontal-scroll-bars", Vdefault_frame_horizontal_scroll_bars,
+ doc: /* Default value for horizontal scroll bars on this window-system. */);
+#ifdef HAVE_WINDOW_SYSTEM
+ Vdefault_frame_horizontal_scroll_bars = Qt;
+#else
+ Vdefault_frame_horizontal_scroll_bars = Qnil;
+#endif
+
DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
scroll_bar_adjust_thumb_portion_p,
doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
Vtool_bar_mode = Qnil;
#endif
+ DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height,
+ doc: /* Height of tool bar of initial frame. */);
+ Vframe_initial_frame_tool_bar_height = make_number (0);
+
DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
doc: /* Minibufferless frames use this frame's minibuffer.
Emacs cannot create minibufferless frames unless this is set to an
is non-nil, no rounding occurs, hence frame sizes can increase/decrease
by one pixel.
-With some window managers you have to set this to non-nil in order to
-fully maximize frames. To resize your initial frame pixelwise,
-set this option to a non-nil value in your init file. */);
+With some window managers you may have to set this to non-nil in order
+to fully maximize frames. To resize your initial frame pixelwise, set
+this option to a non-nil value in your init file. */);
frame_resize_pixelwise = 0;
+ DEFVAR_BOOL ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
+ doc: /* Non-nil means do not resize frame implicitly.
+If this option is nil, setting default font, menubar mode, fringe width,
+or scroll bar mode of a specific frame may resize the frame in order to
+preserve the number of columns or lines it displays. If this option is
+non-nil, no such resizing is done. */);
+ frame_inhibit_implied_resize = 0;
+
staticpro (&Vframe_list);
defsubr (&Sframep);
defsubr (&Sframe_text_cols);
defsubr (&Sframe_text_lines);
defsubr (&Sframe_total_cols);
+ defsubr (&Sframe_total_lines);
defsubr (&Sframe_text_width);
defsubr (&Sframe_text_height);
defsubr (&Sscroll_bar_width);
+ defsubr (&Sscroll_bar_height);
defsubr (&Sfringe_width);
defsubr (&Sborder_width);
defsubr (&Sright_divider_width);
ENUM_BF (output_method) output_method : 3;
#ifdef HAVE_WINDOW_SYSTEM
-
/* See FULLSCREEN_ enum on top. */
ENUM_BF (fullscreen_type) want_fullscreen : 4;
display the scroll bars of this type on this frame. */
ENUM_BF (vertical_scroll_bar_type) vertical_scroll_bar_type : 2;
+ /* Nonzero if we should actually display horizontal scroll bars on this frame. */
+ bool_bf horizontal_scroll_bars : 1;
#endif /* HAVE_WINDOW_SYSTEM */
+ /* Whether new_height and new_width shall be interpreted
+ in pixels. */
+ bool_bf new_pixelwise : 1;
+
+ /* True if frame has been added to Vframe_list and is henceforth
+ considered official. For in-official frames we neither process
+ x_set_window_size requests nor do we allow running
+ window-configuration-change-hook when resizing windows. */
+ bool_bf official : 1;
+
/* Bitfield area ends here. */
- /* Margin at the top of the frame. Used to display the tool-bar. */
+ /* Number of lines (rounded up) of tool bar. REMOVE THIS */
int tool_bar_lines;
- /* Pixel height of tool bar. */
+ /* Height of frame internal tool bar in pixels. */
int tool_bar_height;
int n_tool_bar_rows;
/* Cost of deleting n lines on this frame. */
int *delete_n_lines_cost;
- /* Text width of this frame (excluding fringes, scroll bars and
- internal border width) and text height (excluding internal border
- width) in units of canonical characters. */
+ /* Text width of this frame (excluding fringes, vertical scroll bar
+ and internal border widths) and text height (excluding menu bar,
+ tool bar, horizontal scroll bar and internal border widths) in
+ units of canonical characters. */
int text_cols, text_lines;
- /* Total width of this frame (including fringes and scroll bars) in
+ /* Total width of this frame (including fringes, vertical scroll bar
+ and internal border widths) and total height (including menu bar,
+ tool bar, horizontal scroll bar and internal border widths) in
units of canonical characters. */
- int total_cols;
+ int total_cols, total_lines;
- /* Text width of this frame (excluding fringes, scroll bars and
- internal border width) and text height (excluding internal border
- width) in pixels. */
+ /* Text width of this frame (excluding fringes, vertical scroll bar
+ and internal border widths) and text height (excluding menu bar,
+ tool bar, horizontal scroll bar and internal border widths) in
+ pixels. */
int text_width, text_height;
/* New text height and width for pending size change. 0 if no change
text width/height of the frame. */
int new_width, new_height;
- /* Whether new_height and new_width shall be interpreted
- in pixels. */
- bool new_pixelwise;
-
/* Pixel position of the frame window (x and y offsets in root window). */
int left_pos, top_pos;
- /* Size of the frame window (including internal border widths) in
+ /* Total width of this frame (including fringes, vertical scroll bar
+ and internal border widths) and total height (including menu bar,
+ tool bar, horizontal scroll bar and internal border widths) in
pixels. */
int pixel_width, pixel_height;
a highlighting is displayed inside the internal border. */
int internal_border_width;
- /* Width of borders between this frame's windows. */
- int right_divider_width;
- int bottom_divider_width;
+ /* Widths of dividers between this frame's windows in pixels. */
+ int right_divider_width, bottom_divider_width;
+
+ /* Widths of fringes in pixels. */
+ int left_fringe_width, right_fringe_width;
+
+ /* Total width of fringes reserved for drawing truncation bitmaps,
+ continuation bitmaps and alike - REMOVE THIS !!!!. */
+ int fringe_cols;
+
+ /* Number of lines of menu bar. */
+ int menu_bar_lines;
+
+ /* Pixel height of menubar. */
+ int menu_bar_height;
/* Canonical X unit. Width of default font, in pixels. */
int column_width;
/* List of font-drivers available on the frame. */
struct font_driver_list *font_driver_list;
- /* Total width of fringes reserved for drawing truncation bitmaps,
- continuation bitmaps and alike. The width is in canonical char
- units of the frame. This must currently be the case because window
- sizes aren't pixel values. If it weren't the case, we wouldn't be
- able to split windows horizontally nicely. */
- int fringe_cols;
-
- /* The extra width (in pixels) currently allotted for fringes. */
- int left_fringe_width, right_fringe_width;
-
- /* Number of lines of menu bar. */
- int menu_bar_lines;
-
- /* Pixel height of menubar. */
- int menu_bar_height;
-
#if defined (HAVE_X_WINDOWS)
/* Used by x_wait_for_event when watching for an X event on this frame. */
int wait_event_type;
int config_scroll_bar_width;
int config_scroll_bar_cols;
+ /* Configured height of the scroll bar, in pixels and in characters.
+ config_scroll_bar_lines tracks config_scroll_bar_height if the
+ latter is positive; a zero value in config_scroll_bar_height means
+ to compute the actual width on the fly, using
+ config_scroll_bar_lines and the current font width. */
+ int config_scroll_bar_height;
+ int config_scroll_bar_lines;
+
/* The baud rate that was used to calculate costs for this frame. */
int cost_calculation_baud_rate;
/* Pixel width of frame F. */
#define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width)
-/* Pixel height of frame F, including non-toolkit menu bar and
- non-toolkit tool bar lines. */
+/* Pixel height of frame F. */
#define FRAME_PIXEL_HEIGHT(f) ((f)->pixel_height)
/* Width of frame F, measured in canonical character columns,
#define FRAME_TEXT_WIDTH(f) (f)->text_width
/* Height of frame F, measured in pixels not including the height
- for internal borders. */
+ for scroll bar and internal borders. */
#define FRAME_TEXT_HEIGHT(f) (f)->text_height
/* Number of lines of frame F used for menu bar.
#else
#define FRAME_EXTERNAL_MENU_BAR(f) false
#endif
+
+/* True if frame F is currently visible. */
#define FRAME_VISIBLE_P(f) (f)->visible
/* True if frame F is currently visible but hidden. */
#define FRAME_FOCUS_FRAME(f) f->focus_frame
#ifdef HAVE_WINDOW_SYSTEM
-
+
/* This frame slot says whether scroll bars are currently enabled for frame F,
and which side they are on. */
#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type)
#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) \
((f)->vertical_scroll_bar_type != vertical_scroll_bar_none)
+#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
+ ((f)->horizontal_scroll_bars)
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) \
((f)->vertical_scroll_bar_type == vertical_scroll_bar_left)
#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \
If scroll bars are turned off, this is still nonzero. */
#define FRAME_CONFIG_SCROLL_BAR_WIDTH(f) ((f)->config_scroll_bar_width)
+/* Height that a scroll bar in frame F should have, if there is one.
+ Measured in pixels.
+ If scroll bars are turned off, this is still nonzero. */
+#define FRAME_CONFIG_SCROLL_BAR_HEIGHT(f) ((f)->config_scroll_bar_height)
+
/* Width that a scroll bar in frame F should have, if there is one.
Measured in columns (characters).
If scroll bars are turned off, this is still nonzero. */
#define FRAME_CONFIG_SCROLL_BAR_COLS(f) ((f)->config_scroll_bar_cols)
-/* Width of a scroll bar in frame F, measured in columns (characters),
- but only if scroll bars are on the left. If scroll bars are on
- the right in this frame, or there are no scroll bars, value is 0. */
-
-#define FRAME_LEFT_SCROLL_BAR_COLS(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \
- ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \
- : 0)
+/* Height that a scroll bar in frame F should have, if there is one.
+ Measured in lines (characters).
+ If scroll bars are turned off, this is still nonzero. */
+#define FRAME_CONFIG_SCROLL_BAR_LINES(f) ((f)->config_scroll_bar_lines)
/* Width of a left scroll bar in frame F, measured in pixels */
-
#define FRAME_LEFT_SCROLL_BAR_AREA_WIDTH(f) \
(FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \
? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
: 0)
-/* Width of a scroll bar in frame F, measured in columns (characters),
- but only if scroll bars are on the right. If scroll bars are on
- the left in this frame, or there are no scroll bars, value is 0. */
-
-#define FRAME_RIGHT_SCROLL_BAR_COLS(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \
- ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \
- : 0)
-
/* Width of a right scroll bar area in frame F, measured in pixels */
-
#define FRAME_RIGHT_SCROLL_BAR_AREA_WIDTH(f) \
(FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \
? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
: 0)
-/* Actual width of a scroll bar in frame F, measured in columns. */
+/* Width of a left scroll bar in frame F, measured in columns
+ (characters), but only if scroll bars are on the left. If scroll
+ bars are on the right in this frame, or there are no scroll bars,
+ value is 0. */
+#define FRAME_LEFT_SCROLL_BAR_COLS(f) \
+ (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \
+ ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \
+ : 0)
-#define FRAME_SCROLL_BAR_COLS(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
+/* Width of a right scroll bar in frame F, measured in columns
+ (characters), but only if scroll bars are on the right. If scroll
+ bars are on the left in this frame, or there are no scroll bars,
+ value is 0. */
+#define FRAME_RIGHT_SCROLL_BAR_COLS(f) \
+ (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \
? FRAME_CONFIG_SCROLL_BAR_COLS (f) \
: 0)
-/* Actual width of a scroll bar area in frame F, measured in pixels. */
+/* Width of a vertical scroll bar area in frame F, measured in
+ pixels. */
+#define FRAME_SCROLL_BAR_AREA_WIDTH(f) \
+ (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
+ ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
+ : 0)
-#define FRAME_SCROLL_BAR_AREA_WIDTH(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
- ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
+/* Height of horizontal scroll bar area in frame F, measured in
+ pixels. */
+#define FRAME_SCROLL_BAR_AREA_HEIGHT(f) \
+ (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \
+ ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \
+ : 0)
+
+/* Width of vertical scroll bar in frame F, measured in columns. */
+#define FRAME_SCROLL_BAR_COLS(f) \
+ (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
+ ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \
+ : 0)
+
+/* Height of horizontal scroll bar in frame F, measured in lines. */
+#define FRAME_SCROLL_BAR_LINES(f) \
+ (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \
+ ? FRAME_CONFIG_SCROLL_BAR_LINES (f) \
: 0)
/* Total width of frame F, in columns (characters),
including the width used by scroll bars if any. */
#define FRAME_TOTAL_COLS(f) ((f)->total_cols)
+/* Total height of frame F, in lines (characters),
+ including the height used by scroll bars if any. */
+#define FRAME_TOTAL_LINES(f) ((f)->total_lines)
+
/* Set the character widths of frame F. WIDTH specifies a nominal
character text width. */
#define SET_FRAME_COLS(f, width) \
+ FRAME_SCROLL_BAR_COLS (f) \
+ FRAME_FRINGE_COLS (f)))
-/* Set the pixel widths of frame F. WIDTH specifies a nominal pixel
- text width. */
+/* Set the character heights of frame F. HEIGHT specifies a nominal
+ character text height. */
+#define SET_FRAME_LINES(f, height) \
+ ((f)->text_lines = (height), \
+ (f)->total_lines = ((height) \
+ + FRAME_TOP_MARGIN (f) \
+ + FRAME_SCROLL_BAR_LINES (f)))
+
+/* Set the widths of frame F. WIDTH specifies a nominal pixel text
+ width. */
#define SET_FRAME_WIDTH(f, width) \
((f)->text_width = (width), \
(f)->pixel_width = ((width) \
+ FRAME_TOTAL_FRINGE_WIDTH (f) \
+ 2 * FRAME_INTERNAL_BORDER_WIDTH (f)))
-/* Set the pixel heights of frame F. HEIGHT specifies a nominal pixel
- text width. */
+/* Set the heights of frame F. HEIGHT specifies a nominal pixel text
+ height. */
#define SET_FRAME_HEIGHT(f, height) \
((f)->text_height = (height), \
(f)->pixel_height = ((height) \
- + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)))
+ + FRAME_TOP_MARGIN_HEIGHT (f) \
+ + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)))
/* Maximum + 1 legitimate value for FRAME_CURSOR_X. */
-
#define FRAME_CURSOR_X_LIMIT(f) \
(FRAME_COLS (f) + FRAME_LEFT_SCROLL_BAR_COLS (f))
+/* Nonzero if frame F has scroll bars. */
#define FRAME_SCROLL_BARS(f) (f->scroll_bars)
-
#define FRAME_CONDEMNED_SCROLL_BARS(f) (f->condemned_scroll_bars)
+
#define FRAME_MENU_BAR_ITEMS(f) (f->menu_bar_items)
#define FRAME_COST_BAUD_RATE(f) ((f)->cost_calculation_baud_rate)
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);
+extern bool frame_inhibit_resize (struct frame *, bool);
extern Lisp_Object Vframe_list;
/* Canonical y-unit on frame F.
This value currently equals the line height of the frame (which is
the height of the default font of F). */
-
#define FRAME_LINE_HEIGHT(F) ((F)->line_height)
/* Canonical x-unit on frame F.
This value currently equals the average width of the default font of F. */
-
#define FRAME_COLUMN_WIDTH(F) ((F)->column_width)
/* Pixel width of areas used to display truncation marks, continuation
units of the frame. This must currently be the case because window
sizes aren't pixel values. If it weren't the case, we wouldn't be
able to split windows horizontally nicely. */
-
#define FRAME_FRINGE_COLS(F) ((F)->fringe_cols)
/* Pixel-width of the left and right fringe. */
/* Convert canonical value X to pixels. F is the frame whose
canonical char width is to be used. X must be a Lisp integer or
float. Value is a C integer. */
-
#define FRAME_PIXEL_X_FROM_CANON_X(F, X) \
(INTEGERP (X) \
? XINT (X) * FRAME_COLUMN_WIDTH (F) \
/* Convert canonical value Y to pixels. F is the frame whose
canonical character height is to be used. X must be a Lisp integer
or float. Value is a C integer. */
-
#define FRAME_PIXEL_Y_FROM_CANON_Y(F, Y) \
(INTEGERP (Y) \
? XINT (Y) * FRAME_LINE_HEIGHT (F) \
canonical character width is to be used. X is a C integer. Result
is a Lisp float if X is not a multiple of the canon width,
otherwise it's a Lisp integer. */
-
#define FRAME_CANON_X_FROM_PIXEL_X(F, X) \
((X) % FRAME_COLUMN_WIDTH (F) != 0 \
? make_float ((double) (X) / FRAME_COLUMN_WIDTH (F)) \
canonical character height is to be used. Y is a C integer.
Result is a Lisp float if Y is not a multiple of the canon width,
otherwise it's a Lisp integer. */
-
#define FRAME_CANON_Y_FROM_PIXEL_Y(F, Y) \
((Y) % FRAME_LINE_HEIGHT (F) \
? make_float ((double) (Y) / FRAME_LINE_HEIGHT (F)) \
Return the upper/left pixel position of the character cell on frame F
at ROW/COL. */
-
#define FRAME_LINE_TO_PIXEL_Y(f, row) \
(((row) < FRAME_TOP_MARGIN (f) ? 0 : FRAME_INTERNAL_BORDER_WIDTH (f)) \
+ (row) * FRAME_LINE_HEIGHT (f))
/* Return the pixel width/height of frame F if it has
COLS columns/LINES rows. */
-
#define FRAME_TEXT_COLS_TO_PIXEL_WIDTH(f, cols) \
- (FRAME_COL_TO_PIXEL_X (f, cols) \
+ ((cols) * FRAME_COLUMN_WIDTH (f) \
+ FRAME_SCROLL_BAR_AREA_WIDTH (f) \
+ FRAME_TOTAL_FRINGE_WIDTH (f) \
- + FRAME_INTERNAL_BORDER_WIDTH (f))
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
#define FRAME_TEXT_LINES_TO_PIXEL_HEIGHT(f, lines) \
((lines) * FRAME_LINE_HEIGHT (f) \
+ + FRAME_TOP_MARGIN_HEIGHT (f) \
+ + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \
+ 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
/* Return the row/column (zero-based) of the character cell containing
the pixel on FRAME at Y/X. */
-
#define FRAME_PIXEL_Y_TO_LINE(f, y) \
(((y) < FRAME_TOP_MARGIN_HEIGHT (f) \
? (y) \
- : ((y) < FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \
- ? (y) - (FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \
+ : ((y) < (FRAME_TOP_MARGIN_HEIGHT (f) \
+ + FRAME_INTERNAL_BORDER_WIDTH (f)) \
+ ? (y) - (FRAME_TOP_MARGIN_HEIGHT (f) \
+ + FRAME_INTERNAL_BORDER_WIDTH (f) \
/* Arrange for the division to round down. */ \
+ FRAME_LINE_HEIGHT (f) - 1) \
: (y) - FRAME_INTERNAL_BORDER_WIDTH (f))) \
/ FRAME_COLUMN_WIDTH (f))
/* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
- frame F? */
-
+ frame F (so we round down)? */
#define FRAME_PIXEL_WIDTH_TO_TEXT_COLS(f, width) \
- (FRAME_PIXEL_X_TO_COL (f, ((width) \
- - FRAME_INTERNAL_BORDER_WIDTH (f) \
- - FRAME_TOTAL_FRINGE_WIDTH (f) \
- - FRAME_SCROLL_BAR_AREA_WIDTH (f)))) \
+ (((width) \
+ - FRAME_TOTAL_FRINGE_WIDTH (f) \
+ - FRAME_SCROLL_BAR_AREA_WIDTH (f) \
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) \
+ / FRAME_COLUMN_WIDTH (f)) \
#define FRAME_PIXEL_HEIGHT_TO_TEXT_LINES(f, height) \
- (FRAME_PIXEL_Y_TO_LINE (f, ((height) \
- - FRAME_INTERNAL_BORDER_WIDTH (f))))
+ (((height) \
+ - FRAME_TOP_MARGIN_HEIGHT (f) \
+ - FRAME_SCROLL_BAR_AREA_HEIGHT (f) \
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) \
+ / FRAME_LINE_HEIGHT (f))
/* Return the pixel width/height of frame F with a text size of
- width/height. */
-
+ width/heigh. */
#define FRAME_TEXT_TO_PIXEL_WIDTH(f, width) \
((width) \
+ FRAME_SCROLL_BAR_AREA_WIDTH (f) \
+ 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
#define FRAME_TEXT_TO_PIXEL_HEIGHT(f, height) \
- ((height) + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+ ((height) \
+ + FRAME_TOP_MARGIN_HEIGHT (f) \
+ + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
/* Return the text width/height of frame F with a pixel size of
width/height. */
-
#define FRAME_PIXEL_TO_TEXT_WIDTH(f, width) \
((width) \
- FRAME_SCROLL_BAR_AREA_WIDTH (f) \
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
#define FRAME_PIXEL_TO_TEXT_HEIGHT(f, height) \
- ((height) - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+ ((height) \
+ - FRAME_TOP_MARGIN_HEIGHT (f) \
+ - FRAME_SCROLL_BAR_AREA_HEIGHT (f) \
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+
+/* Return the width/height reserved for the windows of frame F. */
+#define FRAME_WINDOWS_WIDTH(f) \
+ (FRAME_PIXEL_WIDTH (f) \
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
-/* Value is the smallest width of any character in any font on frame F. */
+#define FRAME_WINDOWS_HEIGHT(f) \
+ (FRAME_PIXEL_HEIGHT (f) \
+ - FRAME_TOP_MARGIN_HEIGHT (f) \
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+/* Value is the smallest width of any character in any font on frame F. */
#define FRAME_SMALLEST_CHAR_WIDTH(f) \
FRAME_DISPLAY_INFO (f)->smallest_char_width
/* Value is the smallest height of any font on frame F. */
-
#define FRAME_SMALLEST_FONT_HEIGHT(f) \
FRAME_DISPLAY_INFO (f)->smallest_font_height
extern Lisp_Object Qparent_id;
extern Lisp_Object Qunsplittable, Qvisibility;
extern Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
+extern Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars;
extern Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
extern Lisp_Object Qscreen_gamma;
extern Lisp_Object Qline_spacing;
/* The class of this X application. */
#define EMACS_CLASS "Emacs"
-/* These are in xterm.c, w32term.c, etc. */
+/* If these are not in frame.c they are in xterm.c, w32term.c, etc. */
+extern void adjust_frame_size (struct frame *, int, int, int, bool);
+extern int frame_windows_min_size (Lisp_Object, Lisp_Object, Lisp_Object);
extern void x_set_scroll_bar_default_width (struct frame *);
+extern void x_set_scroll_bar_default_height (struct frame *);
extern void x_set_offset (struct frame *, int, int, int);
extern void x_wm_set_size_hint (struct frame *f, long flags, bool user_position);
-
extern Lisp_Object x_new_font (struct frame *, Lisp_Object, int);
-
-
extern Lisp_Object Qface_set_after_frame_default;
-
extern void x_set_frame_parameters (struct frame *, Lisp_Object);
-
extern void x_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_screen_gamma (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_font (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_font_backend (struct frame *, Lisp_Object, Lisp_Object);
-extern void x_set_fringe_width (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_left_fringe (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_right_fringe (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_border_width (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_internal_border_width (struct frame *, Lisp_Object,
Lisp_Object);
extern void x_set_autoraise (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_autolower (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_unsplittable (struct frame *, Lisp_Object, Lisp_Object);
-extern void x_set_vertical_scroll_bars (struct frame *, Lisp_Object,
- Lisp_Object);
-extern void x_set_scroll_bar_width (struct frame *, Lisp_Object,
- Lisp_Object);
+extern void x_set_vertical_scroll_bars (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_horizontal_scroll_bars (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_scroll_bar_width (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object);
extern long x_figure_window_size (struct frame *, Lisp_Object, bool);
}
-/* Compute actual fringe widths for frame F.
-
- If REDRAW is 1, redraw F if the fringe settings was actually
- modified and F is visible.
-
- Since the combined left and right fringe must occupy an integral
- number of columns, we may need to add some pixels to each fringe.
- Typically, we add an equal amount (+/- 1 pixel) to each fringe,
- but a negative width value is taken literally (after negating it).
-
- We never make the fringes narrower than specified.
-*/
-
-void
-compute_fringe_widths (struct frame *f, bool redraw_p)
-{
- int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
- int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
- int o_cols = FRAME_FRINGE_COLS (f);
-
- Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
- Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
- int left_fringe_width, right_fringe_width;
-
- if (!NILP (left_fringe))
- left_fringe = Fcdr (left_fringe);
- if (!NILP (right_fringe))
- right_fringe = Fcdr (right_fringe);
-
- left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
- XINT (left_fringe));
- right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
- XINT (right_fringe));
-
- if (left_fringe_width || right_fringe_width)
- {
- int left_wid = eabs (left_fringe_width);
- int right_wid = eabs (right_fringe_width);
- int conf_wid = left_wid + right_wid;
- int font_wid = FRAME_COLUMN_WIDTH (f);
- int cols = (left_wid + right_wid + font_wid-1) / font_wid;
- int real_wid = cols * font_wid;
- if (left_wid && right_wid)
- {
- if (left_fringe_width < 0)
- {
- /* Left fringe width is fixed, adjust right fringe if necessary */
- FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
- FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
- }
- else if (right_fringe_width < 0)
- {
- /* Right fringe width is fixed, adjust left fringe if necessary */
- FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
- FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
- }
- else
- {
- /* Adjust both fringes with an equal amount.
- Note that we are doing integer arithmetic here, so don't
- lose a pixel if the total width is an odd number. */
- int fill = real_wid - conf_wid;
- FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
- FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
- }
- }
- else if (left_fringe_width)
- {
- FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
- FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
- }
- else
- {
- FRAME_LEFT_FRINGE_WIDTH (f) = 0;
- FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
- }
- FRAME_FRINGE_COLS (f) = cols;
- }
- else
- {
- FRAME_LEFT_FRINGE_WIDTH (f) = 0;
- FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
- FRAME_FRINGE_COLS (f) = 0;
- }
-
- if (redraw_p && FRAME_VISIBLE_P (f))
- if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
- o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
- o_cols != FRAME_FRINGE_COLS (f))
- redraw_frame (f);
-}
-
/* Free resources used by a user-defined bitmap. */
#define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
static void update_theme_scrollbar_width (void);
+static void update_theme_scrollbar_height (void);
#define TB_INFO_KEY "xg_frame_tb_info"
struct xg_frame_tb_info
/* Clear under internal border if any. As we use a mix of Gtk+ and X calls
and use a GtkFixed widget, this doesn't happen automatically. */
-static void
+void
xg_clear_under_internal_border (struct frame *f)
{
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
change_frame_size (f, width, height, 0, 1, 0, 1);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
+
+ do_pending_window_change (0);
}
}
x_wait_for_event (f, ConfigureNotify);
}
else
- change_frame_size (f, width, height, 0, 1, 0, 1);
+ adjust_frame_size (f, -1, -1, 5, 0);
}
/* Handle height/width changes (i.e. add/remove/move menu/toolbar).
kbd_buffer_store_event (&event);
update_theme_scrollbar_width ();
+ update_theme_scrollbar_height ();
/* If scroll bar width changed, we need set the new size on all frames
on this display. */
&& FRAME_X_DISPLAY (f) == dpy)
{
x_set_scroll_bar_default_width (f);
+ x_set_scroll_bar_default_height (f);
xg_frame_set_char_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f));
}
}
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1)
+ FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
- check_frame_size (f, &min_cols, &min_rows, 0);
if (min_cols > 0) --min_cols; /* We used one col in base_width = ... 1); */
if (min_rows > 0) --min_rows; /* We used one row in base_height = ... 1); */
bool xg_ignore_gtk_scrollbar;
-/* The width of the scroll bar for the current theme. */
-
+/* Width and height of scroll bars for the current theme. */
static int scroll_bar_width_for_theme;
+static int scroll_bar_height_for_theme;
/* Xlib's `Window' fits in 32 bits. But we want to store pointers, and they
may be larger than 32 bits. Keep a mapping from integer index to widget
scroll_bar_width_for_theme = w;
}
+static void
+update_theme_scrollbar_height (void)
+{
+#ifdef HAVE_GTK3
+ GtkAdjustment *hadj;
+#else
+ GtkObject *hadj;
+#endif
+ GtkWidget *wscroll;
+ int w = 0, b = 0;
+
+ hadj = gtk_adjustment_new (YG_SB_MIN, YG_SB_MIN, YG_SB_MAX, 0.1, 0.1, 0.1);
+ wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj));
+ g_object_ref_sink (G_OBJECT (wscroll));
+ gtk_widget_style_get (wscroll, "slider-width", &w, "trough-border", &b, NULL);
+ gtk_widget_destroy (wscroll);
+ g_object_unref (G_OBJECT (wscroll));
+ w += 2*b;
+ if (w < 12) w = 12;
+ scroll_bar_height_for_theme = w;
+}
+
int
xg_get_default_scrollbar_width (void)
{
return scroll_bar_width_for_theme;
}
+int
+xg_get_default_scrollbar_height (void)
+{
+ /* Apparently there's no default height for themes. */
+ return scroll_bar_width_for_theme;
+}
+
/* Return the scrollbar id for X Window WID on display DPY.
Return -1 if WID not in id_to_widget. */
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
bar->x_window = scroll_id;
+ bar->horizontal = 0;
+}
+
+/* Create a horizontal scroll bar widget for frame F. Store the scroll
+ bar in BAR. SCROLL_CALLBACK is the callback to invoke when the value
+ of the bar changes. END_CALLBACK is the callback to invoke when
+ scrolling ends. SCROLL_BAR_NAME is the name we use for the scroll
+ bar. Can be used to set resources for the widget. */
+
+void
+xg_create_horizontal_scroll_bar (struct frame *f,
+ struct scroll_bar *bar,
+ GCallback scroll_callback,
+ GCallback end_callback,
+ const char *scroll_bar_name)
+{
+ GtkWidget *wscroll;
+ GtkWidget *webox;
+ intptr_t scroll_id;
+#ifdef HAVE_GTK3
+ GtkAdjustment *hadj;
+#else
+ GtkObject *hadj;
+#endif
+
+ /* Page, step increment values are not so important here, they
+ will be corrected in x_set_toolkit_scroll_bar_thumb. */
+ hadj = gtk_adjustment_new (YG_SB_MIN, YG_SB_MIN, YG_SB_MAX,
+ 0.1, 0.1, 0.1);
+
+ wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj));
+ webox = gtk_event_box_new ();
+ gtk_widget_set_name (wscroll, scroll_bar_name);
+#ifndef HAVE_GTK3
+ gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
+#endif
+ g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
+
+ scroll_id = xg_store_widget_in_map (wscroll);
+
+ g_signal_connect (G_OBJECT (wscroll),
+ "destroy",
+ G_CALLBACK (xg_gtk_scroll_destroy),
+ (gpointer) scroll_id);
+ g_signal_connect (G_OBJECT (wscroll),
+ "change-value",
+ scroll_callback,
+ (gpointer) bar);
+ g_signal_connect (G_OBJECT (wscroll),
+ "button-release-event",
+ end_callback,
+ (gpointer) bar);
+
+ /* The scroll bar widget does not draw on a window of its own. Instead
+ it draws on the parent window, in this case the edit widget. So
+ whenever the edit widget is cleared, the scroll bar needs to redraw
+ also, which causes flicker. Put an event box between the edit widget
+ and the scroll bar, so the scroll bar instead draws itself on the
+ event box window. */
+ gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
+ gtk_container_add (GTK_CONTAINER (webox), wscroll);
+
+
+ /* Set the cursor to an arrow. */
+ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
+
+ bar->x_window = scroll_id;
+ bar->horizontal = 1;
}
/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */
}
}
+
+/* Update the position of the horizontal scroll bar represented by SCROLLBAR_ID
+ in frame F.
+ TOP/LEFT are the new pixel positions where the bar shall appear.
+ WIDTH, HEIGHT is the size in pixels the bar shall have. */
+
+void
+xg_update_horizontal_scrollbar_pos (struct frame *f,
+ ptrdiff_t scrollbar_id,
+ int top,
+ int left,
+ int width,
+ int height)
+{
+
+ GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+
+ if (wscroll)
+ {
+ GtkWidget *wfixed = f->output_data.x->edit_widget;
+ GtkWidget *wparent = gtk_widget_get_parent (wscroll);
+ gint msl;
+
+ /* Clear out old position. */
+ int oldx = -1, oldy = -1, oldw, oldh;
+ if (gtk_widget_get_parent (wparent) == wfixed)
+ {
+ gtk_container_child_get (GTK_CONTAINER (wfixed), wparent,
+ "x", &oldx, "y", &oldy, NULL);
+ gtk_widget_get_size_request (wscroll, &oldw, &oldh);
+ }
+
+ /* Move and resize to new values. */
+ gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top);
+ gtk_widget_style_get (wscroll, "min-slider-length", &msl, NULL);
+ if (msl > width)
+ {
+ /* No room. Hide scroll bar as some themes output a warning if
+ the width is less than the min size. */
+ gtk_widget_hide (wparent);
+ gtk_widget_hide (wscroll);
+ }
+ else
+ {
+ gtk_widget_show_all (wparent);
+ gtk_widget_set_size_request (wscroll, width, height);
+ }
+ gtk_widget_queue_draw (wfixed);
+ gdk_window_process_all_updates ();
+ if (oldx != -1 && oldw > 0 && oldh > 0)
+ /* Clear under old scroll bar position. This must be done after
+ the gtk_widget_queue_draw and gdk_window_process_all_updates
+ above. */
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ oldx, oldy, oldw, oldh);
+
+ /* GTK does not redraw until the main loop is entered again, but
+ if there are no X events pending we will not enter it. So we sync
+ here to get some events. */
+
+ x_sync (f);
+ SET_FRAME_GARBAGED (f);
+ cancel_mouse_face (f);
+ }
+}
+
+
/* Get the current value of the range, truncated to an integer. */
static int
}
}
+/* Set the thumb size and position of horizontal scroll bar BAR. We are
+ currently displaying PORTION out of a whole WHOLE, and our position
+ POSITION. */
+void
+xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
+ int portion,
+ int position,
+ int whole)
+{
+ GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
+
+ if (wscroll && bar->dragging == -1)
+ {
+ GtkAdjustment *adj;
+ int lower = 0;
+ int upper = max (whole - 1, 0);
+ int pagesize = min (upper, max (portion, 0));
+ int value = max (0, min (position, upper - pagesize));
+ /* These should be set to something more <portion, whole>
+ related. */
+ int page_increment = 4;
+ int step_increment = 1;
+
+ block_input ();
+ adj = gtk_range_get_adjustment (GTK_RANGE (wscroll));
+
+ /* gtk_adjustment_set_lower (adj, (gdouble) lower);
+ gtk_adjustment_set_upper (adj, (gdouble) upper);
+ gtk_adjustment_set_page_size (adj, (gdouble) pagesize);
+ gtk_adjustment_set_value (adj, (gdouble) value);
+ gtk_adjustment_set_page_increment (adj, (gdouble) page_increment);
+ gtk_adjustment_set_step_increment (adj, (gdouble)
+ step_increment); */
+ gtk_adjustment_configure (adj, (gdouble) value, (gdouble) lower,
+ (gdouble) upper, (gdouble) step_increment,
+ (gdouble) page_increment, (gdouble) pagesize);
+ gtk_adjustment_changed (adj);
+ unblock_input ();
+ }
+}
+
/* Return true if EVENT is for a scroll bar in frame F.
When the same X window is used for several Gtk+ widgets, we cannot
say for sure based on the X window alone if an event is for the
gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
"cancel", 0);
update_theme_scrollbar_width ();
+ update_theme_scrollbar_height ();
#ifdef HAVE_FREETYPE
x_last_font_name = NULL;
#define XG_SB_MIN 1
#define XG_SB_MAX 10000000
#define XG_SB_RANGE (XG_SB_MAX-XG_SB_MIN)
+#define YG_SB_MIN 1
+#define YG_SB_MAX 10000000
+#define YG_SB_RANGE (YG_SB_MAX-YG_SB_MIN)
/* Key for data that is valid for menus and scroll bars in a frame */
#define XG_FRAME_DATA "emacs_frame"
GCallback scroll_callback,
GCallback end_callback,
const char *scroll_bar_name);
+extern void xg_create_horizontal_scroll_bar (struct frame *f,
+ struct scroll_bar *bar,
+ GCallback scroll_callback,
+ GCallback end_callback,
+ const char *scroll_bar_name);
extern void xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id);
extern void xg_update_scrollbar_pos (struct frame *f,
int left,
int width,
int height);
+extern void xg_update_horizontal_scrollbar_pos (struct frame *f,
+ ptrdiff_t scrollbar_id,
+ int top,
+ int left,
+ int width,
+ int height);
extern void xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
int portion,
int position,
int whole);
+extern void xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
+ int portion,
+ int position,
+ int whole);
extern bool xg_event_is_for_scrollbar (struct frame *, const XEvent *);
extern int xg_get_default_scrollbar_width (void);
+extern int xg_get_default_scrollbar_height (void);
extern void update_frame_tool_bar (struct frame *f);
extern void free_frame_tool_bar (struct frame *f);
extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos);
+extern void xg_clear_under_internal_border (struct frame *f);
extern void xg_frame_resized (struct frame *f,
int pixelwidth,
int pixelheight);
extern void xg_show_tooltip (struct frame *f, int root_x, int root_y);
extern bool xg_hide_tooltip (struct frame *f);
-
/* Mark all callback data that are Lisp_object:s during GC. */
extern void xg_mark_data (void);
QUIT;
}
\f
+/* If the selected window's old pointm is adjacent or covered by the
+ region from FROM to TO, unsuspend auto hscroll in that window. */
+
+static void
+adjust_suspend_auto_hscroll (ptrdiff_t from, ptrdiff_t to)
+{
+ if (WINDOWP (selected_window))
+ {
+ struct window *w = XWINDOW (selected_window);
+
+ if (BUFFERP (w->contents)
+ && XBUFFER (w->contents) == current_buffer
+ && XMARKER (w->old_pointm)->charpos >= from
+ && XMARKER (w->old_pointm)->charpos <= to)
+ w->suspend_auto_hscroll = 0;
+ }
+}
+
+
/* Adjust all markers for a deletion
whose range in bytes is FROM_BYTE to TO_BYTE.
The range in charpos is FROM to TO.
struct Lisp_Marker *m;
ptrdiff_t charpos;
+ adjust_suspend_auto_hscroll (from, to);
for (m = BUF_MARKERS (current_buffer); m; m = m->next)
{
charpos = m->charpos;
ptrdiff_t nchars = to - from;
ptrdiff_t nbytes = to_byte - from_byte;
+ adjust_suspend_auto_hscroll (from, to);
for (m = BUF_MARKERS (current_buffer); m; m = m->next)
{
eassert (m->bytepos >= m->charpos
ptrdiff_t diff_chars = new_chars - old_chars;
ptrdiff_t diff_bytes = new_bytes - old_bytes;
+ adjust_suspend_auto_hscroll (from, from + old_chars);
for (m = BUF_MARKERS (current_buffer); m; m = m->next)
{
if (m->bytepos >= prev_to_byte)
event->kind == FOCUS_IN_EVENT)
#ifdef USE_TOOLKIT_SCROLL_BARS
&& !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
- && event->kind == SCROLL_BAR_CLICK_EVENT
+ && (event->kind == SCROLL_BAR_CLICK_EVENT
+ || event->kind == HORIZONTAL_SCROLL_BAR_CLICK_EVENT)
&& event->part == scroll_bar_handle
&& event->modifiers == 0)
#endif
#ifdef HAVE_GPM
|| sp->kind == GPM_CLICK_EVENT
#endif
- || sp->kind == SCROLL_BAR_CLICK_EVENT)
+ || sp->kind == SCROLL_BAR_CLICK_EVENT
+ || sp->kind == HORIZONTAL_SCROLL_BAR_CLICK_EVENT)
{
sp->kind = NO_EVENT;
}
/* Scroll bar parts. */
static Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
-Lisp_Object Qup, Qdown, Qbottom;
+static Lisp_Object Qbefore_handle, Qhorizontal_handle, Qafter_handle;
+Lisp_Object Qup, Qdown, Qtop, Qbottom;
+Lisp_Object Qleft, Qright, Qleftmost, Qrightmost;
static Lisp_Object Qend_scroll;
-Lisp_Object Qtop;
static Lisp_Object Qratio;
/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */
static Lisp_Object *const scroll_bar_parts[] = {
&Qabove_handle, &Qhandle, &Qbelow_handle,
- &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio
+ &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio,
+ &Qbefore_handle, &Qhorizontal_handle, &Qafter_handle,
+ &Qleft, &Qright, &Qleftmost, &Qrightmost, &Qend_scroll, &Qratio
};
/* A vector, indexed by button number, giving the down-going location
#endif
#ifndef USE_TOOLKIT_SCROLL_BARS
case SCROLL_BAR_CLICK_EVENT:
+ case HORIZONTAL_SCROLL_BAR_CLICK_EVENT:
#endif
{
int button = event->code;
return list2 (head, position);
}
+ case HORIZONTAL_SCROLL_BAR_CLICK_EVENT:
+ {
+ Lisp_Object position, head, window, portion_whole, part;
+
+ window = event->frame_or_window;
+ portion_whole = Fcons (event->x, event->y);
+ part = *scroll_bar_parts[(int) event->part];
+
+ position = list5 (window, Qhorizontal_scroll_bar, portion_whole,
+ make_number (event->timestamp), part);
+
+ /* Always treat scroll bar events as clicks. */
+ event->modifiers |= click_modifier;
+ event->modifiers &= ~up_modifier;
+
+ if (event->code >= ASIZE (mouse_syms))
+ mouse_syms = larger_vector (mouse_syms,
+ event->code - ASIZE (mouse_syms) + 1,
+ -1);
+
+ /* Get the symbol we should use for the mouse click. */
+ head = modify_event_symbol (event->code,
+ event->modifiers,
+ Qmouse_click,
+ Vlispy_mouse_stem,
+ NULL, &mouse_syms,
+ ASIZE (mouse_syms));
+ return list2 (head, position);
+ }
+
#endif /* USE_TOOLKIT_SCROLL_BARS */
case DRAG_N_DROP_EVENT:
with a window system; but suspend should be disabled in that case. */
get_tty_size (fileno (CURTTY ()->input), &width, &height);
if (width != old_width || height != old_height)
- change_frame_size (SELECTED_FRAME (), width, height, 0, 0, 0, 0);
+ change_frame_size (SELECTED_FRAME (), width, height
+ - FRAME_MENU_BAR_LINES (SELECTED_FRAME ()), 0, 0, 0, 0);
/* Run suspend-resume-hook. */
hook = intern ("suspend-resume-hook");
DEFSYM (Qbottom, "bottom");
DEFSYM (Qend_scroll, "end-scroll");
DEFSYM (Qratio, "ratio");
+ DEFSYM (Qbefore_handle, "before-handle");
+ DEFSYM (Qhorizontal_handle, "horizontal-handle");
+ DEFSYM (Qafter_handle, "after-handle");
+ DEFSYM (Qleft, "left");
+ DEFSYM (Qright, "right");
+ DEFSYM (Qleftmost, "leftmost");
+ DEFSYM (Qrightmost, "rightmost");
DEFSYM (Qevent_kind, "event-kind");
DEFSYM (Qevent_symbol_elements, "event-symbol-elements");
set_window_buffer (minibuf_window, Fcurrent_buffer (), 0, 0);
Fselect_window (minibuf_window, Qnil);
XWINDOW (minibuf_window)->hscroll = 0;
+ XWINDOW (minibuf_window)->suspend_auto_hscroll = 0;
Fmake_local_variable (Qprint_escape_newlines);
print_escape_newlines = 1;
extern Lisp_Object Qtop;
extern Lisp_Object Qdisplay;
extern Lisp_Object Qvertical_scroll_bars;
+extern Lisp_Object Qhorizontal_scroll_bars;
extern Lisp_Object Qauto_raise;
extern Lisp_Object Qauto_lower;
extern Lisp_Object Qbox;
extern Lisp_Object Qscroll_bar_width;
+extern Lisp_Object Qscroll_bar_height;
extern Lisp_Object Qx_resource_name;
extern Lisp_Object Qface_set_after_frame_default;
extern Lisp_Object Qunderline, Qundefined;
}
+void
+x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+
+ CHECK_TYPE_RANGED_INTEGER (int, arg);
+ FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
+ if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
+ FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
+
+ if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width)
+ return;
+
+ if (FRAME_X_WINDOW (f) != 0)
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ SET_FRAME_GARBAGED (f);
+}
+
+
static void
ns_implicitly_set_icon_type (struct frame *f)
{
x_set_mouse_color,
x_explicitly_set_name,
x_set_scroll_bar_width, /* generic OK */
+ x_set_scroll_bar_height, /* generic OK */
x_set_title,
x_set_unsplittable, /* generic OK */
x_set_vertical_scroll_bars, /* generic OK */
+ x_set_horizontal_scroll_bars, /* generic OK */
x_set_visibility, /* generic OK */
x_set_tool_bar_lines,
0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */
x_set_screen_gamma, /* generic OK */
x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
- x_set_fringe_width, /* generic OK */
- x_set_fringe_width, /* generic OK */
+ x_set_left_fringe, /* generic OK */
+ x_set_right_fringe, /* generic OK */
0, /* x_set_wait_for_wm, will ignore */
x_set_fullscreen, /* generic OK */
x_set_font_backend, /* generic OK */
"internalBorderWidth", "InternalBorderWidth",
RES_TYPE_NUMBER);
- /* default scrollbars on right on Mac */
+ /* default vertical scrollbars on right on Mac */
{
Lisp_Object spos
#ifdef NS_IMPL_GNUSTEP
"verticalScrollBars", "VerticalScrollBars",
RES_TYPE_SYMBOL);
}
+ x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qt,
+ "horizontalScrollBars", "HorizontalScrollBars",
+ RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
"foreground", "Foreground", RES_TYPE_STRING);
x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
= [NSCursor arrowCursor];
+ FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
+ = [NSCursor arrowCursor];
f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
[[EmacsView alloc] initFrameFromEmacs: f];
x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
"scrollBarWidth", "ScrollBarWidth",
RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
+ "scrollBarHeight", "ScrollBarHeight",
+ RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qfullscreen, Qnil,
wid - 1) / wid;
}
+void
+x_set_scroll_bar_default_height (struct frame *f)
+{
+ int height = FRAME_LINE_HEIGHT (f);
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) +
+ height - 1) / height;
+}
+
/* terms impl this instead of x-get-resource directly */
char *
x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
/* The cursor to use for vertical scroll bars. */
Cursor vertical_scroll_bar_cursor;
+ /* The cursor to use for horizontal scroll bars. */
+ Cursor horizontal_scroll_bar_cursor;
+
/* Information about the range of text currently shown in
mouse-face. */
Mouse_HLInfo mouse_highlight;
#endif
/* Compute pixel size for vertical scroll bars */
-#define NS_SCROLL_BAR_WIDTH(f) \
-(FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
- ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \
- ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
- : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \
- : 0)
+#define NS_SCROLL_BAR_WIDTH(f) \
+ (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
+ ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \
+ ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
+ : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \
+ : 0)
+
+/* Compute pixel size for horizontal scroll bars */
+#define NS_SCROLL_BAR_HEIGHT(f) \
+ (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \
+ ? rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 \
+ ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \
+ : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f))) \
+ : 0)
/* Difference btwn char-column-calculated and actual SB widths.
This is only a concern for rendering when SB on left. */
(FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \
- NS_SCROLL_BAR_WIDTH (f)) : 0)
+/* Difference btwn char-line-calculated and actual SB heights.
+ This is only a concern for rendering when SB on top. */
+#define NS_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f) \
+ (WINDOW_HAS_HORIZONTAL_SCROLL_BARS (w) ? \
+ (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \
+ - NS_SCROLL_BAR_HEIGHT (f)) : 0)
+
/* XXX: fix for GNUstep inconsistent accounting for titlebar */
#ifdef NS_IMPL_GNUSTEP
#define NS_TOP_POS(f) ((f)->top_pos + 18)
/* First position where characters can be shown (instead of scrollbar, if
it is on left. */
-#define FIRST_CHAR_POSITION(f) \
- (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \
+#define FIRST_CHAR_POSITION(f) \
+ (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \
: FRAME_SCROLL_BAR_COLS (f))
extern struct ns_display_info *ns_term_init (Lisp_Object display_name);
#define SCREENMAX 16000
#define NS_SCROLL_BAR_WIDTH_DEFAULT [EmacsScroller scrollerWidth]
+#define NS_SCROLL_BAR_HEIGHT_DEFAULT [EmacsScroller scrollerHeight]
/* This is to match emacs on other platforms, ugly though it is. */
#define NS_SELECTION_BG_COLOR_DEFAULT @"LightGoldenrod2";
#define NS_SELECTION_FG_COLOR_DEFAULT @"Black";
block_input ();
- check_frame_size (f, &width, &height, pixelwise);
-
- compute_fringe_widths (f, 0);
-
if (pixelwise)
{
pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
cancel_mouse_face (f);
unblock_input ();
+
+ do_pending_window_change (0);
}
{
int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
-
- if (bx < 0)
- {
- /* Bitmap fills the fringe. */
- if (bar_area_x + bar_area_width == p->x)
- bx = bar_area_x + sb_width;
- else if (p->x + p->wd == bar_area_x)
- bx = bar_area_x;
- if (bx >= 0)
- {
- int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
- nx = bar_area_width - sb_width;
- by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y));
- ny = row->visible_height;
- }
- }
- else
- {
- if (bar_area_x + bar_area_width == bx)
- {
- bx = bar_area_x + sb_width;
- nx += bar_area_width - sb_width;
- }
- else if (bx + nx == bar_area_x)
- nx += bar_area_width - sb_width;
- }
- }
- }
-
if (bx >= 0 && nx > 0)
{
NSRect r = NSMakeRect (bx, by, nx, ny);
NSRect r, v;
struct frame *f = XFRAME (WINDOW_FRAME (window));
EmacsView *view = FRAME_NS_VIEW (f);
- int window_y, window_height;
- int top, left, height, width, sb_width, sb_left;
EmacsScroller *bar;
- BOOL fringe_extended_p;
+ int window_y, window_height;
+ int top, left, height, width;
/* optimization; display engine sends WAY too many of these.. */
if (!NILP (window->vertical_scroll_bar))
width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
left = WINDOW_SCROLL_BAR_AREA_X (window);
- /* allow for displaying a skinnier scrollbar than char area allotted */
- sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ?
- WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width;
- sb_left = left;
-
- r = NSMakeRect (sb_left, top, sb_width, height);
+ r = NSMakeRect (left, top, width, height);
/* the parent view is flipped, so we need to flip y value */
v = [view frame];
r.origin.y = (v.size.height - r.size.height - r.origin.y);
- fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (window);
-
XSETWINDOW (win, window);
block_input ();
[bar removeFromSuperview];
wset_vertical_scroll_bar (window, Qnil);
}
- ns_clear_frame_area (f, sb_left, top, width, height);
+ ns_clear_frame_area (f, left, top, width, height);
unblock_input ();
return;
}
if (NILP (window->vertical_scroll_bar))
{
if (width > 0 && height > 0)
- {
- if (fringe_extended_p)
- ns_clear_frame_area (f, sb_left, top, sb_width, height);
- else
- ns_clear_frame_area (f, left, top, width, height);
- }
+ ns_clear_frame_area (f, left, top, width, height);
bar = [[EmacsScroller alloc] initFrame: r window: win];
wset_vertical_scroll_bar (window, make_save_ptr (bar));
if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
{
if (oldRect.origin.x != r.origin.x)
- ns_clear_frame_area (f, sb_left, top, width, height);
+ ns_clear_frame_area (f, left, top, width, height);
+ [bar setFrame: r];
+ }
+ }
+
+ [bar setPosition: position portion: portion whole: whole];
+ unblock_input ();
+}
+
+
+static void
+ns_set_horizontal_scroll_bar (struct window *window,
+ int portion, int whole, int position)
+/* --------------------------------------------------------------------------
+ External (hook): Update or add scrollbar
+ -------------------------------------------------------------------------- */
+{
+ Lisp_Object win;
+ NSRect r, v;
+ struct frame *f = XFRAME (WINDOW_FRAME (window));
+ EmacsView *view = FRAME_NS_VIEW (f);
+ EmacsScroller *bar;
+ int top, height, left, width;
+ int window_x, window_width;
+ int pixel_width = WINDOW_PIXEL_WIDTH (window);
+
+ /* optimization; display engine sends WAY too many of these.. */
+ if (!NILP (window->horizontal_scroll_bar))
+ {
+ bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
+ if ([bar checkSamePosition: position portion: portion whole: whole])
+ {
+ if (view->scrollbarsNeedingUpdate == 0)
+ {
+ if (!windows_or_buffers_changed)
+ return;
+ }
+ else
+ view->scrollbarsNeedingUpdate--;
+ }
+ }
+
+ NSTRACE (ns_set_horizontal_scroll_bar);
+
+ /* Get dimensions. */
+ window_box (window, ANY_AREA, 0, &window_x, &window_width, 0);
+ left = window_x;
+ width = window_width;
+ height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f);
+ top = WINDOW_SCROLL_BAR_AREA_Y (window);
+
+ r = NSMakeRect (left, top, width, height);
+ /* the parent view is flipped, so we need to flip y value */
+ v = [view frame];
+ /* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */
+ r.origin.y = (v.size.height - r.size.height - r.origin.y);
+
+ XSETWINDOW (win, window);
+ block_input ();
+
+ if (WINDOW_TOTAL_COLS (window) < 5)
+ {
+ if (!NILP (window->horizontal_scroll_bar))
+ {
+ bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
+ [bar removeFromSuperview];
+ wset_horizontal_scroll_bar (window, Qnil);
+ }
+ ns_clear_frame_area (f, left, top, width, height);
+ unblock_input ();
+ return;
+ }
+
+ if (NILP (window->horizontal_scroll_bar))
+ {
+ if (width > 0 && height > 0)
+ ns_clear_frame_area (f, left, top, width, height);
+
+ bar = [[EmacsScroller alloc] initFrame: r window: win];
+ wset_horizontal_scroll_bar (window, make_save_ptr (bar));
+ }
+ else
+ {
+ NSRect oldRect;
+ bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
+ oldRect = [bar frame];
+ r.size.width = oldRect.size.width;
+ if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
+ {
+ if (oldRect.origin.x != r.origin.x)
+ ns_clear_frame_area (f, left, top, width, height);
[bar setFrame: r];
}
}
bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
[bar reprieve];
}
+
+ if (!NILP (window->horizontal_scroll_bar))
+ {
+ bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
+ [bar reprieve];
+ }
}
[self sendEvent:event];
[self updateWindows];
} while (shouldKeepRunning);
-
+
[pool release];
}
((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES;
#endif
[NSApp setServicesProvider: NSApp];
-
- [self antialiasThresholdDidChange:nil];
-#ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(antialiasThresholdDidChange:)
- name:NSAntialiasThresholdChangedNotification
- object:nil];
-#endif
-#endif
-
ns_send_appdefined (-2);
}
-- (void)antialiasThresholdDidChange:(NSNotification *)notification
-{
-#ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- macfont_update_antialias_threshold ();
-#endif
-#endif
-}
-
/* Termination sequences:
C-x C-c:
if (nr_eff_screens == 1)
return [super constrainFrameRect:frameRect toScreen:screen];
-
+
/* The default implementation does two things 1) ensure that the top
of the rectangle is below the menu bar (or below the top of the
screen) and 2) resizes windows larger than the screen. As we
FRAME_COLUMN_WIDTH (f) = font->average_width;
FRAME_LINE_HEIGHT (f) = font->height;
- compute_fringe_widths (f, 1);
-
/* Compute the scroll bar width in character columns. */
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
{
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
}
+ /* Compute the scroll bar height in character lines. */
+ if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0)
+ {
+ int height = FRAME_LINE_HEIGHT (f);
+ FRAME_CONFIG_SCROLL_BAR_LINES (f)
+ = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
+ }
+ else
+ {
+ int height = FRAME_LINE_HEIGHT (f);
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
+ }
+
/* Now make the frame display the given font. */
if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen])
x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
was suspended. */
get_tty_size (fileno (t->display_info.tty->input), &width, &height);
if (width != old_width || height != old_height)
- change_frame_size (f, width, height, 0, 0, 0, 0);
+ change_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 0, 0, 0, 0);
SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
}
terminal->fullscreen_hook = 0;
terminal->menu_show_hook = 0;
terminal->set_vertical_scroll_bar_hook = 0;
+ terminal->set_horizontal_scroll_bar_hook = 0;
terminal->condemn_scroll_bars_hook = 0;
terminal->redeem_scroll_bar_hook = 0;
terminal->judge_scroll_bars_hook = 0;
tty->specified_window = height;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+ FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = 0;
tty->char_ins_del_ok = 1;
baud_rate = 19200;
}
scroll_bar_to_top,
scroll_bar_to_bottom,
scroll_bar_end_scroll,
- scroll_bar_move_ratio
+ scroll_bar_move_ratio,
+ scroll_bar_before_handle,
+ scroll_bar_horizontal_handle,
+ scroll_bar_after_handle,
+ scroll_bar_left_arrow,
+ scroll_bar_right_arrow,
+ scroll_bar_to_leftmost,
+ scroll_bar_to_rightmost
};
/* Output method of a terminal (and frames on this terminal, respectively). */
whose scroll bar was clicked in.
.timestamp gives a timestamp (in
milliseconds) for the click. */
+ HORIZONTAL_SCROLL_BAR_CLICK_EVENT, /* .code gives the number of the mouse button
+ that was clicked.
+ .modifiers holds the state of the modifier
+ keys.
+ .part is a lisp symbol indicating which
+ part of the scroll bar got clicked.
+ .x gives the distance from the start of the
+ scroll bar of the click; .y gives the total
+ length of the scroll bar.
+ .frame_or_window gives the window
+ whose scroll bar was clicked in.
+ .timestamp gives a timestamp (in
+ milliseconds) for the click. */
SELECTION_REQUEST_EVENT, /* Another X client wants a selection from us.
See `struct selection_input_event'. */
SELECTION_CLEAR_EVENT, /* Another X client cleared our selection. */
int position);
+ /* Set the horizontal scroll bar for WINDOW to have its upper left
+ corner at (TOP, LEFT), and be LENGTH rows high. Set its handle to
+ indicate that we are displaying PORTION characters out of a total
+ of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
+ have a scroll bar, create one for it. */
+ void (*set_horizontal_scroll_bar_hook) (struct window *window,
+ int portion, int whole,
+ int position);
+
+
/* The following three hooks are used when we're doing a thorough
redisplay of the frame. We don't explicitly know which scroll bars
are going to be deleted, because keeping track of when windows go
term->frame_rehighlight_hook = 0;
term->frame_raise_lower_hook = 0;
term->set_vertical_scroll_bar_hook = 0;
+ term->set_horizontal_scroll_bar_hook = 0;
term->condemn_scroll_bars_hook = 0;
term->redeem_scroll_bar_hook = 0;
term->judge_scroll_bars_hook = 0;
void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
-
-
+void x_set_internal_border_width (struct frame *f, Lisp_Object, Lisp_Object);
\f
/* Store the screen positions of frame F into XPTR and YPTR.
{
CHECK_NUMBER (Vx_window_horizontal_drag_shape);
horizontal_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f),
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f),
XINT (Vx_window_horizontal_drag_shape));
}
else
horizontal_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
if (!NILP (Vx_window_vertical_drag_shape))
{
CHECK_NUMBER (Vx_window_vertical_drag_shape);
vertical_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f),
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f),
XINT (Vx_window_vertical_drag_shape));
}
else
vertical_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_v_double_arrow);
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_v_double_arrow);
/* Check and report errors with the above calls. */
x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
unblock_input ();
#endif
}
-
\f
+void
+x_clear_under_internal_border (struct frame *f)
+{
+ int border = FRAME_INTERNAL_BORDER_WIDTH (f);
+
+ /* Clear border if it's larger than before. */
+ if (border != 0)
+ {
+ HDC hdc = get_frame_dc (f);
+ int width = FRAME_PIXEL_WIDTH (f);
+ int height = FRAME_PIXEL_HEIGHT (f);
+
+ block_input ();
+ w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
+ w32_clear_area (f, hdc, 0, 0, border, height);
+ w32_clear_area (f, hdc, width - border, 0, border, height);
+ w32_clear_area (f, hdc, 0, height - border, width, border);
+ release_frame_dc (f, hdc);
+ unblock_input ();
+ }
+}
+
+
+void
+x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ int border;
+
+ CHECK_TYPE_RANGED_INTEGER (int, arg);
+ border = max (XINT (arg), 0);
+
+ if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
+ {
+ FRAME_INTERNAL_BORDER_WIDTH (f) = border;
+
+ if (FRAME_X_WINDOW (f) != 0)
+ {
+ adjust_frame_size (f, -1, -1, 3, 0);
+
+ if (FRAME_VISIBLE_P (f))
+ x_clear_under_internal_border (f);
+ }
+ }
+}
+
+
void
x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_MENU_BAR_HEIGHT (f) = 0;
if (nlines)
- FRAME_EXTERNAL_MENU_BAR (f) = 1;
+ {
+ FRAME_EXTERNAL_MENU_BAR (f) = 1;
+ windows_or_buffers_changed = 23;
+ }
else
{
if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
/* Adjust the frame size so that the client (text) dimensions
remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
- set correctly. */
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ set correctly. Note that we resize twice: The first time upon
+ a request from the window manager who wants to keep the height
+ of the outer rectangle (including decorations) unchanged, and a
+ second time because we want to keep the height of the inner
+ rectangle (without the decorations unchanged). */
+ adjust_frame_size (f, -1, -1, 2, 1);
+
+ /* Not sure whether this is needed. */
+ x_clear_under_internal_border (f);
}
- adjust_frame_glyphs (f);
}
void
x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
- int delta, nlines, root_height;
- int unit = FRAME_LINE_HEIGHT (f);
+ int nlines;
/* Treat tool bars like menu bars. */
if (FRAME_MINIBUF_ONLY_P (f))
else
nlines = 0;
- /* Make sure we redisplay all windows in this frame. */
- windows_or_buffers_changed = 23;
+ x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+}
- /* DELTA is in pixels now. */
- delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit;
- /* Don't resize the tool-bar to more than we have room for. Note: The
- calculations below and the subsequent call to resize_frame_windows
- are inherently flawed because they can make the toolbar higher than
- the containing frame. */
- if (delta > 0)
- {
- root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)));
- if (root_height - delta < unit)
- {
- delta = root_height - unit;
- /* When creating a new frame and toolbar mode is enabled, we
- need at least one toolbar line. */
- nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1);
- }
- }
+/* Set the pixel height of the tool bar of frame F to HEIGHT. */
+void
+x_change_tool_bar_height (struct frame *f, int height)
+{
+ Lisp_Object frame;
+ int unit = FRAME_LINE_HEIGHT (f);
+ int old_height = FRAME_TOOL_BAR_HEIGHT (f);
+ int lines = (height + unit - 1) / unit;
+ int old_text_height = FRAME_TEXT_HEIGHT (f);
- FRAME_TOOL_BAR_LINES (f) = nlines;
- FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
- ++windows_or_buffers_changed;
- resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1);
- adjust_frame_glyphs (f);
+ /* Make sure we redisplay all windows in this frame. */
+ windows_or_buffers_changed = 23;
+
+ /* Recalculate tool bar and frame text sizes. */
+ FRAME_TOOL_BAR_HEIGHT (f) = height;
+ FRAME_TOOL_BAR_LINES (f) = lines;
+ FRAME_TEXT_HEIGHT (f)
+ = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f));
+ FRAME_LINES (f)
+ = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
+ /* Store the `tool-bar-lines' and `height' frame parameters. */
+ store_frame_param (f, Qtool_bar_lines, make_number (lines));
+ store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
- /* We also have to make sure that the internal border at the top of
- the frame, below the menu bar or tool bar, is redrawn when the
- tool bar disappears. This is so because the internal border is
- below the tool bar if one is displayed, but is below the menu bar
- if there isn't a tool bar. The tool bar draws into the area
- below the menu bar. */
if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
{
clear_frame (f);
clear_current_matrices (f);
}
- /* If the tool bar gets smaller, the internal border below it
- has to be cleared. It was formerly part of the display
- of the larger tool bar, and updating windows won't clear it. */
- if (FRAME_INTERNAL_BORDER_WIDTH (f) != 0 && FRAME_VISIBLE_P (f))
- {
- int height = FRAME_INTERNAL_BORDER_WIDTH (f);
- int width = FRAME_PIXEL_WIDTH (f);
- int y = nlines * unit;
- HDC hdc = get_frame_dc (f);
+ if ((height < old_height) && WINDOWP (f->tool_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
- block_input ();
- w32_clear_area (f, hdc, 0, y, width, height);
- release_frame_dc (f, hdc);
- unblock_input ();
- }
+ /* Recalculate toolbar height. */
+ f->n_tool_bar_rows = 0;
- if (delta < 0 && WINDOWP (f->tool_bar_window))
- clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+ adjust_frame_size (f, -1, -1, 4, 0);
- run_window_configuration_change_hook (f);
+ if (FRAME_X_WINDOW (f))
+ x_clear_under_internal_border (f);
}
= (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
}
+
+void
+x_set_scroll_bar_default_height (struct frame *f)
+{
+ int unit = FRAME_LINE_HEIGHT (f);
+
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
+ FRAME_CONFIG_SCROLL_BAR_LINES (f)
+ = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
+}
\f
/* Subroutines for creating a frame. */
}
static HWND
-w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
+w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
{
return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
/* Position and size of scroll bar. */
FRAME_W32_WINDOW (f), NULL, hinst, NULL);
}
+static HWND
+w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
+{
+ return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE,
+ /* Position and size of scroll bar. */
+ bar->left, bar->top, bar->width, bar->height,
+ FRAME_W32_WINDOW (f), NULL, hinst, NULL);
+}
+
static void
w32_createwindow (struct frame *f)
{
SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
- SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (hwnd, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (hwnd, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
/* Enable drag-n-drop. */
M (WM_EMACS_KILL),
M (WM_EMACS_CREATEWINDOW),
M (WM_EMACS_DONE),
- M (WM_EMACS_CREATESCROLLBAR),
+ M (WM_EMACS_CREATEVSCROLLBAR),
+ M (WM_EMACS_CREATEHSCROLLBAR),
M (WM_EMACS_SHOWWINDOW),
M (WM_EMACS_SETWINDOWPOS),
M (WM_EMACS_DESTROYWINDOW),
M (WM_EMACS_SHOW_CARET),
M (WM_EMACS_HIDE_CARET),
M (WM_EMACS_SETCURSOR),
+ M (WM_EMACS_SHOWCURSOR),
M (WM_EMACS_PAINT),
M (WM_CHAR),
#undef M
track_mouse_event_fn (&tme);
track_mouse_window = hwnd;
}
+ case WM_HSCROLL:
case WM_VSCROLL:
if (w32_mouse_move_interval <= 0
|| (msg == WM_MOUSEMOVE && button_state == 0))
return 0;
case WM_WINDOWPOSCHANGING:
- /* Don't restrict the sizing of tip frames. */
- if (frame_resize_pixelwise || hwnd == tip_window)
- return 0;
+ /* Don't restrict the sizing of any kind of frames. If the window
+ manager doesn't, there's no reason to do it ourselves. */
+#if 0
+ if (frame_resize_pixelwise || hwnd == tip_window)
+#endif
+ return 0;
+#if 0
/* Don't restrict the sizing of fullscreened frames, allowing them to be
flush with the sides of the screen. */
f = x_window_to_frame (dpyinfo, hwnd);
DWORD font_width;
DWORD line_height;
DWORD internal_border;
- DWORD scrollbar_extra;
+ DWORD vscrollbar_extra;
+ DWORD hscrollbar_extra;
RECT wr;
wp.length = sizeof (wp);
font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
- scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
+ vscrollbar_extra = GetWindowLong (hwnd, WND_VSCROLLBAR_INDEX);
+ hscrollbar_extra = GetWindowLong (hwnd, WND_HSCROLLBAR_INDEX);
leave_crit ();
/* Force width and height of client area to be exact
multiples of the character cell dimensions. */
wdiff = (lppos->cx - (rect.right - rect.left)
- - 2 * internal_border - scrollbar_extra)
+ - 2 * internal_border - vscrollbar_extra)
% font_width;
hdiff = (lppos->cy - (rect.bottom - rect.top)
- - 2 * internal_border)
+ - 2 * internal_border - hscrollbar_extra)
% line_height;
if (wdiff || hdiff)
}
goto dflt;
+#endif
case WM_GETMINMAXINFO:
/* Hack to allow resizing the Emacs frame above the screen size.
return 0;
}
- case WM_EMACS_CREATESCROLLBAR:
- return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
- (struct scroll_bar *) lParam);
+ case WM_EMACS_SHOWCURSOR:
+ {
+ ShowCursor ((BOOL) wParam);
+
+ return 0;
+ }
+
+ case WM_EMACS_CREATEVSCROLLBAR:
+ return (LRESULT) w32_createvscrollbar ((struct frame *) wParam,
+ (struct scroll_bar *) lParam);
+
+ case WM_EMACS_CREATEHSCROLLBAR:
+ return (LRESULT) w32_createhscrollbar ((struct frame *) wParam,
+ (struct scroll_bar *) lParam);
case WM_EMACS_SHOWWINDOW:
return ShowWindow ((HWND) wParam, (WPARAM) lParam);
SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
/* Tip frames have no scrollbars. */
- SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
+ SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0);
+ SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0);
/* Do this to discard the default setting specified by our parent. */
ShowWindow (tip_window, SW_HIDE);
Lisp_Object name;
int minibuffer_only = 0;
long window_prompting = 0;
- int width, height;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
XSETFRAME (frame, f);
- /* By default, make scrollbars the system standard width. */
- x_set_scroll_bar_default_width (f);
+ /* By default, make scrollbars the system standard width and height. */
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
f->terminal = dpyinfo->terminal;
#endif /* GLYPH_DEBUG */
/* Specify the parent under which to make this window. */
-
if (!NILP (parent))
{
f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
{
fset_name (f, name);
f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
+ /* Use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
x_default_parameter (f, parameters, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
+
/* Extract the window parameters from the supplied values
that are needed to determine window geometry. */
x_default_font_parameter (f, parameters);
+
x_default_parameter (f, parameters, Qborder_width, make_number (2),
"borderWidth", "BorderWidth", RES_TYPE_NUMBER);
"internalBorder", "InternalBorder", RES_TYPE_NUMBER);
if (! EQ (value, Qunbound))
parameters = Fcons (Fcons (Qinternal_border_width, value),
- parameters);
+ parameters);
}
/* Default internalBorderWidth to 0 on Windows to match other programs. */
x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
NULL, NULL, RES_TYPE_NUMBER);
x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
"verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
+ x_default_parameter (f, parameters, Qhorizontal_scroll_bars, Qbottom,
+ "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
/* Also do the stuff which must be set before the window exists. */
x_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
"rightFringe", "RightFringe", RES_TYPE_NUMBER);
/* Process alpha here (Bug#16619). */
x_default_parameter (f, parameters, Qalpha, Qnil,
- "alpha", "Alpha", RES_TYPE_NUMBER);
+ "alpha", "Alpha", RES_TYPE_NUMBER);
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
+ /* Init faces first since we need the frame's column width/line
+ height in various occasions. */
init_frame_faces (f);
- /* Avoid calling window-configuration-change-hook; otherwise we
- could get an infloop in next_frame since the frame is not yet in
- Vframe_list. */
- {
- ptrdiff_t count2 = SPECPDL_INDEX ();
-
- record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code);
- inhibit_lisp_code = Qt;
-
- /* PXW: This is a duplicate from below. We have to do it here since
- otherwise x_set_tool_bar_lines will work with the character sizes
- installed by init_frame_faces while the frame's pixel size is still
- calculated from a character size of 1 and we subsequently hit the
- eassert (height >= 0) assertion in window_box_height. The
- non-pixelwise code apparently worked around this because it had one
- frame line vs one toolbar line which left us with a zero root
- window height which was obviously wrong as well ... */
- change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1);
-
- /* The X resources controlling the menu-bar and tool-bar are
- processed specially at startup, and reflected in the mode
- variables; ignore them here. */
- x_default_parameter (f, parameters, Qmenu_bar_lines,
- NILP (Vmenu_bar_mode)
- ? make_number (0) : make_number (1),
- NULL, NULL, RES_TYPE_NUMBER);
- x_default_parameter (f, parameters, Qtool_bar_lines,
- NILP (Vtool_bar_mode)
- ? make_number (0) : make_number (1),
- NULL, NULL, RES_TYPE_NUMBER);
-
- unbind_to (count2, Qnil);
- }
+ /* The following call of change_frame_size is needed since otherwise
+ x_set_tool_bar_lines will already work with the character sizes
+ installed by init_frame_faces while the frame's pixel size is
+ still calculated from a character size of 1 and we subsequently
+ hit the (height >= 0) assertion in window_box_height.
+
+ The non-pixelwise code apparently worked around this because it
+ had one frame line vs one toolbar line which left us with a zero
+ root window height which was obviously wrong as well ... */
+ adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1);
+
+ /* The X resources controlling the menu-bar and tool-bar are
+ processed specially at startup, and reflected in the mode
+ variables; ignore them here. */
+ x_default_parameter (f, parameters, Qmenu_bar_lines,
+ NILP (Vmenu_bar_mode)
+ ? make_number (0) : make_number (1),
+ NULL, NULL, RES_TYPE_NUMBER);
+ x_default_parameter (f, parameters, Qtool_bar_lines,
+ NILP (Vtool_bar_mode)
+ ? make_number (0) : make_number (1),
+ NULL, NULL, RES_TYPE_NUMBER);
x_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
x_default_parameter (f, parameters, Qtitle, Qnil,
"title", "Title", RES_TYPE_STRING);
x_default_parameter (f, parameters, Qfullscreen, Qnil,
- "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
"cursorType", "CursorType", RES_TYPE_SYMBOL);
x_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
"scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
+ x_default_parameter (f, parameters, Qscroll_bar_height, Qnil,
+ "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER);
+
+ /* Consider frame official, now. */
+ f->official = true;
- /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
- Change will not be effected unless different from the current
- FRAME_LINES (f). */
- width = FRAME_TEXT_WIDTH (f);
- height = FRAME_TEXT_HEIGHT (f);
- FRAME_TEXT_HEIGHT (f) = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, width, height, 1, 0, 0, 1);
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1);
/* Tell the server what size and position, etc, we want, and how
badly we want them. This should be done after we have the menu
"cursorColor", "Foreground", RES_TYPE_STRING);
x_default_parameter (f, parms, Qborder_color, build_string ("black"),
"borderColor", "BorderColor", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qalpha, Qnil,
+ "alpha", "Alpha", RES_TYPE_NUMBER);
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
+ /* Init faces before x_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
init_frame_faces (f);
f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
from the current FRAME_LINES (f). */
width = FRAME_COLS (f);
height = FRAME_LINES (f);
- FRAME_LINES (f) = 0;
SET_FRAME_COLS (f, 0);
- change_frame_size (f, width, height, 1, 0, 0, 0);
+ SET_FRAME_LINES (f, 0);
+ adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
+ height * FRAME_LINE_HEIGHT (f), 0, 1);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
below. And the frame needs to be on Vframe_list or making it
visible won't work. */
Vframe_list = Fcons (frame, Vframe_list);
+ f->official = true;
/* Setting attributes of faces of the tooltip frame from resources
and similar will increment face_change_count, which leads to the
x_set_mouse_color,
x_explicitly_set_name,
x_set_scroll_bar_width,
+ x_set_scroll_bar_height,
x_set_title,
x_set_unsplittable,
x_set_vertical_scroll_bars,
+ x_set_horizontal_scroll_bars,
x_set_visibility,
x_set_tool_bar_lines,
0, /* x_set_scroll_bar_foreground, */
0, /* x_set_scroll_bar_background, */
x_set_screen_gamma,
x_set_line_spacing,
- x_set_fringe_width,
- x_set_fringe_width,
+ x_set_left_fringe,
+ x_set_right_fringe,
0, /* x_set_wait_for_wm, */
x_set_fullscreen,
x_set_font_backend,
{
struct frame *f = get_frame ();
- change_frame_size (f, event->dwSize.X, event->dwSize.Y, 0, 1, 0, 0);
+ change_frame_size (f, event->dwSize.X, event->dwSize.Y
+ - FRAME_MENU_BAR_LINES (f), 0, 1, 0, 0);
SET_FRAME_GARBAGED (f);
}
if the size hasn't actually changed. */
change_frame_size (f,
1 + info.srWindow.Right - info.srWindow.Left,
- 1 + info.srWindow.Bottom - info.srWindow.Top,
- 0, 0, 0, 0);
+ 1 + info.srWindow.Bottom - info.srWindow.Top
+ - FRAME_MENU_BAR_LINES (f), 0, 0, 0, 0);
}
#if HAVE_W32NOTIFY
/* Force the window size to be recomputed so that the frame's text
area remains the same, if menubar has just been created. */
if (old_widget == NULL)
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
+ FRAME_TEXT_HEIGHT (f), 2, 0);
}
unblock_input ();
HANDLE hMainThread = NULL;
int vertical_scroll_bar_min_handle;
+int horizontal_scroll_bar_min_handle;
int vertical_scroll_bar_top_border;
int vertical_scroll_bar_bottom_border;
+int horizontal_scroll_bar_left_border;
+int horizontal_scroll_bar_right_border;
int last_scroll_bar_drag_pos;
if (!pfnSetLayeredWindowAttributes)
return;
- if (dpyinfo->x_highlight_frame == f)
+ if (dpyinfo->w32_focus_frame == f)
alpha = f->alpha[0];
else
alpha = f->alpha[1];
Mouse Face
************************************************************************/
-static struct scroll_bar *x_window_to_scroll_bar (Window);
+static struct scroll_bar *x_window_to_scroll_bar (Window, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
unsigned long *);
+static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
+ enum scroll_bar_part *,
+ Lisp_Object *, Lisp_Object *,
+ unsigned long *);
static void x_check_fullscreen (struct frame *);
static void
{
PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
}
+
/* Return the current position of the mouse.
*fp should be a frame which indicates which display to ask about.
block_input ();
if (dpyinfo->last_mouse_scroll_bar && insist == 0)
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ {
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+
+ if (bar->horizontal)
+ x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ else
+ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ }
else
{
POINT pt;
if (! f1)
{
struct scroll_bar *bar
- = x_window_to_scroll_bar (WindowFromPoint (pt));
+ = x_window_to_scroll_bar (WindowFromPoint (pt), 2);
if (bar)
f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
/* Scroll bar support. */
-/* Given a window ID, find the struct scroll_bar which manages it.
- This can be called in GC, so we have to make sure to strip off mark
- bits. */
+/* Given a window ID, find the struct scroll_bar which manages it
+ vertically. This can be called in GC, so we have to make sure to
+ strip off mark bits. */
static struct scroll_bar *
-x_window_to_scroll_bar (Window window_id)
+x_window_to_scroll_bar (Window window_id, int type)
{
Lisp_Object tail, frame;
condemned = Qnil,
! NILP (bar));
bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
+ if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id
+ && (type = 2
+ || (type == 1 && XSCROLL_BAR (bar)->horizontal)
+ || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
return XSCROLL_BAR (bar);
}
\f
-/* Set the thumb size and position of scroll bar BAR. We are currently
+/* Set the thumb size and position of vertical scroll bar BAR. We are currently
displaying PORTION out of a whole WHOLE, and our position POSITION. */
static void
unblock_input ();
}
+/* Set the thumb size and position of horizontal scroll bar BAR. We are currently
+ displaying PORTION out of a whole WHOLE, and our position POSITION. */
+
+static void
+w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
+ int portion, int position, int whole)
+{
+ Window w = SCROLL_BAR_W32_WINDOW (bar);
+ SCROLLINFO si;
+
+ block_input ();
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = whole;
+ /* Allow nPage to be one larger than nPos so we don't allow to scroll
+ an already fully visible buffer. */
+ si.nPage = min (portion, si.nMax) + 1;
+ si.nPos = min (position, si.nMax);
+ SetScrollInfo (w, SB_CTL, &si, TRUE);
+
+ unblock_input ();
+}
+
\f
/************************************************************************
Scroll bars, general
************************************************************************/
static HWND
-my_create_scrollbar (struct frame * f, struct scroll_bar * bar)
+my_create_vscrollbar (struct frame * f, struct scroll_bar * bar)
+{
+ return (HWND) SendMessage (FRAME_W32_WINDOW (f),
+ WM_EMACS_CREATEVSCROLLBAR, (WPARAM) f,
+ (LPARAM) bar);
+}
+
+static HWND
+my_create_hscrollbar (struct frame * f, struct scroll_bar * bar)
{
return (HWND) SendMessage (FRAME_W32_WINDOW (f),
- WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
+ WM_EMACS_CREATEHSCROLLBAR, (WPARAM) f,
(LPARAM) bar);
}
scroll bar. */
static struct scroll_bar *
-x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
+x_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HWND hwnd;
bar->start = 0;
bar->end = 0;
bar->dragging = 0;
+ bar->horizontal = horizontal;
/* Requires geometry to be set before call to create the real window */
- hwnd = my_create_scrollbar (f, bar);
+ if (horizontal)
+ hwnd = my_create_hscrollbar (f, bar);
+ else
+ hwnd = my_create_vscrollbar (f, bar);
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0;
- si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
- + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+ if (horizontal)
+ si.nMax = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width)
+ + HORIZONTAL_SCROLL_BAR_MIN_HANDLE;
+ else
+ si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ + VERTICAL_SCROLL_BAR_MIN_HANDLE;
si.nPage = si.nMax;
si.nPos = 0;
my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
/* Dissociate this scroll bar from its window. */
- wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
+ if (bar->horizontal)
+ wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
+ else
+ wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
unblock_input ();
}
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
+/* Set the handle of the vertical scroll bar for WINDOW to indicate that
+ we are displaying PORTION characters out of a total of WHOLE
+ characters, starting at POSITION. If WINDOW has no vertical scroll
+ bar, create one. */
static void
w32_set_vertical_scroll_bar (struct window *w,
int portion, int whole, int position)
}
unblock_input ();
- bar = x_scroll_bar_create (w, top, left, width, height);
+ bar = x_scroll_bar_create (w, left, top, width, height, 0);
}
else
{
wset_vertical_scroll_bar (w, barobj);
}
+/* Set the handle of the horizontal scroll bar for WINDOW to indicate
+ that we are displaying PORTION characters out of a total of WHOLE
+ characters, starting at POSITION. If WINDOW has no horizontal scroll
+ bar, create one. */
+static void
+w32_set_horizontal_scroll_bar (struct window *w,
+ int portion, int whole, int position)
+{
+ struct frame *f = XFRAME (w->frame);
+ Lisp_Object barobj;
+ struct scroll_bar *bar;
+ int top, height, left, width;
+ int window_x, window_width;
+ int clear_left = WINDOW_LEFT_EDGE_X (w);
+ int clear_width = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+
+ /* Get window dimensions. */
+ window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
+ left = window_x;
+ height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+ width = window_width;
+ top = WINDOW_SCROLL_BAR_AREA_Y (w);
+
+ /* Does the scroll bar exist yet? */
+ if (NILP (w->horizontal_scroll_bar))
+ {
+ HDC hdc;
+ block_input ();
+ if (width > 0 && height > 0)
+ {
+ hdc = get_frame_dc (f);
+ w32_clear_area (f, hdc, clear_left, top, clear_width, height);
+ release_frame_dc (f, hdc);
+ }
+ unblock_input ();
+
+ bar = x_scroll_bar_create (w, left, top, width, height, 1);
+ }
+ else
+ {
+ /* It may just need to be moved and resized. */
+ HWND hwnd;
+
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+ hwnd = SCROLL_BAR_W32_WINDOW (bar);
+
+ /* If already correctly positioned, do nothing. */
+ if (bar->left == left && bar->top == top
+ && bar->width == width && bar->height == height)
+ {
+ /* Redraw after clear_frame. */
+ if (!my_show_window (f, hwnd, SW_NORMAL))
+ InvalidateRect (hwnd, NULL, FALSE);
+ }
+ else
+ {
+ HDC hdc;
+ SCROLLINFO si;
+
+ block_input ();
+ if (width && height)
+ {
+ hdc = get_frame_dc (f);
+ /* Since Windows scroll bars are smaller than the space reserved
+ for them on the frame, we have to clear "under" them. */
+ w32_clear_area (f, hdc, clear_left, top, clear_width, height);
+ release_frame_dc (f, hdc);
+ }
+ /* Make sure scroll bar is "visible" before moving, to ensure the
+ area of the parent window now exposed will be refreshed. */
+ my_show_window (f, hwnd, SW_HIDE);
+ MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
+
+ /* +++ SetScrollInfo +++ */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = whole;
+ si.nPage = min (portion, si.nMax) + 1;
+ si.nPos = min (position, si.nMax);
+ SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
+
+ my_show_window (f, hwnd, SW_NORMAL);
+ /* InvalidateRect (w, NULL, FALSE); */
+
+ /* Remember new settings. */
+ bar->left = left;
+ bar->top = top;
+ bar->width = width;
+ bar->height = height;
+
+ unblock_input ();
+ }
+ }
+
+ w32_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
+ XSETVECTOR (barobj, bar);
+ wset_horizontal_scroll_bar (w, barobj);
+}
+
/* The following three hooks are used when we're doing a thorough
redisplay of the frame. We don't explicitly know which scroll bars
static void
w32_condemn_scroll_bars (struct frame *frame)
{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
+ if (!NILP (FRAME_SCROLL_BARS (frame)))
{
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- fset_condemned_scroll_bars (frame, bar);
+ if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+ {
+ /* Prepend scrollbars to already condemned ones. */
+ Lisp_Object last = FRAME_SCROLL_BARS (frame);
+
+ while (!NILP (XSCROLL_BAR (last)->next))
+ last = XSCROLL_BAR (last)->next;
+
+ XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+ XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
+ }
+
+ fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
+ fset_scroll_bars (frame, Qnil);
}
}
Note that WINDOW isn't necessarily condemned at all. */
static void
-w32_redeem_scroll_bar (struct window *window)
+w32_redeem_scroll_bar (struct window *w)
{
struct scroll_bar *bar;
Lisp_Object barobj;
struct frame *f;
/* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
+ if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
emacs_abort ();
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- f = XFRAME (WINDOW_FRAME (window));
- if (NILP (bar->prev))
+ if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
{
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- fset_condemned_scroll_bars (f, bar->next);
+ bar = XSCROLL_BAR (w->vertical_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ goto horizontal;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->vertical_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- emacs_abort ();
+ XSCROLL_BAR (bar->prev)->next = bar->next;
+
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
+ horizontal:
+ if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+ {
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ return;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->horizontal_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
+ else
+ XSCROLL_BAR (bar->prev)->next = bar->next;
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (barobj, bar);
- fset_scroll_bars (f, barobj);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ }
}
/* Remove all scroll bars on FRAME that haven't been saved since the
and they should get garbage-collected. */
}
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than NO_EVENT, it is enqueued.
+/* Handle a mouse click on the vertical scroll bar BAR. If
+ *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
+ enqueued.
This may be called from a signal handler, so we have to ignore GC
mark bits. */
}
}
-/* Return information to the user about the current position of the mouse
- on the scroll bar. */
+/* Handle a mouse click on the horizontal scroll bar BAR. If
+ *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
+ enqueued.
+
+ This may be called from a signal handler, so we have to ignore GC
+ mark bits. */
+static int
+w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
+ struct input_event *emacs_event)
+{
+ if (! WINDOWP (bar->window))
+ emacs_abort ();
+
+ emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
+ emacs_event->code = 0;
+ /* not really meaningful to distinguish left/right */
+ emacs_event->modifiers = msg->dwModifiers;
+ emacs_event->frame_or_window = bar->window;
+ emacs_event->arg = Qnil;
+ emacs_event->timestamp = msg->msg.time;
+
+ {
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ int x;
+ int dragging = bar->dragging;
+ SCROLLINFO si;
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+
+ GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+ x = si.nPos;
+
+ bar->dragging = 0;
+ FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
+
+ switch (LOWORD (msg->msg.wParam))
+ {
+ case SB_LINELEFT:
+ emacs_event->part = scroll_bar_left_arrow;
+ break;
+ case SB_LINERIGHT:
+ emacs_event->part = scroll_bar_right_arrow;
+ break;
+ case SB_PAGELEFT:
+ emacs_event->part = scroll_bar_before_handle;
+ break;
+ case SB_PAGERIGHT:
+ emacs_event->part = scroll_bar_after_handle;
+ break;
+ case SB_LEFT:
+ emacs_event->part = scroll_bar_horizontal_handle;
+ x = 0;
+ break;
+ case SB_RIGHT:
+ emacs_event->part = scroll_bar_horizontal_handle;
+ x = left_range;
+ break;
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ if (HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width) <= 0xffff)
+ x = HIWORD (msg->msg.wParam);
+ bar->dragging = 1;
+ emacs_event->part = scroll_bar_horizontal_handle;
+
+ /* "Silently" update current position. */
+ {
+ SCROLLINFO si;
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ si.nPos = min (x, XWINDOW (bar->window)->hscroll_whole - 1);
+ /* Remember apparent position (we actually lag behind the real
+ position, so don't set that directly). */
+ last_scroll_bar_drag_pos = x;
+
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+ }
+ break;
+ case SB_ENDSCROLL:
+ /* If this is the end of a drag sequence, then reset the scroll
+ handle size to normal and do a final redraw. Otherwise do
+ nothing. */
+ if (dragging)
+ {
+ SCROLLINFO si;
+ int start = bar->start;
+ int end = bar->end;
+
+ si.cbSize = sizeof (si);
+/** si.fMask = SIF_PAGE | SIF_POS; **/
+ si.fMask = SIF_POS;
+/** si.nPage = end - start + HORIZONTAL_SCROLL_BAR_MIN_HANDLE; **/
+ si.nPos = min (last_scroll_bar_drag_pos,
+ XWINDOW (bar->window)->hscroll_whole - 1);
+/** si.nPos = last_scroll_bar_drag_pos; **/
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
+ }
+ /* fall through */
+ default:
+ emacs_event->kind = NO_EVENT;
+ return FALSE;
+ }
+
+ XSETINT (emacs_event->x, x);
+ XSETINT (emacs_event->y, left_range);
+
+ return TRUE;
+ }
+}
+
+/* Return information to the user about the current position of the mouse
+ on the vertical scroll bar. */
static void
x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
enum scroll_bar_part *part,
unblock_input ();
}
+/* Return information to the user about the current position of the mouse
+ on the horizontal scroll bar. */
+static void
+x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
+ enum scroll_bar_part *part,
+ Lisp_Object *x, Lisp_Object *y,
+ unsigned long *time)
+{
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+ Window w = SCROLL_BAR_W32_WINDOW (bar);
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ int pos;
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ SCROLLINFO si;
+
+ block_input ();
+
+ *fp = f;
+ *bar_window = bar->window;
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+
+ GetScrollInfo (w, SB_CTL, &si);
+ pos = si.nPos;
+ left_range = si.nMax - si.nPage + 1;
+
+ switch (LOWORD (dpyinfo->last_mouse_scroll_bar_pos))
+ {
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ *part = scroll_bar_handle;
+ if (HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width) <= 0xffff)
+ pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos);
+ break;
+ case SB_LINERIGHT:
+ *part = scroll_bar_handle;
+ pos++;
+ break;
+ default:
+ *part = scroll_bar_handle;
+ break;
+ }
+
+ XSETINT (*y, pos);
+ XSETINT (*x, left_range);
+
+ f->mouse_moved = 0;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+
+ *time = dpyinfo->last_mouse_movement_time;
+
+ unblock_input ();
+}
+
/* The screen has been cleared so we may have changed foreground or
background colors, and the scroll bars may need to be redrawn.
/* We can have scroll bars even if this is 0,
if we just turned off scroll bar mode.
But in that case we should not clear them. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ || FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
{
construct_drag_n_drop (&inev, &msg, f);
break;
+ case WM_HSCROLL:
+ {
+ struct scroll_bar *bar =
+ x_window_to_scroll_bar ((HWND)msg.msg.lParam, 1);
+
+ if (bar)
+ w32_horizontal_scroll_bar_handle_click (bar, &msg, &inev);
+ break;
+ }
+
case WM_VSCROLL:
{
struct scroll_bar *bar =
- x_window_to_scroll_bar ((HWND)msg.msg.lParam);
+ x_window_to_scroll_bar ((HWND)msg.msg.lParam, 0);
if (bar)
w32_scroll_bar_handle_click (bar, &msg, &inev);
change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
- /* Do we want to set these here ???? */
-/** FRAME_PIXEL_WIDTH (f) = width; **/
-/** FRAME_TEXT_WIDTH (f) = text_width; **/
-/** FRAME_PIXEL_HEIGHT (f) = height; **/
f->win_gravity = NorthWestGravity;
}
}
FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
FRAME_LINE_HEIGHT (f) = font->height;
- compute_fringe_widths (f, 1);
-
/* Compute number of scrollbar columns. */
unit = FRAME_COLUMN_WIDTH (f);
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
doing it because it's done in Fx_show_tip, and it leads to
problems because the tip frame has no widget. */
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
- x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
+ adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0);
}
/* X version sets font of input methods here also. */
HWND hwnd = FRAME_W32_WINDOW(f);
DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
RECT rect;
+ enum fullscreen_type prev_fsmode = FRAME_PREV_FSMODE (f);
block_input();
f->want_fullscreen &= ~FULLSCREEN_WAIT;
if (f->want_fullscreen == FULLSCREEN_NONE)
ShowWindow (hwnd, SW_SHOWNORMAL);
else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
- ShowWindow (hwnd, SW_MAXIMIZE);
+ {
+ if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH
+ || prev_fsmode == FULLSCREEN_HEIGHT)
+ /* Make window normal since otherwise the subsequent
+ maximization might fail in some cases. */
+ ShowWindow (hwnd, SW_SHOWNORMAL);
+ ShowWindow (hwnd, SW_MAXIMIZE);
+ }
else if (f->want_fullscreen == FULLSCREEN_BOTH)
{
w32_fullscreen_rect (hwnd, f->want_fullscreen,
x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
int pixelwidth, pixelheight;
+ RECT rect;
block_input ();
- check_frame_size (f, &width, &height, pixelwise);
-
- compute_fringe_widths (f, 0);
-
- if (frame_resize_pixelwise)
+ if (pixelwise)
{
- if (pixelwise)
- {
- pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
- pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
- }
- else
- {
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
- }
+ pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
+ pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
}
else
{
- /* If we don't resize frames pixelwise, round sizes to multiples
- of character sizes here. Otherwise, when enforcing size hints
- while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might
- clip our frame rectangle to a multiple of the frame's character
- size and subsequently lose our mode line or scroll bar.
- Bug#16923 could be one possible consequence of this. Carefully
- reverse-engineer what WM_WINDOWPOSCHANGING does here since
- otherwise we might make our frame too small, see Bug#17077. */
- int unit_width = FRAME_COLUMN_WIDTH (f);
- int unit_height = FRAME_LINE_HEIGHT (f);
-
- pixelwidth = (((((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f)))
- + FRAME_TOTAL_FRINGE_WIDTH (f))
- / unit_width) * unit_width)
- + FRAME_SCROLL_BAR_AREA_WIDTH (f)
- + 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
- pixelheight = ((((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f)))
- / unit_height) * unit_height)
- + 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
+ pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
}
f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
- {
- RECT rect;
+ f->want_fullscreen = FULLSCREEN_NONE;
+ w32fullscreen_hook (f);
- rect.left = rect.top = 0;
- rect.right = pixelwidth;
- rect.bottom = pixelheight;
+ rect.left = rect.top = 0;
+ rect.right = pixelwidth;
+ rect.bottom = pixelheight;
- AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
+ AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
+ FRAME_EXTERNAL_MENU_BAR (f));
- my_set_window_pos (FRAME_W32_WINDOW (f),
- NULL,
- 0, 0,
- rect.right - rect.left,
- rect.bottom - rect.top,
- SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
- }
+ my_set_window_pos (FRAME_W32_WINDOW (f),
+ NULL,
+ 0, 0,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
/* If w32_enable_frame_resize_hack is non-nil, immediately apply the
new pixel sizes to the frame and its subwindows.
}
unblock_input ();
+
+ do_pending_window_change (0);
}
\f
/* Mouse warping. */
SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
- SetWindowLong (window, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (window, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (window, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
leave_crit ();
}
dpyinfo->smallest_font_height = 1;
dpyinfo->smallest_char_width = 1;
dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
+ dpyinfo->horizontal_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
/* TODO: dpyinfo->gray */
reset_mouse_highlight (&dpyinfo->mouse_highlight);
terminal->menu_show_hook = w32_menu_show;
terminal->popup_dialog_hook = w32_popup_dialog;
terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
+ terminal->set_horizontal_scroll_bar_hook = w32_set_horizontal_scroll_bar;
terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
#undef LOAD_PROC
- /* Ensure scrollbar handle is at least 5 pixels. */
+ /* Ensure scrollbar handles are at least 5 pixels. */
vertical_scroll_bar_min_handle = 5;
+ horizontal_scroll_bar_min_handle = 5;
/* For either kind of scroll bar, take account of the arrows; these
effectively form the border of the main scroll bar range. */
vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
= GetSystemMetrics (SM_CYVSCROLL);
+ horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
+ = GetSystemMetrics (SM_CYHSCROLL);
}
}
/* The cursor to use for vertical scroll bars. */
Cursor vertical_scroll_bar_cursor;
+ /* The cursor to use for horizontal scroll bars. */
+ Cursor horizontal_scroll_bar_cursor;
+
/* Resource data base */
XrmDatabase xrdb;
/* Time of last mouse movement. */
Time last_mouse_movement_time;
+
+ /* Value returned by last call of ShowCursor. */
+ int cursor_display_counter;
};
/* This is a chain of structures for all the displays currently in use. */
extern void x_set_tool_bar_lines (struct frame *f,
Lisp_Object value,
Lisp_Object oldval);
+extern void x_set_internal_border_width (struct frame *f,
+ Lisp_Object value,
+ Lisp_Object oldval);
extern void x_activate_menubar (struct frame *);
extern int x_bitmap_icon (struct frame *, Lisp_Object);
extern void initialize_frame_menubar (struct frame *);
place where the user grabbed it. If the handle isn't currently
being dragged, this is Qnil. */
int dragging;
+
+ /* true if the scroll bar is horizontal. */
+ bool horizontal;
};
/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
/* Return the inside width of a vertical scroll bar, given the outside
width. */
-#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
- ((width) \
- - VERTICAL_SCROLL_BAR_LEFT_BORDER \
+#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
+ ((width) \
+ - VERTICAL_SCROLL_BAR_LEFT_BORDER \
- VERTICAL_SCROLL_BAR_RIGHT_BORDER)
/* Return the length of the rectangle within which the top of the
This is the real range of motion for the scroll bar, so when we're
scaling buffer positions to scroll bar positions, we use this, not
VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */
-#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \
+#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \
(VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, height) - VERTICAL_SCROLL_BAR_MIN_HANDLE)
/* Return the inside height of vertical scroll bar, given the outside
height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */
-#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \
+#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \
((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
+/* Return the inside height of a horizontal scroll bar, given the
+ outside height. */
+#define HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \
+ ((height) \
+ - HORIZONTAL_SCROLL_BAR_TOP_BORDER \
+ - HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER)
+
+/* Return the length of the rectangle within which the left of the
+ handle must stay. This isn't equivalent to the inside width,
+ because the scroll bar handle has a minimum width.
+
+ This is the real range of motion for the scroll bar, so when we're
+ scaling buffer positions to scroll bar positions, we use this, not
+ HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH. */
+#define HORIZONTAL_SCROLL_BAR_LEFT_RANGE(f,width) \
+ (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH (f, width) - HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
+
+/* Return the inside width of horizontal scroll bar, given the outside
+ width. See HORIZONTAL_SCROLL_BAR_LEFT_RANGE too. */
+#define HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
+ ((width) - HORIZONTAL_SCROLL_BAR_LEFT_BORDER - HORIZONTAL_SCROLL_BAR_RIGHT_BORDER)
+
/* Border widths for scroll bars.
#define VERTICAL_SCROLL_BAR_TOP_BORDER (vertical_scroll_bar_top_border)
#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (vertical_scroll_bar_bottom_border)
+#define HORIZONTAL_SCROLL_BAR_LEFT_BORDER (horizontal_scroll_bar_left_border)
+#define HORIZONTAL_SCROLL_BAR_RIGHT_BORDER (horizontal_scroll_bar_right_border)
+#define HORIZONTAL_SCROLL_BAR_TOP_BORDER (0)
+#define HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER (0)
+
/* Minimum lengths for scroll bar handles, in pixels. */
#define VERTICAL_SCROLL_BAR_MIN_HANDLE (vertical_scroll_bar_min_handle)
+#define HORIZONTAL_SCROLL_BAR_MIN_HANDLE (horizontal_scroll_bar_min_handle)
struct frame; /* from frame.h */
#define WM_EMACS_KILL (WM_EMACS_START + 0)
#define WM_EMACS_CREATEWINDOW (WM_EMACS_START + 1)
#define WM_EMACS_DONE (WM_EMACS_START + 2)
-#define WM_EMACS_CREATESCROLLBAR (WM_EMACS_START + 3)
-#define WM_EMACS_SHOWWINDOW (WM_EMACS_START + 4)
-#define WM_EMACS_SETWINDOWPOS (WM_EMACS_START + 5)
-#define WM_EMACS_DESTROYWINDOW (WM_EMACS_START + 6)
-#define WM_EMACS_TRACKPOPUPMENU (WM_EMACS_START + 7)
-#define WM_EMACS_SETFOCUS (WM_EMACS_START + 8)
-#define WM_EMACS_SETFOREGROUND (WM_EMACS_START + 9)
-#define WM_EMACS_SETLOCALE (WM_EMACS_START + 10)
-#define WM_EMACS_SETKEYBOARDLAYOUT (WM_EMACS_START + 11)
-#define WM_EMACS_REGISTER_HOT_KEY (WM_EMACS_START + 12)
-#define WM_EMACS_UNREGISTER_HOT_KEY (WM_EMACS_START + 13)
-#define WM_EMACS_TOGGLE_LOCK_KEY (WM_EMACS_START + 14)
-#define WM_EMACS_TRACK_CARET (WM_EMACS_START + 15)
-#define WM_EMACS_DESTROY_CARET (WM_EMACS_START + 16)
-#define WM_EMACS_SHOW_CARET (WM_EMACS_START + 17)
-#define WM_EMACS_HIDE_CARET (WM_EMACS_START + 18)
-#define WM_EMACS_SETCURSOR (WM_EMACS_START + 19)
-#define WM_EMACS_PAINT (WM_EMACS_START + 20)
-#define WM_EMACS_BRINGTOTOP (WM_EMACS_START + 21)
-#define WM_EMACS_INPUT_READY (WM_EMACS_START + 22)
-#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 23)
-#define WM_EMACS_END (WM_EMACS_START + 24)
+#define WM_EMACS_CREATEVSCROLLBAR (WM_EMACS_START + 3)
+#define WM_EMACS_CREATEHSCROLLBAR (WM_EMACS_START + 4)
+#define WM_EMACS_SHOWWINDOW (WM_EMACS_START + 5)
+#define WM_EMACS_SETWINDOWPOS (WM_EMACS_START + 6)
+#define WM_EMACS_DESTROYWINDOW (WM_EMACS_START + 7)
+#define WM_EMACS_TRACKPOPUPMENU (WM_EMACS_START + 8)
+#define WM_EMACS_SETFOCUS (WM_EMACS_START + 9)
+#define WM_EMACS_SETFOREGROUND (WM_EMACS_START + 10)
+#define WM_EMACS_SETLOCALE (WM_EMACS_START + 11)
+#define WM_EMACS_SETKEYBOARDLAYOUT (WM_EMACS_START + 12)
+#define WM_EMACS_REGISTER_HOT_KEY (WM_EMACS_START + 13)
+#define WM_EMACS_UNREGISTER_HOT_KEY (WM_EMACS_START + 14)
+#define WM_EMACS_TOGGLE_LOCK_KEY (WM_EMACS_START + 15)
+#define WM_EMACS_TRACK_CARET (WM_EMACS_START + 16)
+#define WM_EMACS_DESTROY_CARET (WM_EMACS_START + 17)
+#define WM_EMACS_SHOW_CARET (WM_EMACS_START + 18)
+#define WM_EMACS_HIDE_CARET (WM_EMACS_START + 19)
+#define WM_EMACS_SETCURSOR (WM_EMACS_START + 20)
+#define WM_EMACS_SHOWCURSOR (WM_EMACS_START + 21)
+#define WM_EMACS_PAINT (WM_EMACS_START + 22)
+#define WM_EMACS_BRINGTOTOP (WM_EMACS_START + 23)
+#define WM_EMACS_INPUT_READY (WM_EMACS_START + 24)
+#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 25)
+#define WM_EMACS_END (WM_EMACS_START + 26)
#define WND_FONTWIDTH_INDEX (0)
#define WND_LINEHEIGHT_INDEX (4)
#define WND_BORDER_INDEX (8)
-#define WND_SCROLLBAR_INDEX (12)
-#define WND_BACKGROUND_INDEX (16)
-#define WND_LAST_INDEX (20)
+#define WND_VSCROLLBAR_INDEX (12)
+#define WND_HSCROLLBAR_INDEX (16)
+#define WND_BACKGROUND_INDEX (20)
+#define WND_LAST_INDEX (24)
#define WND_EXTRA_BYTES (WND_LAST_INDEX)
}
#endif /* 0 */
{
- struct frame *f = ew->emacs_frame.frame;
Dimension pixel_width, pixel_height;
/* Take into account the size of the scrollbar. Always use the
frame's character width which is bad for vertically split
windows. */
- compute_fringe_widths (f, 0);
-
#if 0 /* This can run Lisp code, and it is dangerous to give
out the frame to Lisp code before it officially exists.
This is handled in Fx_create_frame so not needed here. */
/* This happens when the frame is just created. */
if (! wmshell) return;
-#if 0
- check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0);
-#endif
-
pixel_to_char_size (ew, ew->core.width, ew->core.height,
&char_width, &char_height);
char_to_pixel_size (ew, char_width, char_height,
if (true || frame_resize_pixelwise)
{
int width, height;
+/** int width = (ew->core.width **/
+/** - FRAME_SCROLL_BAR_AREA_WIDTH (f) **/
+/** - FRAME_TOTAL_FRINGE_WIDTH (f) **/
+/** - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
+
+/** int height = (ew->core.height **/
+/** - FRAME_TOOLBAR_HEIGHT (f) **/
+/** - FRAME_SCROLL_BAR_AREA_HEIGHT (f) **/
+/** - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
change_frame_size (f, width, height, 0, 1, 0, 1);
EmacsFrame ew = (EmacsFrame) widget;
struct frame *f = ew->emacs_frame.frame;
- x_set_window_size (f, 0, columns, rows, 0);
+ if (!frame_inhibit_resize (f, 0) && !frame_inhibit_resize (f, 1))
+ x_set_window_size (f, 0, columns, rows, 0);
}
\f
static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
+static Lisp_Object Qwindow_sanitize_window_sizes;
static Lisp_Object Qwindow_pixel_to_total;
static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
static struct window *set_window_margins (struct window *, Lisp_Object,
Lisp_Object);
static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
- Lisp_Object, Lisp_Object);
+ Lisp_Object, Lisp_Object, Lisp_Object);
static void apply_window_adjustment (struct window *);
/* This is the window in which the terminal's cursor should
{
w->combination_limit = val;
}
+
static void
wset_dedicated (struct window *w, Lisp_Object val)
{
w->dedicated = val;
}
+
static void
wset_display_table (struct window *w, Lisp_Object val)
{
w->display_table = val;
}
+
static void
wset_new_normal (struct window *w, Lisp_Object val)
{
w->new_normal = val;
}
+
static void
wset_new_total (struct window *w, Lisp_Object val)
{
w->new_total = val;
}
+
static void
wset_normal_cols (struct window *w, Lisp_Object val)
{
w->normal_cols = val;
}
+
static void
wset_normal_lines (struct window *w, Lisp_Object val)
{
w->normal_lines = val;
}
+
static void
wset_parent (struct window *w, Lisp_Object val)
{
w->parent = val;
}
+
static void
wset_pointm (struct window *w, Lisp_Object val)
{
w->pointm = val;
}
+
+static void
+wset_old_pointm (struct window *w, Lisp_Object val)
+{
+ w->old_pointm = val;
+}
+
static void
wset_start (struct window *w, Lisp_Object val)
{
w->start = val;
}
+
static void
wset_temslot (struct window *w, Lisp_Object val)
{
w->temslot = val;
}
+
static void
wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
{
w->vertical_scroll_bar_type = val;
}
+
static void
wset_window_parameters (struct window *w, Lisp_Object val)
{
w->window_parameters = val;
}
+
static void
wset_combination (struct window *w, bool horflag, Lisp_Object val)
{
{
int height = (w->pixel_height
- WINDOW_HEADER_LINE_HEIGHT (w)
+ - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+ ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+ : 0)
- WINDOW_MODE_LINE_HEIGHT (w)
- WINDOW_BOTTOM_DIVIDER_WIDTH (w));
return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
}
+DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
+ Swindow_scroll_bar_height, 0, 1, 0,
+ doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
+WINDOW must be a live window and defaults to the selected one. */)
+ (Lisp_Object window)
+{
+ return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window))));
+}
+
DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
WINDOW must be a live window and defaults to the selected one. */)
XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
w->hscroll = new_hscroll;
+ w->suspend_auto_hscroll = 1;
+
return make_number (new_hscroll);
}
return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
+ WINDOW_LEFT_MARGIN_COLS (w)
- + WINDOW_LEFT_FRINGE_COLS (w)),
+ + ((WINDOW_LEFT_FRINGE_WIDTH (w)
+ + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+ / WINDOW_FRAME_COLUMN_WIDTH (w))),
(WINDOW_TOP_EDGE_LINE (w)
+ WINDOW_HEADER_LINE_LINES (w)),
(WINDOW_BOX_RIGHT_EDGE_COL (w)
- WINDOW_RIGHT_MARGIN_COLS (w)
- - WINDOW_RIGHT_FRINGE_COLS (w)),
+ - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
+ + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+ / WINDOW_FRAME_COLUMN_WIDTH (w))),
(WINDOW_BOTTOM_EDGE_LINE (w)
- WINDOW_MODE_LINE_LINES (w)));
}
&& x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
&& x <= right_x)
return ON_RIGHT_DIVIDER;
+ /* On the horizontal scroll bar? (Including the empty space at its
+ right!) */
+ else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+ && y >= (bottom_y
+ - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+ - CURRENT_MODE_LINE_HEIGHT (w)
+ - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ && y <= (bottom_y
+ - CURRENT_MODE_LINE_HEIGHT (w)
+ - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
+ return ON_HORIZONTAL_SCROLL_BAR;
/* On the mode or header line? */
else if ((WINDOW_WANTS_MODELINE_P (w)
&& y >= (bottom_y
/* Outside any interesting column? */
if (x < left_x || x > right_x)
- return ON_SCROLL_BAR;
+ return ON_VERTICAL_SCROLL_BAR;
lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
case ON_RIGHT_MARGIN:
return Qright_margin;
- case ON_SCROLL_BAR:
+ case ON_VERTICAL_SCROLL_BAR:
/* Historically we are supposed to return nil in this case. */
return Qnil;
+ case ON_HORIZONTAL_SCROLL_BAR:
+ return Qnil;
+
case ON_RIGHT_DIVIDER:
return Qright_divider;
return Fmarker_position (w->pointm);
}
+DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
+ doc: /* Return old value of point in WINDOW.
+WINDOW must be a live window and defaults to the selected one. */)
+ (Lisp_Object window)
+{
+ return Fmarker_position (decode_live_window (window)->old_pointm);
+}
+
DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
doc: /* Return position at which display currently starts in WINDOW.
WINDOW must be a live window and defaults to the selected one.
return Qnil;
}
+
static Lisp_Object
resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
{
}
+Lisp_Object
+sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
+{
+ return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
+}
+
+
static Lisp_Object
window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
{
- return call2(Qwindow_pixel_to_total, frame, horizontal);
+ return call2 (Qwindow_pixel_to_total, frame, horizontal);
}
window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
}
}
-
-/* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the
- minimum allowable size. PIXELWISE means interpret these as pixel
- sizes. */
-
-void
-check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
-{
- /* For height, we have to see:
- how many windows the frame has at minimum (one or two),
- and whether it has a menu bar or other special stuff at the top. */
- if (pixelwise)
- {
- int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame);
- int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame);
-
- if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame))
- min_height = 2 * min_height;
-
- min_height += FRAME_TOP_MARGIN_HEIGHT (frame);
- min_height += FRAME_INTERNAL_BORDER_WIDTH (frame);
-
- if (*height < min_height)
- *height = min_height;
- if (*width < min_width)
- *width = min_width;
- }
- else
- {
- int min_height
- = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
- ? MIN_SAFE_WINDOW_HEIGHT
- : 2 * MIN_SAFE_WINDOW_HEIGHT);
-
- if (FRAME_TOP_MARGIN (frame) > 0)
- min_height += FRAME_TOP_MARGIN (frame);
-
- if (*height < min_height)
- *height = min_height;
- if (*width < MIN_SAFE_WINDOW_WIDTH)
- *width = MIN_SAFE_WINDOW_WIDTH;
- }
-}
-
-/* Adjust the margins of window W if text area is too small.
- Return 1 if window width is ok after adjustment; 0 if window
- is still too narrow. */
-
-static int
-adjust_window_margins (struct window *w)
-{
- int box_width = (WINDOW_PIXEL_WIDTH (w)
- - WINDOW_FRINGES_WIDTH (w)
- - WINDOW_SCROLL_BAR_AREA_WIDTH (w));
- int margin_width = WINDOW_MARGINS_WIDTH (w);
-
- if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
- return 1;
-
- if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
- return 0;
- else
- /* Window's text area is too narrow, but reducing the window
- margins will fix that. */
- {
- int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
-
- margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w);
-
- if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0)
- {
- if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0)
- w->left_margin_cols = w->right_margin_cols =
- margin_width / (2 * unit);
- else
- w->right_margin_cols = margin_width / unit;
- }
- else
- w->left_margin_cols = margin_width / unit;
-
- return 1;
- }
-}
\f
/* The following three routines are needed for running a window's
configuration change hook. */
= Fdefault_value (Qwindow_configuration_change_hook);
XSETFRAME (frame, f);
- if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
+ if (NILP (Vrun_hooks) || !(f->official))
return;
/* Use the right buffer. Matters when running the local hooks. */
w->last_cursor_vpos = 0;
if (!(keep_margins_p && samebuf))
- { /* If we're not actually changing the buffer, don't reset hscroll and
- vscroll. This case happens for example when called from
+ { /* If we're not actually changing the buffer, don't reset hscroll
+ and vscroll. This case happens for example when called from
change_frame_size_1, where we use a dummy call to
- Fset_window_buffer on the frame's selected window (and no other)
- just in order to run window-configuration-change-hook.
- Resetting hscroll and vscroll here is problematic for things like
- image-mode and doc-view-mode since it resets the image's position
- whenever we resize the frame. */
- w->hscroll = w->min_hscroll = 0;
+ Fset_window_buffer on the frame's selected window (and no
+ other) just in order to run window-configuration-change-hook
+ (no longer true since change_frame_size_1 directly calls
+ run_window_configuration_change_hook). Resetting hscroll and
+ vscroll here is problematic for things like image-mode and
+ doc-view-mode since it resets the image's position whenever we
+ resize the frame. */
+ w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+ w->suspend_auto_hscroll = 0;
w->vscroll = 0;
set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
+ set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
set_marker_restricted (w->start,
make_number (b->last_window_start),
buffer);
Fset_buffer (buffer);
XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
+ XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
if (!keep_margins_p)
{
BVAR (b, right_fringe_width),
BVAR (b, fringes_outside_margins));
set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
- BVAR (b, vertical_scroll_bar_type), Qnil);
+ BVAR (b, vertical_scroll_bar_type),
+ BVAR (b, scroll_bar_height),
+ BVAR (b, horizontal_scroll_bar_type));
set_window_margins (w, BVAR (b, left_margin_cols),
BVAR (b, right_margin_cols));
apply_window_adjustment (w);
Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
Vminibuf_scroll_window = window;
w = XWINDOW (window);
- w->hscroll = 0;
- w->min_hscroll = 0;
+ w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+ w->suspend_auto_hscroll = 0;
set_marker_restricted_both (w->start, buf, BEG, BEG);
set_marker_restricted_both (w->pointm, buf, BEG, BEG);
+ set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
/* Run temp-buffer-show-hook, with the chosen window selected
and its buffer current. */
/* ...but now P becomes an internal window. */
wset_start (p, Qnil);
wset_pointm (p, Qnil);
+ wset_old_pointm (p, Qnil);
wset_buffer (p, Qnil);
wset_combination (p, horflag, window);
wset_combination_limit (p, Qnil);
wset_new_pixel (w, make_number (0));
wset_start (w, Fmake_marker ());
wset_pointm (w, Fmake_marker ());
+ wset_old_pointm (w, Fmake_marker ());
wset_vertical_scroll_bar_type (w, Qt);
+ wset_horizontal_scroll_bar_type (w, Qt);
/* These Lisp fields are marked specially so they're not set to nil by
allocate_window. */
wset_prev_buffers (w, Qnil);
#endif
w->sequence_number = ++sequence_number;
w->scroll_bar_width = -1;
+ w->scroll_bar_height = -1;
w->column_number_displayed = -1;
-
/* Reset window_list. */
Vwindow_list = Qnil;
/* Return window. */
}
}
else
- {
- adjust_window_margins (w);
- /* Bug#15957. */
- w->window_end_valid = 0;
- }
+ /* Bug#15957. */
+ w->window_end_valid = 0;
}
/* old_size is the old size of the frame's root window. */
int old_size = horflag ? r->total_cols : r->total_lines;
int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
+ int old_pixel_top = r->pixel_top;
/* new_size is the new size of the frame's root window. */
int new_size, new_pixel_size;
int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
new_pixel_size = max (horflag
? size
: (size
- - FRAME_TOP_MARGIN_HEIGHT (f)
+/** - FRAME_TOP_MARGIN_HEIGHT (f) **/
- ((FRAME_HAS_MINIBUF_P (f)
&& !FRAME_MINIBUF_ONLY_P (f))
? FRAME_LINE_HEIGHT (f) : 0)),
new_size = max (horflag
? size
: (size
- - FRAME_TOP_MARGIN (f)
+/** - FRAME_TOP_MARGIN (f) **/
- ((FRAME_HAS_MINIBUF_P (f)
&& !FRAME_MINIBUF_ONLY_P (f))
? 1 : 0)),
r->top_line = FRAME_TOP_MARGIN (f);
r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
- if (new_pixel_size == old_pixel_size)
+ if (new_pixel_size == old_pixel_size
+ && r->pixel_top == old_pixel_top)
;
else if (WINDOW_LEAF_P (r))
/* For a leaf root window just set the size. */
{
window_resize_apply (r, horflag);
window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+#if 0 /* Let's try without safe sizes and/or killing other windows. */
}
else
{
window_resize_apply (r, horflag);
window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
}
-#if 0 /* Let's try without killing other windows. */
else
{
/* We lost. Delete all windows but the frame's
n->right_fringe_width = r->right_fringe_width;
n->fringes_outside_margins = r->fringes_outside_margins;
n->scroll_bar_width = r->scroll_bar_width;
+ n->scroll_bar_height = r->scroll_bar_height;
wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
+ wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
/* Directly assign orthogonal coordinates and sizes. */
if (horflag)
{
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
+ unchain_marker (XMARKER (w->old_pointm));
unchain_marker (XMARKER (w->start));
wset_buffer (w, Qnil);
}
return ht;
}
+
\f
/************************************************************************
Window Scrolling
void *itdata = NULL;
int window_total_lines;
int frame_line_height = default_line_pixel_height (w);
+ bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+ Fwindow_old_point (window)));
SET_TEXT_POS_FROM_MARKER (start, w->start);
/* Scrolling a minibuffer window via scroll bar when the echo area
{
ptrdiff_t start_pos = IT_CHARPOS (it);
int dy = frame_line_height;
+
dy = max ((window_box_height (w)
- next_screen_context_lines * dy),
dy) * n;
}
}
bidi_unshelve_cache (itdata, 0);
+
+ if (adjust_old_pointm)
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
}
ptrdiff_t startpos = marker_position (w->start);
ptrdiff_t startbyte = marker_byte_position (w->start);
Lisp_Object original_pos = Qnil;
+ bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+ Fwindow_old_point (window)));
/* If scrolling screen-fulls, compute the number of lines to
scroll from the window's height. */
struct position posit
= *compute_motion (startpos, startbyte, 0, 0, 0,
PT, ht, 0, -1, w->hscroll, 0, w);
+
window_scroll_preserve_vpos = posit.vpos;
window_scroll_preserve_hpos = posit.hpos + w->hscroll;
}
else
xsignal0 (Qend_of_buffer);
}
+
+ if (adjust_old_pointm)
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
}
Fset_buffer (w->contents);
SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
+ SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
if (NILP (arg))
window_scroll (window, 1, 1, 1);
}
set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
+ set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
unbind_to (count, Qnil);
return Qnil;
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
+ w->suspend_auto_hscroll = 1;
+
return result;
}
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
+ w->suspend_auto_hscroll = 1;
+
return result;
}
if (buf != current_buffer)
error ("`recenter'ing a window that does not display current-buffer.");
-
+
/* If redisplay is suppressed due to an error, try again. */
buf->display_error_modiff = 0;
}
DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
- 0, 1, 0,
+ 0, 2, 0,
doc: /* Return the width in columns of the text display area of WINDOW.
WINDOW must be a live window and defaults to the selected one.
The returned width does not include dividers, scrollbars, margins,
fringes, nor any partial-width columns at the right of the text
-area. */)
- (Lisp_Object window)
+area.
+
+Optional argument PIXELWISE non-nil, means to return the width in
+pixels. */)
+ (Lisp_Object window, Lisp_Object pixelwise)
{
struct window *w = decode_live_window (window);
- return make_number (window_box_width (w, TEXT_AREA)
- / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+ if (NILP (pixelwise))
+ return make_number (window_box_width (w, TEXT_AREA)
+ / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+ else
+ return make_number (window_box_width (w, TEXT_AREA));
}
DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
- 0, 1, 0,
+ 0, 2, 0,
doc: /* Return the height in lines of the text display area of WINDOW.
WINDOW must be a live window and defaults to the selected one.
The returned height does not include dividers, the mode line, any header
-line, nor any partial-height lines at the bottom of the text area. */)
- (Lisp_Object window)
+line, nor any partial-height lines at the bottom of the text area.
+
+Optional argument PIXELWISE non-nil, means to return the height in
+pixels. */)
+ (Lisp_Object window, Lisp_Object pixelwise)
{
struct window *w = decode_live_window (window);
- return make_number (window_box_height (w)
- / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+ if (NILP (pixelwise))
+ return make_number (window_box_height (w)
+ / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+ else
+ return make_number (window_box_height (w));
}
\f
DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
{
struct vectorlike_header header;
- Lisp_Object window, buffer, start, pointm;
+ Lisp_Object window, buffer, start, pointm, old_pointm;
Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
Lisp_Object left_col, top_line, total_cols, total_lines;
Lisp_Object normal_cols, normal_lines;
- Lisp_Object hscroll, min_hscroll;
+ Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
Lisp_Object parent, prev;
Lisp_Object start_at_line_beg;
Lisp_Object display_table;
Lisp_Object left_margin_cols, right_margin_cols;
Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
+ Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
Lisp_Object combination_limit, window_parameters;
};
return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
}
-/* From Chong's unwind_create_frame_1. */
-static void
-unwind_change_frame (Lisp_Object val)
+DEFUN ("set-window-configuration", Fset_window_configuration,
+ Sset_window_configuration, 1, 1, 0,
+ doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
+CONFIGURATION must be a value previously returned
+by `current-window-configuration' (which see).
+If CONFIGURATION was made from a frame that is now deleted,
+only frame-independent values can be restored. In this case,
+the return value is nil. Otherwise the value is t. */)
+ (Lisp_Object configuration)
{
- inhibit_lisp_code = val;
+ register struct save_window_data *data;
+ struct Lisp_Vector *saved_windows;
+ Lisp_Object new_current_buffer;
+ Lisp_Object frame;
+ struct frame *f;
+ ptrdiff_t old_point = -1;
+
+ CHECK_WINDOW_CONFIGURATION (configuration);
+
+ data = (struct save_window_data *) XVECTOR (configuration);
+ saved_windows = XVECTOR (data->saved_windows);
+
+ new_current_buffer = data->current_buffer;
+ if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
+ new_current_buffer = Qnil;
+ else
+ {
+ if (XBUFFER (new_current_buffer) == current_buffer)
+ /* The code further down "preserves point" by saving here PT in
+ old_point and then setting it later back into PT. When the
+ current-selected-window and the final-selected-window both show
+ the current buffer, this suffers from the problem that the
+ current PT is the window-point of the current-selected-window,
+ while the final PT is the point of the final-selected-window, so
+ this copy from one PT to the other would end up moving the
+ window-point of the final-selected-window to the window-point of
+ the current-selected-window. So we have to be careful which
+ point of the current-buffer we copy into old_point. */
+ if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
+ && WINDOWP (selected_window)
+ && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
+ && !EQ (selected_window, data->current_window))
+ old_point = marker_position (XWINDOW (data->current_window)->pointm);
+ else
+ old_point = PT;
+ else
+ /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
+ point in new_current_buffer as of the last time this buffer was
+ used. This can be non-deterministic since it can be changed by
+ things like jit-lock by mere temporary selection of some random
+ window that happens to show this buffer.
+ So if possible we want this arbitrary choice of "which point" to
+ be the one from the to-be-selected-window so as to prevent this
+ window's cursor from being copied from another window. */
+ if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
+ /* If current_window = selected_window, its point is in BUF_PT. */
+ && !EQ (selected_window, data->current_window))
+ old_point = marker_position (XWINDOW (data->current_window)->pointm);
+ else
+ old_point = BUF_PT (XBUFFER (new_current_buffer));
+ }
+
+ frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
+ f = XFRAME (frame);
+
+ /* If f is a dead frame, don't bother rebuilding its window tree.
+ However, there is other stuff we should still try to do below. */
+ if (FRAME_LIVE_P (f))
+ {
+ Lisp_Object window;
+ Lisp_Object dead_windows = Qnil;
+ register Lisp_Object tem, par, pers;
+ register struct window *w;
+ register struct saved_window *p;
+ struct window *root_window;
+ struct window **leaf_windows;
+ int n_leaf_windows;
+ ptrdiff_t k;
+ int i, n;
+
+ /* Don't do this within the main loop below: This may call Lisp
+ code and is thus potentially unsafe while input is blocked. */
+ for (k = 0; k < saved_windows->header.size; k++)
+ {
+ p = SAVED_WINDOW_N (saved_windows, k);
+ window = p->window;
+ w = XWINDOW (window);
+ if (BUFFERP (w->contents)
+ && !EQ (w->contents, p->buffer)
+ && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+ /* If a window we restore gets another buffer, record the
+ window's old buffer. */
+ call1 (Qrecord_window_buffer, window);
+ }
+
+ /* Consider frame unofficial, temporarily. */
+ f->official = false;
+ /* The mouse highlighting code could get screwed up
+ if it runs during this. */
+ block_input ();
+
+ /* "Swap out" point from the selected window's buffer
+ into the window itself. (Normally the pointm of the selected
+ window holds garbage.) We do this now, before
+ restoring the window contents, and prevent it from
+ being done later on when we select a new window. */
+ if (! NILP (XWINDOW (selected_window)->contents))
+ {
+ w = XWINDOW (selected_window);
+ set_marker_both (w->pointm,
+ w->contents,
+ BUF_PT (XBUFFER (w->contents)),
+ BUF_PT_BYTE (XBUFFER (w->contents)));
+ }
+
+ fset_redisplay (f);
+ FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+
+ /* Problem: Freeing all matrices and later allocating them again
+ is a serious redisplay flickering problem. What we would
+ really like to do is to free only those matrices not reused
+ below. */
+ root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
+ leaf_windows = alloca (count_windows (root_window)
+ * sizeof *leaf_windows);
+ n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
+
+ /* Kludge Alert!
+ Mark all windows now on frame as "deleted".
+ Restoring the new configuration "undeletes" any that are in it.
+
+ Save their current buffers in their height fields, since we may
+ need it later, if a buffer saved in the configuration is now
+ dead. */
+ delete_all_child_windows (FRAME_ROOT_WINDOW (f));
+
+ for (k = 0; k < saved_windows->header.size; k++)
+ {
+ p = SAVED_WINDOW_N (saved_windows, k);
+ window = p->window;
+ w = XWINDOW (window);
+ wset_next (w, Qnil);
+
+ if (!NILP (p->parent))
+ wset_parent
+ (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
+ else
+ wset_parent (w, Qnil);
+
+ if (!NILP (p->prev))
+ {
+ wset_prev
+ (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
+ wset_next (XWINDOW (w->prev), p->window);
+ }
+ else
+ {
+ wset_prev (w, Qnil);
+ if (!NILP (w->parent))
+ wset_combination (XWINDOW (w->parent),
+ (XINT (p->total_cols)
+ != XWINDOW (w->parent)->total_cols),
+ p->window);
+ }
+
+ /* If we squirreled away the buffer, restore it now. */
+ if (BUFFERP (w->combination_limit))
+ wset_buffer (w, w->combination_limit);
+ w->pixel_left = XFASTINT (p->pixel_left);
+ w->pixel_top = XFASTINT (p->pixel_top);
+ w->pixel_width = XFASTINT (p->pixel_width);
+ w->pixel_height = XFASTINT (p->pixel_height);
+ w->left_col = XFASTINT (p->left_col);
+ w->top_line = XFASTINT (p->top_line);
+ w->total_cols = XFASTINT (p->total_cols);
+ w->total_lines = XFASTINT (p->total_lines);
+ wset_normal_cols (w, p->normal_cols);
+ wset_normal_lines (w, p->normal_lines);
+ w->hscroll = XFASTINT (p->hscroll);
+ w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
+ w->min_hscroll = XFASTINT (p->min_hscroll);
+ w->hscroll_whole = XFASTINT (p->hscroll_whole);
+ wset_display_table (w, p->display_table);
+ w->left_margin_cols = XINT (p->left_margin_cols);
+ w->right_margin_cols = XINT (p->right_margin_cols);
+ w->left_fringe_width = XINT (p->left_fringe_width);
+ w->right_fringe_width = XINT (p->right_fringe_width);
+ w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
+ w->scroll_bar_width = XINT (p->scroll_bar_width);
+ w->scroll_bar_height = XINT (p->scroll_bar_height);
+ wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
+ wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
+ wset_dedicated (w, p->dedicated);
+ wset_combination_limit (w, p->combination_limit);
+ /* Restore any window parameters that have been saved.
+ Parameters that have not been saved are left alone. */
+ for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
+ {
+ pers = XCAR (tem);
+ if (CONSP (pers))
+ {
+ if (NILP (XCDR (pers)))
+ {
+ par = Fassq (XCAR (pers), w->window_parameters);
+ if (CONSP (par) && !NILP (XCDR (par)))
+ /* Reset a parameter to nil if and only if it
+ has a non-nil association. Don't make new
+ associations. */
+ Fsetcdr (par, Qnil);
+ }
+ else
+ /* Always restore a non-nil value. */
+ Fset_window_parameter (window, XCAR (pers), XCDR (pers));
+ }
+ }
+
+ if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+ /* If saved buffer is alive, install it. */
+ {
+ wset_buffer (w, p->buffer);
+ w->start_at_line_beg = !NILP (p->start_at_line_beg);
+ set_marker_restricted (w->start, p->start, w->contents);
+ set_marker_restricted (w->pointm, p->pointm, w->contents);
+ set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
+ /* As documented in Fcurrent_window_configuration, don't
+ restore the location of point in the buffer which was
+ current when the window configuration was recorded. */
+ if (!EQ (p->buffer, new_current_buffer)
+ && XBUFFER (p->buffer) == current_buffer)
+ Fgoto_char (w->pointm);
+ }
+ else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
+ /* Keep window's old buffer; make sure the markers are real. */
+ {
+ /* Set window markers at start of visible range. */
+ if (XMARKER (w->start)->buffer == 0)
+ set_marker_restricted_both (w->start, w->contents, 0, 0);
+ if (XMARKER (w->pointm)->buffer == 0)
+ set_marker_restricted_both
+ (w->pointm, w->contents,
+ BUF_PT (XBUFFER (w->contents)),
+ BUF_PT_BYTE (XBUFFER (w->contents)));
+ if (XMARKER (w->old_pointm)->buffer == 0)
+ set_marker_restricted_both
+ (w->old_pointm, w->contents,
+ BUF_PT (XBUFFER (w->contents)),
+ BUF_PT_BYTE (XBUFFER (w->contents)));
+ w->start_at_line_beg = 1;
+ }
+ else if (!NILP (w->start))
+ /* Leaf window has no live buffer, get one. */
+ {
+ /* Get the buffer via other_buffer_safely in order to
+ avoid showing an unimportant buffer and, if necessary, to
+ recreate *scratch* in the course (part of Juanma's bs-show
+ scenario from March 2011). */
+ wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
+ /* This will set the markers to beginning of visible
+ range. */
+ set_marker_restricted_both (w->start, w->contents, 0, 0);
+ set_marker_restricted_both (w->pointm, w->contents, 0, 0);
+ set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
+ w->start_at_line_beg = 1;
+ if (!NILP (w->dedicated))
+ /* Record this window as dead. */
+ dead_windows = Fcons (window, dead_windows);
+ /* Make sure window is no more dedicated. */
+ wset_dedicated (w, Qnil);
+ }
+ }
+
+ fset_root_window (f, data->root_window);
+ /* Arrange *not* to restore point in the buffer that was
+ current when the window configuration was saved. */
+ if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
+ set_marker_restricted (XWINDOW (data->current_window)->pointm,
+ make_number (old_point),
+ XWINDOW (data->current_window)->contents);
+
+ /* In the following call to `select-window', prevent "swapping out
+ point" in the old selected window using the buffer that has
+ been restored into it. We already swapped out that point from
+ that window's old buffer.
+
+ Do not record the buffer here. We do that in a separate call
+ to select_window below. See also Bug#16207. */
+ select_window (data->current_window, Qt, 1);
+ BVAR (XBUFFER (XWINDOW (selected_window)->contents),
+ last_selected_window)
+ = selected_window;
+
+ if (NILP (data->focus_frame)
+ || (FRAMEP (data->focus_frame)
+ && FRAME_LIVE_P (XFRAME (data->focus_frame))))
+ Fredirect_frame_focus (frame, data->focus_frame);
+
+ /* Now, free glyph matrices in windows that were not reused. */
+ for (i = n = 0; i < n_leaf_windows; ++i)
+ {
+ if (NILP (leaf_windows[i]->contents))
+ free_window_matrices (leaf_windows[i]);
+ else if (EQ (leaf_windows[i]->contents, new_current_buffer))
+ ++n;
+ }
+
+ /* Make frame official again and apply frame size changes if
+ needed. */
+ f->official = true;
+ adjust_frame_size (f, -1, -1, 1, 0);
+
+ adjust_frame_glyphs (f);
+ unblock_input ();
+
+ /* Scan dead buffer windows. */
+ for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
+ {
+ window = XCAR (dead_windows);
+ if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
+ delete_deletable_window (window);
+ }
+
+ /* Record the selected window's buffer here. The window should
+ already be the selected one from the call above. */
+ select_window (data->current_window, Qnil, 0);
+
+ /* Fselect_window will have made f the selected frame, so we
+ reselect the proper frame here. Fhandle_switch_frame will change the
+ selected window too, but that doesn't make the call to
+ Fselect_window above totally superfluous; it still sets f's
+ selected window. */
+ if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
+ do_switch_frame (data->selected_frame, 0, 0, Qnil);
+
+ run_window_configuration_change_hook (f);
+ }
+
+ if (!NILP (new_current_buffer))
+ {
+ Fset_buffer (new_current_buffer);
+ /* If the new current buffer doesn't appear in the selected
+ window, go to its old point (see bug#12208). */
+ if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
+ Fgoto_char (make_number (old_point));
+ }
+
+ Vminibuf_scroll_window = data->minibuf_scroll_window;
+ minibuf_selected_window = data->minibuf_selected_window;
+
+ return (FRAME_LIVE_P (f) ? Qt : Qnil);
}
+
+#if 0
DEFUN ("set-window-configuration", Fset_window_configuration,
Sset_window_configuration, 1, 1, 0,
doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
call1 (Qrecord_window_buffer, window);
}
- /* Don't run lisp in the following segment since the frame is in a
- completely inconsistent state. See Bug#16207. */
- record_unwind_protect (unwind_change_frame, inhibit_lisp_code);
- inhibit_lisp_code = Qt;
+ /* Consider frame unofficial, temporarily. */
+ f->official = false;
/* The mouse highlighting code could get screwed up
if it runs during this. */
block_input ();
if (data->frame_text_width != previous_frame_text_width
|| data->frame_text_height != previous_frame_text_height)
- change_frame_size (f, data->frame_text_width,
- data->frame_text_height, 0, 0, 0, 1);
+ /* Make frame size fit the one in data, so window sizes restored
+ from data match those of the frame. */
+ adjust_frame_size (f, data->frame_text_width,
+ data->frame_text_height, 5, 0);
if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines)
{
wset_normal_cols (w, p->normal_cols);
wset_normal_lines (w, p->normal_lines);
w->hscroll = XFASTINT (p->hscroll);
+ w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
w->min_hscroll = XFASTINT (p->min_hscroll);
+ w->hscroll_whole = XFASTINT (p->hscroll_whole);
wset_display_table (w, p->display_table);
w->left_margin_cols = XINT (p->left_margin_cols);
w->right_margin_cols = XINT (p->right_margin_cols);
w->right_fringe_width = XINT (p->right_fringe_width);
w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
w->scroll_bar_width = XINT (p->scroll_bar_width);
+ w->scroll_bar_height = XINT (p->scroll_bar_height);
wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
+ wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
wset_dedicated (w, p->dedicated);
wset_combination_limit (w, p->combination_limit);
/* Restore any window parameters that have been saved.
wset_buffer (w, p->buffer);
w->start_at_line_beg = !NILP (p->start_at_line_beg);
set_marker_restricted (w->start, p->start, w->contents);
- set_marker_restricted (w->pointm, p->pointm,
- w->contents);
-
+ set_marker_restricted (w->pointm, p->pointm, w->contents);
+ set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
/* As documented in Fcurrent_window_configuration, don't
restore the location of point in the buffer which was
current when the window configuration was recorded. */
if (!EQ (p->buffer, new_current_buffer)
&& XBUFFER (p->buffer) == current_buffer)
Fgoto_char (w->pointm);
- }
+ }
else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
/* Keep window's old buffer; make sure the markers are real. */
{
(w->pointm, w->contents,
BUF_PT (XBUFFER (w->contents)),
BUF_PT_BYTE (XBUFFER (w->contents)));
+ if (XMARKER (w->old_pointm)->buffer == 0)
+ set_marker_restricted_both
+ (w->old_pointm, w->contents,
+ BUF_PT (XBUFFER (w->contents)),
+ BUF_PT_BYTE (XBUFFER (w->contents)));
w->start_at_line_beg = 1;
}
else if (!NILP (w->start))
/* Leaf window has no live buffer, get one. */
{
/* Get the buffer via other_buffer_safely in order to
- avoid showing an unimportant buffer and, if necessary, to
- recreate *scratch* in the course (part of Juanma's bs-show
- scenario from March 2011). */
+ avoid showing an unimportant buffer and, if necessary, to
+ recreate *scratch* in the course (part of Juanma's bs-show
+ scenario from March 2011). */
wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
/* This will set the markers to beginning of visible
range. */
set_marker_restricted_both (w->start, w->contents, 0, 0);
set_marker_restricted_both (w->pointm, w->contents, 0, 0);
+ set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
w->start_at_line_beg = 1;
if (!NILP (w->dedicated))
/* Record this window as dead. */
/* Set the frame size to the value it had before this function. */
if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
|| previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
- change_frame_size (f, previous_frame_text_width,
- previous_frame_text_height, 0, 0, 0, 1);
+ adjust_frame_size (f, previous_frame_text_width,
+ previous_frame_text_height, 5, 0);
if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
{
++n;
}
+ /* Make frame official again and apply frame size changes if
+ needed. */
+ f->official = true;
+ adjust_frame_size (f, -1, -1, 1, 0);
+
adjust_frame_glyphs (f);
unblock_input ();
- unbind_to (count, Qnil);
/* Scan dead buffer windows. */
for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
return (FRAME_LIVE_P (f) ? Qt : Qnil);
}
+#endif
void
restore_window_configuration (Lisp_Object configuration)
{
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
+ unchain_marker (XMARKER (w->old_pointm));
unchain_marker (XMARKER (w->start));
/* Since combination limit makes sense for an internal windows
only, we use this slot to save the buffer for the sake of
p->normal_cols = w->normal_cols;
p->normal_lines = w->normal_lines;
XSETFASTINT (p->hscroll, w->hscroll);
+ p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
XSETFASTINT (p->min_hscroll, w->min_hscroll);
+ XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
p->display_table = w->display_table;
p->left_margin_cols = make_number (w->left_margin_cols);
p->right_margin_cols = make_number (w->right_margin_cols);
p->right_fringe_width = make_number (w->right_fringe_width);
p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
p->scroll_bar_width = make_number (w->scroll_bar_width);
+ p->scroll_bar_height = make_number (w->scroll_bar_height);
p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
+ p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
p->dedicated = w->dedicated;
p->combination_limit = w->combination_limit;
p->window_parameters = Qnil;
BUF_PT_BYTE (XBUFFER (w->contents)));
else
p->pointm = Fcopy_marker (w->pointm, Qnil);
+ p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
XMARKER (p->pointm)->insertion_type
= !NILP (buffer_local_value /* Don't signal error if void. */
(Qwindow_point_insertion_type, w->contents));
+ XMARKER (p->old_pointm)->insertion_type
+ = !NILP (buffer_local_value /* Don't signal error if void. */
+ (Qwindow_point_insertion_type, w->contents));
p->start = Fcopy_marker (w->start, Qnil);
p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
else
{
p->pointm = Qnil;
+ p->old_pointm = Qnil;
p->start = Qnil;
p->start_at_line_beg = Qnil;
}
apply_window_adjustment (struct window *w)
{
eassert (w);
- adjust_window_margins (w);
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = 0;
windows_or_buffers_changed = 30;
Lisp_Object right_width)
{
int left, right;
+ int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
- /* FIXME: what about margins that are too wide? */
left = (NILP (left_width) ? 0
: (CHECK_NATNUM (left_width), XINT (left_width)));
right = (NILP (right_width) ? 0
if (w->left_margin_cols != left || w->right_margin_cols != right)
{
- w->left_margin_cols = left;
- w->right_margin_cols = right;
- return w;
+ /* Don't change anything if new margins won't fit. */
+ if ((WINDOW_PIXEL_WIDTH (w)
+ - WINDOW_FRINGES_WIDTH (w)
+ - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+ - (left + right) * unit)
+ >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+ {
+ w->left_margin_cols = left;
+ w->right_margin_cols = right;
+
+ return w;
+ }
+ else
+ return NULL;
}
- return NULL;
+ else
+ return NULL;
}
DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
|| w->right_fringe_width != right
|| w->fringes_outside_margins != outside))
{
+ if (left > 0 || right > 0)
+ {
+ /* Don't change anything if new fringes don't fit. */
+ if ((WINDOW_PIXEL_WIDTH (w)
+ - WINDOW_MARGINS_WIDTH (w)
+ - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+ - max (left, 0) - max (right, 0))
+ < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+ return NULL;
+ }
+
w->left_fringe_width = left;
w->right_fringe_width = right;
w->fringes_outside_margins = outside;
+
return w;
}
- return NULL;
+ else
+ return NULL;
}
DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
static struct window *
set_window_scroll_bars (struct window *w, Lisp_Object width,
- Lisp_Object vertical_type, Lisp_Object horizontal_type)
+ Lisp_Object vertical_type, Lisp_Object height,
+ Lisp_Object horizontal_type)
{
int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
+ int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
+ bool changed = 0;
if (iwidth == 0)
vertical_type = Qnil;
if (w->scroll_bar_width != iwidth
|| !EQ (w->vertical_scroll_bar_type, vertical_type))
{
- w->scroll_bar_width = iwidth;
- wset_vertical_scroll_bar_type (w, vertical_type);
- return w;
+ /* Don't change anything if new scroll bar won't fit. */
+ if ((WINDOW_PIXEL_WIDTH (w)
+ - WINDOW_MARGINS_WIDTH (w)
+ - WINDOW_FRINGES_WIDTH (w)
+ - max (iwidth, 0))
+ >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+ {
+ w->scroll_bar_width = iwidth;
+ wset_vertical_scroll_bar_type (w, vertical_type);
+ changed = 1;
+ }
+ }
+
+ if (MINI_WINDOW_P (w) || iheight == 0)
+ horizontal_type = Qnil;
+
+ if (!(NILP (horizontal_type)
+ || EQ (horizontal_type, Qbottom)
+ || EQ (horizontal_type, Qt)))
+ error ("Invalid type of horizontal scroll bar");
+
+ if (w->scroll_bar_height != iheight
+ || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
+ {
+ /* Don't change anything if new scroll bar won't fit. */
+ if ((WINDOW_PIXEL_HEIGHT (w)
+ - WINDOW_HEADER_LINE_HEIGHT (w)
+ - WINDOW_MODE_LINE_HEIGHT (w)
+ - max (iheight, 0))
+ >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
+ {
+ w->scroll_bar_height = iheight;
+ wset_horizontal_scroll_bar_type (w, horizontal_type);
+ changed = 1;
+ }
}
- return NULL;
+
+ return changed ? w : NULL;
}
DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
- Sset_window_scroll_bars, 2, 4, 0,
+ Sset_window_scroll_bars, 1, 5, 0,
doc: /* Set width and type of scroll bars of window WINDOW.
WINDOW must be a live window and defaults to the selected one.
Second parameter WIDTH specifies the pixel width for the scroll bar.
Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
-bar: left, right, or nil.
-If WIDTH is nil, use the frame's scroll-bar width.
-If VERTICAL-TYPE is t, use the frame's scroll-bar type.
-Fourth parameter HORIZONTAL-TYPE is currently unused.
+bar: left, right, or nil. If WIDTH is nil, use the frame's scroll-bar
+width. If VERTICAL-TYPE is t, use the frame's scroll-bar type.
+
+Fourth parameter HEIGHT specifies the pixel height for the scroll bar.
+Fifth parameter HORIZONTAL-TYPE specifies the type of the vertical
+scroll bar: nil, bottom, or t. If HEIGHT is nil, use the frame's
+scroll-bar height. If HORIZONTAL-TYPE is t, use the frame's scroll-bar
+type.
Return t if scroll bars were actually changed and nil otherwise. */)
- (Lisp_Object window, Lisp_Object width,
- Lisp_Object vertical_type, Lisp_Object horizontal_type)
+ (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
+ Lisp_Object height, Lisp_Object horizontal_type)
{
struct window *w
= set_window_scroll_bars (decode_live_window (window),
- width, vertical_type, horizontal_type);
+ width, vertical_type, height, horizontal_type);
return w ? (apply_window_adjustment (w), Qt) : Qnil;
}
doc: /* Get width and type of scroll bars of window WINDOW.
WINDOW must be a live window and defaults to the selected one.
-Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
-If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
-value. */)
+Value is a list of the form (WIDTH COLS VERTICAL-TYPE HEIGHT LINES
+HORIZONTAL-TYPE). If WIDTH or HEIGHT is nil or TYPE is t, the window is
+using the frame's corresponding value. */)
(Lisp_Object window)
{
struct window *w = decode_live_window (window);
- return list4 (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
- make_number (WINDOW_SCROLL_BAR_COLS (w)),
- w->vertical_scroll_bar_type, Qnil);
+ return Fcons (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
+ list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
+ w->vertical_scroll_bar_type,
+ make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (w)),
+ make_number (WINDOW_SCROLL_BAR_LINES (w)),
+ w->horizontal_scroll_bar_type));
}
-
-
\f
/***********************************************************************
Smooth scrolling
|| !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
|| !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
|| !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
- || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
+ || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
+ || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
+ || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
return 0;
}
DEFSYM (Qdelete_window, "delete-window");
DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
+ DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
DEFSYM (Qsafe, "safe");
DEFSYM (Qdisplay_buffer, "display-buffer");
defsubr (&Swindow_right_divider_width);
defsubr (&Swindow_bottom_divider_width);
defsubr (&Swindow_scroll_bar_width);
+ defsubr (&Swindow_scroll_bar_height);
defsubr (&Swindow_inside_edges);
defsubr (&Swindow_inside_pixel_edges);
defsubr (&Swindow_inside_absolute_pixel_edges);
defsubr (&Scoordinates_in_window_p);
defsubr (&Swindow_at);
defsubr (&Swindow_point);
+ defsubr (&Swindow_old_point);
defsubr (&Swindow_start);
defsubr (&Swindow_end);
defsubr (&Sset_window_point);
each one can have its own value of point. */
Lisp_Object pointm;
+ /* A marker pointing to where in the text point was in this window
+ at the time of last redisplay. The value is saved for the
+ selected window too. */
+ Lisp_Object old_pointm;
+
/* No permanent meaning; used by save-window-excursion's
bookkeeping. */
Lisp_Object temslot;
- /* This window's vertical scroll bar. This field is only for use
- by the window-system-dependent code which implements the
- scroll bars; it can store anything it likes here. If this
- window is newly created and we haven't displayed a scroll bar in
- it yet, or if the frame doesn't have any scroll bars, this is nil. */
+ /* This window's vertical scroll bar. This field is only for use by
+ the window-system-dependent code which implements the scroll
+ bars; it can store anything it likes here. If this window is
+ newly created and we haven't displayed a scroll bar in it yet, or
+ if the frame doesn't have any scroll bars, this is nil. */
Lisp_Object vertical_scroll_bar;
/* Type of vertical scroll bar. A value of nil means
no scroll bar. A value of t means use frame value. */
Lisp_Object vertical_scroll_bar_type;
+ /* This window's horizontal scroll bar. This field is only for use
+ by the window-system-dependent code which implements the scroll
+ bars; it can store anything it likes here. If this window is
+ newly created and we haven't displayed a scroll bar in it yet, or
+ if the frame doesn't have any scroll bars, this is nil. */
+ Lisp_Object horizontal_scroll_bar;
+
+ /* Type of horizontal scroll bar. A value of nil means
+ no scroll bar. A value of t means use frame value. */
+ Lisp_Object horizontal_scroll_bar_type;
+
/* Display-table to use for displaying chars in this window.
Nil means use the buffer's own display-table. */
Lisp_Object display_table;
the user has set, by set-window-hscroll for example. */
ptrdiff_t min_hscroll;
+ /* Maximum line length in pixels within window bound by size of
+ window (set up by set_horizontal_scroll_bar). */
+ ptrdiff_t hscroll_whole;
+
/* Displayed buffer's text modification events counter as of last time
display completed. */
EMACS_INT last_modified;
A value of -1 means use frame values. */
int scroll_bar_width;
+ /* Pixel height of scroll bars.
+ A value of -1 means use frame values. */
+ int scroll_bar_height;
+
/* Effective height of the mode line, or -1 if not known. */
int mode_line_height;
/* True if it needs to be redisplayed. */
bool_bf redisplay : 1;
+ /* True if auto hscrolling is currently suspended in this
+ window. */
+ bool_bf suspend_auto_hscroll : 1;
+
/* Amount by which lines of this window are scrolled in
y-direction (smooth scrolling). */
int vscroll;
w->vertical_scroll_bar = val;
}
+INLINE void
+wset_horizontal_scroll_bar (struct window *w, Lisp_Object val)
+{
+ w->horizontal_scroll_bar = val;
+}
+
+INLINE void
+wset_horizontal_scroll_bar_type (struct window *w, Lisp_Object val)
+{
+ w->horizontal_scroll_bar_type = val;
+}
+
INLINE void
wset_prev_buffers (struct window *w, Lisp_Object val)
{
}
/* True if W is a minibuffer window. */
+#define MINI_WINDOW_P(W) ((W)->mini)
-#define MINI_WINDOW_P(W) ((W)->mini)
+/* 1 if W is a non-only minibuffer window. */
+/* The first check is redundant and the second overly complicated. */
+#define MINI_NON_ONLY_WINDOW_P(W) \
+ (MINI_WINDOW_P (W) \
+ && (EQ (W->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))
+
+/* 1 if W is a minibuffer-only window. */
+#define MINI_ONLY_WINDOW_P(W) \
+ (MINI_WINDOW_P (W) && NILP (W->prev))
/* General window layout:
#define WINDOW_VERTICAL_COMBINATION_P(W) \
(WINDOWP ((W)->contents) && !(W)->horizontal)
-#define WINDOW_XFRAME(W) \
- (XFRAME (WINDOW_FRAME ((W))))
+/* WINDOW's XFRAME. */
+#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W))))
-/* Return the canonical column width of the frame of window W. */
+/* Whether WINDOW is a pseudo window. */
+#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p)
+/* Return the canonical column width of the frame of window W. */
#define WINDOW_FRAME_COLUMN_WIDTH(W) \
(FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W))))
/* Return the canonical column width of the frame of window W. */
-
#define WINDOW_FRAME_LINE_HEIGHT(W) \
(FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W))))
#define WINDOW_LEFTMOST_P(W) \
(WINDOW_LEFT_PIXEL_EDGE (W) == 0)
+/* True if window W's has no other windows above in its frame. */
+#define WINDOW_TOPMOST_P(W) \
+ (WINDOW_TOP_PIXEL_EDGE (W) == 0)
+
/* True if window W's has no other windows to its right in its frame. */
#define WINDOW_RIGHTMOST_P(W) \
(WINDOW_RIGHT_PIXEL_EDGE (W) \
/* Return the frame column at which the text (or left fringe) in
window W starts. This is different from the `LEFT_EDGE' because it
does not include a left-hand scroll bar if any. */
-
#define WINDOW_BOX_LEFT_EDGE_COL(W) \
(WINDOW_LEFT_EDGE_COL (W) \
+ WINDOW_LEFT_SCROLL_BAR_COLS (W))
/* Return the window column before which the text in window W ends.
This is different from WINDOW_RIGHT_EDGE_COL because it does not
include a scroll bar or window-separating line on the right edge. */
-
#define WINDOW_BOX_RIGHT_EDGE_COL(W) \
(WINDOW_RIGHT_EDGE_COL (W) \
- WINDOW_RIGHT_SCROLL_BAR_COLS (W))
#define WINDOW_FRINGES_WIDTH(W) \
(WINDOW_LEFT_FRINGE_WIDTH (W) + WINDOW_RIGHT_FRINGE_WIDTH (W))
-/* Widths of fringes in columns. */
-#define WINDOW_FRINGE_COLS(W) \
- ((W->left_fringe_width >= 0 \
- && W->right_fringe_width >= 0) \
- ? ((WINDOW_FRINGES_WIDTH (W) \
- + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \
- / WINDOW_FRAME_COLUMN_WIDTH (W)) \
- : FRAME_FRINGE_COLS (WINDOW_XFRAME (W)))
-
-#define WINDOW_LEFT_FRINGE_COLS(W) \
- ((WINDOW_LEFT_FRINGE_WIDTH ((W)) \
- + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \
- / WINDOW_FRAME_COLUMN_WIDTH (W))
-
-#define WINDOW_RIGHT_FRINGE_COLS(W) \
- ((WINDOW_RIGHT_FRINGE_WIDTH ((W)) \
- + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \
- / WINDOW_FRAME_COLUMN_WIDTH (W))
-
/* Are fringes outside display margins in window W. */
#define WINDOW_HAS_FRINGES_OUTSIDE_MARGINS(W) \
((W)->fringes_outside_margins)
-/* Say whether scroll bars are currently enabled for window W,
+/* Say whether vertical scroll bars are currently enabled for window W,
and which side they are on. */
-#define WINDOW_VERTICAL_SCROLL_BAR_TYPE(w) \
- (EQ (w->vertical_scroll_bar_type, Qt) \
- ? FRAME_VERTICAL_SCROLL_BAR_TYPE (WINDOW_XFRAME (w)) \
- : EQ (w->vertical_scroll_bar_type, Qleft) \
+#define WINDOW_VERTICAL_SCROLL_BAR_TYPE(W) \
+ (WINDOW_PSEUDO_P (W) \
+ ? vertical_scroll_bar_none \
+ : EQ (W->vertical_scroll_bar_type, Qt) \
+ ? FRAME_VERTICAL_SCROLL_BAR_TYPE (WINDOW_XFRAME (W)) \
+ : EQ (W->vertical_scroll_bar_type, Qleft) \
? vertical_scroll_bar_left \
- : EQ (w->vertical_scroll_bar_type, Qright) \
+ : EQ (W->vertical_scroll_bar_type, Qright) \
? vertical_scroll_bar_right \
- : vertical_scroll_bar_none) \
-
-#define WINDOW_HAS_VERTICAL_SCROLL_BAR(w) \
- (EQ (w->vertical_scroll_bar_type, Qt) \
- ? FRAME_HAS_VERTICAL_SCROLL_BARS (WINDOW_XFRAME (w)) \
- : !NILP (w->vertical_scroll_bar_type))
-
-#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT(w) \
- (EQ (w->vertical_scroll_bar_type, Qt) \
- ? FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (WINDOW_XFRAME (w)) \
- : EQ (w->vertical_scroll_bar_type, Qleft))
-
-#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT(w) \
- (EQ (w->vertical_scroll_bar_type, Qt) \
- ? FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (WINDOW_XFRAME (w)) \
- : EQ (w->vertical_scroll_bar_type, Qright))
+ : vertical_scroll_bar_none)
+
+#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT(W) \
+ (WINDOW_VERTICAL_SCROLL_BAR_TYPE (W) == vertical_scroll_bar_left)
+
+#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT(W) \
+ (WINDOW_VERTICAL_SCROLL_BAR_TYPE (W) == vertical_scroll_bar_right)
+
+#define WINDOW_HAS_VERTICAL_SCROLL_BAR(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \
+ || WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W))
+
+/* Say whether horizontal scroll bars are currently enabled for window
+ W. Horizontal scrollbars exist for toolkit versions only. */
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
+#define WINDOW_HAS_HORIZONTAL_SCROLL_BAR(W) \
+ ((WINDOW_PSEUDO_P (W) || MINI_NON_ONLY_WINDOW_P (W)) \
+ ? false \
+ : EQ (W->horizontal_scroll_bar_type, Qt) \
+ ? FRAME_HAS_HORIZONTAL_SCROLL_BARS (WINDOW_XFRAME (W)) \
+ : EQ (W->horizontal_scroll_bar_type, Qbottom) \
+ ? true \
+ : false)
+#else
+#define WINDOW_HAS_HORIZONTAL_SCROLL_BAR(W) false
+#endif
/* Width that a scroll bar in window W should have, if there is one.
Measured in pixels. If scroll bars are turned off, this is still
nonzero. */
-#define WINDOW_CONFIG_SCROLL_BAR_WIDTH(w) \
- (w->scroll_bar_width >= 0 \
- ? w->scroll_bar_width \
- : FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w)))
+#define WINDOW_CONFIG_SCROLL_BAR_WIDTH(W) \
+ (W->scroll_bar_width >= 0 \
+ ? W->scroll_bar_width \
+ : FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (W)))
/* Width that a scroll bar in window W should have, if there is one.
Measured in columns (characters). If scroll bars are turned off,
this is still nonzero. */
-#define WINDOW_CONFIG_SCROLL_BAR_COLS(w) \
- (w->scroll_bar_width >= 0 \
- ? ((w->scroll_bar_width \
- + WINDOW_FRAME_COLUMN_WIDTH (w) - 1) \
- / WINDOW_FRAME_COLUMN_WIDTH (w)) \
- : FRAME_CONFIG_SCROLL_BAR_COLS (WINDOW_XFRAME (w)))
+#define WINDOW_CONFIG_SCROLL_BAR_COLS(W) \
+ (W->scroll_bar_width >= 0 \
+ ? ((W->scroll_bar_width \
+ + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \
+ / WINDOW_FRAME_COLUMN_WIDTH (W)) \
+ : FRAME_CONFIG_SCROLL_BAR_COLS (WINDOW_XFRAME (W)))
/* Width of left scroll bar in window W, measured in columns
(characters). If scroll bars are on the right in this frame, or
there are no scroll bars, value is 0. */
-#define WINDOW_LEFT_SCROLL_BAR_COLS(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \
- ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w)) \
+#define WINDOW_LEFT_SCROLL_BAR_COLS(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \
+ ? (WINDOW_CONFIG_SCROLL_BAR_COLS (W)) \
: 0)
/* Width of right scroll bar in window W, measured in columns
(characters). If scroll bars are on the left in this frame, or there
are no scroll bars, value is 0. */
-#define WINDOW_RIGHT_SCROLL_BAR_COLS(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w) \
- ? WINDOW_CONFIG_SCROLL_BAR_COLS (w) \
+#define WINDOW_RIGHT_SCROLL_BAR_COLS(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_COLS (W) \
: 0)
/* Width of a scroll bar in window W, measured in columns. */
-#define WINDOW_SCROLL_BAR_COLS(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) \
- ? WINDOW_CONFIG_SCROLL_BAR_COLS (w) \
+#define WINDOW_SCROLL_BAR_COLS(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_COLS (W) \
: 0)
/* Width of a left scroll bar area in window W, measured in pixels. */
-#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \
- ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \
+#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \
: 0)
/* Width of a right scroll bar area in window W, measured in pixels. */
-#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w) \
- ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \
+#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \
: 0)
/* Width of scroll bar area in window W, measured in pixels. */
-#define WINDOW_SCROLL_BAR_AREA_WIDTH(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) \
- ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \
+#define WINDOW_SCROLL_BAR_AREA_WIDTH(W) \
+ (WINDOW_HAS_VERTICAL_SCROLL_BAR (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \
: 0)
-/* Return the frame position where the scroll bar of window W starts. */
+/* Return the frame position where the vertical scroll bar of window W
+ starts. */
#define WINDOW_SCROLL_BAR_AREA_X(W) \
(WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \
? WINDOW_BOX_RIGHT_EDGE_X (W) \
? 0 \
: FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
+/* Height that a scroll bar in window W should have, if there is one.
+ Measured in pixels. If scroll bars are turned off, this is still
+ nonzero. */
+#define WINDOW_CONFIG_SCROLL_BAR_HEIGHT(W) \
+ (W->scroll_bar_height >= 0 \
+ ? W->scroll_bar_height \
+ : FRAME_CONFIG_SCROLL_BAR_HEIGHT (WINDOW_XFRAME (W)))
+
+/* Height that a scroll bar in window W should have, if there is one.
+ Measured in lines (characters). If scroll bars are turned off, this
+ is still nonzero. */
+#define WINDOW_CONFIG_SCROLL_BAR_LINES(W) \
+ (W->scroll_bar_height >= 0 \
+ ? ((W->scroll_bar_height \
+ + WINDOW_FRAME_LINE_HEIGHT (W) - 1) \
+ / WINDOW_FRAME_LINE_HEIGHT (W)) \
+ : FRAME_CONFIG_SCROLL_BAR_LINES (WINDOW_XFRAME (W)))
+
+/* Height of a scroll bar in window W, measured in columns. */
+#define WINDOW_SCROLL_BAR_LINES(W) \
+ (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_LINES (W) \
+ : 0)
+
+/* Height of scroll bar area in window W, measured in pixels. */
+#define WINDOW_SCROLL_BAR_AREA_HEIGHT(W) \
+ (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \
+ ? WINDOW_CONFIG_SCROLL_BAR_HEIGHT (W) \
+ : 0)
+
/* Height in pixels, and in lines, of the mode line.
May be zero if W doesn't have a mode line. */
#define WINDOW_MODE_LINE_HEIGHT(W) \
: 0)
#define WINDOW_MODE_LINE_LINES(W) \
- (!! WINDOW_WANTS_MODELINE_P ((W)))
+ (!! WINDOW_WANTS_MODELINE_P (W))
/* Height in pixels, and in lines, of the header line.
Zero if W doesn't have a header line. */
#define WINDOW_HEADER_LINE_HEIGHT(W) \
- (WINDOW_WANTS_HEADER_LINE_P ((W)) \
+ (WINDOW_WANTS_HEADER_LINE_P (W) \
? CURRENT_HEADER_LINE_HEIGHT (W) \
: 0)
#define WINDOW_HEADER_LINE_LINES(W) \
- (!! WINDOW_WANTS_HEADER_LINE_P ((W)))
+ (!! WINDOW_WANTS_HEADER_LINE_P (W))
-/* Pixel height of window W without mode line and bottom divider. */
+/* Pixel height of window W without mode line, bottom scroll bar and
+ bottom divider. */
#define WINDOW_BOX_HEIGHT_NO_MODE_LINE(W) \
- (WINDOW_PIXEL_HEIGHT ((W)) \
+ (WINDOW_PIXEL_HEIGHT (W) \
- WINDOW_BOTTOM_DIVIDER_WIDTH (W) \
- - WINDOW_MODE_LINE_HEIGHT ((W)))
+ - WINDOW_SCROLL_BAR_AREA_HEIGHT (W) \
+ - WINDOW_MODE_LINE_HEIGHT (W))
/* Pixel height of window W without mode and header line and bottom
divider. */
#define WINDOW_BOX_TEXT_HEIGHT(W) \
(WINDOW_PIXEL_HEIGHT ((W)) \
- WINDOW_BOTTOM_DIVIDER_WIDTH (W) \
- - WINDOW_MODE_LINE_HEIGHT ((W)) \
- - WINDOW_HEADER_LINE_HEIGHT ((W)))
+ - WINDOW_SCROLL_BAR_AREA_HEIGHT (W) \
+ - WINDOW_MODE_LINE_HEIGHT (W) \
+ - WINDOW_HEADER_LINE_HEIGHT (W))
+
+/* Return the frame position where the horizontal scroll bar of window W
+ starts. */
+#define WINDOW_SCROLL_BAR_AREA_Y(W) \
+ (WINDOW_TOP_EDGE_Y (W) \
+ + (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \
+ ? WINDOW_BOX_HEIGHT_NO_MODE_LINE (W) : 0))
/* Convert window W relative pixel X to frame pixel coordinates. */
#define WINDOW_TO_FRAME_PIXEL_X(W, X) \
((X) + WINDOW_BOX_LEFT_EDGE_X ((W)))
/* Convert window W relative pixel Y to frame pixel coordinates. */
-#define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \
- ((Y) + WINDOW_TOP_EDGE_Y ((W)))
+#define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \
+ ((Y) + WINDOW_TOP_EDGE_Y (W))
/* Convert frame relative pixel X to window relative pixel X. */
-#define FRAME_TO_WINDOW_PIXEL_X(W, X) \
+#define FRAME_TO_WINDOW_PIXEL_X(W, X) \
((X) - WINDOW_BOX_LEFT_EDGE_X ((W)))
/* Convert frame relative pixel Y to window relative pixel Y. */
-#define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \
- ((Y) - WINDOW_TOP_EDGE_Y ((W)))
+#define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \
+ ((Y) - WINDOW_TOP_EDGE_Y (W))
/* Convert a text area relative x-position in window W to frame X
pixel coordinates. */
#define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X) \
(window_box_left ((W), TEXT_AREA) + (X))
-/* True if the background of the window W's fringe that is adjacent to
- a scroll bar is extended to the gap between the fringe and the bar. */
-
-#define WINDOW_FRINGE_EXTENDED_P(w) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \
- ? (WINDOW_LEFTMOST_P (w) \
- && WINDOW_LEFT_FRINGE_WIDTH (w) \
- && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) \
- || WINDOW_LEFT_MARGIN_COLS (w) == 0)) \
- : (WINDOW_RIGHTMOST_P (w) \
- && WINDOW_RIGHT_FRINGE_WIDTH (w) \
- && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) \
- || WINDOW_RIGHT_MARGIN_COLS (w) == 0)))
-
/* This is the window in which the terminal's cursor should be left when
nothing is being done with it. This must always be a leaf window, and its
buffer is selected by the top level editing loop at the end of each command.
above already does it, so it's only needed in unusual cases. */
extern void redisplay_other_windows (void);
-/* If *ROWS or *COLS are too small a size for FRAME, set them to the
- minimum allowable size. */
-
-extern void check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise);
-
/* Return a pointer to the glyph W's physical cursor is on. Value is
null if W's current matrix is invalid, so that no meaningful glyph
can be returned. */
CHECK_TYPE (WINDOW_LIVE_P (WINDOW), Qwindow_live_p, WINDOW)
/* These used to be in lisp.h. */
-
extern Lisp_Object Qwindow_live_p;
extern Lisp_Object Vwindow_list;
extern void temp_output_buffer_show (Lisp_Object);
extern void replace_buffer_in_windows (Lisp_Object);
extern void replace_buffer_in_windows_safely (Lisp_Object);
+extern Lisp_Object sanitize_window_sizes (Lisp_Object, Lisp_Object);
/* This looks like a setter, but it is a bit special. */
extern void wset_buffer (struct window *, Lisp_Object);
extern bool window_outdated (struct window *);
if (WINDOW_WANTS_MODELINE_P (w))
height -= CURRENT_MODE_LINE_HEIGHT (w);
+ height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+
return height;
}
eassert (height >= 0);
height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
/* Note: the code below that determines the mode-line/header-line
height is essentially the same as that contained in the macro
if (pix_y < 0)
pix_y = 0;
- else if (pix_y > FRAME_LINES (f))
- pix_y = FRAME_LINES (f);
+ else if (pix_y > FRAME_TOTAL_LINES (f))
+ pix_y = FRAME_TOTAL_LINES (f);
}
}
#endif
gx = WINDOW_PIXEL_WIDTH (w) - width;
goto row_glyph;
- case ON_SCROLL_BAR:
+ case ON_VERTICAL_SCROLL_BAR:
gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
? 0
: (window_box_right_offset (w, RIGHT_MARGIN_AREA)
{
wset_buffer (w, buffer);
set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
+ set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
}
bset_undo_list (current_buffer, Qt);
Vwith_echo_area_save_vector = Qnil;
if (NILP (vector))
- vector = Fmake_vector (make_number (9), Qnil);
+ vector = Fmake_vector (make_number (11), Qnil);
XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
ASET (vector, i, Vdeactivate_mark); ++i;
ASET (vector, i, w->contents); ++i;
ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
+ ASET (vector, i, make_number (marker_position (w->old_pointm))); ++i;
+ ASET (vector, i, make_number (marker_byte_position (w->old_pointm))); ++i;
ASET (vector, i, make_number (marker_position (w->start))); ++i;
ASET (vector, i, make_number (marker_byte_position (w->start))); ++i;
}
else
{
- int end = i + 6;
+ int end = i + 8;
for (; i < end; ++i)
ASET (vector, i, Qnil);
}
set_marker_both (w->pointm, buffer,
XFASTINT (AREF (vector, 5)),
XFASTINT (AREF (vector, 6)));
- set_marker_both (w->start, buffer,
+ set_marker_both (w->old_pointm, buffer,
XFASTINT (AREF (vector, 7)),
XFASTINT (AREF (vector, 8)));
+ set_marker_both (w->start, buffer,
+ XFASTINT (AREF (vector, 9)),
+ XFASTINT (AREF (vector, 10)));
}
Vwith_echo_area_save_vector = vector;
int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
#else
int do_update = (WINDOWP (f->tool_bar_window)
- && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
+ && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
#endif
if (do_update)
}
-/* Max tool-bar height. Basically, this is what makes all other windows
- disappear when the frame gets too small. Rethink this! */
-
-#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
- ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
-
/* Value is the number of pixels needed to make all tool-bar items of
frame F visible. The actual number of glyph rows needed is
returned in *N_ROWS if non-NULL. */
-
static int
tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
{
/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
height should be changed. */
-
static int
redisplay_tool_bar (struct frame *f)
{
can turn off tool-bars by specifying tool-bar-lines zero. */
if (!WINDOWP (f->tool_bar_window)
|| (w = XWINDOW (f->tool_bar_window),
- WINDOW_PIXEL_HEIGHT (w) == 0))
+ WINDOW_TOTAL_LINES (w) == 0))
return 0;
/* Set up an iterator for the tool-bar window. */
if (new_height != WINDOW_PIXEL_HEIGHT (w))
{
- Lisp_Object frame;
- int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
- / FRAME_LINE_HEIGHT (f));
-
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (new_lines))));
+ x_change_tool_bar_height (f, new_height);
/* Always do that now. */
clear_glyph_matrix (w->desired_matrix);
f->fonts_changed = 1;
if (!NILP (Vauto_resize_tool_bars))
{
- /* Do we really allow the toolbar to occupy the whole frame? */
- int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
int change_height_p = 0;
/* If we couldn't display everything, change the tool-bar's
height if there is room for more. */
- if (IT_STRING_CHARPOS (it) < it.end_charpos
- && it.current_y < max_tool_bar_height)
+ if (IT_STRING_CHARPOS (it) < it.end_charpos)
change_height_p = 1;
/* We subtract 1 because display_tool_bar_line advances the
/* If row displays tool-bar items, but is partially visible,
change the tool-bar's height. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
- && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
- && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
+ && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
change_height_p = 1;
/* Resize windows as needed by changing the `tool-bar-lines'
frame parameter. */
if (change_height_p)
{
- Lisp_Object frame;
int nrows;
int new_height = tool_bar_height (f, &nrows, 1);
if (change_height_p)
{
- /* Current size of the tool-bar window in canonical line
- units. */
- int old_lines = WINDOW_TOTAL_LINES (w);
- /* Required size of the tool-bar window in canonical
- line units. */
- int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
- / FRAME_LINE_HEIGHT (f));
- /* Maximum size of the tool-bar window in canonical line
- units that this frame can allow. */
- int max_lines =
- WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
-
- /* Don't try to change the tool-bar window size and set
- the fonts_changed flag unless really necessary. That
- flag causes redisplay to give up and retry
- redisplaying the frame from scratch, so setting it
- unnecessarily can lead to nasty redisplay loops. */
- if (new_lines <= max_lines
- && eabs (new_lines - old_lines) >= 1)
- {
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (new_lines))));
- clear_glyph_matrix (w->desired_matrix);
- f->n_tool_bar_rows = nrows;
- f->fonts_changed = 1;
- return 1;
- }
+ x_change_tool_bar_height (f, new_height);
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ f->fonts_changed = 1;
+
+ return 1;
}
}
}
/* Scroll when cursor is inside this scroll margin. */
h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
+ /* If the position of this window's point has explicitly
+ changed, no more suspend auto hscrolling. */
+ if (NILP (Fequal (Fwindow_point (window), Fwindow_old_point (window))))
+ w->suspend_auto_hscroll = 0;
+
+ /* Remember window point. */
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
+
if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
+ && w->suspend_auto_hscroll == 0
/* In some pathological cases, like restoring a window
configuration into a frame that is much smaller than
the one from which the configuration was saved, we
inside the left margin and the window is already
hscrolled. */
&& ((!row_r2l_p
- && ((w->hscroll
- && w->cursor.x <= h_margin)
+ && ((w->hscroll && w->cursor.x <= h_margin)
|| (cursor_row->enabled_p
&& cursor_row->truncated_on_right_p
&& (w->cursor.x >= text_area_width - h_margin))))
return rc;
}
+
void
set_vertical_scroll_bar (struct window *w)
{
}
+void
+set_horizontal_scroll_bar (struct window *w)
+{
+ int start, end, whole, box_width;
+
+ if (!MINI_WINDOW_P (w)
+ || (w == XWINDOW (minibuf_window)
+ && NILP (echo_area_buffer[0])))
+ {
+ struct buffer *b = XBUFFER (w->contents);
+ struct buffer *old_buffer = NULL;
+ struct it it;
+ struct text_pos startp;
+
+ if (b != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (b);
+ }
+
+ SET_TEXT_POS_FROM_MARKER (startp, w->start);
+ start_display (&it, w, startp);
+ it.last_visible_x = INT_MAX;
+ whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
+ MOVE_TO_X | MOVE_TO_Y);
+ /* whole = move_it_to (&it, w->window_end_pos, INT_MAX,
+ window_box_height (w), -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); */
+
+ start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+ box_width = window_box_width (w, TEXT_AREA);
+ end = start + box_width;
+
+ /* The following is needed to ensure that if after maximizing a
+ window we get hscroll > 0, we can still drag the thumb to the
+ left. */
+ whole = max (whole, w->hscroll + box_width);
+ whole = max (whole, end - start);
+
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+ }
+ else
+ start = end = whole = 0;
+
+ w->hscroll_whole = whole;
+
+ /* Indicate what this scroll bar ought to be displaying now. */
+ if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+ (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+ (w, end - start, whole, start);
+}
+
+
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
{
ptrdiff_t new_pt = marker_position (w->pointm);
ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
+
if (new_pt < BEGV)
{
new_pt = BEGV;
redisplay_tool_bar (f);
#else
if (WINDOWP (f->tool_bar_window)
- && (FRAME_TOOL_BAR_HEIGHT (f) > 0
+ && (FRAME_TOOL_BAR_LINES (f) > 0
|| !NILP (Vauto_resize_tool_bars))
&& redisplay_tool_bar (f))
ignore_mouse_drag_p = 1;
;
finish_scroll_bars:
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+ if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
{
- /* Set the thumb's position and size. */
- set_vertical_scroll_bar (w);
+ if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+ /* Set the thumb's position and size. */
+ set_vertical_scroll_bar (w);
+
+ if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+ /* Set the thumb's position and size. */
+ set_horizontal_scroll_bar (w);
/* Note that we actually used the scroll bar attached to this
window, so it shouldn't be deleted at the end of redisplay. */
else
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
- || part == ON_SCROLL_BAR)
+ || part == ON_VERTICAL_SCROLL_BAR
+ || part == ON_HORIZONTAL_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
cursor = FRAME_X_OUTPUT (f)->text_cursor;
if (w == 0 || h == 0)
{
r.x = r.y = 0;
- r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
- r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
+ r.width = FRAME_TEXT_WIDTH (f);
+ r.height = FRAME_TEXT_HEIGHT (f);
+/** r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f); **/
+/** r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f); **/
}
else
{
DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
doc: /* The pointer shape to show in void text areas.
-A value of nil means to show the text pointer. Other options are `arrow',
-`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
+A value of nil means to show the text pointer. Other options are
+`arrow', `text', `hand', `vdrag', `hdrag', `nhdrag', `modeline', and
+`hourglass'. */);
Vvoid_text_area_pointer = Qarrow;
DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
r->total_cols = FRAME_COLS (f);
r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
- r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
- m->top_line = FRAME_LINES (f) - 1;
+ m->top_line = FRAME_TOTAL_LINES (f) - 1;
m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
m->total_cols = FRAME_COLS (f);
m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
#else /* not USE_X_TOOLKIT && not USE_GTK */
FRAME_MENU_BAR_LINES (f) = nlines;
FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
- resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1);
+ adjust_frame_size (f, -1, -1, 2, 1);
if (FRAME_X_WINDOW (f))
x_clear_under_internal_border (f);
x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
-#if ! defined (USE_GTK)
- int delta, root_height;
- int unit = FRAME_LINE_HEIGHT (f);
-#endif
/* Treat tool bars like menu bars. */
if (FRAME_MINIBUF_ONLY_P (f))
else
nlines = 0;
-#ifdef USE_GTK
+ x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+}
+
+/* Set the pixel height of the tool bar of frame F to HEIGHT. */
+void
+x_change_tool_bar_height (struct frame *f, int height)
+{
+#ifdef USE_GTK
FRAME_TOOL_BAR_LINES (f) = 0;
FRAME_TOOL_BAR_HEIGHT (f) = 0;
- if (nlines)
+ if (height)
{
FRAME_EXTERNAL_TOOL_BAR (f) = 1;
if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
free_frame_tool_bar (f);
FRAME_EXTERNAL_TOOL_BAR (f) = 0;
}
-
#else /* !USE_GTK */
+ int unit = FRAME_LINE_HEIGHT (f);
+ int old_height = FRAME_TOOL_BAR_HEIGHT (f);
+ int lines = (height + unit - 1) / unit;
/* Make sure we redisplay all windows in this frame. */
windows_or_buffers_changed = 60;
- /* DELTA is in pixels now. */
- delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit;
- /* Don't resize the tool-bar to more than we have room for. Note: The
- calculations below and the subsequent call to resize_frame_windows
- are inherently flawed because they can make the toolbar higher than
- the containing frame. */
- if (delta > 0)
- {
- root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)));
- if (root_height - delta < unit)
- {
- delta = root_height - unit;
- /* When creating a new frame and toolbar mode is enabled, we
- need at least one toolbar line. */
- nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1);
- }
- }
-
- FRAME_TOOL_BAR_LINES (f) = nlines;
- FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
- resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1);
-#if !defined USE_X_TOOLKIT && !defined USE_GTK
- if (FRAME_X_WINDOW (f))
- x_clear_under_internal_border (f);
-#endif
- adjust_frame_glyphs (f);
+ /* Recalculate tool bar and frame text sizes. */
+ FRAME_TOOL_BAR_HEIGHT (f) = height;
+ FRAME_TOOL_BAR_LINES (f) = lines;
+ FRAME_TEXT_HEIGHT (f)
+ = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f));
+ FRAME_LINES (f)
+ = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
+ /* Store the `tool-bar-lines' and `height' frame parameters. */
+ store_frame_param (f, Qtool_bar_lines, make_number (lines));
+ store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
/* We also have to make sure that the internal border at the top of
the frame, below the menu bar or tool bar, is redrawn when the
clear_current_matrices (f);
}
- /* If the tool bar gets smaller, the internal border below it
- has to be cleared. It was formerly part of the display
- of the larger tool bar, and updating windows won't clear it. */
- if (delta < 0)
+ if ((height < old_height) && WINDOWP (f->tool_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+
+ /* Recalculate toolbar height. */
+ f->n_tool_bar_rows = 0;
+
+ adjust_frame_size (f, -1, -1, 4, 0);
+
+/** #if !defined USE_X_TOOLKIT **/
+ if (FRAME_X_WINDOW (f))
+ x_clear_under_internal_border (f);
+/** #endif **/
+
+#endif /* USE_GTK */
+}
+
+
+void
+x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ int border;
+
+ CHECK_TYPE_RANGED_INTEGER (int, arg);
+ border = max (XINT (arg), 0);
+
+ if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
{
- int height = FRAME_INTERNAL_BORDER_WIDTH (f);
- int width = FRAME_PIXEL_WIDTH (f);
- int y = nlines * unit;
+ FRAME_INTERNAL_BORDER_WIDTH (f) = border;
- /* height can be zero here. */
- if (height > 0 && width > 0)
+#ifdef USE_X_TOOLKIT
+ if (FRAME_X_OUTPUT (f)->edit_widget)
+ widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
+#endif
+
+ if (FRAME_X_WINDOW (f) != 0)
{
- block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height);
- unblock_input ();
- }
+ adjust_frame_size (f, -1, -1, 3, 0);
- if (WINDOWP (f->tool_bar_window))
- clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+#ifdef USE_GTK
+ xg_clear_under_internal_border (f);
+#else
+ x_clear_under_internal_border (f);
+#endif
+ }
}
- run_window_configuration_change_hook (f);
-#endif /* USE_GTK */
}
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
#else
- /* The width of a non-toolkit scrollbar is at least 14 pixels and a
- multiple of the frame's character width. */
+ /* The width of a non-toolkit scrollbar is 14 pixels. */
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
= FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
#endif
}
+void
+x_set_scroll_bar_default_height (struct frame *f)
+{
+ int height = FRAME_LINE_HEIGHT (f);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_GTK
+ int min_height = xg_get_default_scrollbar_height ();
+#else
+ int min_height = 16;
+#endif
+ /* A minimum height of 14 doesn't look good for toolkit scroll bars. */
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
+#else
+ /* The height of a non-toolkit scrollbar is 14 pixels. */
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
+
+ /* Use all of that space (aside from required margins) for the
+ scroll bar. */
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
+#endif
+}
+
\f
/* Record in frame F the specified or default value according to ALIST
of the parameter named PROP (a Lisp symbol). If no value is
unwind_create_frame (frame);
}
-static void
-unwind_create_frame_1 (Lisp_Object val)
-{
- inhibit_lisp_code = val;
-}
-
static void
x_default_font_parameter (struct frame *f, Lisp_Object parms)
{
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1, 1, 0,
doc: /* Make a new X window, which is called a "frame" in Emacs terms.
-Return an Emacs frame object.
-PARMS is an alist of frame parameters.
+Return an Emacs frame object. PARMS is an alist of frame parameters.
If the parameters specify that the frame should not have a minibuffer,
-and do not specify a specific minibuffer window to use,
-then `default-minibuffer-frame' must be a frame whose minibuffer can
-be shared by the new frame.
+and do not specify a specific minibuffer window to use, then
+`default-minibuffer-frame' must be a frame whose minibuffer can be
+shared by the new frame.
This function is an internal primitive--use `make-frame' instead. */)
(Lisp_Object parms)
Lisp_Object name;
int minibuffer_only = 0;
long window_prompting = 0;
- int width, height;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
}
/* Specify the parent under which to make this X window. */
-
if (!NILP (parent))
{
f->output_data.x->parent_desc = (Window) XFASTINT (parent);
{
fset_name (f, name);
f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
+ /* Use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
#endif
"verticalScrollBars", "ScrollBars",
RES_TYPE_SYMBOL);
+ x_default_parameter (f, parms, Qhorizontal_scroll_bars,
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
+ Qt,
+#else
+ Qnil,
+#endif
+ "horizontalScrollBars", "ScrollBars",
+ RES_TYPE_SYMBOL);
/* Also do the stuff which must be set before the window exists. */
x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
+ /* Init faces before x_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
init_frame_faces (f);
- /* PXW: This is a duplicate from below. We have to do it here since
- otherwise x_set_tool_bar_lines will work with the character sizes
- installed by init_frame_faces while the frame's pixel size is still
- calculated from a character size of 1 and we subsequently hit the
- eassert (height >= 0) assertion in window_box_height. The
- non-pixelwise code apparently worked around this because it had one
- frame line vs one toolbar line which left us with a zero root
- window height which was obviously wrong as well ... */
- change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1);
+ /* The following call of change_frame_size is needed since otherwise
+ x_set_tool_bar_lines will already work with the character sizes
+ installed by init_frame_faces while the frame's pixel size is
+ still calculated from a character size of 1 and we subsequently
+ hit the (height >= 0) assertion in window_box_height.
+
+ The non-pixelwise code apparently worked around this because it
+ had one frame line vs one toolbar line which left us with a zero
+ root window height which was obviously wrong as well ... */
+ adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1);
/* Set the menu-bar-lines and tool-bar-lines parameters. We don't
look up the X resources controlling the menu-bar and tool-bar
here; they are processed specially at startup, and reflected in
- the values of the mode variables.
+ the values of the mode variables. */
- Avoid calling window-configuration-change-hook; otherwise we
- could get an infloop in next_frame since the frame is not yet in
- Vframe_list. */
- {
- ptrdiff_t count2 = SPECPDL_INDEX ();
- record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code);
- inhibit_lisp_code = Qt;
-
- x_default_parameter (f, parms, Qmenu_bar_lines,
- NILP (Vmenu_bar_mode)
- ? make_number (0) : make_number (1),
- NULL, NULL, RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines,
- NILP (Vtool_bar_mode)
- ? make_number (0) : make_number (1),
- NULL, NULL, RES_TYPE_NUMBER);
-
- unbind_to (count2, Qnil);
- }
+ x_default_parameter (f, parms, Qmenu_bar_lines,
+ NILP (Vmenu_bar_mode)
+ ? make_number (0) : make_number (1),
+ NULL, NULL, RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qtool_bar_lines,
+ NILP (Vtool_bar_mode)
+ ? make_number (0) : make_number (1),
+ NULL, NULL, RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate",
x_default_parameter (f, parms, Qwait_for_wm, Qt,
"waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
x_default_parameter (f, parms, Qfullscreen, Qnil,
- "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qtool_bar_position,
FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
"scrollBarWidth", "ScrollBarWidth",
RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
+ "scrollBarHeight", "ScrollBarHeight",
+ RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
- /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
- Change will not be effected unless different from the current
- FRAME_LINES (f). */
- width = FRAME_TEXT_WIDTH (f);
- height = FRAME_TEXT_HEIGHT (f);
- FRAME_TEXT_HEIGHT (f) = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, width, height, 1, 0, 0, 1);
+ /* Consider frame official, now. */
+ f->official = true;
+
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1);
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Create the menu bar. */
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
+ /* Init faces before x_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
init_frame_faces (f);
f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
width = FRAME_COLS (f);
height = FRAME_LINES (f);
SET_FRAME_COLS (f, 0);
- FRAME_LINES (f) = 0;
+ SET_FRAME_LINES (f, 0);
change_frame_size (f, width, height, 1, 0, 0, 0);
/* Add `tooltip' frame parameter's default value. */
below. And the frame needs to be on Vframe_list or making it
visible won't work. */
Vframe_list = Fcons (frame, Vframe_list);
-
+ f->official = true;
/* Setting attributes of faces of the tooltip frame from resources
and similar will increment face_change_count, which leads to the
x_set_mouse_color,
x_explicitly_set_name,
x_set_scroll_bar_width,
+ x_set_scroll_bar_height,
x_set_title,
x_set_unsplittable,
x_set_vertical_scroll_bars,
+ x_set_horizontal_scroll_bars,
x_set_visibility,
x_set_tool_bar_lines,
x_set_scroll_bar_foreground,
x_set_scroll_bar_background,
x_set_screen_gamma,
x_set_line_spacing,
- x_set_fringe_width,
- x_set_fringe_width,
+ x_set_left_fringe,
+ x_set_right_fringe,
x_set_wait_for_wm,
x_set_fullscreen,
x_set_font_backend,
xg_update_frame_menubar (f);
#else
struct x_output *x;
- int columns, rows;
+/** int columns, rows; **/
eassert (FRAME_X_P (f));
block_input ();
/* Save the size of the frame because the pane widget doesn't accept
to resize itself. So force it. */
- columns = FRAME_COLS (f);
- rows = FRAME_LINES (f);
+/** columns = FRAME_COLS (f); **/
+/** rows = FRAME_LINES (f); **/
/* Do the voodoo which means "I'm changing lots of things, don't try
to refigure sizes until I'm done." */
lw_refigure_widget (x->column_widget, True);
/* Force the pane widget to resize itself with the right values. */
- EmacsFrameSetCharSize (x->edit_widget, columns, rows);
+/** EmacsFrameSetCharSize (x->edit_widget, columns, rows); **/
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 2, 0);
unblock_input ();
#endif
}
void
set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
{
- xt_or_gtk_widget menubar_widget;
+ xt_or_gtk_widget menubar_widget, old_widget;
#ifdef USE_X_TOOLKIT
LWLIB_ID id;
#endif
eassert (FRAME_X_P (f));
- menubar_widget = f->output_data.x->menubar_widget;
+ menubar_widget = old_widget = f->output_data.x->menubar_widget;
XSETFRAME (Vmenu_updating_frame, f);
if (x1 == 0 && y1 == 0)
XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
#endif
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
+ FRAME_TEXT_HEIGHT (f), 2, 0);
+ /*
+ if (frame_inhibit_resize (f, 0))
+ change_frame_size (f, 0, 0, 0, 0, 0, 1);
+ else
+ x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
+ FRAME_TEXT_HEIGHT (f), 1);
+ */
}
unblock_input ();
}
static void x_flush (struct frame *f);
static void x_update_begin (struct frame *);
static void x_update_window_begin (struct window *);
-static struct scroll_bar *x_window_to_scroll_bar (Display *, Window);
+static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
Time *);
+static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
+ enum scroll_bar_part *,
+ Lisp_Object *, Lisp_Object *,
+ Time *);
static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
static void x_check_fullscreen (struct frame *);
static void x_check_expected_move (struct frame *, int, int);
static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
static void x_initialize (void);
+static int get_current_wm_state (struct frame *, Window, int *, int *);
/* Flush display of frame F. */
}
-/* Clear under internal border if any for non-toolkit builds. */
-
-
-#if !defined USE_X_TOOLKIT && !defined USE_GTK
+/* Clear under internal border if any (GTK has its own version). */
+#ifndef USE_GTK
void
x_clear_under_internal_border (struct frame *f)
{
block_input ();
if (dpyinfo->last_mouse_scroll_bar && insist == 0)
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
+ {
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+
+ if (bar->horizontal)
+ x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
+ else
+ x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
+ }
else
{
Window root;
{
struct scroll_bar *bar;
- bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
+ bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
if (bar)
{
bits. */
static struct scroll_bar *
-x_window_to_scroll_bar (Display *display, Window window_id)
+x_window_to_scroll_bar (Display *display, Window window_id, int type)
{
Lisp_Object tail, frame;
condemned = Qnil,
! NILP (bar));
bar = XSCROLL_BAR (bar)->next)
- if (XSCROLL_BAR (bar)->x_window == window_id &&
- FRAME_X_DISPLAY (XFRAME (frame)) == display)
+ if (XSCROLL_BAR (bar)->x_window == window_id
+ && FRAME_X_DISPLAY (XFRAME (frame)) == display
+ && (type = 2
+ || (type == 1 && XSCROLL_BAR (bar)->horizontal)
+ || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
return XSCROLL_BAR (bar);
}
#ifdef USE_TOOLKIT_SCROLL_BARS
-static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
+static void x_send_scroll_bar_event (Lisp_Object, int, int, int, bool);
/* Lisp window being scrolled. Set when starting to interact with
a toolkit scroll bar, reset to nil when ending the interaction. */
/* Id of action hook installed for scroll bars. */
static XtActionHookId action_hook_id;
+static XtActionHookId horizontal_action_hook_id;
static Boolean xaw3d_arrow_scroll;
struct scroll_bar *bar;
x_send_scroll_bar_event (window_being_scrolled,
- scroll_bar_end_scroll, 0, 0);
+ scroll_bar_end_scroll, 0, 0, 0);
w = XWINDOW (window_being_scrolled);
bar = XSCROLL_BAR (w->vertical_scroll_bar);
toolkit_scroll_bar_interaction = 0;
}
}
+
+
+static void
+xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
+ XEvent *event, String *params, Cardinal *num_params)
+{
+ int scroll_bar_p;
+ const char *end_action;
+
+#ifdef USE_MOTIF
+ scroll_bar_p = XmIsScrollBar (widget);
+ end_action = "Release";
+#else /* !USE_MOTIF i.e. use Xaw */
+ scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
+ end_action = "EndScroll";
+#endif /* USE_MOTIF */
+
+ if (scroll_bar_p
+ && strcmp (action_name, end_action) == 0
+ && WINDOWP (window_being_scrolled))
+ {
+ struct window *w;
+ struct scroll_bar *bar;
+
+ x_send_scroll_bar_event (window_being_scrolled,
+ scroll_bar_end_scroll, 0, 0, 1);
+ w = XWINDOW (window_being_scrolled);
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+
+ if (bar->dragging != -1)
+ {
+ bar->dragging = -1;
+ /* The thumb size is incorrect while dragging: fix it. */
+ set_horizontal_scroll_bar (w);
+ }
+ window_being_scrolled = Qnil;
+#if defined (USE_LUCID)
+ bar->last_seen_part = scroll_bar_nowhere;
+#endif
+ /* Xt timeouts no longer needed. */
+ toolkit_scroll_bar_interaction = 0;
+ }
+}
#endif /* not USE_GTK */
/* Send a client message with message type Xatom_Scrollbar for a
amount to scroll of a whole of WHOLE. */
static void
-x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
+x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole, bool horizontal)
{
XEvent event;
XClientMessageEvent *ev = &event.xclient;
/* Construct a ClientMessage event to send to the frame. */
ev->type = ClientMessage;
- ev->message_type = FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar;
+ ev->message_type = (horizontal
+ ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
+ : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
ev->display = FRAME_X_DISPLAY (f);
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
ievent->modifiers = 0;
}
+/* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
+ input event in *IEVENT. */
+
+static void
+x_horizontal_scroll_bar_to_input_event (const XEvent *event,
+ struct input_event *ievent)
+{
+ const XClientMessageEvent *ev = &event->xclient;
+ Lisp_Object window;
+ struct window *w;
+
+ /* See the comment in the function above. */
+ intptr_t iw0 = ev->data.l[0];
+ intptr_t iw1 = ev->data.l[1];
+ intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
+ w = (struct window *) iw;
+
+ XSETWINDOW (window, w);
+
+ ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
+ ievent->frame_or_window = window;
+ ievent->arg = Qnil;
+#ifdef USE_GTK
+ ievent->timestamp = CurrentTime;
+#else
+ ievent->timestamp =
+ XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
+#endif
+ ievent->code = 0;
+ ievent->part = ev->data.l[2];
+ ievent->x = make_number (ev->data.l[3]);
+ ievent->y = make_number (ev->data.l[4]);
+ ievent->modifiers = 0;
+}
+
#ifdef USE_MOTIF
#define XM_SB_MAX 10000000
-
/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
struct scroll_bar *bar = client_data;
XmScrollBarCallbackStruct *cs = call_data;
int part = -1, whole = 0, portion = 0;
+ int horizontal = bar->horizontal;
switch (cs->reason)
{
case XmCR_DECREMENT:
bar->dragging = -1;
- part = scroll_bar_up_arrow;
+ part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
break;
case XmCR_INCREMENT:
bar->dragging = -1;
- part = scroll_bar_down_arrow;
+ part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
break;
case XmCR_PAGE_DECREMENT:
bar->dragging = -1;
- part = scroll_bar_above_handle;
+ part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
break;
case XmCR_PAGE_INCREMENT:
bar->dragging = -1;
- part = scroll_bar_below_handle;
+ part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
break;
case XmCR_TO_TOP:
bar->dragging = -1;
- part = scroll_bar_to_top;
+ part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
break;
case XmCR_TO_BOTTOM:
bar->dragging = -1;
- part = scroll_bar_to_bottom;
+ part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
break;
case XmCR_DRAG:
{
int slider_size;
- /* Get the slider size. */
block_input ();
XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
unblock_input ();
- whole = XM_SB_MAX - slider_size;
- portion = min (cs->value, whole);
- part = scroll_bar_handle;
+ if (horizontal)
+ {
+ whole = bar->whole;
+ portion = (((float) cs->value
+ / (XM_SB_MAX - slider_size))
+ * (whole
+ - ((float) slider_size / XM_SB_MAX) * whole));
+ portion = max (0, portion);
+ part = scroll_bar_horizontal_handle;
+ }
+ else
+ {
+ whole = XM_SB_MAX - slider_size;
+ portion = min (cs->value, whole);
+ part = scroll_bar_handle;
+ }
+
bar->dragging = cs->value;
}
break;
if (part >= 0)
{
window_being_scrolled = bar->window;
- x_send_scroll_bar_event (bar->window, part, portion, whole);
+ x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
}
}
if (FRAME_DISPLAY_INFO (f)->grabbed != 0
&& FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
{
- part = scroll_bar_handle;
- whole = gtk_adjustment_get_upper (adj) -
- gtk_adjustment_get_page_size (adj);
- portion = min ((int)value, whole);
- bar->dragging = portion;
- }
+ if (bar->horizontal)
+ {
+ part = scroll_bar_horizontal_handle;
+ whole = (int)(gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj));
+ portion = min ((int)value, whole);
+ bar->dragging = portion;
+ }
+ else
+ {
+ part = scroll_bar_handle;
+ whole = gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj);
+ portion = min ((int)value, whole);
+ bar->dragging = portion;
+ }
+ }
break;
case GTK_SCROLL_STEP_BACKWARD:
- part = scroll_bar_up_arrow;
+ part = (bar->horizontal
+ ? scroll_bar_left_arrow : scroll_bar_up_arrow);
bar->dragging = -1;
break;
case GTK_SCROLL_STEP_FORWARD:
- part = scroll_bar_down_arrow;
+ part = (bar->horizontal
+ ? scroll_bar_right_arrow : scroll_bar_down_arrow);
bar->dragging = -1;
break;
case GTK_SCROLL_PAGE_BACKWARD:
- part = scroll_bar_above_handle;
+ part = (bar->horizontal
+ ? scroll_bar_before_handle : scroll_bar_above_handle);
bar->dragging = -1;
break;
case GTK_SCROLL_PAGE_FORWARD:
- part = scroll_bar_below_handle;
+ part = (bar->horizontal
+ ? scroll_bar_after_handle : scroll_bar_below_handle);
bar->dragging = -1;
break;
}
if (part >= 0)
{
window_being_scrolled = bar->window;
- x_send_scroll_bar_event (bar->window, part, portion, whole);
+ x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
}
return FALSE;
if (WINDOWP (window_being_scrolled))
{
x_send_scroll_bar_event (window_being_scrolled,
- scroll_bar_end_scroll, 0, 0);
+ scroll_bar_end_scroll, 0, 0, bar->horizontal);
window_being_scrolled = Qnil;
}
float shown;
int whole, portion, height;
enum scroll_bar_part part;
+ int horizontal = bar->horizontal;
/* Get the size of the thumb, a value between 0 and 1. */
block_input ();
XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
unblock_input ();
- whole = 10000000;
- portion = shown < 1 ? top * whole : 0;
-
- if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
- /* Some derivatives of Xaw refuse to shrink the thumb when you reach
- the bottom, so we force the scrolling whenever we see that we're
- too close to the bottom (in x_set_toolkit_scroll_bar_thumb
- we try to ensure that we always stay two pixels away from the
- bottom). */
- part = scroll_bar_down_arrow;
+ if (horizontal)
+ {
+ whole = bar->whole;
+ portion = (top * (whole - (shown * whole))) / (1 - shown);
+ portion = max (0, portion);
+ part = scroll_bar_horizontal_handle;
+ }
else
part = scroll_bar_handle;
window_being_scrolled = bar->window;
bar->dragging = portion;
bar->last_seen_part = part;
- x_send_scroll_bar_event (bar->window, part, portion, whole);
+ x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
}
window_being_scrolled = bar->window;
bar->dragging = -1;
bar->last_seen_part = part;
- x_send_scroll_bar_event (bar->window, part, position, height);
+ x_send_scroll_bar_event (bar->window, part, position, height, bar->horizontal);
}
#endif /* not USE_GTK and not USE_MOTIF */
#define SCROLL_BAR_NAME "verticalScrollBar"
+#define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
/* Create the widget for scroll bar BAR on frame F. Record the widget
and X window of the scroll bar in BAR. */
unblock_input ();
}
+static void
+x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
+{
+ const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
+
+ block_input ();
+ xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+ G_CALLBACK (xg_end_scroll_callback),
+ scroll_bar_name);
+ unblock_input ();
+}
+
#else /* not USE_GTK */
static void
SET_SCROLL_BAR_X_WIDGET (bar, widget);
xwindow = XtWindow (widget);
bar->x_window = xwindow;
+ bar->whole = 1;
+ bar->horizontal = 0;
+
+ unblock_input ();
+}
+
+static void
+x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
+{
+ Window xwindow;
+ Widget widget;
+ Arg av[20];
+ int ac = 0;
+ const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
+ unsigned long pixel;
+
+ block_input ();
+
+#ifdef USE_MOTIF
+ /* Set resources. Create the widget. */
+ XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
+ XtSetArg (av[ac], XmNminimum, 0); ++ac;
+ XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
+ XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
+ XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
+ XtSetArg (av[ac], XmNincrement, 1); ++ac;
+ XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
+
+ pixel = f->output_data.x->scroll_bar_foreground_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XmNforeground, pixel);
+ ++ac;
+ }
+
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XmNbackground, pixel);
+ ++ac;
+ }
+
+ widget = XmCreateScrollBar (f->output_data.x->edit_widget,
+ (char *) scroll_bar_name, av, ac);
+
+ /* Add one callback for everything that can happen. */
+ XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
+ (XtPointer) bar);
+ XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
+ (XtPointer) bar);
+
+ /* Realize the widget. Only after that is the X window created. */
+ XtRealizeWidget (widget);
+
+ /* Set the cursor to an arrow. I didn't find a resource to do that.
+ And I'm wondering why it hasn't an arrow cursor by default. */
+ XDefineCursor (XtDisplay (widget), XtWindow (widget),
+ f->output_data.x->nontext_cursor);
+
+#else /* !USE_MOTIF i.e. use Xaw */
+
+ /* Set resources. Create the widget. The background of the
+ Xaw3d scroll bar widget is a little bit light for my taste.
+ We don't alter it here to let users change it according
+ to their taste with `emacs*verticalScrollBar.background: xxx'. */
+ XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
+ XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
+ /* For smoother scrolling with Xaw3d -sm */
+ /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
+
+ pixel = f->output_data.x->scroll_bar_foreground_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XtNforeground, pixel);
+ ++ac;
+ }
+
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XtNbackground, pixel);
+ ++ac;
+ }
+
+ /* Top/bottom shadow colors. */
+
+ /* Allocate them, if necessary. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (pixel != -1)
+ {
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
+ FRAME_X_COLORMAP (f),
+ &pixel, 1.2, 0x8000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+ }
+ }
+ if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (pixel != -1)
+ {
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
+ FRAME_X_COLORMAP (f),
+ &pixel, 0.6, 0x4000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+ }
+ }
+
+#ifdef XtNbeNiceToColormap
+ /* Tell the toolkit about them. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
+ || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ /* We tried to allocate a color for the top/bottom shadow, and
+ failed, so tell Xaw3d to use dithering instead. */
+ /* But only if we have a small colormap. Xaw3d can allocate nice
+ colors itself. */
+ {
+ XtSetArg (av[ac], XtNbeNiceToColormap,
+ DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
+ ++ac;
+ }
+ else
+ /* Tell what colors Xaw3d should use for the top/bottom shadow, to
+ be more consistent with other emacs 3d colors, and since Xaw3d is
+ not good at dealing with allocation failure. */
+ {
+ /* This tells Xaw3d to use real colors instead of dithering for
+ the shadows. */
+ XtSetArg (av[ac], XtNbeNiceToColormap, False);
+ ++ac;
+
+ /* Specify the colors. */
+ pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XtNtopShadowPixel, pixel);
+ ++ac;
+ }
+ pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
+ ++ac;
+ }
+ }
+#endif
+
+ widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
+ f->output_data.x->edit_widget, av, ac);
+
+ {
+ char const *initial = "";
+ char const *val = initial;
+ XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+ XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
+ XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
+ if (xaw3d_arrow_scroll || val == initial)
+ { /* ARROW_SCROLL */
+ xaw3d_arrow_scroll = True;
+ /* Isn't that just a personal preference ? --Stef */
+ XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
+ }
+ }
+
+ /* Define callbacks. */
+ XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
+ XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
+ (XtPointer) bar);
+
+ /* Realize the widget. Only after that is the X window created. */
+ XtRealizeWidget (widget);
+
+#endif /* !USE_MOTIF */
+
+ /* Install an action hook that lets us detect when the user
+ finishes interacting with a scroll bar. */
+ if (horizontal_action_hook_id == 0)
+ horizontal_action_hook_id
+ = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
+
+ /* Remember X window and widget in the scroll bar vector. */
+ SET_SCROLL_BAR_X_WIDGET (bar, widget);
+ xwindow = XtWindow (widget);
+ bar->x_window = xwindow;
+ bar->whole = 1;
+ bar->horizontal = 1;
unblock_input ();
}
xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
}
+static void
+x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
+{
+ xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
+}
+
#else /* not USE_GTK */
static void
x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
unblock_input ();
}
+
+static void
+x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
+ int whole)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
+ float top, shown;
+
+ block_input ();
+
+#ifdef USE_MOTIF
+ bar->whole = whole;
+ shown = (float) portion / whole;
+ top = (float) position / (whole - portion);
+ {
+ int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
+ int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
+
+ XmScrollBarSetValues (widget, value, size, 0, 0, False);
+ }
+#else /* !USE_MOTIF i.e. use Xaw */
+ bar->whole = whole;
+ if (whole == 0)
+ top = 0, shown = 1;
+ else
+ {
+ top = (float) position / whole;
+ shown = (float) portion / whole;
+ }
+
+ {
+ float old_top, old_shown;
+ Dimension height;
+ XtVaGetValues (widget,
+ XtNtopOfThumb, &old_top,
+ XtNshown, &old_shown,
+ XtNheight, &height,
+ NULL);
+
+#if 0
+ /* Massage the top+shown values. */
+ if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
+ top = max (0, min (1, top));
+ else
+ top = old_top;
+#if ! defined (HAVE_XAW3D)
+ /* With Xaw, 'top' values too closer to 1.0 may
+ cause the thumb to disappear. Fix that. */
+ top = min (top, 0.99f);
+#endif
+ /* Keep two pixels available for moving the thumb down. */
+ shown = max (0, min (1 - top - (2.0f / height), shown));
+#if ! defined (HAVE_XAW3D)
+ /* Likewise with too small 'shown'. */
+ shown = max (shown, 0.01f);
+#endif
+#endif
+
+ /* If the call to XawScrollbarSetThumb below doesn't seem to
+ work, check that 'NARROWPROTO' is defined in src/config.h.
+ If this is not so, most likely you need to fix configure. */
+ XawScrollbarSetThumb (widget, top, shown);
+#if 0
+ if (top != old_top || shown != old_shown)
+ {
+ if (bar->dragging == -1)
+ XawScrollbarSetThumb (widget, top, shown);
+ else
+ {
+ /* Try to make the scrolling a tad smoother. */
+ if (!xaw3d_pick_top)
+ shown = min (shown, old_shown);
+
+ XawScrollbarSetThumb (widget, top, shown);
+ }
+ }
+#endif
+ }
+#endif /* !USE_MOTIF */
+
+ unblock_input ();
+}
#endif /* not USE_GTK */
#endif /* USE_TOOLKIT_SCROLL_BARS */
scroll bar. */
static struct scroll_bar *
-x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
+x_scroll_bar_create (struct window *w, int top, int left, int width, int height, bool horizontal)
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar
block_input ();
#ifdef USE_TOOLKIT_SCROLL_BARS
- x_create_toolkit_scroll_bar (f, bar);
+ if (horizontal)
+ x_create_horizontal_toolkit_scroll_bar (f, bar);
+ else
+ x_create_toolkit_scroll_bar (f, bar);
#else /* not USE_TOOLKIT_SCROLL_BARS */
{
XSetWindowAttributes a;
#ifdef USE_TOOLKIT_SCROLL_BARS
{
#ifdef USE_GTK
- xg_update_scrollbar_pos (f, bar->x_window, top,
- left,width, max (height, 1));
+ if (horizontal)
+ xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
+ left, width, max (height, 1));
+ else
+ xg_update_scrollbar_pos (f, bar->x_window, top,
+ left, width, max (height, 1));
#else /* not USE_GTK */
Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
/* Draw the empty space above the handle. Note that we can't clear
zero-height areas; that means "clear to end of window." */
- if (start > 0)
+ if ((inside_width > 0) && (start > 0))
x_clear_area (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER,
/* Draw the empty space below the handle. Note that we can't
clear zero-height areas; that means "clear to end of window." */
- if (end < inside_height)
+ if ((inside_width > 0) && (end < inside_height))
x_clear_area (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + end,
#endif
/* Dissociate this scroll bar from its window. */
- wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
+ if (bar->horizontal)
+ wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
+ else
+ wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
unblock_input ();
}
window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
top = window_y;
height = window_height;
-
- /* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, left, width, max (height, 1));
+ bar = x_scroll_bar_create (w, top, left, width, max (height, 1), 0);
}
else
{
}
+static void
+XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
+{
+ struct frame *f = XFRAME (w->frame);
+ Lisp_Object barobj;
+ struct scroll_bar *bar;
+ int top, height, left, width;
+ int window_x, window_width;
+ int pixel_width = WINDOW_PIXEL_WIDTH (w);
+
+ /* Get window dimensions. */
+ window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
+ left = window_x;
+ width = window_width;
+ top = WINDOW_SCROLL_BAR_AREA_Y (w);
+ height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+
+ /* Does the scroll bar exist yet? */
+ if (NILP (w->horizontal_scroll_bar))
+ {
+ if (width > 0 && height > 0)
+ {
+ block_input ();
+
+ /* Clear also part between window_width and
+ WINDOW_PIXEL_WIDTH. */
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, pixel_width, height);
+ unblock_input ();
+ }
+
+ bar = x_scroll_bar_create (w, top, left, width, height, 1);
+ }
+ else
+ {
+ /* It may just need to be moved and resized. */
+ unsigned int mask = 0;
+
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+
+ block_input ();
+
+ if (left != bar->left)
+ mask |= CWX;
+ if (top != bar->top)
+ mask |= CWY;
+ if (width != bar->width)
+ mask |= CWWidth;
+ if (height != bar->height)
+ mask |= CWHeight;
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ /* Move/size the scroll bar widget. */
+ if (mask)
+ {
+ /* Since toolkit scroll bars are smaller than the space reserved
+ for them on the frame, we have to clear "under" them. */
+ if (width > 0 && height > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ WINDOW_LEFT_EDGE_X (w), top,
+ pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
+#ifdef USE_GTK
+ xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
+ width, height);
+#else /* not USE_GTK */
+ XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
+ left, top, width, height, 0);
+#endif /* not USE_GTK */
+ }
+#else /* not USE_TOOLKIT_SCROLL_BARS */
+
+ /* Clear areas not covered by the scroll bar because it's not as
+ wide as the area reserved for it. This makes sure a
+ previous mode line display is cleared after C-x 2 C-x 1, for
+ example. */
+ {
+ int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
+ int rest = area_height - height;
+ if (rest > 0 && width > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, rest);
+ }
+
+ /* Move/size the scroll bar window. */
+ if (mask)
+ {
+ XWindowChanges wc;
+
+ wc.x = left;
+ wc.y = top;
+ wc.width = width;
+ wc.height = height;
+ XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
+ mask, &wc);
+ }
+
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
+
+ /* Remember new settings. */
+ bar->left = left;
+ bar->top = top;
+ bar->width = width;
+ bar->height = height;
+
+ unblock_input ();
+ }
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
+#else /* not USE_TOOLKIT_SCROLL_BARS */
+ /* Set the scroll bar's current state, unless we're currently being
+ dragged. */
+ if (bar->dragging == -1)
+ {
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
+
+ if (whole == 0)
+ x_scroll_bar_set_handle (bar, 0, left_range, 0);
+ else
+ {
+ int start = ((double) position * left_range) / whole;
+ int end = ((double) (position + portion) * left_range) / whole;
+ x_scroll_bar_set_handle (bar, start, end, 0);
+ }
+ }
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
+
+ XSETVECTOR (barobj, bar);
+ wset_horizontal_scroll_bar (w, barobj);
+}
+
+
/* The following three hooks are used when we're doing a thorough
redisplay of the frame. We don't explicitly know which scroll bars
are going to be deleted, because keeping track of when windows go
static void
XTcondemn_scroll_bars (struct frame *frame)
{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
+ if (!NILP (FRAME_SCROLL_BARS (frame)))
{
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- fset_condemned_scroll_bars (frame, bar);
+ if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+ {
+ /* Prepend scrollbars to already condemned ones. */
+ Lisp_Object last = FRAME_SCROLL_BARS (frame);
+
+ while (!NILP (XSCROLL_BAR (last)->next))
+ last = XSCROLL_BAR (last)->next;
+
+ XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+ XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
+ }
+
+ fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
+ fset_scroll_bars (frame, Qnil);
}
}
Note that WINDOW isn't necessarily condemned at all. */
static void
-XTredeem_scroll_bar (struct window *window)
+XTredeem_scroll_bar (struct window *w)
{
struct scroll_bar *bar;
- struct frame *f;
Lisp_Object barobj;
+ struct frame *f;
/* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
+ if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
emacs_abort ();
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- f = XFRAME (WINDOW_FRAME (window));
- if (NILP (bar->prev))
+ if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
{
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- fset_condemned_scroll_bars (f, bar->next);
+ bar = XSCROLL_BAR (w->vertical_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ goto horizontal;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->vertical_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- emacs_abort ();
+ XSCROLL_BAR (bar->prev)->next = bar->next;
+
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
+ horizontal:
+ if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+ {
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ return;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->horizontal_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
+ else
+ XSCROLL_BAR (bar->prev)->next = bar->next;
+
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (barobj, bar);
- fset_scroll_bars (f, barobj);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ }
}
/* Remove all scroll bars on FRAME that haven't been saved since the
if (! WINDOWP (bar->window))
emacs_abort ();
- emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
+ emacs_event->kind = (bar->horizontal
+ ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+ : SCROLL_BAR_CLICK_EVENT);
emacs_event->code = event->xbutton.button - Button1;
emacs_event->modifiers
= (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
emacs_event->frame_or_window = bar->window;
emacs_event->arg = Qnil;
emacs_event->timestamp = event->xbutton.time;
- {
- int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
- int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
+ if (bar->horizontal)
+ {
+ int left_range
+ = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
- if (y < 0) y = 0;
- if (y > top_range) y = top_range;
+ if (x < 0) x = 0;
+ if (x > left_range) x = left_range;
- if (y < bar->start)
- emacs_event->part = scroll_bar_above_handle;
- else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
- emacs_event->part = scroll_bar_handle;
- else
- emacs_event->part = scroll_bar_below_handle;
+ if (x < bar->start)
+ emacs_event->part = scroll_bar_before_handle;
+ else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
+ emacs_event->part = scroll_bar_horizontal_handle;
+ else
+ emacs_event->part = scroll_bar_after_handle;
#ifndef USE_TOOLKIT_SCROLL_BARS
- /* If the user has released the handle, set it to its final position. */
- if (event->type == ButtonRelease && bar->dragging != -1)
- {
- int new_start = y - bar->dragging;
- int new_end = new_start + bar->end - bar->start;
+ /* If the user has released the handle, set it to its final position. */
+ if (event->type == ButtonRelease && bar->dragging != -1)
+ {
+ int new_start = - bar->dragging;
+ int new_end = new_start + bar->end - bar->start;
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
- bar->dragging = -1;
- }
+ x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ bar->dragging = -1;
+ }
#endif
- XSETINT (emacs_event->x, y);
- XSETINT (emacs_event->y, top_range);
- }
+ XSETINT (emacs_event->x, left_range);
+ XSETINT (emacs_event->y, x);
+ }
+ else
+ {
+ int top_range
+ = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
+ int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
+
+ if (y < 0) y = 0;
+ if (y > top_range) y = top_range;
+
+ if (y < bar->start)
+ emacs_event->part = scroll_bar_above_handle;
+ else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
+ emacs_event->part = scroll_bar_handle;
+ else
+ emacs_event->part = scroll_bar_below_handle;
+
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ /* If the user has released the handle, set it to its final position. */
+ if (event->type == ButtonRelease && bar->dragging != -1)
+ {
+ int new_start = y - bar->dragging;
+ int new_end = new_start + bar->end - bar->start;
+
+ x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ bar->dragging = -1;
+ }
+#endif
+
+ XSETINT (emacs_event->x, y);
+ XSETINT (emacs_event->y, top_range);
+ }
}
#ifndef USE_TOOLKIT_SCROLL_BARS
}
+/* Return information to the user about the current position of the mouse
+ on the scroll bar. */
+
+static void
+x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
+ enum scroll_bar_part *part, Lisp_Object *x,
+ Lisp_Object *y, Time *timestamp)
+{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+ Window w = bar->x_window;
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ int win_x, win_y;
+ Window dummy_window;
+ int dummy_coord;
+ unsigned int dummy_mask;
+
+ block_input ();
+
+ /* Get the mouse's position relative to the scroll bar window, and
+ report that. */
+ if (XQueryPointer (FRAME_X_DISPLAY (f), w,
+
+ /* Root, child, root x and root y. */
+ &dummy_window, &dummy_window,
+ &dummy_coord, &dummy_coord,
+
+ /* Position relative to scroll bar. */
+ &win_x, &win_y,
+
+ /* Mouse buttons and modifier keys. */
+ &dummy_mask))
+ {
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+
+ win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
+
+ if (bar->dragging != -1)
+ win_x -= bar->dragging;
+
+ if (win_x < 0)
+ win_x = 0;
+ if (win_x > left_range)
+ win_x = left_range;
+
+ *fp = f;
+ *bar_window = bar->window;
+
+ if (bar->dragging != -1)
+ *part = scroll_bar_horizontal_handle;
+ else if (win_x < bar->start)
+ *part = scroll_bar_before_handle;
+ else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
+ *part = scroll_bar_handle;
+ else
+ *part = scroll_bar_after_handle;
+
+ XSETINT (*y, win_x);
+ XSETINT (*x, left_range);
+
+ f->mouse_moved = 0;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+ *timestamp = dpyinfo->last_mouse_movement_time;
+ }
+
+ unblock_input ();
+}
+
+
/* The screen has been cleared so we may have changed foreground or
background colors, and the scroll bars may need to be redrawn.
Clear out the scroll bars, and ask for expose events, so we can
enum xembed_message,
long detail, long data1, long data2);
+static void
+x_net_wm_state (struct frame *f, Window window)
+{
+ int value = FULLSCREEN_NONE;
+ Lisp_Object lval = Qnil;
+ int sticky = 0;
+
+ (void)get_current_wm_state (f, window, &value, &sticky);
+
+ switch (value)
+ {
+ case FULLSCREEN_WIDTH:
+ lval = Qfullwidth;
+ break;
+ case FULLSCREEN_HEIGHT:
+ lval = Qfullheight;
+ break;
+ case FULLSCREEN_BOTH:
+ lval = Qfullboth;
+ break;
+ case FULLSCREEN_MAXIMIZED:
+ lval = Qmaximized;
+ break;
+ }
+
+ store_frame_param (f, Qfullscreen, lval);
+/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
+}
+
/* Handles the XEvent EVENT on display DPYINFO.
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
*finish = X_EVENT_GOTO_OUT;
goto done;
}
+ else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
+ {
+ x_horizontal_scroll_bar_to_input_event (event, &inev.ie);
+ *finish = X_EVENT_GOTO_OUT;
+ goto done;
+ }
#endif /* USE_TOOLKIT_SCROLL_BARS */
/* XEmbed messages from the embedder (if any). */
goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
bar = x_window_to_scroll_bar (event->xexpose.display,
- event->xexpose.window);
+ event->xexpose.window, 2);
if (bar)
x_scroll_bar_expose (bar, event);
#ifndef USE_TOOLKIT_SCROLL_BARS
struct scroll_bar *bar
= x_window_to_scroll_bar (event->xmotion.display,
- event->xmotion.window);
+ event->xmotion.window, 2);
if (bar)
x_scroll_bar_note_movement (bar, &event->xmotion);
#endif
if (f)
{
+ x_net_wm_state (f, event->xconfigure.window);
+
#ifndef USE_X_TOOLKIT
#ifndef USE_GTK
int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
{
struct scroll_bar *bar
= x_window_to_scroll_bar (event->xbutton.display,
- event->xbutton.window);
+ event->xbutton.window, 2);
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Make the "Ctrl-Mouse-2 splits window" work for toolkit
FRAME_COLUMN_WIDTH (f) = font->average_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
- FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+#ifndef USE_X_TOOLKIT \
+/** FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); **/
FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
-
- compute_fringe_widths (f, 1);
+#endif
/* Compute character columns occupied by scrollbar.
}
-/* Change the size of frame F's X window to COLS/ROWS in the case F
+/* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
top-left-corner window gravity for this size change and subsequent
size changes. Otherwise we leave the window gravity unchanged. */
{
int pixelwidth, pixelheight;
- check_frame_size (f, &width, &height, pixelwise);
-
- compute_fringe_widths (f, 0);
-
- pixelwidth = ((pixelwise
- ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
- : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
- + FRAME_TOOLBAR_WIDTH (f));
+/** if (pixelwise) **/
+/** { **/
+/** pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); **/
+/** pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); **/
+/** } **/
+/** else **/
+/** { **/
+/** pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); **/
+/** pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); **/
+/** } **/
+
+/** FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOLBAR_HEIGHT (f); **/
+ pixelwidth = (pixelwise
+ ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
+ : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width));
pixelheight = ((pixelwise
? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
- : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
- + FRAME_MENUBAR_HEIGHT (f)
- + FRAME_TOOLBAR_HEIGHT (f));
+ : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)));
+
+/** pixelwidth = ((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f))) **/
+/** + FRAME_SCROLL_BAR_AREA_WIDTH (f) **/
+/** + FRAME_TOTAL_FRINGE_WIDTH (f) **/
+/** + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
+
+/** pixelheight = ((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f))) **/
+/** + FRAME_TOOLBAR_HEIGHT (f) **/
+/** + FRAME_SCROLL_BAR_AREA_HEIGHT (f) **/
+/** + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
+
if (change_gravity) f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, 0, 0);
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
- pixelwidth, pixelheight);
+ pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
/* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
x_wait_for_event (f, ConfigureNotify);
else
{
- change_frame_size (f, width, height, 0, 1, 0, 1);
+ change_frame_size (f, pixelwidth, pixelheight, 0, 1, 0, 1);
x_sync (f);
}
}
{
block_input ();
- check_frame_size (f, &width, &height, pixelwise);
-
+ /* The following breaks our calculations. If it's really needed,
+ think of something else. */
+#if 0
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
int text_width, text_height;
change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
}
+#endif
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
#else /* not USE_GTK */
x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
-#if !defined USE_X_TOOLKIT
x_clear_under_internal_border (f);
-#endif
#endif /* not USE_GTK */
cancel_mouse_face (f);
unblock_input ();
+
+ do_pending_window_change (0);
}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
XSizeHints size_hints;
Window window = FRAME_OUTER_WINDOW (f);
+ if (!window)
+ return;
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{
base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
- check_frame_size (f, &min_cols, &min_rows, 0);
-
if (frame_resize_pixelwise)
/* Needed to prevent a bad protocol error crash when making the
frame size very small. */
dpyinfo->vertical_scroll_bar_cursor
= XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
+ dpyinfo->horizontal_scroll_bar_cursor
+ = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
+
xrdb = x_load_resources (dpyinfo->display, xrm_option,
resource_name, EMACS_CLASS);
#ifdef HAVE_XRMSETDATABASE
ATOM_REFS_INIT ("DONE", Xatom_DONE)
ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
+ ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
/* EWMH */
ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
terminal->popup_dialog_hook = xw_popup_dialog;
#endif
terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+ terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
/* The cursor to use for vertical scroll bars. */
Cursor vertical_scroll_bar_cursor;
+ /* The cursor to use for horizontal scroll bars. */
+ Cursor horizontal_scroll_bar_cursor;
+
/* The invisible cursor used for pointer blanking.
Unused if this display supports Xfixes extension. */
Cursor invisible_cursor;
/* More atoms for Ghostscript support. */
Atom Xatom_DONE, Xatom_PAGE;
- /* Atom used in toolkit scroll bar client messages. */
- Atom Xatom_Scrollbar;
+ /* Atoms used in toolkit scroll bar client messages. */
+ Atom Xatom_Scrollbar, Xatom_Horizontal_Scrollbar;
/* Atom used in XEmbed client messages. */
Atom Xatom_XEMBED, Xatom_XEMBED_INFO;
/* Last scroll bar part seen in xaw_jump_callback and xaw_scroll_callback. */
enum scroll_bar_part last_seen_part;
#endif
+
+#if defined (USE_TOOLKIT_SCROLL_BARS) && !defined (USE_GTK)
+ /* Last value of whole for horizontal scrollbars. */
+ int whole;
+#endif
+
+ /* 1 if the scroll bar is horizontal. */
+ bool horizontal;
};
/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f, height) \
((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
+/* Return the inside height of a horizontal scroll bar, given the outside
+ height. */
+#define HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT(f, height) \
+ ((height) \
+ - HORIZONTAL_SCROLL_BAR_TOP_BORDER \
+ - HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER)
+
+/* Return the length of the rectangle within which the left part of the
+ handle must stay. This isn't equivalent to the inside width, because
+ the scroll bar handle has a minimum width.
+
+ This is the real range of motion for the scroll bar, so when we're
+ scaling buffer positions to scroll bar positions, we use this, not
+ HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH. */
+#define HORIZONTAL_SCROLL_BAR_LEFT_RANGE(f, width) \
+ (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH (f, width) - HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
+
+/* Return the inside width of horizontal scroll bar, given the outside
+ width. See HORIZONTAL_SCROLL_BAR_LEFT_RANGE too. */
+#define HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH(f, width) \
+ ((width) - HORIZONTAL_SCROLL_BAR_LEFT_BORDER - HORIZONTAL_SCROLL_BAR_LEFT_BORDER)
+
/* Border widths for scroll bars.
#define VERTICAL_SCROLL_BAR_TOP_BORDER (2)
#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (2)
+#define HORIZONTAL_SCROLL_BAR_LEFT_BORDER (2)
+#define HORIZONTAL_SCROLL_BAR_RIGHT_BORDER (2)
+#define HORIZONTAL_SCROLL_BAR_TOP_BORDER (2)
+#define HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER (2)
+
/* Minimum lengths for scroll bar handles, in pixels. */
#define VERTICAL_SCROLL_BAR_MIN_HANDLE (5)
+#define HORIZONTAL_SCROLL_BAR_MIN_HANDLE (5)
/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT
or SELECTION_CLEAR_EVENT, then its contents are really described
extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
extern void x_wait_for_event (struct frame *, int);
+extern void x_clear_under_internal_border (struct frame *f);
/* Defined in xselect.c. */
extern Lisp_Object Qx_gtk_map_stock;
-#if !defined USE_X_TOOLKIT && !defined USE_GTK
-extern void x_clear_under_internal_border (struct frame *f);
-#endif
-
/* Is the frame embedded into another application? */
#define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT(f)->explicit_parent != 0)