Allow moving/resizing undecorated X windows

* exwm-manage.el (exwm-manage--manage-window): Do not manage
undecorated floating X windows (set in _MOTIF_WM_HINTS).

* exwm-floating.el (exwm-floating--start-moveresize)
(exwm-floating--stop-moveresize, exwm-floating--do-moveresize):
Allow moving/resizing undecorated X windows with _NET_WM_MOVERESIZE
client message.
This commit is contained in:
Chris Feng 2016-03-04 19:11:10 +08:00
parent fe9be0b3ef
commit 8706e490fb
2 changed files with 91 additions and 68 deletions

View file

@ -310,18 +310,23 @@
(defun exwm-floating--start-moveresize (id &optional type) (defun exwm-floating--start-moveresize (id &optional type)
"Start move/resize." "Start move/resize."
(let ((buffer (exwm--id->buffer id)) (let ((buffer-or-id (or (exwm--id->buffer id) id))
frame container x y width height cursor) frame container-or-id x y width height cursor)
(when (and buffer (if (bufferp buffer-or-id)
(with-current-buffer buffer ;; Managed.
(setq frame exwm--floating-frame (with-current-buffer buffer-or-id
container exwm--container)) (setq frame exwm--floating-frame
container-or-id exwm--container))
;; Unmanaged.
(setq container-or-id id))
(when (and container-or-id
;; Test if the pointer can be grabbed ;; Test if the pointer can be grabbed
(= xcb:GrabStatus:Success (= xcb:GrabStatus:Success
(slot-value (slot-value
(xcb:+request-unchecked+reply exwm--connection (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:GrabPointer (make-instance 'xcb:GrabPointer
:owner-events 0 :grab-window container :owner-events 0
:grab-window container-or-id
:event-mask xcb:EventMask:NoEvent :event-mask xcb:EventMask:NoEvent
:pointer-mode xcb:GrabMode:Async :pointer-mode xcb:GrabMode:Async
:keyboard-mode xcb:GrabMode:Async :keyboard-mode xcb:GrabMode:Async
@ -332,33 +337,43 @@
(with-slots (root-x root-y win-x win-y) (with-slots (root-x root-y win-x win-y)
(xcb:+request-unchecked+reply exwm--connection (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:QueryPointer :window id)) (make-instance 'xcb:QueryPointer :window id))
(select-window (frame-first-window frame)) ;transfer input focus (if (not (bufferp buffer-or-id))
(setq width (frame-pixel-width frame) ;; Unmanaged.
height (frame-pixel-height frame)) (unless (eq type xcb:ewmh:_NET_WM_MOVERESIZE_MOVE)
(unless type (with-slots ((width* width)
;; Determine the resize type according to the pointer position (height* height))
;; Clicking the center 1/3 part to resize has not effect (xcb:+request-unchecked+reply exwm--connection
(setq x (/ (* 3 win-x) (float width)) (make-instance 'xcb:GetGeometry :drawable id))
y (/ (* 3 win-y) (float height)) (setq width width*
type (cond ((and (< x 1) (< y 1)) height height*)))
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOPLEFT) ;; Managed.
((and (> x 2) (< y 1)) (select-window (frame-first-window frame)) ;transfer input focus
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOPRIGHT) (setq width (frame-pixel-width frame)
((and (> x 2) (> y 2)) height (frame-pixel-height frame))
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT) (unless type
((and (< x 1) (> y 2)) ;; Determine the resize type according to the pointer position
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT) ;; Clicking the center 1/3 part to resize has not effect
((< y 1) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOP) (setq x (/ (* 3 win-x) (float width))
((> x 2) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_RIGHT) y (/ (* 3 win-y) (float height))
((> y 2) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOM) type (cond ((and (< x 1) (< y 1))
((< x 1) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_LEFT)))) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOPLEFT)
((and (> x 2) (< y 1))
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOPRIGHT)
((and (> x 2) (> y 2))
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)
((and (< x 1) (> y 2))
xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)
((> x 2) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_RIGHT)
((> y 2) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOM)
((< x 1) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_LEFT)
((< y 1) xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_TOP)))))
(if (not type) (if (not type)
(exwm-floating--stop-moveresize) (exwm-floating--stop-moveresize)
(cond ((= type xcb:ewmh:_NET_WM_MOVERESIZE_MOVE) (cond ((= type xcb:ewmh:_NET_WM_MOVERESIZE_MOVE)
(setq cursor exwm-floating--cursor-move (setq cursor exwm-floating--cursor-move
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:X (logior xcb:ConfigWindow:X
xcb:ConfigWindow:Y)) xcb:ConfigWindow:Y))
@ -367,7 +382,7 @@
(setq cursor exwm-floating--cursor-top-left (setq cursor exwm-floating--cursor-top-left
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:X (logior xcb:ConfigWindow:X
xcb:ConfigWindow:Y xcb:ConfigWindow:Y
@ -380,7 +395,7 @@
(setq cursor exwm-floating--cursor-top (setq cursor exwm-floating--cursor-top
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:Y (logior xcb:ConfigWindow:Y
xcb:ConfigWindow:Height)) xcb:ConfigWindow:Height))
@ -389,7 +404,7 @@
(setq cursor exwm-floating--cursor-top-right (setq cursor exwm-floating--cursor-top-right
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:Y (logior xcb:ConfigWindow:Y
xcb:ConfigWindow:Width xcb:ConfigWindow:Width
@ -400,13 +415,14 @@
(setq cursor exwm-floating--cursor-right (setq cursor exwm-floating--cursor-right
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer ,xcb:ConfigWindow:Width (vector ,buffer-or-id
,xcb:ConfigWindow:Width
0 0 (- x ,(- root-x width)) 0)))) 0 0 (- x ,(- root-x width)) 0))))
((= type xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT) ((= type xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)
(setq cursor exwm-floating--cursor-bottom-right (setq cursor exwm-floating--cursor-bottom-right
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:Width (logior xcb:ConfigWindow:Width
xcb:ConfigWindow:Height)) xcb:ConfigWindow:Height))
@ -416,14 +432,14 @@
(setq cursor exwm-floating--cursor-bottom (setq cursor exwm-floating--cursor-bottom
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,xcb:ConfigWindow:Height ,xcb:ConfigWindow:Height
0 0 0 (- y ,(- root-y height)))))) 0 0 0 (- y ,(- root-y height))))))
((= type xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT) ((= type xcb:ewmh:_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)
(setq cursor exwm-floating--cursor-bottom-left (setq cursor exwm-floating--cursor-bottom-left
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:X (logior xcb:ConfigWindow:X
xcb:ConfigWindow:Width xcb:ConfigWindow:Width
@ -436,7 +452,7 @@
(setq cursor exwm-floating--cursor-left (setq cursor exwm-floating--cursor-left
exwm-floating--moveresize-calculate exwm-floating--moveresize-calculate
`(lambda (x y) `(lambda (x y)
(vector ,buffer (vector ,buffer-or-id
,(eval-when-compile ,(eval-when-compile
(logior xcb:ConfigWindow:X (logior xcb:ConfigWindow:X
xcb:ConfigWindow:Width)) xcb:ConfigWindow:Width))
@ -444,7 +460,7 @@
;; Select events and change cursor (should always succeed) ;; Select events and change cursor (should always succeed)
(xcb:+request-unchecked+reply exwm--connection (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:GrabPointer (make-instance 'xcb:GrabPointer
:owner-events 0 :grab-window container :owner-events 0 :grab-window container-or-id
:event-mask (eval-when-compile :event-mask (eval-when-compile
(logior xcb:EventMask:ButtonRelease (logior xcb:EventMask:ButtonRelease
xcb:EventMask:ButtonMotion)) xcb:EventMask:ButtonMotion))
@ -459,7 +475,9 @@
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:UngrabPointer :time xcb:Time:CurrentTime)) (make-instance 'xcb:UngrabPointer :time xcb:Time:CurrentTime))
;; Inform the X window that its absolute position is changed ;; Inform the X window that its absolute position is changed
(when exwm-floating--moveresize-calculate (when (and exwm-floating--moveresize-calculate
;; Unmanaged.
(eq major-mode 'exwm-mode))
(let ((edges (window-inside-absolute-pixel-edges (frame-selected-window))) (let ((edges (window-inside-absolute-pixel-edges (frame-selected-window)))
(id (with-current-buffer (window-buffer (frame-selected-window)) (id (with-current-buffer (window-buffer (frame-selected-window))
exwm--id))) exwm--id)))
@ -490,7 +508,7 @@
(geometry (frame-parameter exwm-workspace--current 'exwm-geometry)) (geometry (frame-parameter exwm-workspace--current 'exwm-geometry))
(frame-x 0) (frame-x 0)
(frame-y 0) (frame-y 0)
result value-mask width height) result value-mask width height buffer-or-id container-or-id)
(when geometry (when geometry
(setq frame-x (slot-value geometry 'x) (setq frame-x (slot-value geometry 'x)
frame-y (slot-value geometry 'y))) frame-y (slot-value geometry 'y)))
@ -503,30 +521,38 @@
xcb:ConfigWindow:Height))) xcb:ConfigWindow:Height)))
width (aref result 4) width (aref result 4)
height (aref result 5)) height (aref result 5))
(with-current-buffer (aref result 0) (setq buffer-or-id (aref result 0))
(xcb:+request exwm--connection (setq container-or-id
(make-instance 'xcb:ConfigureWindow (if (bufferp buffer-or-id)
:window exwm--container ;; Managed.
:value-mask (logand (aref result 1) (with-current-buffer buffer-or-id exwm--container)
(eval-when-compile ;; Unmanaged.
(logior xcb:ConfigWindow:X buffer-or-id))
xcb:ConfigWindow:Y))) (xcb:+request exwm--connection
:x (- (aref result 2) frame-x) (make-instance 'xcb:ConfigureWindow
:y (- (aref result 3) frame-y))) :window container-or-id
(xcb:+request exwm--connection :value-mask (aref result 1)
(make-instance 'xcb:ConfigureWindow :x (- (aref result 2) frame-x)
:window (frame-parameter exwm--floating-frame :y (- (aref result 3) frame-y)
'exwm-container) :width width
:value-mask value-mask :height height))
:width width (when (bufferp buffer-or-id)
:height height)) ;; Managed.
(xcb:+request exwm--connection (with-current-buffer buffer-or-id
(make-instance 'xcb:ConfigureWindow (xcb:+request exwm--connection
:window (frame-parameter exwm--floating-frame (make-instance 'xcb:ConfigureWindow
'exwm-outer-id) :window (frame-parameter exwm--floating-frame
:value-mask value-mask 'exwm-container)
:width width :value-mask value-mask
:height height))) :width width
:height height))
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--floating-frame
'exwm-outer-id)
:value-mask value-mask
:width width
:height height))))
(xcb:flush exwm--connection)))) (xcb:flush exwm--connection))))
(defun exwm-floating-move (&optional delta-x delta-y) (defun exwm-floating-move (&optional delta-x delta-y)

View file

@ -99,15 +99,12 @@ corresponding buffer.")
(memq xcb:Atom:_NET_WM_WINDOW_TYPE_UTILITY exwm-window-type) (memq xcb:Atom:_NET_WM_WINDOW_TYPE_UTILITY exwm-window-type)
(memq xcb:Atom:_NET_WM_WINDOW_TYPE_DIALOG exwm-window-type) (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DIALOG exwm-window-type)
(memq xcb:Atom:_NET_WM_WINDOW_TYPE_NORMAL exwm-window-type))) (memq xcb:Atom:_NET_WM_WINDOW_TYPE_NORMAL exwm-window-type)))
;; Check _MOTIF_WM_HINTS for Java applications ;; Check the _MOTIF_WM_HINTS property.
;; See <Xm/MwmUtil.h> for the definitions of these fields
(and exwm--mwm-hints (and exwm--mwm-hints
exwm-instance-name ;; See <Xm/MwmUtil.h> for fields definitions.
(/= 0 (logand (elt exwm--mwm-hints 0) ;MotifWmHints.flags (/= 0 (logand (elt exwm--mwm-hints 0) ;MotifWmHints.flags
2)) ;MWM_HINTS_DECORATIONS 2)) ;MWM_HINTS_DECORATIONS
(= 0 (elt exwm--mwm-hints 2)) ;MotifWmHints.decorations (= 0 (elt exwm--mwm-hints 2)) ;MotifWmHints.decorations
;; Java applications only
(string-prefix-p "sun-awt-X11-" exwm-instance-name)
;; Floating windows only ;; Floating windows only
(or exwm-transient-for exwm--fixed-size (or exwm-transient-for exwm--fixed-size
(memq xcb:Atom:_NET_WM_WINDOW_TYPE_UTILITY (memq xcb:Atom:_NET_WM_WINDOW_TYPE_UTILITY