summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Rudalics <rudalics@gmx.at>2015-07-02 09:03:45 +0200
committerMartin Rudalics <rudalics@gmx.at>2015-07-02 09:03:45 +0200
commit0245cc374015a67f5c17fec1342c8a35cbd41779 (patch)
tree951ee475718a5c39b918fa280713052876f89da0
parentbb35a21c0e8a4b82ac04fa26a53f6ca394afbb24 (diff)
downloademacs-0245cc374015a67f5c17fec1342c8a35cbd41779.tar.gz
Improve accessibility of window dividers. (Bug#20183)
* lisp/faces.el (window-divider) (window-divider-first-pixel, window-divider-last-pixel): Change membership from `frames' to `window-divider' customization group. * lisp/frame.el (window-divider): New customization group. (window-divider-mode): New minor mode. (window-divider-default-bottom-width) (window-divider-default-right-width): New options. (frame--window-divider-previous-mode): New variable. (frame-window-divider-width-valid-p) (frame--window-divider-mode-apply) (frame--window-divider-mode-set-and-apply): New functions. * lisp/menu-bar.el (menu-bar-options-save): Save window-divider-mode settings. (menu-bar-window-divider-customize) (menu-bar-bottom-and-right-window-divider) (menu-bar-right-window-divider, menu-bar-bottom-window-divider) (menu-bar-no-window-divider): New functions. (menu-bar-showhide-window-divider-menu): New variable. (menu-bar-showhide-menu): Show/hide window divider menu. * lisp/mouse.el (mouse-split-window-vertically) (mouse-split-window-horizontally): Replace `error' by `user-error'. Bind `window-combination-resize' to nil. (top-level): Add/reorder mouse key bindings on mode- and vertical-line.
-rw-r--r--lisp/faces.el6
-rw-r--r--lisp/frame.el128
-rw-r--r--lisp/menu-bar.el92
-rw-r--r--lisp/mouse.el33
4 files changed, 244 insertions, 15 deletions
diff --git a/lisp/faces.el b/lisp/faces.el
index 9857a7bd4de..511b3541265 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2506,7 +2506,7 @@ is used for the inner part while the first pixel line/column is
drawn with the `window-divider-first-pixel' face and the last
pixel line/column with the `window-divider-last-pixel' face."
:version "24.4"
- :group 'frames
+ :group 'window-divider
:group 'basic-faces)
(defface window-divider-first-pixel
@@ -2517,7 +2517,7 @@ line/column is drawn with the foreground of this face. If you do
not want to accentuate the first pixel line/column, set this to
the same as `window-divider' face."
:version "24.4"
- :group 'frames
+ :group 'window-divider
:group 'basic-faces)
(defface window-divider-last-pixel
@@ -2528,7 +2528,7 @@ line/column is drawn with the foreground of this face. If you do
not want to accentuate the last pixel line/column, set this to
the same as `window-divider' face."
:version "24.4"
- :group 'frames
+ :group 'window-divider
:group 'basic-faces)
(defface minibuffer-prompt
diff --git a/lisp/frame.el b/lisp/frame.el
index 077687eeb66..ffa01b4dcc1 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1749,6 +1749,134 @@ left untouched. FRAME nil or omitted means use the selected frame."
'delete-frame-functions "22.1")
+;;; Window dividers.
+(defgroup window-divider nil
+ "Window dividers."
+ :version "25.1"
+ :group 'frames
+ :group 'windows)
+
+(defvar frame--window-divider-previous-mode nil
+ "Previous value of `window-divider-mode'.
+This is the value seen when `window-divider-mode' was switched
+off the last time. It's reused when `window-divider-mode' is
+switched on again.")
+
+(defcustom window-divider-mode nil
+ "Specify whether to display window dividers and where.
+Possible values are nil (no dividers), `bottom-only' (dividers on
+the bottom of each window only), `right-only' (dividers on the
+right of each window only), and t (dividers on the bottom and on
+the right of each window)."
+ :type '(choice (const :tag "None (nil)" nil)
+ (const :tag "Bottom only" bottom-only)
+ (const :tag "Right only" right-only)
+ (const :tag "Bottom and right" t))
+ :initialize 'custom-initialize-default
+ :set (lambda (_symbol value)
+ (frame--window-divider-mode-set-and-apply value))
+ :group 'window-divider
+ :version "25.1")
+
+(define-minor-mode window-divider-mode
+ "Display dividers between windows (Window Divider mode).
+With a prefix argument ARG, enable Window Divider mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+The option `window-divider-default-width' allows to customize the
+width of dividers displayed by this mode."
+ :group 'window-divider
+ :global t
+ :variable (window-divider-mode
+ . (lambda (value)
+ (frame--window-divider-mode-set-and-apply
+ (and value
+ (or frame--window-divider-previous-mode
+ (default-value 'window-divider-mode)
+ 'right-only))))))
+
+(defun frame-window-divider-width-valid-p (value)
+ "Return non-nil if VALUE is a positive number."
+ (and (numberp value) (> value 0)))
+
+(defcustom window-divider-default-bottom-width 6
+ "Default width of dividers on bottom of windows.
+The value must be a positive integer and takes effect when bottom
+dividers are displayed by `window-divider-mode'.
+
+To adjust bottom dividers for frames individually, use the frame
+parameter `bottom-divider-width'."
+ :type '(restricted-sexp
+ :tag "Default bottom divider width"
+ :match-alternatives (frame-window-divider-width-valid-p))
+ :group 'window-divider
+ :initialize 'custom-initialize-default
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (when window-divider-mode
+ (frame--window-divider-mode-apply)))
+ :version "25.1")
+
+(defcustom window-divider-default-right-width 6
+ "Default width of dividers on the right of windows.
+The value must be a positive integer and takes effect when right
+dividers are displayed by `window-divider-mode'.
+
+To adjust right dividers for frames individually, use the frame
+parameter `right-divider-width'."
+ :type '(restricted-sexp
+ :tag "Default right divider width"
+ :match-alternatives (frame-window-divider-width-valid-p))
+ :group 'window-divider
+ :initialize 'custom-initialize-default
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (when window-divider-mode
+ (frame--window-divider-mode-apply)))
+ :version "25.1")
+
+(defun frame--window-divider-mode-apply ()
+ "Apply window divider widths."
+ (let ((bottom (if (memq window-divider-mode '(bottom-only t))
+ window-divider-default-bottom-width
+ 0))
+ (right (if (memq window-divider-mode '(right-only t))
+ window-divider-default-right-width
+ 0)))
+ (modify-all-frames-parameters
+ (list (cons 'bottom-divider-width bottom)
+ (cons 'right-divider-width right)))
+ (setq default-frame-alist
+ (assq-delete-all
+ 'bottom-divider-width default-frame-alist))
+ (setq default-frame-alist
+ (assq-delete-all
+ 'right-divider-width default-frame-alist))
+ (when (> bottom 0)
+ (setq default-frame-alist
+ (cons
+ (cons 'bottom-divider-width bottom)
+ default-frame-alist)))
+ (when (> right 0)
+ (setq default-frame-alist
+ (cons
+ (cons 'right-divider-width right)
+ default-frame-alist)))))
+
+(defun frame--window-divider-mode-set-and-apply (value)
+ "Set window divider mode to VALUE and apply widths."
+ (unless value
+ ;; Remember current mode.
+ (setq frame--window-divider-previous-mode window-divider-mode))
+ (set-default 'window-divider-mode value)
+ ;; Pacify customize rigmarole.
+ (put 'window-divider-mode 'customized-value
+ (if (memq value '(nil t))
+ (list value)
+ (list (list 'quote value))))
+ (frame--window-divider-mode-apply))
+
;; Blinking cursor
(defgroup cursor nil
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 22a0b8faaba..5a69084f98d 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -683,7 +683,7 @@ by \"Save Options\" in Custom buffers.")
(dolist (elt '(scroll-bar-mode
debug-on-quit debug-on-error
;; Somehow this works, when tool-bar and menu-bar don't.
- tooltip-mode
+ tooltip-mode window-divider-mode
save-place uniquify-buffer-name-style fringe-mode
indicate-empty-lines indicate-buffer-boundaries
case-fold-search font-use-system-font
@@ -711,6 +711,92 @@ by \"Save Options\" in Custom buffers.")
;; The "Show/Hide" submenu of menu "Options"
+(defun menu-bar-window-divider-customize ()
+ "Show customization buffer for `window-divider' group."
+ (interactive)
+ (customize-group 'window-divider))
+
+(defun menu-bar-bottom-and-right-window-divider ()
+ "Display dividers on the bottom and right of each window."
+ (interactive)
+ (customize-set-variable 'window-divider-mode t))
+
+(defun menu-bar-right-window-divider ()
+ "Display dividers only on the right of each window."
+ (interactive)
+ (customize-set-variable 'window-divider-mode 'right-only))
+
+(defun menu-bar-bottom-window-divider ()
+ "Display dividers only at the bottom of each window."
+ (interactive)
+ (customize-set-variable 'window-divider-mode 'bottom-only))
+
+(defun menu-bar-no-window-divider ()
+ "Do not display window dividers."
+ (interactive)
+ (customize-set-variable 'window-divider-mode nil))
+
+;; For the radio buttons below we check whether the respective dividers
+;; are displayed on the selected frame. This is not fully congruent
+;; with `window-divder-mode' but makes the menu entries work also when
+;; dividers are displayed by manipulating frame parameters directly.
+(defvar menu-bar-showhide-window-divider-menu
+ (let ((menu (make-sparse-keymap "Window Divider")))
+ (bindings--define-key menu [customize]
+ '(menu-item "Customize" menu-bar-window-divider-customize
+ :help "Customize window dividers"
+ :visible (memq (window-system) '(x w32))))
+
+ (bindings--define-key menu [bottom-and-right]
+ '(menu-item "Bottom and Right"
+ menu-bar-bottom-and-right-window-divider
+ :help "Display window divider on the bottom and right of each window"
+ :visible (memq (window-system) '(x w32))
+ :button (:radio
+ . (and (frame-window-divider-width-valid-p
+ (cdr (assq 'bottom-divider-width
+ (frame-parameters))))
+ (frame-window-divider-width-valid-p
+ (cdr (assq 'right-divider-width
+ (frame-parameters))))))))
+ (bindings--define-key menu [right-only]
+ '(menu-item "Right Only"
+ menu-bar-right-window-divider
+ :help "Display window divider on the right of each window only"
+ :visible (memq (window-system) '(x w32))
+ :button (:radio
+ . (and (not (frame-window-divider-width-valid-p
+ (cdr (assq 'bottom-divider-width
+ (frame-parameters)))))
+ (frame-window-divider-width-valid-p
+ (cdr (assq 'right-divider-width
+ (frame-parameters))))))))
+ (bindings--define-key menu [bottom-only]
+ '(menu-item "Bottom Only"
+ menu-bar-bottom-window-divider
+ :help "Display window divider on the bottom of each window only"
+ :visible (memq (window-system) '(x w32))
+ :button (:radio
+ . (and (frame-window-divider-width-valid-p
+ (cdr (assq 'bottom-divider-width
+ (frame-parameters))))
+ (not (frame-window-divider-width-valid-p
+ (cdr (assq 'right-divider-width
+ (frame-parameters)))))))))
+ (bindings--define-key menu [no-divider]
+ '(menu-item "None"
+ menu-bar-no-window-divider
+ :help "Do not display window dividers"
+ :visible (memq (window-system) '(x w32))
+ :button (:radio
+ . (and (not (frame-window-divider-width-valid-p
+ (cdr (assq 'bottom-divider-width
+ (frame-parameters)))))
+ (not (frame-window-divider-width-valid-p
+ (cdr (assq 'right-divider-width
+ (frame-parameters)))))))))
+ menu))
+
(defun menu-bar-showhide-fringe-ind-customize ()
"Show customization buffer for `indicate-buffer-boundaries'."
(interactive)
@@ -1072,6 +1158,10 @@ mail status in mode line"))
(frame-visible-p
(symbol-value 'speedbar-frame))))))
+ (bindings--define-key menu [showhide-window-divider]
+ `(menu-item "Window Divider" ,menu-bar-showhide-window-divider-menu
+ :visible (memq (window-system) '(x w32))))
+
(bindings--define-key menu [showhide-fringe]
`(menu-item "Fringe" ,menu-bar-showhide-fringe-menu
:visible (display-graphic-p)))
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 9bb00cb105e..221d30bc3d8 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -338,9 +338,12 @@ This command must be bound to a mouse click."
(first-line window-min-height)
(last-line (- (window-height) window-min-height)))
(if (< last-line first-line)
- (error "Window too short to split")
- (split-window-vertically
- (min (max new-height first-line) last-line))))))
+ (user-error "Window too short to split")
+ ;; Bind `window-combination-resize' to nil so we are sure to get
+ ;; the split right at the line clicked on.
+ (let (window-combination-resize)
+ (split-window-vertically
+ (min (max new-height first-line) last-line)))))))
(defun mouse-split-window-horizontally (click)
"Select Emacs window mouse is on, then split it horizontally in half.
@@ -354,9 +357,12 @@ This command must be bound to a mouse click."
(first-col window-min-width)
(last-col (- (window-width) window-min-width)))
(if (< last-col first-col)
- (error "Window too narrow to split")
- (split-window-horizontally
- (min (max new-width first-col) last-col))))))
+ (user-error "Window too narrow to split")
+ ;; Bind `window-combination-resize' to nil so we are sure to get
+ ;; the split right at the column clicked on.
+ (let (window-combination-resize)
+ (split-window-horizontally
+ (min (max new-width first-col) last-col)))))))
(defun mouse-drag-line (start-event line)
"Drag a mode line, header line, or vertical line with the mouse.
@@ -1915,20 +1921,25 @@ choose a font."
;; vertical-line prevents Emacs from signaling an error when the mouse
;; button is released after dragging these lines, on non-toolkit
;; versions.
-(global-set-key [mode-line mouse-1] 'mouse-select-window)
-(global-set-key [mode-line drag-mouse-1] 'mouse-select-window)
-(global-set-key [mode-line down-mouse-1] 'mouse-drag-mode-line)
(global-set-key [header-line down-mouse-1] 'mouse-drag-header-line)
(global-set-key [header-line mouse-1] 'mouse-select-window)
+;; (global-set-key [mode-line drag-mouse-1] 'mouse-select-window)
+(global-set-key [mode-line down-mouse-1] 'mouse-drag-mode-line)
+(global-set-key [mode-line mouse-1] 'mouse-select-window)
(global-set-key [mode-line mouse-2] 'mouse-delete-other-windows)
(global-set-key [mode-line mouse-3] 'mouse-delete-window)
(global-set-key [mode-line C-mouse-2] 'mouse-split-window-horizontally)
(global-set-key [vertical-scroll-bar C-mouse-2] 'mouse-split-window-vertically)
-(global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
+(global-set-key [horizontal-scroll-bar C-mouse-2] 'mouse-split-window-horizontally)
(global-set-key [vertical-line down-mouse-1] 'mouse-drag-vertical-line)
+(global-set-key [vertical-line mouse-1] 'mouse-select-window)
+(global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
(global-set-key [right-divider down-mouse-1] 'mouse-drag-vertical-line)
+(global-set-key [right-divider mouse-1] 'ignore)
+(global-set-key [right-divider C-mouse-2] 'mouse-split-window-vertically)
(global-set-key [bottom-divider down-mouse-1] 'mouse-drag-mode-line)
-(global-set-key [vertical-line mouse-1] 'mouse-select-window)
+(global-set-key [bottom-divider mouse-1] 'ignore)
+(global-set-key [bottom-divider C-mouse-2] 'mouse-split-window-horizontally)
(provide 'mouse)