From 94bdbfc0da7c8ef14acdc8aa4e73dc1c8fee9700 Mon Sep 17 00:00:00 2001 From: Philip Date: Mon, 24 Aug 2015 19:09:42 +0000 Subject: [PATCH] Avoid using the "no window manager" code in Emacs * exwm.el (exwm--on-ClientMessage): Handle fullscreen requests for frames. (exwm-init): Initialize workspaces after unlocking events. * exwm-workspace.el (exwm-workspace--init): Create frames as invisible, then make them visible only once their OverrideRedirect property has been set. * exwm-randr.el (exwm-randr--refresh): New frame parameter `exwm-geometry'. * exwm-layout.el (exwm-layout--set-frame-fullscreen): New function. The Emacs code is buggy, see https://github.com/ch11ng/exwm/issues/39 https://github.com/ch11ng/exwm/pull/42 --- exwm-layout.el | 28 ++++++++++++++++++++++++++++ exwm-randr.el | 6 ++++++ exwm-workspace.el | 14 ++++++++++---- exwm.el | 18 ++++++++++++++++-- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/exwm-layout.el b/exwm-layout.el index 1ffb3b9..735b156 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -162,6 +162,34 @@ (setq exwm--fullscreen nil) (exwm-input-grab-keyboard))) +;; This function is superficially similar to `exwm-layout-set-fullscreen', but +;; they do very different things: `exwm-layout--set-frame-fullscreen' resizes a +;; frame to the actual monitor size, `exwm-layout-set-fullscreen' resizes an X +;; window to the frame size. +(defun exwm-layout--set-frame-fullscreen (frame) + "Make frame FRAME fullscreen, with regard to its XRandR output if applicable." + (let ((geometry (or (frame-parameter frame 'exwm-geometry) + (xcb:+request-unchecked+reply + exwm--connection + (make-instance 'xcb:GetGeometry + :drawable exwm--root)) + (make-instance 'xcb:RECTANGLE :x 0 :y 0 + :width (x-display-width) + :height (x-display-height)))) + (id (frame-parameter frame 'exwm-outer-id))) + (with-slots (x y width height) geometry + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window id + :value-mask (logior xcb:ConfigWindow:X + xcb:ConfigWindow:Y + xcb:ConfigWindow:Width + xcb:ConfigWindow:Height) + :x x :y y + :width width + :height height)) + (xcb:flush exwm--connection)))) + (defun exwm-layout--refresh () "Refresh layout." (let ((frame (selected-frame)) diff --git a/exwm-randr.el b/exwm-randr.el index cd40fb4..6bddb00 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -85,6 +85,12 @@ (setq geometry default-geometry output nil)) (set-frame-parameter frame 'exwm-randr-output output) + (set-frame-parameter frame 'exwm-geometry + (make-instance 'xcb:RECTANGLE + :x (elt geometry 0) + :y (elt geometry 1) + :width (elt geometry 2) + :height (elt geometry 3))) (set-frame-parameter frame 'exwm-x (elt geometry 0)) (set-frame-parameter frame 'exwm-y (elt geometry 1)) (xcb:+request exwm--connection diff --git a/exwm-workspace.el b/exwm-workspace.el index 7ac1fec..8e3839f 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -231,13 +231,11 @@ The optional FORCE option is for internal use only." (unless (frame-parameter i 'window-id) (setq exwm-workspace--list (delq i exwm-workspace--list))))) (cl-assert (= 1 (length exwm-workspace--list))) - (exwm--make-emacs-idle-for 0.1) ;wait for the frame ready - ;; Configure the existing frame - (set-frame-parameter (car exwm-workspace--list) 'fullscreen 'fullboth) ;; Create remaining frames (dotimes (i (1- exwm-workspace-number)) (nconc exwm-workspace--list - (list (make-frame '((window-system . x) (fullscreen . fullboth)))))) + (list (make-frame '((window-system . x) + (visibility . nil)))))) ;; Configure workspaces (dolist (i exwm-workspace--list) (let ((window-id (string-to-int (frame-parameter i 'window-id))) @@ -256,6 +254,14 @@ The optional FORCE option is for internal use only." :window window-id :value-mask xcb:CW:EventMask :event-mask xcb:EventMask:SubstructureRedirect)))) (xcb:flush exwm--connection) + ;; We have to delay making the frame visible until the + ;; override-redirect flag has been set. + (select-frame-set-input-focus (car exwm-workspace--list)) + (dolist (i exwm-workspace--list) + (set-frame-parameter i 'visibility t) + (lower-frame i) + (set-frame-parameter i 'fullscreen 'fullboth)) + (raise-frame (car exwm-workspace--list)) ;; Handle unexpected frame switch (add-hook 'focus-in-hook 'exwm-workspace--on-focus-in) ;; Switch to the first workspace diff --git a/exwm.el b/exwm.el index 7dffa87..a52e114 100644 --- a/exwm.el +++ b/exwm.el @@ -441,6 +441,20 @@ (props (list (elt data 1) (elt data 2))) (buffer (exwm--id->buffer id)) props-new) + ;; only support _NET_WM_STATE_FULLSCREEN / _NET_WM_STATE_ADD for frames + (when (and (not buffer) + (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN props) + (= action xcb:ewmh:_NET_WM_STATE_ADD)) + (dolist (f exwm-workspace--list) + (when (equal (frame-parameter f 'exwm-outer-id) id) + (exwm-layout--set-frame-fullscreen f) + (xcb:+request + exwm--connection + (make-instance 'xcb:ewmh:set-_NET_WM_STATE + :window id + :data (vector + xcb:Atom:_NET_WM_STATE_FULLSCREEN))) + (xcb:flush exwm--connection)))) (when buffer ;ensure it's managed (with-current-buffer buffer ;; _NET_WM_STATE_MODAL @@ -609,14 +623,14 @@ ;; (xcb:icccm:init exwm--connection) (xcb:ewmh:init exwm--connection) (exwm--lock) - (exwm-workspace--init) (exwm--init-icccm-ewmh) (exwm-layout--init) (exwm-floating--init) (exwm-manage--init) (exwm-input--init) (exwm--unlock) - ;; Manage exiting windows + (exwm-workspace--init) + ;; Manage existing windows (exwm-manage--scan) (run-hooks 'exwm-init-hook)))))