[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/exwm 810b471 3/3: Update timestamp for WM_TAKE_FOCUS Cl
From: |
Chris Feng |
Subject: |
[elpa] externals/exwm 810b471 3/3: Update timestamp for WM_TAKE_FOCUS ClientMessage |
Date: |
Tue, 9 Aug 2016 05:49:18 +0000 (UTC) |
branch: externals/exwm
commit 810b4716a10169e1de29c52cf2e3aeb2e79f2018
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>
Update timestamp for WM_TAKE_FOCUS ClientMessage
* exwm-input.el (exwm-input--timestamp-window)
(exwm-input--timestamp-atom, exwm-input--timestamp-callback): New
variables for updating timestamp.
(exwm-input--set-focus): Send WM_TAKE_FOCUS ClientMessage with updated
timestamp.
(exwm-input--update-timestamp): New utility function for fetching
timestamp.
(exwm-input--on-PropertyNotify): New function for handling
PropertyNotify event to extract the timestamp.
(exwm-input--init): Create resources for updating timestamp; attach the
event listener.
(exwm-input--on-ButtonPress, exwm-input--on-KeyPress):
* exwm.el (exwm--on-PropertyNotify): No longer update timestamp.
* exwm-input.el (exwm-input--set-focus): Avoid setting input focus on
already focused X windows, or when the input focus in not on a Emacs
frame if globally active model is in use.
* exwm-floating.el (exwm-floating--set-floating):
* exwm-workspace.el (exwm-workspace-move-window)
(exwm-workspace--add-frame-as-workspace, exwm-workspace--init):
Set 'exwm-id' frame parameter as the numerical (inner) frame X ID.
---
exwm-floating.el | 5 ++-
exwm-input.el | 129 ++++++++++++++++++++++++++++++++++++++++-------------
exwm-workspace.el | 9 ++++
exwm.el | 3 +-
4 files changed, 112 insertions(+), 34 deletions(-)
diff --git a/exwm-floating.el b/exwm-floating.el
index 56d2932..7c5d811 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -99,7 +99,9 @@ context of the corresponding buffer.")
(height . ,window-min-height)
(unsplittable . t))))) ;and fix the size later
(outer-id (string-to-number (frame-parameter frame 'outer-window-id)))
- (container (buffer-local-value 'exwm--container (exwm--id->buffer
id)))
+ (window-id (string-to-number (frame-parameter frame 'window-id)))
+ (container (buffer-local-value 'exwm--container
+ (exwm--id->buffer id)))
(frame-container (xcb:generate-id exwm--connection))
(window (frame-first-window frame)) ;and it's the only window
(x (slot-value exwm--geometry 'x))
@@ -118,6 +120,7 @@ context of the corresponding buffer.")
width height x y)
;; Save frame parameters.
(set-frame-parameter frame 'exwm-outer-id outer-id)
+ (set-frame-parameter frame 'exwm-id window-id)
(set-frame-parameter frame 'exwm-container frame-container)
;; Fix illegal parameters
;; FIXME: check normal hints restrictions
diff --git a/exwm-input.el b/exwm-input.el
index 7506267..668e495 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -48,10 +48,9 @@
(defvar exwm-input--resize-keysym nil)
(defvar exwm-input--resize-mask nil)
-(defvar exwm-input--timestamp xcb:Time:CurrentTime
- "A recent timestamp received from X server.
-
-It's updated in several occasions, and only used by `exwm-input--set-focus'.")
+(defvar exwm-input--timestamp-window nil)
+(defvar exwm-input--timestamp-atom nil)
+(defvar exwm-input--timestamp-callback nil)
(defvar exwm-workspace--current)
(defvar exwm-workspace--switch-history-outdated)
@@ -62,37 +61,81 @@ It's updated in several occasions, and only used by
`exwm-input--set-focus'.")
(defun exwm-input--set-focus (id)
"Set input focus to window ID in a proper way."
(when (exwm--id->buffer id)
- (with-current-buffer (exwm--id->buffer id)
- (if (and (not exwm--hints-input)
- (memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))
- (progn
- (exwm--log "Focus on #x%x with WM_TAKE_FOCUS" id)
+ (let ((focus (slot-value (xcb:+request-unchecked+reply exwm--connection
+ (make-instance 'xcb:GetInputFocus))
+ 'focus)))
+ (unless (= focus id)
+ (with-current-buffer (exwm--id->buffer id)
+ (cond
+ ((and (not exwm--hints-input)
+ (memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))
+ (when (= focus (frame-parameter nil 'exwm-id))
+ (exwm--log "Focus on #x%x with WM_TAKE_FOCUS" id)
+ (exwm-input--update-timestamp
+ (lambda (timestamp id)
+ (let ((event (make-instance 'xcb:icccm:WM_TAKE_FOCUS
+ :window id
+ :time timestamp)))
+ (setq event (xcb:marshal event exwm--connection))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:icccm:SendEvent
+ :destination id
+ :event event))
+ (exwm-input--set-active-window id)
+ (xcb:flush exwm--connection)))
+ id)))
+ (t
+ (exwm--log "Focus on #x%x with SetInputFocus" id)
(xcb:+request exwm--connection
- (make-instance 'xcb:icccm:SendEvent
- :destination id
- :event (xcb:marshal
- (make-instance 'xcb:icccm:WM_TAKE_FOCUS
- :window id
- :time
- exwm-input--timestamp)
- exwm--connection))))
- (exwm--log "Focus on #x%x with SetInputFocus" id)
- (xcb:+request exwm--connection
- (make-instance 'xcb:SetInputFocus
- :revert-to xcb:InputFocus:Parent
- :focus id
- :time xcb:Time:CurrentTime)))
- (exwm-input--set-active-window id)
- (xcb:flush exwm--connection))))
+ (make-instance 'xcb:SetInputFocus
+ :revert-to xcb:InputFocus:Parent
+ :focus id
+ :time xcb:Time:CurrentTime))
+ (exwm-input--set-active-window id)
+ (xcb:flush exwm--connection))))))))
+
+(defun exwm-input--update-timestamp (callback &rest args)
+ "Fetch the latest timestamp from the server and feed it to CALLBACK.
+
+ARGS are additional arguments to CALLBACK."
+ (setq exwm-input--timestamp-callback (cons callback args))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:ChangeProperty
+ :mode xcb:PropMode:Replace
+ :window exwm-input--timestamp-window
+ :property exwm-input--timestamp-atom
+ :type xcb:Atom:CARDINAL
+ :format 32
+ :data-len 0
+ :data nil))
+ (xcb:flush exwm--connection))
+
+(defun exwm-input--on-PropertyNotify (data _synthetic)
+ "Handle PropertyNotify events."
+ (when exwm-input--timestamp-callback
+ (let ((obj (make-instance 'xcb:PropertyNotify)))
+ (xcb:unmarshal obj data)
+ (when (= exwm-input--timestamp-window
+ (slot-value obj 'window))
+ (apply (car exwm-input--timestamp-callback)
+ (slot-value obj 'time)
+ (cdr exwm-input--timestamp-callback))
+ (setq exwm-input--timestamp-callback nil)))))
(defun exwm-input--on-FocusIn (data _synthetic)
"Handle FocusIn events."
(let ((obj (make-instance 'xcb:FocusIn)))
(xcb:unmarshal obj data)
- (when (= (slot-value obj 'detail) xcb:NotifyDetail:Inferior)
- ;; Transfer input focus back to the workspace when the workspace
- ;; container unexpectedly receives it.
- (x-focus-frame exwm-workspace--current))))
+ ;; Not sure if this is the right thing to do but the point is the
+ ;; input focus should not stay at the root window or any container,
+ ;; or the result would be unpredictable. `x-focus-frame' would
+ ;; first set the input focus to the (previously) selected frame, and
+ ;; then `select-window' would further update the input focus if the
+ ;; selected window is displaying an `exwm-mode' buffer. Perhaps we
+ ;; should carefully filter out FocusIn events with certain 'detail'
+ ;; and 'mode' combinations, but this just works.
+ (x-focus-frame (selected-frame))
+ (select-window (selected-window))))
(defun exwm-input--on-workspace-list-change ()
"Run in `exwm-input--update-global-prefix-keys'."
@@ -247,7 +290,6 @@ This value should always be overwritten.")
window buffer frame)
(xcb:unmarshal obj data)
(with-slots (detail time event state) obj
- (setq exwm-input--timestamp time)
(setq window (get-buffer-window (exwm--id->buffer event) t)
buffer (window-buffer window))
(cond ((and (= state exwm-input--move-mask)
@@ -296,7 +338,6 @@ This value should always be overwritten.")
"Handle KeyPress event."
(let ((obj (make-instance 'xcb:KeyPress)))
(xcb:unmarshal obj data)
- (setq exwm-input--timestamp (slot-value obj 'time))
(if (eq major-mode 'exwm-mode)
(funcall exwm--on-KeyPress obj data)
(exwm-input--on-KeyPress-char-mode obj))))
@@ -657,7 +698,33 @@ Its usage is the same with
`exwm-input-set-simulation-keys'."
exwm-input--move-mask (cdr move-key)
exwm-input--resize-keysym (car resize-key)
exwm-input--resize-mask (cdr resize-key)))
+ ;; Create the X window and intern the atom used to fetch timestamp.
+ (setq exwm-input--timestamp-window (xcb:generate-id exwm--connection))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:CreateWindow
+ :depth 0
+ :wid exwm-input--timestamp-window
+ :parent exwm--root
+ :x -1
+ :y -1
+ :width 1
+ :height 1
+ :border-width 0
+ :class xcb:WindowClass:CopyFromParent
+ :visual 0
+ :value-mask xcb:CW:EventMask
+ :event-mask xcb:EventMask:PropertyChange))
+ (let ((atom "_TIME"))
+ (setq exwm-input--timestamp-atom
+ (slot-value (xcb:+request-unchecked+reply exwm--connection
+ (make-instance 'xcb:InternAtom
+ :only-if-exists 0
+ :name-len (length atom)
+ :name atom))
+ 'atom)))
;; Attach event listeners
+ (xcb:+event exwm--connection 'xcb:PropertyNotify
+ #'exwm-input--on-PropertyNotify)
(xcb:+event exwm--connection 'xcb:KeyPress #'exwm-input--on-KeyPress)
(xcb:+event exwm--connection 'xcb:ButtonPress #'exwm-input--on-ButtonPress)
(xcb:+event exwm--connection 'xcb:ButtonRelease
diff --git a/exwm-workspace.el b/exwm-workspace.el
index 4789aeb..977cfe6 100644
--- a/exwm-workspace.el
+++ b/exwm-workspace.el
@@ -691,10 +691,13 @@ INDEX must not exceed the current number of workspaces."
(outer-id (string-to-number
(frame-parameter new-frame
'outer-window-id)))
+ (window-id (string-to-number
+ (frame-parameter new-frame 'window-id)))
(frame-container (frame-parameter old-frame
'exwm-container))
(window (frame-root-window new-frame)))
(set-frame-parameter new-frame 'exwm-outer-id outer-id)
+ (set-frame-parameter new-frame 'exwm-id window-id)
(set-frame-parameter new-frame 'exwm-container
frame-container)
(make-frame-invisible new-frame)
@@ -1149,10 +1152,12 @@ Please check `exwm-workspace--minibuffer-own-frame-p'
first."
(setq exwm-workspace--list (nconc exwm-workspace--list (list frame)))
(let ((outer-id (string-to-number (frame-parameter frame
'outer-window-id)))
+ (window-id (string-to-number (frame-parameter frame 'window-id)))
(container (xcb:generate-id exwm--connection))
(workspace (xcb:generate-id exwm--connection)))
;; Save window IDs
(set-frame-parameter frame 'exwm-outer-id outer-id)
+ (set-frame-parameter frame 'exwm-id window-id)
(set-frame-parameter frame 'exwm-container container)
(set-frame-parameter frame 'exwm-workspace workspace)
;; In case it's created by emacsclient.
@@ -1356,9 +1361,13 @@ applied to all subsequently created X frames."
(let ((outer-id (string-to-number
(frame-parameter exwm-workspace--minibuffer
'outer-window-id)))
+ (window-id (string-to-number
+ (frame-parameter exwm-workspace--minibuffer
+ 'window-id)))
(container (xcb:generate-id exwm--connection)))
(set-frame-parameter exwm-workspace--minibuffer
'exwm-outer-id outer-id)
+ (set-frame-parameter exwm-workspace--minibuffer 'exwm-id window-id)
(set-frame-parameter exwm-workspace--minibuffer 'exwm-container
container)
(xcb:+request exwm--connection
diff --git a/exwm.el b/exwm.el
index dd279bb..afec152 100644
--- a/exwm.el
+++ b/exwm.el
@@ -315,8 +315,7 @@
atom id buffer)
(xcb:unmarshal obj data)
(setq id (slot-value obj 'window)
- atom (slot-value obj 'atom)
- exwm-input--timestamp (slot-value obj 'time))
+ atom (slot-value obj 'atom))
(setq buffer (exwm--id->buffer id))
(if (not (buffer-live-p buffer))
;; Properties of unmanaged X windows.