github.com/rajveermalviya/gamen@v0.1.2-0.20220930195403-9be15877c1aa/internal/wayland/keyboard.go (about) 1 //go:build linux && !android 2 3 package wayland 4 5 /* 6 7 #include <stdlib.h> 8 #include "wayland-client-protocol.h" 9 10 */ 11 import "C" 12 13 import ( 14 "log" 15 "runtime/cgo" 16 "time" 17 "unsafe" 18 19 "github.com/rajveermalviya/gamen/events" 20 "github.com/rajveermalviya/gamen/internal/xkbcommon" 21 "golang.org/x/sys/unix" 22 ) 23 24 type Keyboard struct { 25 d *Display 26 keyboard *C.struct_wl_keyboard 27 28 // from repeat_info event 29 haveServerRepeat bool 30 serverRepeatRate uint32 31 serverRepeatDelay time.Duration 32 33 // some state to handle key repeats 34 // key that was pressed 35 repeatKey uint32 36 // time when key was first pressed 37 repeatKeyStartTime time.Time 38 // time when we sent the last synthetic key press event 39 repeatKeyLastSendTime time.Time 40 41 // which surface has keyboard focus 42 focus *C.struct_wl_surface 43 44 modifiers events.ModifiersState 45 } 46 47 func (k *Keyboard) destroy() { 48 if k.keyboard != nil { 49 k.d.l.wl_keyboard_destroy(k.keyboard) 50 k.keyboard = nil 51 } 52 } 53 54 //export keyboardHandleKeymap 55 func keyboardHandleKeymap(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, format C.uint32_t, fd C.int32_t, size C.uint32_t) { 56 defer unix.Close(int(fd)) 57 58 ev, ok := (*cgo.Handle)(data).Value().(*Display) 59 if !ok { 60 return 61 } 62 63 if ev.xkb == nil { 64 return 65 } 66 67 buf, err := unix.Mmap(int(fd), 0, int(size), unix.PROT_READ, unix.MAP_SHARED) 68 if err != nil { 69 log.Printf("failed to mmap keymap: %v\n", err) 70 return 71 } 72 defer unix.Munmap(buf) 73 74 err = ev.xkb.KeymapFromBuffer(buf) 75 if err != nil { 76 log.Printf("failed to create keymap from buffer: %v\n", err) 77 return 78 } 79 } 80 81 //export keyboardHandleEnter 82 func keyboardHandleEnter(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, serial C.uint32_t, surface *C.struct_wl_surface, keys *C.struct_wl_array) { 83 d, ok := (*cgo.Handle)(data).Value().(*Display) 84 if !ok { 85 return 86 } 87 k := d.keyboard 88 89 k.focus = surface 90 91 w, ok := d.windows[surface] 92 if !ok { 93 return 94 } 95 96 if cb := w.focusedCb.Load(); cb != nil { 97 if cb := (*cb); cb != nil { 98 cb() 99 } 100 } 101 102 // send modifiers that are already pressed 103 if k.modifiers != 0 { 104 if cb := w.modifiersChangedCb.Load(); cb != nil { 105 if cb := (*cb); cb != nil { 106 cb(k.modifiers) 107 } 108 } 109 } 110 } 111 112 //export keyboardHandleLeave 113 func keyboardHandleLeave(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, serial C.uint32_t, surface *C.struct_wl_surface) { 114 d, ok := (*cgo.Handle)(data).Value().(*Display) 115 if !ok { 116 return 117 } 118 k := d.keyboard 119 120 w, ok := d.windows[surface] 121 if !ok { 122 return 123 } 124 125 // remove modifiers if pressed 126 if k.modifiers != 0 { 127 if cb := w.modifiersChangedCb.Load(); cb != nil { 128 if cb := (*cb); cb != nil { 129 cb(0) 130 } 131 } 132 } 133 134 if cb := w.unfocusedCb.Load(); cb != nil { 135 if cb := (*cb); cb != nil { 136 cb() 137 } 138 } 139 140 k.repeatKey = 0 141 k.focus = nil 142 } 143 144 //export keyboardHandleKey 145 func keyboardHandleKey(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, serial C.uint32_t, _time C.uint32_t, key C.uint32_t, state enum_wl_keyboard_key_state) { 146 d, ok := (*cgo.Handle)(data).Value().(*Display) 147 if !ok { 148 return 149 } 150 151 xkb := d.xkb 152 if xkb == nil { 153 return 154 } 155 156 k := d.keyboard 157 if k.focus == nil { 158 return 159 } 160 161 now := time.Now() 162 k.repeatKeyStartTime = now 163 k.repeatKeyLastSendTime = now 164 if state == WL_KEYBOARD_KEY_STATE_RELEASED && k.repeatKey == uint32(key) { 165 k.repeatKey = 0 166 } 167 168 k.handleKeyEvent(key, state) 169 170 if state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb.KeyRepeats(xkbcommon.KeyCode(key+8)) { 171 k.repeatKey = uint32(key) 172 k.repeatKeyStartTime = time.Now() 173 k.repeatKeyLastSendTime = k.repeatKeyStartTime 174 } 175 } 176 177 func (k *Keyboard) handleKeyEvent(key C.uint32_t, state enum_wl_keyboard_key_state) { 178 xkb := k.d.xkb 179 w, ok := k.d.windows[k.focus] 180 if !ok { 181 return 182 } 183 184 key += 8 185 sym := xkb.GetOneSym(xkbcommon.KeyCode(key)) 186 187 if cb := w.keyboardInputCb.Load(); cb != nil { 188 if cb := (*cb); cb != nil { 189 var buttonState events.ButtonState 190 switch state { 191 case WL_KEYBOARD_KEY_STATE_PRESSED: 192 buttonState = events.ButtonStatePressed 193 case WL_KEYBOARD_KEY_STATE_RELEASED: 194 buttonState = events.ButtonStateReleased 195 } 196 197 cb( 198 buttonState, 199 events.ScanCode(key), 200 xkbcommon.KeySymToVirtualKey(sym), 201 ) 202 } 203 } 204 205 if state == WL_KEYBOARD_KEY_STATE_PRESSED { 206 if cb := w.receivedCharacterCb.Load(); cb != nil { 207 if cb := (*cb); cb != nil { 208 utf8 := xkb.GetUtf8(xkbcommon.KeyCode(key), xkbcommon.KeySym(sym)) 209 for _, char := range utf8 { 210 cb(char) 211 } 212 } 213 } 214 } 215 } 216 217 //export keyboardHandleModifiers 218 func keyboardHandleModifiers(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, serial C.uint32_t, mods_depressed C.uint32_t, mods_latched C.uint32_t, mods_locked C.uint32_t, group C.uint32_t) { 219 d, ok := (*cgo.Handle)(data).Value().(*Display) 220 if !ok { 221 return 222 } 223 k := d.keyboard 224 225 if d.xkb == nil { 226 return 227 } 228 229 if d.xkb.UpdateMask( 230 xkbcommon.ModMask(mods_depressed), 231 xkbcommon.ModMask(mods_latched), 232 xkbcommon.ModMask(mods_locked), 233 0, 234 0, 235 xkbcommon.LayoutIndex(group), 236 ) { 237 return 238 } 239 240 var m events.ModifiersState 241 242 if d.xkb.ModIsShift() { 243 m |= events.ModifiersStateShift 244 } 245 if d.xkb.ModIsCtrl() { 246 m |= events.ModifiersStateCtrl 247 } 248 if d.xkb.ModIsAlt() { 249 m |= events.ModifiersStateAlt 250 } 251 if d.xkb.ModIsLogo() { 252 m |= events.ModifiersStateLogo 253 } 254 255 k.modifiers = m 256 257 if k.focus == nil { 258 return 259 } 260 261 w, ok := d.windows[k.focus] 262 if !ok { 263 return 264 } 265 266 if cb := w.modifiersChangedCb.Load(); cb != nil { 267 if cb := (*cb); cb != nil { 268 cb(m) 269 } 270 } 271 } 272 273 //export keyboardHandleRepeatInfo 274 func keyboardHandleRepeatInfo(data unsafe.Pointer, wl_keyboard *C.struct_wl_keyboard, rate C.int32_t, delay C.int32_t) { 275 d, ok := (*cgo.Handle)(data).Value().(*Display) 276 if !ok { 277 return 278 } 279 280 k := d.keyboard 281 282 k.haveServerRepeat = true 283 k.serverRepeatRate = uint32(rate) 284 k.serverRepeatDelay = time.Duration(delay) * time.Millisecond 285 }