@@ -134,25 +134,36 @@ The width is useful to adjust the tab-bar alignment when
134134
135135(defvar xcb:Atom:_NET_SYSTEM_TRAY_S0 )
136136
137+ (defun exwm-systemtray--get-geometry (icon )
138+ " Return the geometry (width . height) of ICON.
139+ The returned geometry will be scaled to fit the systemtray."
140+ (let (width* height*)
141+ (with-slots (width height)
142+ (xcb:+request-unchecked+reply exwm-systemtray--connection
143+ (make-instance 'xcb:GetGeometry :drawable icon))
144+ (setq height* exwm-systemtray-height
145+ width* (round (* width (/ (float height*) height))))
146+ (when (< width* exwm-systemtray--icon-min-size)
147+ (setq width* exwm-systemtray--icon-min-size
148+ height* (round (* height (/ (float width*) width)))))
149+ (exwm--log " Resize from %dx%d to %dx%d"
150+ width height width* height*))
151+ (cons width* height*)))
152+
137153(defun exwm-systemtray--embed (icon )
138154 " Embed an ICON."
139155 (exwm--log " Try to embed #x%x" icon)
140- (let ((info (xcb:+request-unchecked+reply exwm-systemtray--connection
141- (make-instance 'xcb:xembed:get-_XEMBED_INFO
142- :window icon)))
143- width* height* visible)
144- (when info
145- (exwm--log " Embed #x%x" icon)
146- (with-slots (width height)
147- (xcb:+request-unchecked+reply exwm-systemtray--connection
148- (make-instance 'xcb:GetGeometry :drawable icon))
149- (setq height* exwm-systemtray-height
150- width* (round (* width (/ (float height*) height))))
151- (when (< width* exwm-systemtray--icon-min-size)
152- (setq width* exwm-systemtray--icon-min-size
153- height* (round (* height (/ (float width*) width)))))
154- (exwm--log " Resize from %dx%d to %dx%d"
155- width height width* height*))
156+ (when-let* ((info (xcb:+request-unchecked+reply
157+ exwm-systemtray--connection
158+ (make-instance 'xcb:xembed:get-_XEMBED_INFO
159+ :window icon))))
160+ (exwm--log " Embed #x%x" icon)
161+ (pcase-let
162+ ((visible (if-let* ((flags (slot-value info 'flags )))
163+ (/= 0 (logand flags xcb:xembed:MAPPED))
164+ t )) ; default to visible.
165+ (`(, width . , height )
166+ (exwm-systemtray--get-geometry icon)))
156167 ; ; Add this icon to save-set.
157168 (xcb:+request exwm-systemtray--connection
158169 (make-instance 'xcb:ChangeSaveSet
@@ -165,16 +176,16 @@ The width is useful to adjust the tab-bar alignment when
165176 :parent exwm-systemtray--embedder-window
166177 :x 0
167178 ; ; Vertically centered.
168- :y (/ (- exwm-systemtray-height height* ) 2 )))
179+ :y (/ (- exwm-systemtray-height height) 2 )))
169180 ; ; Resize the icon.
170181 (xcb:+request exwm-systemtray--connection
171182 (make-instance 'xcb:ConfigureWindow
172183 :window icon
173184 :value-mask (logior xcb:ConfigWindow:Width
174185 xcb:ConfigWindow:Height
175186 xcb:ConfigWindow:BorderWidth)
176- :width width*
177- :height height*
187+ :width width
188+ :height height
178189 :border-width 0 ))
179190 ; ; Set event mask.
180191 (xcb:+request exwm-systemtray--connection
@@ -194,12 +205,6 @@ The width is useful to adjust the tab-bar alignment when
194205 :key xcb:Grab:Any
195206 :pointer-mode xcb:GrabMode:Async
196207 :keyboard-mode xcb:GrabMode:Async)))
197- (setq visible (slot-value info 'flags ))
198- (if visible
199- (setq visible
200- (/= 0 (logand (slot-value info 'flags ) xcb:xembed:MAPPED)))
201- ; ; Default to visible.
202- (setq visible t ))
203208 (when visible
204209 (exwm--log " Map the window" )
205210 (xcb:+request exwm-systemtray--connection
@@ -217,8 +222,8 @@ The width is useful to adjust the tab-bar alignment when
217222 :version 0 )
218223 exwm-systemtray--connection)))
219224 (push `(, icon . ,(make-instance 'exwm-systemtray--icon
220- :width width*
221- :height height*
225+ :width width
226+ :height height
222227 :visible visible))
223228 exwm-systemtray--list)
224229 (exwm-systemtray--refresh))))
@@ -368,73 +373,66 @@ Argument DATA contains the raw event data."
368373 " Resize the tray icon on ResizeRequest.
369374Argument DATA contains the raw event data."
370375 (exwm--log)
371- (let ((obj (xcb:unmarshal-new 'xcb:ResizeRequest data))
372- attr)
373- (with-slots (window width height) obj
374- (when (setq attr (cdr (assoc window exwm-systemtray--list)))
375- (with-slots ((width* width)
376- (height* height))
377- attr
378- (setq height* exwm-systemtray-height
379- width* (round (* width (/ (float height*) height))))
380- (when (< width* exwm-systemtray--icon-min-size)
381- (setq width* exwm-systemtray--icon-min-size
382- height* (round (* height (/ (float width*) width)))))
383- (xcb:+request exwm-systemtray--connection
384- (make-instance 'xcb:ConfigureWindow
385- :window window
386- :value-mask (logior xcb:ConfigWindow:Y
387- xcb:ConfigWindow:Width
388- xcb:ConfigWindow:Height)
389- ; ; Vertically centered.
390- :y (/ (- exwm-systemtray-height height*) 2 )
391- :width width*
392- :height height*)))
393- (exwm-systemtray--refresh)))))
376+ (with-slots (window width height)
377+ (xcb:unmarshal-new 'xcb:ResizeRequest data)
378+ (when-let* ((attr (alist-get window exwm-systemtray--list)))
379+ (with-slots ((width* width) (height* height)) attr
380+ (setq height* exwm-systemtray-height
381+ width* (round (* width (/ (float height*) height))))
382+ (when (< width* exwm-systemtray--icon-min-size)
383+ (setq width* exwm-systemtray--icon-min-size
384+ height* (round (* height (/ (float width*) width)))))
385+ (xcb:+request exwm-systemtray--connection
386+ (make-instance 'xcb:ConfigureWindow
387+ :window window
388+ :value-mask (logior xcb:ConfigWindow:Y
389+ xcb:ConfigWindow:Width
390+ xcb:ConfigWindow:Height)
391+ ; ; Vertically centered.
392+ :y (/ (- exwm-systemtray-height height*) 2 )
393+ :width width*
394+ :height height*)))
395+ (exwm-systemtray--refresh))))
394396
395397(defun exwm-systemtray--on-PropertyNotify (data _synthetic )
396398 " Map/Unmap the tray icon on PropertyNotify.
397399Argument DATA contains the raw event data."
398400 (exwm--log)
399- (let ((obj (xcb:unmarshal-new 'xcb:PropertyNotify data))
400- attr info visible)
401- (with-slots (window atom state) obj
402- (when (and (eq state xcb:Property:NewValue)
403- (eq atom xcb:Atom:_XEMBED_INFO)
404- (setq attr (cdr (assoc window exwm-systemtray--list))))
405- (setq info (xcb:+request-unchecked+reply exwm-systemtray--connection
406- (make-instance 'xcb:xembed:get-_XEMBED_INFO
407- :window window)))
408- (when info
409- (setq visible (/= 0 (logand (slot-value info 'flags )
410- xcb:xembed:MAPPED)))
411- (exwm--log " #x%x visible? %s" window visible)
412- (if visible
413- (xcb:+request exwm-systemtray--connection
414- (make-instance 'xcb:MapWindow :window window))
415- (xcb:+request exwm-systemtray--connection
416- (make-instance 'xcb:UnmapWindow :window window)))
417- (setf (slot-value attr 'visible ) visible)
418- (exwm-systemtray--refresh))))))
401+ (with-slots (window atom state)
402+ (xcb:unmarshal-new 'xcb:PropertyNotify data)
403+ (when-let* ((_(eq state xcb:Property:NewValue))
404+ (_(eq atom xcb:Atom:_XEMBED_INFO))
405+ (attr (alist-get window exwm-systemtray--list))
406+ (info (xcb:+request-unchecked+reply
407+ exwm-systemtray--connection
408+ (make-instance 'xcb:xembed:get-_XEMBED_INFO
409+ :window window))))
410+ (let ((visible (/= 0 (logand (slot-value info 'flags )
411+ xcb:xembed:MAPPED))))
412+ (exwm--log " #x%x visible? %s" window visible)
413+ (xcb:+request exwm-systemtray--connection
414+ (make-instance (if visible 'xcb:MapWindow 'xcb:UnmapWindow )
415+ :window window))
416+ (setf (slot-value attr 'visible ) visible)
417+ (exwm-systemtray--refresh)))))
419418
420419(defun exwm-systemtray--on-ClientMessage (data _synthetic )
421420 " Handle client messages.
422421Argument DATA contains the raw event data."
423- (let ((obj (xcb:unmarshal-new 'xcb:ClientMessage data))
424- opcode data32)
422+ (let ((obj (xcb:unmarshal-new 'xcb:ClientMessage data)))
425423 (with-slots (window type data) obj
426424 (when (eq type xcb:Atom:_NET_SYSTEM_TRAY_OPCODE)
427- (setq data32 (slot-value data 'data32 )
428- opcode (elt data32 1 ))
429- (exwm--log " opcode: %s" opcode)
430- (cond ((= opcode xcb:systemtray:opcode:REQUEST-DOCK)
431- (unless (assoc (elt data32 2 ) exwm-systemtray--list)
432- (exwm-systemtray--embed (elt data32 2 ))))
433- ; ; Not implemented (rarely used nowadays).
434- ((or (= opcode xcb:systemtray:opcode:BEGIN-MESSAGE)
435- (= opcode xcb:systemtray:opcode:CANCEL-MESSAGE)))
436- (t
437- (exwm--log " Unknown opcode message: %s" obj)))))))
425+ (let* (( data32 (slot-value data 'data32 ) )
426+ ( opcode (elt data32 1 ) ))
427+ (exwm--log " opcode: %s" opcode)
428+ (cond ((= opcode xcb:systemtray:opcode:REQUEST-DOCK)
429+ (unless (assoc (elt data32 2 ) exwm-systemtray--list)
430+ (exwm-systemtray--embed (elt data32 2 ))))
431+ ; ; Not implemented (rarely used nowadays).
432+ ((or (= opcode xcb:systemtray:opcode:BEGIN-MESSAGE)
433+ (= opcode xcb:systemtray:opcode:CANCEL-MESSAGE)))
434+ (t
435+ (exwm--log " Unknown opcode message: %s" obj) )))))))
438436
439437(defun exwm-systemtray--on-KeyPress (data _synthetic )
440438 " Forward all KeyPress events to Emacs frame.
0 commit comments