about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Feng <chris.w.feng@gmail.com>2015-09-11T09·13+0800
committerChris Feng <chris.w.feng@gmail.com>2015-09-11T09·16+0800
commitdbcabe7946592c0af550c31b9a47a9856fd2d501 (patch)
treec646efe48c75f13158b715ffa880ab53a0e2bb6e
parent1d435157d3c9b3f807aca55bb4e6d16d5cb6c5df (diff)
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.
-rw-r--r--exwm-floating.el34
-rw-r--r--exwm-layout.el97
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