about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--exwm-xim.el138
1 files changed, 74 insertions, 64 deletions
diff --git a/exwm-xim.el b/exwm-xim.el
index 6a213acc0cb5..23512144c9c5 100644
--- a/exwm-xim.el
+++ b/exwm-xim.el
@@ -490,70 +490,8 @@ The actual XIM request is in client message data or a property."
            (exwm--log "FORWARD-EVENT")
            (setq req (make-instance 'xim:forward-event))
            (xcb:unmarshal req data)
-           (let ((im-func (with-current-buffer (window-buffer)
-                            input-method-function))
-                 key-event keysym event result)
-             ;; Note: The flag slot is ignored.
-             ;; Do conversion in client's byte-order.
-             (let ((xcb:lsb xim:lsb))
-               (setq key-event (make-instance 'xcb:KeyPress))
-               (xcb:unmarshal key-event (slot-value req 'event)))
-             (with-slots (detail state) key-event
-               (setq keysym (xcb:keysyms:keycode->keysym exwm-xim--conn detail
-                                                         state))
-               (when (/= (car keysym) 0)
-                 (setq event (xcb:keysyms:keysym->event
-                              exwm-xim--conn
-                              (car keysym)
-                              (logand state (lognot (cdr keysym)))))))
-             (if exwm-xim--event-pending
-                 ;; In case any event reaches here, it should be forwarded
-                 ;; to Emacs.
-                 (when event
-                   (setq unread-command-events
-                         (append unread-command-events (list event))))
-               (setq exwm-xim--event-pending t)
-               (if (or (not im-func)
-                       ;; `list' is the default method.
-                       (eq im-func #'list)
-                       (not event)
-                       ;; Select only printable keys.
-                       (not (integerp event)) (> #x20 event) (< #x7e event))
-                   ;; Either there is no active input method, or invalid key
-                   ;; is detected.
-                   (with-slots (im-id ic-id serial-number event) req
-                     (push (make-instance 'xim:forward-event
-                                          :im-id im-id
-                                          :ic-id ic-id
-                                          :flag xim:commit-flag:synchronous
-                                          :serial-number serial-number
-                                          :event event)
-                           replies))
-                 (when (eq exwm--selected-input-mode 'char-mode)
-                   ;; Grab keyboard temporarily for char-mode.
-                   (exwm-input--grab-keyboard))
-                 (unwind-protect
-                     (with-temp-buffer
-                       ;; Always show key strokes.
-                       (let ((input-method-use-echo-area t))
-                         (setq result (funcall im-func event))))
-                   (when (eq exwm--selected-input-mode 'char-mode)
-                     (exwm-input--release-keyboard)))
-                 ;; This also works for portable character encoding.
-                 (setq result
-                       (encode-coding-string (concat result)
-                                             'compound-text-with-extensions))
-                 (message "")
-                 (push
-                  (make-instance 'xim:commit-x-lookup-chars
-                                 :im-id (slot-value req 'im-id)
-                                 :ic-id (slot-value req 'ic-id)
-                                 :flag (logior xim:commit-flag:synchronous
-                                               xim:commit-flag:x-lookup-chars)
-                                 :length (length result)
-                                 :string result)
-                  replies))
-               (setq exwm-xim--event-pending nil))))
+           (exwm-xim--handle-forward-event-request req xim:lsb conn
+                                                   client-xwin))
           ((= opcode xim:opcode:sync)
            (exwm--log "SYNC")
            (setq req (make-instance 'xim:sync))
@@ -591,6 +529,78 @@ The actual XIM request is in client message data or a property."
             replies)
       (xcb:flush conn))))
 
+(defun exwm-xim--handle-forward-event-request (req lsb conn client-xwin)
+  (let ((im-func (with-current-buffer (window-buffer)
+                   input-method-function))
+        key-event keysym event result)
+    ;; Note: The flag slot is ignored.
+    ;; Do conversion in client's byte-order.
+    (let ((xcb:lsb lsb))
+      (setq key-event (make-instance 'xcb:KeyPress))
+      (xcb:unmarshal key-event (slot-value req 'event)))
+    (with-slots (detail state) key-event
+      (setq keysym (xcb:keysyms:keycode->keysym exwm-xim--conn detail
+                                                state))
+      (when (/= (car keysym) 0)
+        (setq event (xcb:keysyms:keysym->event
+                     exwm-xim--conn
+                     (car keysym)
+                     (logand state (lognot (cdr keysym)))))))
+    (if exwm-xim--event-pending
+        ;; In case any event reaches here, it should be forwarded
+        ;; to Emacs.
+        (when event
+          (setq unread-command-events
+                (append unread-command-events (list event))))
+      (setq exwm-xim--event-pending t)
+      (if (or (not im-func)
+              ;; `list' is the default method.
+              (eq im-func #'list)
+              (not event)
+              ;; Select only printable keys.
+              (not (integerp event)) (> #x20 event) (< #x7e event))
+          ;; Either there is no active input method, or invalid key
+          ;; is detected.
+          (with-slots (im-id ic-id serial-number event) req
+            (exwm-xim--make-request
+             (make-instance 'xim:forward-event
+                            :im-id im-id
+                            :ic-id ic-id
+                            :flag xim:commit-flag:synchronous
+                            :serial-number serial-number
+                            :event event)
+             conn client-xwin)
+            (xcb:flush conn))
+        (when (eq exwm--selected-input-mode 'char-mode)
+          ;; Grab keyboard temporarily for char-mode.
+          (exwm-input--grab-keyboard))
+        (unwind-protect
+            (with-temp-buffer
+              ;; Always show key strokes.
+              (let ((input-method-use-echo-area t))
+                (while (or event unread-command-events)
+                  (unless event
+                    (setq event (pop unread-command-events)))
+                  (setq result (funcall im-func event)
+                        event nil)
+                  ;; This also works for portable character encoding.
+                  (setq result
+                        (encode-coding-string (concat result)
+                                              'compound-text-with-extensions))
+                  (exwm-xim--make-request
+                   (make-instance 'xim:commit-x-lookup-chars
+                                  :im-id (slot-value req 'im-id)
+                                  :ic-id (slot-value req 'ic-id)
+                                  :flag (logior xim:commit-flag:synchronous
+                                                xim:commit-flag:x-lookup-chars)
+                                  :length (length result)
+                                  :string result)
+                   conn client-xwin)
+                  (xcb:flush conn))))
+          (when (eq exwm--selected-input-mode 'char-mode)
+            (exwm-input--release-keyboard))))
+      (setq exwm-xim--event-pending nil))))
+
 (defun exwm-xim--make-request (req conn client-xwin)
   "Make an XIM request REQ via connection CONN.