Dear list, the following is my attempt to get some cyrillic characters
from my keyboard into McCLIM. It is a little crude, and definitely
requires some love before it is in a shape to go in, but it appears to
work for me.
Of course I'm sending the CLX part to a wrong list.
What it does?
1. CLX part
First, it tells CLX to ask the X server to enable XKEYBOARD.
This part wants to be performed conditionally, depending on the
extension's existence, obviously, which I skipped.
Next, it defines keysym -> CL character mappings for the
Cyrillic part of Unicode.
2. McCLIM side
Teach McCLIM to use the extended state bits (those reserved in
the core protocol) in the key-press/release events. This part
is rather agnostic wrt. XKEYBOARD presence, by design of the latter.
Honestly, x-event-to-key-name-and-modifiers appeared like a
low-pass filter to me, and I'm not sure what was the proper way
to approach it. So I just plastered the extended bits over,
without spending much time to understand what I was doing.
Anyway, hopefully this appears more useful than harmful.
regards, Samium Gromoff
diff --git a/clx.asd b/clx.asd
--- a/clx.asd
+++ b/clx.asd
@@ -70,6 +70,7 @@
((:file "shape")
(:file "big-requests")
(:file "xvidmode")
+ (:file "xkeyboard")
(:xrender-source-file "xrender")
(:file "glx")
(:file "gl" :depends-on ("glx"))
diff --git a/display.lisp b/display.lisp
--- a/display.lisp
+++ b/display.lisp
@@ -392,6 +392,7 @@ gethostname(3) - is used instead."
(initialize-resource-allocator disp)
(initialize-predefined-atoms disp)
(initialize-extensions disp)
+ (xkb-enable disp)
(when (assoc "BIG-REQUESTS" (display-extension-alist disp)
:test #'string=)
(enable-big-requests disp))
--- a/xkeyboard.lisp 2008-06-10 07:06:18.024003983 +0400
+++ b/xkeyboard.lisp 2008-06-23 01:20:07.000000000 +0400
@@ -0,0 +1,19 @@
+(in-package :xlib)
+
+(define-extension "XKEYBOARD"
+ :events ()
+ :errors (xf86-xkeyboard-keyboard))
+
+(define-condition xf86-xkeyboard-keyboard (request-error) ())
+
+(define-error xf86-xkeyboard-keyboard decode-core-error)
+
+(defconstant +xkb-enable+ 0)
+
+(defun xkb-enable (display)
+ (declare (type display display))
+ (with-buffer-request-and-reply (display (extension-opcode display "XKEYBOARD") nil :sizes (8 16))
+ ((data +xkb-enable+)
+ (card16 1)
+ (card16 0))
+ (values (boolean-get 8))))
diff --git a/keysyms.lisp b/keysyms.lisp
--- a/keysyms.lisp
+++ b/keysyms.lisp
@@ -157,6 +157,100 @@
(define-keysym #\} 125)
(define-keysym #\~ 126)
+;; (define-keysym #\SERBIAN_dje (keysym 6 #xa1))
+;; (define-keysym #\MACEDONIA_gje (keysym 6 #xa2))
+(define-keysym #\CYRILLIC_small_letter_io (keysym 6 #xa3))
+;; (define-keysym #\UKRAINIAN_ie (keysym 6 #xa4))
+;; (define-keysym #\MACEDONIA_dse (keysym 6 #xa5))
+;; (define-keysym #\UKRAINIAN_i (keysym 6 #xa6))
+;; (define-keysym #\UKRAINIAN_yi (keysym 6 #xa7))
+(define-keysym #\CYRILLIC_small_letter_je (keysym 6 #xa8))
+(define-keysym #\CYRILLIC_small_letter_lje (keysym 6 #xa9))
+(define-keysym #\CYRILLIC_small_letter_nje (keysym 6 #xaa))
+;; (define-keysym #\SERBIAN_tshe (keysym 6 #xab))
+;; (define-keysym #\MACEDONIA_kje (keysym 6 #xac))
+;; (define-keysym #\BYELORUSSIAN_shortu (keysym 6 #xae))
+(define-keysym #\CYRILLIC_small_letter_dzhe (keysym 6 #xaf))
+;; (define-keysym #\NUMEROSIGN (keysym 6 #xb0))
+;; (define-keysym #\SERBIAN_DJE (keysym 6 #xb1))
+;; (define-keysym #\MACEDONIA_GJE (keysym 6 #xb2))
+(define-keysym #\CYRILLIC_CAPITAL_LETTER_IO (keysym 6 #xb3))
+;; (define-keysym #\UKRAINIAN_IE (keysym 6 #xb4))
+;; (define-keysym #\MACEDONIA_DSE (keysym 6 #xb5))
+;; (define-keysym #\UKRAINIAN_I (keysym 6 #xb6))
+;; (define-keysym #\UKRAINIAN_YI (keysym 6 #xb7))
+(define-keysym #\CYRILLIC_CAPITAL_LETTER_JE (keysym 6 #xb8))
+(define-keysym #\CYRILLIC_CAPITAL_LETTER_LJE (keysym 6 #xb9))
+(define-keysym #\CYRILLIC_CAPITAL_LETTER_NJE (keysym 6 #xba))
+;; (define-keysym #\SERBIAN_TSHE (keysym 6 #xbb))
+;; (define-keysym #\MACEDONIA_KJE (keysym 6 #xbc))
+;; (define-keysym #\BYELORUSSIAN_SHORTU (keysym 6 #xbe))
+(define-keysym #\CYRILLIC_CAPITAL_LETTER_DZHE (keysym 6 #xbf))
+(define-keysym #\CYRILLIC_small_letter_yu (keysym 6 #xc0))
+(define-keysym #\CYRILLIC_small_letter_a (keysym 6 #xc1))
+(define-keysym #\CYRILLIC_small_letter_be (keysym 6 #xc2))
+(define-keysym #\CYRILLIC_small_letter_tse (keysym 6 #xc3))
+(define-keysym #\CYRILLIC_small_letter_de (keysym 6 #xc4))
+(define-keysym #\CYRILLIC_small_letter_ie (keysym 6 #xc5))
+(define-keysym #\CYRILLIC_small_letter_ef (keysym 6 #xc6))
+(define-keysym #\CYRILLIC_small_letter_ghe (keysym 6 #xc7))
+(define-keysym #\CYRILLIC_small_letter_ha (keysym 6 #xc8))
+(define-keysym #\CYRILLIC_small_letter_i (keysym 6 #xc9))
+(define-keysym #\CYRILLIC_small_letter_short_i (keysym 6 #xca))
+(define-keysym #\CYRILLIC_small_letter_ka (keysym 6 #xcb))
+(define-keysym #\CYRILLIC_small_letter_el (keysym 6 #xcc))
+(define-keysym #\CYRILLIC_small_letter_em (keysym 6 #xcd))
+(define-keysym #\CYRILLIC_small_letter_en (keysym 6 #xce))
+(define-keysym #\CYRILLIC_small_letter_o (keysym 6 #xcf))
+(define-keysym #\CYRILLIC_small_letter_pe (keysym 6 #xd0))
+(define-keysym #\CYRILLIC_small_letter_ya (keysym 6 #xd1))
+(define-keysym #\CYRILLIC_small_letter_er (keysym 6 #xd2))
+(define-keysym #\CYRILLIC_small_letter_es (keysym 6 #xd3))
+(define-keysym #\CYRILLIC_small_letter_te (keysym 6 #xd4))
+(define-keysym #\CYRILLIC_small_letter_u (keysym 6 #xd5))
+(define-keysym #\CYRILLIC_small_letter_zhe (keysym 6 #xd6))
+(define-keysym #\CYRILLIC_small_letter_ve (keysym 6 #xd7))
+(define-keysym #\CYRILLIC_small_letter_soft_sign (keysym 6 #xd8))
+(define-keysym #\CYRILLIC_small_letter_yeru (keysym 6 #xd9))
+(define-keysym #\CYRILLIC_small_letter_ze (keysym 6 #xda))
+(define-keysym #\CYRILLIC_small_letter_sha (keysym 6 #xdb))
+(define-keysym #\CYRILLIC_small_letter_e (keysym 6 #xdc))
+(define-keysym #\CYRILLIC_small_letter_shcha (keysym 6 #xdd))
+(define-keysym #\CYRILLIC_small_letter_che (keysym 6 #xde))
+(define-keysym #\CYRILLIC_small_letter_hard_sign (keysym 6 #xdf))
+(define-keysym #\CYRILLIC_capital_letter_YU (keysym 6 #xe0))
+(define-keysym #\CYRILLIC_capital_letter_A (keysym 6 #xe1))
+(define-keysym #\CYRILLIC_capital_letter_BE (keysym 6 #xe2))
+(define-keysym #\CYRILLIC_capital_letter_TSE (keysym 6 #xe3))
+(define-keysym #\CYRILLIC_capital_letter_DE (keysym 6 #xe4))
+(define-keysym #\CYRILLIC_capital_letter_IE (keysym 6 #xe5))
+(define-keysym #\CYRILLIC_capital_letter_EF (keysym 6 #xe6))
+(define-keysym #\CYRILLIC_capital_letter_GHE (keysym 6 #xe7))
+(define-keysym #\CYRILLIC_capital_letter_HA (keysym 6 #xe8))
+(define-keysym #\CYRILLIC_capital_letter_I (keysym 6 #xe9))
+(define-keysym #\CYRILLIC_capital_letter_SHORT_I (keysym 6 #xea))
+(define-keysym #\CYRILLIC_capital_letter_KA (keysym 6 #xeb))
+(define-keysym #\CYRILLIC_capital_letter_EL (keysym 6 #xec))
+(define-keysym #\CYRILLIC_capital_letter_EM (keysym 6 #xed))
+(define-keysym #\CYRILLIC_capital_letter_EN (keysym 6 #xee))
+(define-keysym #\CYRILLIC_capital_letter_O (keysym 6 #xef))
+(define-keysym #\CYRILLIC_capital_letter_PE (keysym 6 #xf0))
+(define-keysym #\CYRILLIC_capital_letter_YA (keysym 6 #xf1))
+(define-keysym #\CYRILLIC_capital_letter_ER (keysym 6 #xf2))
+(define-keysym #\CYRILLIC_capital_letter_ES (keysym 6 #xf3))
+(define-keysym #\CYRILLIC_capital_letter_TE (keysym 6 #xf4))
+(define-keysym #\CYRILLIC_capital_letter_U (keysym 6 #xf5))
+(define-keysym #\CYRILLIC_capital_letter_ZHE (keysym 6 #xf6))
+(define-keysym #\CYRILLIC_capital_letter_VE (keysym 6 #xf7))
+(define-keysym #\CYRILLIC_capital_letter_SOFT_SIGN (keysym 6 #xf8))
+(define-keysym #\CYRILLIC_capital_letter_YERU (keysym 6 #xf9))
+(define-keysym #\CYRILLIC_capital_letter_ZE (keysym 6 #xfa))
+(define-keysym #\CYRILLIC_capital_letter_SHA (keysym 6 #xfb))
+(define-keysym #\CYRILLIC_capital_letter_E (keysym 6 #xfc))
+(define-keysym #\CYRILLIC_capital_letter_SHCHA (keysym 6 #xfd))
+(define-keysym #\CYRILLIC_capital_letter_CHE (keysym 6 #xfe))
+(define-keysym #\CYRILLIC_capital_letter_HARD_SIGN (keysym 6 #xff))
+
(progn ;; Semi-standard characters
(define-keysym #\rubout (keysym 255 255)) ; :tty
(define-keysym #\tab (keysym 255 009)) ; :tty
diff --git a/Backends/CLX/keysyms-common.lisp b/Backends/CLX/keysyms-common.lisp
--- a/Backends/CLX/keysyms-common.lisp
+++ b/Backends/CLX/keysyms-common.lisp
@@ -118,8 +118,8 @@
(defgeneric x-event-state-modifiers (port state)
(:documentation "For the X STATE, returns as multiple values, the
- corresponding set of CLIM modifiers and flags for shift lock, caps lock, and
- mode switch."))
+ corresponding set of CLIM modifiers and flags for shift lock, caps lock,
+ mode switch and the group number."))
(defmethod x-event-state-modifiers ((port keysym-port-mixin) state)
(with-accessors ((modifier-cache modifier-cache))
@@ -133,7 +133,8 @@
(values clim-modifiers
(logtest +shift-lock+ other-modifiers)
(logtest +caps-lock+ other-modifiers)
- (logtest +mode-switch+ other-modifiers)))))
+ (logtest +mode-switch+ other-modifiers)
+ (ldb (byte 2 13) state)))))
(defun modify-modifiers (event-key keysym-keyword modifiers)
(let ((keysym-modifier (loop for (keysyms modifier) in +clim-modifiers+
diff --git a/Backends/CLX/keysyms.lisp b/Backends/CLX/keysyms.lisp
--- a/Backends/CLX/keysyms.lisp
+++ b/Backends/CLX/keysyms.lisp
@@ -40,7 +40,7 @@
;;; reflect the post event state.
(defun x-event-to-key-name-and-modifiers (port event-key keycode state)
- (multiple-value-bind (clim-modifiers shift-lock? caps-lock? mode-switch?)
+ (multiple-value-bind (clim-modifiers shift-lock? caps-lock? mode-switch? group-number)
(clim-xcommon:x-event-state-modifiers port state)
;; We filter away the shift state if there is a difference between
;; the shifted and unshifted keysym. This is so eg. #\A will not
@@ -53,10 +53,12 @@
(if caps-lock? t shift?)))
(shifted-keysym (xlib:keycode->keysym display keycode
(+ 1 (if mode-switch?
- 2 0))))
+ 2 0)
+ (ash group-number 1))))
(unshifted-keysym (xlib:keycode->keysym display keycode
- (if mode-switch?
- 2 0)))
+ (+ (if mode-switch?
+ 2 0)
+ (ash group-number 1))))
(keysym (if shift-modifier?
shifted-keysym
unshifted-keysym)))