diff options
-rw-r--r-- | exwm-xim.el | 138 |
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. |