From dbcabe7946592c0af550c31b9a47a9856fd2d501 Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Fri, 11 Sep 2015 17:13:43 +0800 Subject: Implement move/resize with keyboard * exwm-floating.el: Remove an invalid TODO item. * exwm-floating.el (exwm-floating--set-floating) (exwm-floating-hide-mode-line, exwm-floating-show-mode-line): Set window-size-fixed only for fixed-size floating windows. * exwm-floating.el (exwm-floating-move): New function for moving a floating window. * exwm-layout.el (exwm-layout-enlarge-window) (exwm-layout-enlarge-window-horizontally, exwm-layout-shrink-window) (exwm-layout-shrink-window-horizontally): New commands for interactively resizing a floating window. --- exwm-floating.el | 34 +++++++++++++++----- exwm-layout.el | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/exwm-floating.el b/exwm-floating.el index 4ea495d0d256..04493764bd0f 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -24,9 +24,6 @@ ;; This module deals with the conversion between floating and non-floating ;; states and implements moving/resizing operations on floating windows. -;; Todo: -;; + move/resize with keyboard. - ;;; Code: (require 'xcb-cursor) @@ -184,7 +181,7 @@ (xcb:flush exwm--connection) ;; Set window/buffer (with-current-buffer (exwm--id->buffer id) - (setq window-size-fixed t ;make frame fixed size + (setq window-size-fixed exwm--fixed-size exwm--frame original-frame exwm--floating-frame frame) (set-window-buffer window (current-buffer)) ;this changes current buffer @@ -242,8 +239,8 @@ Default to resize `exwm--floating-frame' unless FRAME-OUTER-ID is non-nil. This function will issue an `xcb:GetGeometry' request unless WIDTH and HEIGHT -are provided. You should call `xcb:flush' and assign `window-size-fixed' a -non-nil value afterwards." +are provided. You should call `xcb:flush' and restore the value of +`window-size-fixed' afterwards." (setq window-size-fixed nil) (unless (and width height) (let ((geometry (xcb:+request-unchecked+reply exwm--connection @@ -274,7 +271,7 @@ non-nil value afterwards." mode-line-format nil) (exwm-floating--fit-frame-to-window) (xcb:flush exwm--connection) - (setq window-size-fixed t))) + (setq window-size-fixed exwm--fixed-size))) (defun exwm-floating-show-mode-line () "Show mode-line of a floating frame." @@ -287,7 +284,7 @@ non-nil value afterwards." (exwm-floating--fit-frame-to-window) (exwm-input-grab-keyboard) ;mode-line-format may be outdated (xcb:flush exwm--connection) - (setq window-size-fixed t))) + (setq window-size-fixed exwm--fixed-size))) (defvar exwm-floating--moveresize-calculate nil "Calculate move/resize parameters [frame-id event-mask x y width height].") @@ -462,6 +459,27 @@ non-nil value afterwards." :width (elt result 4) :height (elt result 5))) (xcb:flush exwm--connection)))) +(defun exwm-floating-move (&optional delta-x delta-y) + "Move a floating window right by DELTA-X pixels and down by DELTA-Y pixels. + +Both DELTA-X and DELTA-Y default to 1. This command should be bound locally." + (unless (and (eq major-mode 'exwm-mode) exwm--floating-frame) + (user-error "[EXWM] `exwm-floating-move' is only for floating X windows")) + (unless delta-x (setq delta-x 1)) + (unless delta-y (setq delta-y 1)) + (unless (and (= 0 delta-x) (= 0 delta-y)) + (let* ((id (frame-parameter exwm--floating-frame 'exwm-outer-id)) + (geometry (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:GetGeometry :drawable id)))) + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window id + :value-mask (logior xcb:ConfigWindow:X + xcb:ConfigWindow:Y) + :x (+ (slot-value geometry 'x) delta-x) + :y (+ (slot-value geometry 'y) delta-y)))) + (xcb:flush exwm--connection))) + (defun exwm-floating--init () "Initialize floating module." ;; Initialize cursors for moving/resizing a window diff --git a/exwm-layout.el b/exwm-layout.el index ae1f48de8f86..27533a5ebd8a 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -263,6 +263,103 @@ exwm--floating-frame))) (exwm-layout--refresh))))) +(defun exwm-layout-enlarge-window (delta &optional horizontal) + "Make the selected window DELTA pixels taller. + +If no argument is given, make the selected window one pixel taller. If the +optional argument HORIZONTAL is non-nil, make selected window DELTA pixels +wider. If DELTA is negative, shrink selected window by -DELTA pixels. + +Normal hints are checked and regarded if the selected window is displaying an +`exwm-mode' buffer. However, this may violate the normal hints set on other X +windows." + (interactive "p") + (cond + ((zerop delta)) ;no operation + ((window-minibuffer-p)) ;avoid resize minibuffer-window + ((not (and (eq major-mode 'exwm-mode) exwm--floating-frame)) + ;; Resize on tiling layout + (unless (= 0 (window-resizable nil delta horizontal nil t)) ;not resizable + (let ((window-resize-pixelwise t)) + (window-resize nil delta horizontal nil t)))) + ;; Resize on floating layout + (exwm--fixed-size) ;fixed size + (horizontal + (let* ((width (frame-pixel-width)) + (edges (window-inside-pixel-edges)) + (inner-width (- (elt edges 2) (elt edges 0))) + (margin (- width inner-width))) + (if (> delta 0) + (if (not exwm--normal-hints-max-width) + (cl-incf width delta) + (if (>= inner-width exwm--normal-hints-max-width) + (setq width nil) + (setq width (min (+ exwm--normal-hints-max-width margin) + (+ width delta))))) + (if (not exwm--normal-hints-min-width) + (cl-incf width delta) + (if (<= inner-width exwm--normal-hints-min-width) + (setq width nil) + (setq width (max (+ exwm--normal-hints-min-width margin) + (+ width delta)))))) + (when width + (setq exwm--floating-edges nil) ;invalid from now on + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window (frame-parameter exwm--floating-frame + 'exwm-outer-id) + :value-mask xcb:ConfigWindow:Width + :width width)) + (xcb:flush exwm--connection)))) + (t + (let* ((height (frame-pixel-height)) + (edges (window-inside-pixel-edges)) + (inner-height (- (elt edges 3) (elt edges 1))) + (margin (- height inner-height))) + (if (> delta 0) + (if (not exwm--normal-hints-max-height) + (cl-incf height delta) + (if (>= inner-height exwm--normal-hints-max-height) + (setq height nil) + (setq height (min (+ exwm--normal-hints-max-height margin) + (+ height delta))))) + (if (not exwm--normal-hints-min-height) + (cl-incf height delta) + (if (<= inner-height exwm--normal-hints-min-height) + (setq height nil) + (setq height (max (+ exwm--normal-hints-min-height margin) + (+ height delta)))))) + (when height + (setq exwm--floating-edges nil) ;invalid from now on + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window (frame-parameter exwm--floating-frame + 'exwm-outer-id) + :value-mask xcb:ConfigWindow:Height + :height height)) + (xcb:flush exwm--connection)))))) + +(defun exwm-layout-enlarge-window-horizontally (delta) + "Make the selected window DELTA pixels wider. + +See also `exwm-layout-enlarge-window'." + (interactive "p") + (exwm-layout-enlarge-window delta t)) + +(defun exwm-layout-shrink-window (delta) + "Make the selected window DELTA pixels lower. + +See also `exwm-layout-enlarge-window'." + (interactive "p") + (exwm-layout-enlarge-window (- delta))) + +(defun exwm-layout-shrink-window-horizontally (delta) + "Make the selected window DELTA pixels narrower. + +See also `exwm-layout-enlarge-window'." + (interactive "p") + (exwm-layout-enlarge-window (- delta) t)) + (defun exwm-layout--init () "Initialize layout module." ;; Auto refresh layout -- cgit 1.4.1