-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keyboard support #9
Keyboard support #9
Conversation
Add json serialization lib Add collection lib Add key mappings Add sending key to flutter Add sending key from flutter to wlroots Add passing key from wlroots to view
Add sending key events from flutter to wayland client Add json serialization library Add collections header lib Add key maps for xcb to flutter keys
src/key_mapping.cc
Outdated
|
||
// DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT | ||
// This file is generated by | ||
// flutter/flutter@dev/tools/gen_keycodes/bin/gen_keycodes.dart and should not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this file unmodified from the generator, or has there been modifications?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
original is from generator, this one is not. I will remove comment
const int pointerKindUnknown = 3; | ||
|
||
const Map<int, int> physicalToXkbMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this mapping from? Is there any reason not to do this on the C side where the other parts of the mapping live?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is taken from the gtk embedding iirc and it's just a reversed version of the xkb to physical map. Imo it should be in dart as it's easier to handle there as in c, but I'm open to anything really
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What @HrX03 said. This mapping is take from Linux embedder https://github.com/flutter/engine/blob/master/shell/platform/linux/key_mapping.cc#L20
it's documented here https://github.com/flutter/flutter/blob/master/dev/tools/gen_keycodes/README.md
platform.channel | ||
.invokeMethod("testing") | ||
.then((value) => {print("testing message response")}) | ||
.catchError((error) => {print("error")}); | ||
|
||
platform.addHandler("flutter/keyevent", (call) async { | ||
print('got event: ${call.arguments["keymap"]}'); | ||
print('got event: ${call.arguments["keyCode"]}'); | ||
print('got event: ${call.arguments["type"]}'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should likely be removed, debug code
status = KeyStatus.released; | ||
} | ||
|
||
int? keycode = physicalToXkbMap[event.physicalKey.usbHidUsage]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the function for this in the compositor
if (event is KeyDownEvent) { | ||
status = KeyStatus.pressed; | ||
} else { | ||
status = KeyStatus.released; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessarily Down
OR Up
? What about key repeat event?
It would at least be nice to do an is
check on both of these branches, then debug print if we get an event type we didn't expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wlroots doesn't have a concept for repeat, instead it decides to "repeat" once it gets enough down events for the same key (at least by observing how it behaves + no enum entry for repeat)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does seem like wlroots has the concept of repeats, as evident by wlr_keyboard_set_repeat_info
.
So wlroots uses subsequent PRESSED
events as the signal of a repeat key then? This should be converted to the Repeat
event in the flutter engine on the C side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pardon, i corrected myself in a comment later on. As i stated there, as long as a key is signaled as being pressed then it will be "repeated". Once the key is signaled as up then it will stop being repeated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically what @HrX03 said. wlroots will send up events which will work as repeat.
goto error; | ||
} | ||
|
||
wlr_seat_keyboard_notify_key(instance->seat, message.timestamp / NS_PER_MS, message.keycode - 8, type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No management of active seat surface at all? Might be considered part of point 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By looking at various wl impls keyboard focus should be moved only on view focus, like when opening a new surface or when the user clicks the view to focus. We should change the flutter side to have one big global listener indeed instead of one for each surface as it doesn't really match with how wlroots handles keyboard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's 1 surface for now.
src/input.c
Outdated
|
||
|
||
// void fwr_handle_key_press(struct fwr_instance *instance, const FlutterPlatformMessageResponseHandle *handle, struct dart_value *args){ | ||
// struct wlr_seat *seat = instance->seat; | ||
|
||
// struct key_event_message message; | ||
// if (!decode_key_event_message(args, &message)) { | ||
// wlr_log(WLR_ERROR, "Invalid key event message"); | ||
// return; | ||
// } | ||
|
||
// uint32_t xkb_key = physical_to_xkb_key(message.physical_key_id - 8); | ||
// // wlr_log(WLR_INFO, "should transform key %s", xkb_key); | ||
|
||
|
||
// wlr_seat_keyboard_notify_key(seat, message.timestamp, | ||
// xkb_key, message.key_state); | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused code
@@ -14,6 +15,43 @@ static void cb(const uint8_t *data, size_t size, void *user_data) { | |||
wlr_log(WLR_INFO, "callback"); | |||
} | |||
|
|||
static void focus_view(struct fwr_view *view, struct wlr_surface *surface) { | |||
/* Note: this function only deals with keyboard focus. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inconsistent formatting
@@ -63,7 +101,10 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data) { | |||
|
|||
instance->fl_proc_table.PlatformMessageReleaseResponseHandle(instance->engine, | |||
response_handle); | |||
|
|||
focus_view(view, view->surface); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No proper focus management? Part of point 4?
src/surface.c
Outdated
view->instance = instance; | ||
view->surface = xdg_surface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for this move?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, was having some issues and moved stuff around to test, just forgot to put it back where it once was
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restored
include/jsmn.h
Outdated
JSMN_UNDEFINED = 0, | ||
JSMN_OBJECT = 1, | ||
JSMN_ARRAY = 2, | ||
JSMN_STRING = 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use 1 2 3 4 instead of the bit shifted constants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like original lib has bitshift operatoions but flutter-pi has constants. I reverted to bit shift operators because I'd rather no to modify extrenal library
include/key_mapping.h
Outdated
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef KEYBOARD_MAP_H_ | ||
#define KEYBOARD_MAP_H_ | ||
|
||
#include <xkbcommon/xkbcommon.h> | ||
|
||
#define WLR_USE_UNSTABLE | ||
#include <wlr/types/wlr_keyboard.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
|
||
// Mask for the 32-bit value portion of the key code. | ||
extern const uint64_t kValueMask; | ||
|
||
// The plane value for keys which have a Unicode representation. | ||
extern const uint64_t kUnicodePlane; | ||
|
||
// The plane value for the private keys defined by the GTK embedding. | ||
extern const uint64_t kGtkPlane; | ||
|
||
uint64_t apply_id_plane(uint64_t logical_id, uint64_t plane); | ||
|
||
uint64_t event_to_physical_key(struct wlr_event_keyboard_key *event); | ||
|
||
uint64_t event_to_logical_key(struct wlr_event_keyboard_key *event, struct xkb_state *state); | ||
|
||
uint32_t event_to_unicode(struct wlr_event_keyboard_key *event, struct xkb_state *state); | ||
|
||
uint64_t event_to_timestamp(struct wlr_event_keyboard_key *event); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // KEYBOARD_MAP_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This + the c impl should be replaced with the xkb based methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate on that?
// uint32_t unicode = event_to_unicode(event, kb_state); | ||
|
||
struct xkb_state *kb_state = keyboard->device->keyboard->xkb_state; | ||
uint32_t modifiers = keyboard_state_is_shift_active(kb_state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is directly taken from the flutter-pi docs but I think I should be able to get some docs from flutter code
| (keyboard_state_is_alt_active(kb_state) << 3) | ||
| (keyboard_state_is_numlock_active(kb_state) << 4) | ||
| (keyboard_state_is_meta_active(kb_state) << 28); | ||
uint16_t scan_code = (uint16_t)event->keycode + 8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, but instead of flutter some xkb/libinput docs
switch(event->state) { | ||
case WL_KEYBOARD_KEY_STATE_PRESSED: | ||
type = "keydown"; | ||
flType = kFlutterKeyEventTypeDown; | ||
break; | ||
case WL_KEYBOARD_KEY_STATE_RELEASED: | ||
default: | ||
type = "keyup"; | ||
flType = kFlutterKeyEventTypeUp; | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct for the flutter part but wlroots has no concept of repeat as far as I'm concerned, until one key is kept pressed it's going to keep it pressed apparently
wlr_keyboard_set_keymap(device->keyboard, keymap); | ||
xkb_keymap_unref(keymap); | ||
xkb_context_unref(context); | ||
wlr_keyboard_set_repeat_info(device->keyboard, 25, 600); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tinywl source code iirc
goto error; | ||
} | ||
|
||
wlr_seat_keyboard_notify_key(instance->seat, message.timestamp / NS_PER_MS, message.keycode - 8, type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By looking at various wl impls keyboard focus should be moved only on view focus, like when opening a new surface or when the user clicks the view to focus. We should change the flutter side to have one big global listener indeed instead of one for each surface as it doesn't really match with how wlroots handles keyboard
src/surface.c
Outdated
view->instance = instance; | ||
view->surface = xdg_surface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, was having some issues and moved stuff around to test, just forgot to put it back where it once was
removed duplicated key map in surface removed debug code
Todos:
|
Move assert code to asserts.h Revert unnecessary code changes
Thanks! |
This PR targets https://github.com/PlayPulseCom/flutter_wlroots/issues/1
Current status:
Forward input from wlroots backend to the flutter engine. This includes handling the new keyboard signal emitted by wlroots and registering handlers for key events which call into the flutter engine API.
Implement keyboard event handling in SurfaceWidget. This would involve introducing a focus node and adding a handler for keyboard events. Implementing focus-on-click vs focus-on-hover (or some other mechanism) is best left to the consumer, but the dart library should make this easy.
Make sure the surface receives keyboard events correctly. This involves making a new message handler for keyboard events in native code which forwards the events to wlroots. This would be called by the SurfaceWidget when input events are received.
Make sure the surface receives/loses keyboard focus when the focus node receives/loses focus. This involves making a new message handler for managing focus changes in the native code, then forwarding that to wlroots. This would then be called by the SurfaceWidget when the focus node changes state.
^ We might want to add this in separate request when we have more than 1 SurfaceWidget and easy way to switch between them