| Flutter Linux Embedder |

fl_keyboard_handler.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/linux/fl_keyboard_handler.h"
6
7 #include <array>
8 #include <cinttypes>
9 #include <memory>
10 #include <string>
11
12 #include "flutter/shell/platform/linux/fl_key_channel_responder.h"
13 #include "flutter/shell/platform/linux/fl_key_embedder_responder.h"
14 #include "flutter/shell/platform/linux/fl_keyboard_pending_event.h"
15 #include "flutter/shell/platform/linux/key_mapping.h"
16 #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
17 #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
18
19 // Turn on this flag to print complete layout data when switching IMEs. The data
20 // is used in unit tests.
21 #define DEBUG_PRINT_LAYOUT
22
23 static constexpr char kChannelName[] = "flutter/keyboard";
24 static constexpr char kGetKeyboardStateMethod[] = "getKeyboardState";
25
26 /* Declarations of private classes */
27
28 #define FL_TYPE_KEYBOARD_HANDLER_USER_DATA \
29 fl_keyboard_handler_user_data_get_type()
30 G_DECLARE_FINAL_TYPE(FlKeyboardHandlerUserData,
31 fl_keyboard_handler_user_data,
32 FL,
33 KEYBOARD_HANDLER_USER_DATA,
34 GObject);
35
36 /* End declarations */
37
38 namespace {
39
40 // The maxiumum keycode in a derived layout.
41 //
42 // Although X supports higher keycodes, Flutter only cares about standard keys,
43 // which are below this.
44 constexpr size_t kLayoutSize = 128;
45 // Describes the derived layout of a keyboard group.
46 //
47 // Maps from keycode to logical key. Value being 0 stands for empty.
48 typedef std::array<uint64_t, kLayoutSize> DerivedGroupLayout;
49 // Describes the derived layout of the entire keyboard.
50 //
51 // Maps from group ID to group layout.
52 typedef std::map<guint8, DerivedGroupLayout> DerivedLayout;
53
54 // Context variables for the foreach call used to dispatch events to responders.
55 typedef struct {
56 FlKeyEvent* event;
57 uint64_t specified_logical_key;
58 FlKeyboardHandlerUserData* user_data;
59 } DispatchToResponderLoopContext;
60
61 bool is_eascii(uint16_t character) {
62 return character < 256;
63 }
64
65 #ifdef DEBUG_PRINT_LAYOUT
66 // Prints layout entries that will be parsed by `MockLayoutData`.
67 void debug_format_layout_data(std::string& debug_layout_data,
68 uint16_t keycode,
69 uint16_t clue1,
70 uint16_t clue2) {
71 if (keycode % 4 == 0) {
72 debug_layout_data.append(" ");
73 }
74
75 constexpr int kBufferSize = 30;
76 char buffer[kBufferSize];
77 buffer[0] = 0;
78 buffer[kBufferSize - 1] = 0;
79
80 snprintf(buffer, kBufferSize, "0x%04x, 0x%04x, ", clue1, clue2);
81 debug_layout_data.append(buffer);
82
83 if (keycode % 4 == 3) {
84 snprintf(buffer, kBufferSize, " // 0x%02x", keycode);
85 debug_layout_data.append(buffer);
86 }
87 }
88 #endif
89
90 } // namespace
91
92 static uint64_t get_logical_key_from_layout(FlKeyEvent* event,
93 const DerivedLayout& layout) {
94 guint8 group = fl_key_event_get_group(event);
95 guint16 keycode = fl_key_event_get_keycode(event);
96 if (keycode >= kLayoutSize) {
97 return 0;
98 }
99
100 auto found_group_layout = layout.find(group);
101 if (found_group_layout != layout.end()) {
102 return found_group_layout->second[keycode];
103 }
104 return 0;
105 }
106
107 /* Define FlKeyboardHandlerUserData */
108
109 /**
110 * FlKeyboardHandlerUserData:
111 * The user_data used when #FlKeyboardHandler sends event to
112 * responders.
113 */
114
115 struct _FlKeyboardHandlerUserData {
116 GObject parent_instance;
117
118 // A weak reference to the owner handler.
119 FlKeyboardHandler* handler;
120 uint64_t sequence_id;
121 };
122
123 G_DEFINE_TYPE(FlKeyboardHandlerUserData,
124 fl_keyboard_handler_user_data,
125 G_TYPE_OBJECT)
126
127 static void fl_keyboard_handler_user_data_dispose(GObject* object) {
128 g_return_if_fail(FL_IS_KEYBOARD_HANDLER_USER_DATA(object));
129 FlKeyboardHandlerUserData* self = FL_KEYBOARD_HANDLER_USER_DATA(object);
130 if (self->handler != nullptr) {
131 g_object_remove_weak_pointer(G_OBJECT(self->handler),
132 reinterpret_cast<gpointer*>(&(self->handler)));
133 self->handler = nullptr;
134 }
135 }
136
137 static void fl_keyboard_handler_user_data_class_init(
138 FlKeyboardHandlerUserDataClass* klass) {
139 G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_user_data_dispose;
140 }
141
142 static void fl_keyboard_handler_user_data_init(
143 FlKeyboardHandlerUserData* self) {}
144
145 // Creates a new FlKeyboardHandlerUserData private class with all information.
146 static FlKeyboardHandlerUserData* fl_keyboard_handler_user_data_new(
147 FlKeyboardHandler* handler,
148 uint64_t sequence_id) {
149 FlKeyboardHandlerUserData* self = FL_KEYBOARD_HANDLER_USER_DATA(
150 g_object_new(fl_keyboard_handler_user_data_get_type(), nullptr));
151
152 self->handler = handler;
153 // Add a weak pointer so we can know if the key event responder disappeared
154 // while the framework was responding.
155 g_object_add_weak_pointer(G_OBJECT(handler),
156 reinterpret_cast<gpointer*>(&(self->handler)));
157 self->sequence_id = sequence_id;
158 return self;
159 }
160
161 /* Define FlKeyboardHandler */
162
163 struct _FlKeyboardHandler {
164 GObject parent_instance;
165
166 FlKeyboardViewDelegate* view_delegate;
167
168 // An array of #FlKeyResponder. Elements are added with
169 // #fl_keyboard_handler_add_responder immediately after initialization and are
170 // automatically released on dispose.
171 GPtrArray* responder_list;
172
173 // An array of #FlKeyboardPendingEvent.
174 //
175 // Its elements are *not* unreferenced when removed. When FlKeyboardHandler is
176 // disposed, this array will be set with a free_func so that the elements are
177 // unreferenced when removed.
178 GPtrArray* pending_responds;
179
180 // An array of #FlKeyboardPendingEvent.
181 //
182 // Its elements are unreferenced when removed.
183 GPtrArray* pending_redispatches;
184
185 // The last sequence ID used. Increased by 1 by every use.
186 uint64_t last_sequence_id;
187
188 // Record the derived layout.
189 //
190 // It is cleared when the platform reports a layout switch. Each entry,
191 // which corresponds to a group, is only initialized on the arrival of the
192 // first event for that group that has a goal keycode.
193 std::unique_ptr<DerivedLayout> derived_layout;
194 // A static map from keycodes to all layout goals.
195 //
196 // It is set up when the handler is initialized and is not changed ever after.
197 std::unique_ptr<std::map<uint16_t, const LayoutGoal*>> keycode_to_goals;
198 // A static map from logical keys to all mandatory layout goals.
199 //
200 // It is set up when the handler is initialized and is not changed ever after.
201 std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
202 logical_to_mandatory_goals;
203
204 // The channel used by the framework to query the keyboard pressed state.
205 FlMethodChannel* channel;
206 };
207
208 G_DEFINE_TYPE(FlKeyboardHandler, fl_keyboard_handler, G_TYPE_OBJECT);
209
210 // This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
211 // reports that can not find symbol g_ptr_array_find_with_equal_func, despite
212 // the fact that it runs well locally.
213 static gboolean g_ptr_array_find_with_equal_func1(GPtrArray* haystack,
214 gconstpointer needle,
215 GEqualFunc equal_func,
216 guint* index_) {
217 guint i;
218 g_return_val_if_fail(haystack != NULL, FALSE);
219 if (equal_func == NULL) {
220 equal_func = g_direct_equal;
221 }
222 for (i = 0; i < haystack->len; i++) {
223 if (equal_func(g_ptr_array_index(haystack, i), needle)) {
224 if (index_ != NULL) {
225 *index_ = i;
226 }
227 return TRUE;
228 }
229 }
230
231 return FALSE;
232 }
233
234 // Compare a #FlKeyboardPendingEvent with the given sequence_id.
235 static gboolean compare_pending_by_sequence_id(gconstpointer a,
236 gconstpointer b) {
237 FlKeyboardPendingEvent* pending =
238 FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
239 uint64_t sequence_id = *reinterpret_cast<const uint64_t*>(b);
240 return fl_keyboard_pending_event_get_sequence_id(pending) == sequence_id;
241 }
242
243 // Compare a #FlKeyboardPendingEvent with the given hash.
244 static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b) {
245 FlKeyboardPendingEvent* pending =
246 FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
247 uint64_t hash = *reinterpret_cast<const uint64_t*>(b);
248 return fl_keyboard_pending_event_get_hash(pending) == hash;
249 }
250
251 // Try to remove a pending event from `pending_redispatches` with the target
252 // hash.
253 //
254 // Returns true if the event is found and removed.
255 static bool fl_keyboard_handler_remove_redispatched(FlKeyboardHandler* self,
256 uint64_t hash) {
257 guint result_index;
258 gboolean found = g_ptr_array_find_with_equal_func1(
259 self->pending_redispatches, static_cast<const uint64_t*>(&hash),
260 compare_pending_by_hash, &result_index);
261 if (found) {
262 // The removed object is freed due to `pending_redispatches`'s free_func.
263 g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
264 return TRUE;
265 } else {
266 return FALSE;
267 }
268 }
269
270 // The callback used by a responder after the event was dispatched.
271 static void responder_handle_event_callback(bool handled,
272 gpointer user_data_ptr) {
273 g_return_if_fail(FL_IS_KEYBOARD_HANDLER_USER_DATA(user_data_ptr));
274 FlKeyboardHandlerUserData* user_data =
275 FL_KEYBOARD_HANDLER_USER_DATA(user_data_ptr);
276 FlKeyboardHandler* self = user_data->handler;
277 g_return_if_fail(self->view_delegate != nullptr);
278
279 guint result_index = -1;
280 gboolean found = g_ptr_array_find_with_equal_func1(
281 self->pending_responds, &user_data->sequence_id,
282 compare_pending_by_sequence_id, &result_index);
283 g_return_if_fail(found);
284 FlKeyboardPendingEvent* pending = FL_KEYBOARD_PENDING_EVENT(
285 g_ptr_array_index(self->pending_responds, result_index));
286 g_return_if_fail(pending != nullptr);
287 fl_keyboard_pending_event_mark_replied(pending, handled);
288 // All responders have replied.
289 if (fl_keyboard_pending_event_is_complete(pending)) {
290 g_object_unref(user_data_ptr);
291 gpointer removed =
292 g_ptr_array_remove_index_fast(self->pending_responds, result_index);
293 g_return_if_fail(removed == pending);
294 bool should_redispatch =
295 !fl_keyboard_pending_event_get_any_handled(pending) &&
296 !fl_keyboard_view_delegate_text_filter_key_press(
297 self->view_delegate, fl_keyboard_pending_event_get_event(pending));
298 if (should_redispatch) {
299 g_ptr_array_add(self->pending_redispatches, pending);
300 fl_keyboard_view_delegate_redispatch_event(
301 self->view_delegate,
302 FL_KEY_EVENT(fl_keyboard_pending_event_get_event(pending)));
303 } else {
304 g_object_unref(pending);
305 }
306 }
307 }
308
309 static uint16_t convert_key_to_char(FlKeyboardViewDelegate* view_delegate,
310 guint keycode,
311 gint group,
312 gint level) {
313 GdkKeymapKey key = {keycode, group, level};
314 constexpr int kBmpMax = 0xD7FF;
315 guint origin = fl_keyboard_view_delegate_lookup_key(view_delegate, &key);
316 return origin < kBmpMax ? origin : 0xFFFF;
317 }
318
319 // Make sure that Flutter has derived the layout for the group of the event,
320 // if the event contains a goal keycode.
321 static void guarantee_layout(FlKeyboardHandler* self, FlKeyEvent* event) {
322 guint8 group = fl_key_event_get_group(event);
323 if (self->derived_layout->find(group) != self->derived_layout->end()) {
324 return;
325 }
326 if (self->keycode_to_goals->find(fl_key_event_get_keycode(event)) ==
327 self->keycode_to_goals->end()) {
328 return;
329 }
330
331 DerivedGroupLayout& layout = (*self->derived_layout)[group];
332
333 // Clone all mandatory goals. Each goal is removed from this cloned map when
334 // fulfilled, and the remaining ones will be assigned to a default position.
335 std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
336 *self->logical_to_mandatory_goals;
337
338 #ifdef DEBUG_PRINT_LAYOUT
339 std::string debug_layout_data;
340 for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
341 std::vector<uint16_t> this_key_clues = {
342 convert_key_to_char(self->view_delegate, keycode, group, 0),
343 convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
344 };
345 debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
346 this_key_clues[1]);
347 }
348 #endif
349
350 // It's important to only traverse layout goals instead of all keycodes.
351 // Some key codes outside of the standard keyboard also gives alpha-numeric
352 // letters, and will therefore take over mandatory goals from standard
353 // keyboard keys if they come first. Example: French keyboard digit 1.
354 for (const LayoutGoal& keycode_goal : layout_goals) {
355 uint16_t keycode = keycode_goal.keycode;
356 std::vector<uint16_t> this_key_clues = {
357 convert_key_to_char(self->view_delegate, keycode, group, 0),
358 convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
359 };
360
361 // The logical key should be the first available clue from below:
362 //
363 // - Mandatory goal, if it matches any clue. This ensures that all alnum
364 // keys can be found somewhere.
365 // - US layout, if neither clue of the key is EASCII. This ensures that
366 // there are no non-latin logical keys.
367 // - A value derived on the fly from keycode & keyval.
368 for (uint16_t clue : this_key_clues) {
369 auto matching_goal = remaining_mandatory_goals.find(clue);
370 if (matching_goal != remaining_mandatory_goals.end()) {
371 // Found a key that produces a mandatory char. Use it.
372 g_return_if_fail(layout[keycode] == 0);
373 layout[keycode] = clue;
374 remaining_mandatory_goals.erase(matching_goal);
375 break;
376 }
377 }
378 bool has_any_eascii =
379 is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
380 // See if any produced char meets the requirement as a logical key.
381 if (layout[keycode] == 0 && !has_any_eascii) {
382 auto found_us_layout = self->keycode_to_goals->find(keycode);
383 if (found_us_layout != self->keycode_to_goals->end()) {
384 layout[keycode] = found_us_layout->second->logical_key;
385 }
386 }
387 }
388
389 // Ensure all mandatory goals are assigned.
390 for (const auto mandatory_goal_iter : remaining_mandatory_goals) {
391 const LayoutGoal* goal = mandatory_goal_iter.second;
392 layout[goal->keycode] = goal->logical_key;
393 }
394 }
395
396 // Returns the keyboard pressed state.
397 static FlMethodResponse* get_keyboard_state(FlKeyboardHandler* self) {
398 g_autoptr(FlValue) result = fl_value_new_map();
399
400 GHashTable* pressing_records =
401 fl_keyboard_view_delegate_get_keyboard_state(self->view_delegate);
402
403 g_hash_table_foreach(
404 pressing_records,
405 [](gpointer key, gpointer value, gpointer user_data) {
406 int64_t physical_key = reinterpret_cast<int64_t>(key);
407 int64_t logical_key = reinterpret_cast<int64_t>(value);
408 FlValue* fl_value_map = reinterpret_cast<FlValue*>(user_data);
409
410 fl_value_set_take(fl_value_map, fl_value_new_int(physical_key),
411 fl_value_new_int(logical_key));
412 },
413 result);
414 return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
415 }
416
417 // Called when a method call on flutter/keyboard is received from Flutter.
418 static void method_call_handler(FlMethodChannel* channel,
419 FlMethodCall* method_call,
420 gpointer user_data) {
421 FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(user_data);
422
423 const gchar* method = fl_method_call_get_name(method_call);
424
425 g_autoptr(FlMethodResponse) response = nullptr;
426 if (strcmp(method, kGetKeyboardStateMethod) == 0) {
427 response = get_keyboard_state(self);
428 } else {
429 response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
430 }
431
432 g_autoptr(GError) error = nullptr;
433 if (!fl_method_call_respond(method_call, response, &error)) {
434 g_warning("Failed to send method call response: %s", error->message);
435 }
436 }
437
438 // The loop body to dispatch an event to a responder.
439 static void dispatch_to_responder(gpointer responder_data,
440 gpointer foreach_data_ptr) {
441 DispatchToResponderLoopContext* context =
442 reinterpret_cast<DispatchToResponderLoopContext*>(foreach_data_ptr);
443 FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
444 fl_key_responder_handle_event(
445 responder, context->event, responder_handle_event_callback,
446 context->user_data, context->specified_logical_key);
447 }
448
449 static void fl_keyboard_handler_dispose(GObject* object) {
450 FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(object);
451
452 if (self->view_delegate != nullptr) {
453 fl_keyboard_view_delegate_subscribe_to_layout_change(self->view_delegate,
454 nullptr);
455 g_object_remove_weak_pointer(
456 G_OBJECT(self->view_delegate),
457 reinterpret_cast<gpointer*>(&(self->view_delegate)));
458 self->view_delegate = nullptr;
459 }
460
461 self->derived_layout.reset();
462 self->keycode_to_goals.reset();
463 self->logical_to_mandatory_goals.reset();
464
465 g_ptr_array_free(self->responder_list, TRUE);
466 g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
467 g_ptr_array_free(self->pending_responds, TRUE);
468 g_ptr_array_free(self->pending_redispatches, TRUE);
469
470 G_OBJECT_CLASS(fl_keyboard_handler_parent_class)->dispose(object);
471 }
472
473 static void fl_keyboard_handler_class_init(FlKeyboardHandlerClass* klass) {
474 G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_dispose;
475 }
476
477 static void fl_keyboard_handler_init(FlKeyboardHandler* self) {
478 self->derived_layout = std::make_unique<DerivedLayout>();
479
480 self->keycode_to_goals =
481 std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
482 self->logical_to_mandatory_goals =
483 std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
484 for (const LayoutGoal& goal : layout_goals) {
485 (*self->keycode_to_goals)[goal.keycode] = &goal;
486 if (goal.mandatory) {
487 (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
488 }
489 }
490
491 self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
492
493 self->pending_responds = g_ptr_array_new();
494 self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
495
496 self->last_sequence_id = 1;
497 }
498
499 FlKeyboardHandler* fl_keyboard_handler_new(
500 FlBinaryMessenger* messenger,
501 FlKeyboardViewDelegate* view_delegate) {
502 g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate), nullptr);
503
504 FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(
505 g_object_new(fl_keyboard_handler_get_type(), nullptr));
506
507 self->view_delegate = view_delegate;
508 g_object_add_weak_pointer(
509 G_OBJECT(view_delegate),
510 reinterpret_cast<gpointer*>(&(self->view_delegate)));
511
512 // The embedder responder must be added before the channel responder.
513 g_ptr_array_add(
514 self->responder_list,
515 FL_KEY_RESPONDER(fl_key_embedder_responder_new(
516 [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
517 void* callback_user_data, void* send_key_event_user_data) {
518 FlKeyboardHandler* self =
519 FL_KEYBOARD_HANDLER(send_key_event_user_data);
520 g_return_if_fail(self->view_delegate != nullptr);
521 fl_keyboard_view_delegate_send_key_event(
522 self->view_delegate, event, callback, callback_user_data);
523 },
524 self)));
525 g_ptr_array_add(self->responder_list,
526 FL_KEY_RESPONDER(fl_key_channel_responder_new(
527 fl_keyboard_view_delegate_get_messenger(view_delegate))));
528
529 fl_keyboard_view_delegate_subscribe_to_layout_change(
530 self->view_delegate, [self]() { self->derived_layout->clear(); });
531
532 // Setup the flutter/keyboard channel.
533 g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
534 self->channel =
535 fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
536 fl_method_channel_set_method_call_handler(self->channel, method_call_handler,
537 self, nullptr);
538 return self;
539 }
540
541 gboolean fl_keyboard_handler_handle_event(FlKeyboardHandler* self,
542 FlKeyEvent* event) {
543 g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), FALSE);
544 g_return_val_if_fail(event != nullptr, FALSE);
545 g_return_val_if_fail(self->view_delegate != nullptr, FALSE);
546
547 guarantee_layout(self, event);
548
549 uint64_t incoming_hash = fl_key_event_hash(event);
550 if (fl_keyboard_handler_remove_redispatched(self, incoming_hash)) {
551 return FALSE;
552 }
553
554 FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(
555 event, ++self->last_sequence_id, self->responder_list->len);
556
557 g_ptr_array_add(self->pending_responds, pending);
558 FlKeyboardHandlerUserData* user_data = fl_keyboard_handler_user_data_new(
559 self, fl_keyboard_pending_event_get_sequence_id(pending));
560 DispatchToResponderLoopContext data{
561 .event = event,
562 .specified_logical_key =
563 get_logical_key_from_layout(event, *self->derived_layout),
564 .user_data = user_data,
565 };
566 g_ptr_array_foreach(self->responder_list, dispatch_to_responder, &data);
567
568 return TRUE;
569 }
570
571 gboolean fl_keyboard_handler_is_state_clear(FlKeyboardHandler* self) {
572 g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), FALSE);
573 return self->pending_responds->len == 0 &&
574 self->pending_redispatches->len == 0;
575 }
576
577 void fl_keyboard_handler_sync_modifier_if_needed(FlKeyboardHandler* self,
578 guint state,
579 double event_time) {
580 g_return_if_fail(FL_IS_KEYBOARD_HANDLER(self));
581
582 // The embedder responder is the first element in
583 // FlKeyboardHandler.responder_list.
584 FlKeyEmbedderResponder* responder =
585 FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
586 fl_key_embedder_responder_sync_modifiers_if_needed(responder, state,
587 event_time);
588 }
589
590 GHashTable* fl_keyboard_handler_get_pressed_state(FlKeyboardHandler* self) {
591 g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), nullptr);
592
593 // The embedder responder is the first element in
594 // FlKeyboardHandler.responder_list.
595 FlKeyEmbedderResponder* responder =
596 FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
597 return fl_key_embedder_responder_get_pressed_state(responder);
598 }
fl_keyboard_pending_event_get_hash
uint64_t fl_keyboard_pending_event_get_hash(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:81
fl_keyboard_handler_handle_event
gboolean fl_keyboard_handler_handle_event(FlKeyboardHandler *self, FlKeyEvent *event)
Definition: fl_keyboard_handler.cc:541
if
if(end==-1)
Definition: fl_accessible_text_field.cc:42
fl_keyboard_view_delegate_redispatch_event
void fl_keyboard_view_delegate_redispatch_event(FlKeyboardViewDelegate *self, FlKeyEvent *event)
Definition: fl_keyboard_view_delegate.cc:42
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
get_keyboard_state
static FlMethodResponse * get_keyboard_state(FlKeyboardHandler *self)
Definition: fl_keyboard_handler.cc:397
fl_keyboard_pending_event_get_event
FlKeyEvent * fl_keyboard_pending_event_get_event(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:70
layout_goals
const std::vector< LayoutGoal > layout_goals
Definition: key_mapping.g.cc:462
kChannelName
static constexpr char kChannelName[]
Definition: fl_keyboard_handler.cc:23
_FlKeyboardHandler::derived_layout
std::unique_ptr< DerivedLayout > derived_layout
Definition: fl_keyboard_handler.cc:193
fl_method_channel_new
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
Definition: fl_method_channel.cc:112
fl_key_event_get_group
guint8 fl_key_event_get_group(FlKeyEvent *self)
Definition: fl_key_event.cc:104
fl_key_embedder_responder_get_pressed_state
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
Definition: fl_key_embedder_responder.cc:896
fl_keyboard_view_delegate_subscribe_to_layout_change
void fl_keyboard_view_delegate_subscribe_to_layout_change(FlKeyboardViewDelegate *self, KeyboardLayoutNotifier notifier)
Definition: fl_keyboard_view_delegate.cc:51
LayoutGoal
Definition: key_mapping.h:40
fl_keyboard_handler_user_data_class_init
static void fl_keyboard_handler_user_data_class_init(FlKeyboardHandlerUserDataClass *klass)
Definition: fl_keyboard_handler.cc:137
fl_method_not_implemented_response_new
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
Definition: fl_method_response.cc:179
fl_standard_method_codec_new
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
Definition: fl_standard_method_codec.cc:291
_FlKeyboardHandler::pending_responds
GPtrArray * pending_responds
Definition: fl_keyboard_handler.cc:178
_FlKeyboardHandlerUserData
Definition: fl_keyboard_handler.cc:115
fl_keyboard_handler_get_pressed_state
GHashTable * fl_keyboard_handler_get_pressed_state(FlKeyboardHandler *self)
Definition: fl_keyboard_handler.cc:590
fl_key_embedder_responder.h
fl_method_channel.h
i
int i
Definition: fl_socket_accessible.cc:18
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_keyboard_handler_user_data_new
static FlKeyboardHandlerUserData * fl_keyboard_handler_user_data_new(FlKeyboardHandler *handler, uint64_t sequence_id)
Definition: fl_keyboard_handler.cc:146
LayoutGoal::keycode
uint16_t keycode
Definition: key_mapping.h:42
LayoutGoal::logical_key
uint64_t logical_key
Definition: key_mapping.h:45
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
fl_value_set_take
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition: fl_value.cc:618
_FlKeyboardHandlerUserData::sequence_id
uint64_t sequence_id
Definition: fl_keyboard_handler.cc:120
_FlKeyboardHandlerUserData::handler
FlKeyboardHandler * handler
Definition: fl_keyboard_handler.cc:119
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
convert_key_to_char
static uint16_t convert_key_to_char(FlKeyboardViewDelegate *view_delegate, guint keycode, gint group, gint level)
Definition: fl_keyboard_handler.cc:309
fl_method_success_response_new
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
Definition: fl_method_response.cc:126
state
AtkStateType state
Definition: fl_accessible_node.cc:10
fl_key_channel_responder_new
FlKeyChannelResponder * fl_key_channel_responder_new(FlBinaryMessenger *messenger, FlKeyChannelResponderMock *mock)
Definition: fl_key_channel_responder.cc:186
g_ptr_array_find_with_equal_func1
static gboolean g_ptr_array_find_with_equal_func1(GPtrArray *haystack, gconstpointer needle, GEqualFunc equal_func, guint *index_)
Definition: fl_keyboard_handler.cc:213
fl_keyboard_pending_event_get_sequence_id
uint64_t fl_keyboard_pending_event_get_sequence_id(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:75
fl_keyboard_handler.h
fl_keyboard_view_delegate_lookup_key
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate *self, const GdkKeymapKey *key)
Definition: fl_keyboard_view_delegate.cc:60
fl_keyboard_pending_event_is_complete
gboolean fl_keyboard_pending_event_is_complete(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:102
kGetKeyboardStateMethod
static constexpr char kGetKeyboardStateMethod[]
Definition: fl_keyboard_handler.cc:24
fl_keyboard_pending_event_get_any_handled
gboolean fl_keyboard_pending_event_get_any_handled(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:96
fl_key_embedder_responder_new
FlKeyEmbedderResponder * fl_key_embedder_responder_new(EmbedderSendKeyEvent send_key_event, void *send_key_event_user_data)
Definition: fl_key_embedder_responder.cc:263
fl_method_call_respond
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
Definition: fl_method_call.cc:77
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
guarantee_layout
static void guarantee_layout(FlKeyboardHandler *self, FlKeyEvent *event)
Definition: fl_keyboard_handler.cc:321
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
fl_key_responder_handle_event
void fl_key_responder_handle_event(FlKeyResponder *self, FlKeyEvent *event, FlKeyResponderAsyncCallback callback, gpointer user_data, uint64_t specified_logical_key)
Definition: fl_key_responder.cc:11
fl_keyboard_handler_remove_redispatched
static bool fl_keyboard_handler_remove_redispatched(FlKeyboardHandler *self, uint64_t hash)
Definition: fl_keyboard_handler.cc:255
fl_keyboard_pending_event_mark_replied
void fl_keyboard_pending_event_mark_replied(FlKeyboardPendingEvent *self, gboolean handled)
Definition: fl_keyboard_pending_event.cc:86
_FlKeyboardHandler::parent_instance
GObject parent_instance
Definition: fl_keyboard_handler.cc:164
fl_method_call_get_name
const G_MODULE_EXPORT gchar * fl_method_call_get_name(FlMethodCall *self)
Definition: fl_method_call.cc:67
key_mapping.h
fl_keyboard_handler_is_state_clear
gboolean fl_keyboard_handler_is_state_clear(FlKeyboardHandler *self)
Definition: fl_keyboard_handler.cc:571
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
_FlKeyboardHandler::keycode_to_goals
std::unique_ptr< std::map< uint16_t, const LayoutGoal * > > keycode_to_goals
Definition: fl_keyboard_handler.cc:197
responder_handle_event_callback
static void responder_handle_event_callback(bool handled, gpointer user_data_ptr)
Definition: fl_keyboard_handler.cc:271
fl_keyboard_handler_user_data_init
static void fl_keyboard_handler_user_data_init(FlKeyboardHandlerUserData *self)
Definition: fl_keyboard_handler.cc:142
_FlKeyboardHandler::logical_to_mandatory_goals
std::unique_ptr< std::map< uint64_t, const LayoutGoal * > > logical_to_mandatory_goals
Definition: fl_keyboard_handler.cc:202
fl_keyboard_view_delegate_text_filter_key_press
gboolean fl_keyboard_view_delegate_text_filter_key_press(FlKeyboardViewDelegate *self, FlKeyEvent *event)
Definition: fl_keyboard_view_delegate.cc:25
fl_key_embedder_responder_sync_modifiers_if_needed
void fl_key_embedder_responder_sync_modifiers_if_needed(FlKeyEmbedderResponder *responder, guint state, double event_time)
Definition: fl_key_embedder_responder.cc:879
_FlKeyboardHandlerUserData::parent_instance
GObject parent_instance
Definition: fl_keyboard_handler.cc:116
FL
FL
Definition: fl_binary_messenger.cc:27
method_call_handler
static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
Definition: fl_keyboard_handler.cc:418
fl_standard_method_codec.h
fl_method_channel_set_method_call_handler
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_method_channel.cc:134
result
GAsyncResult * result
Definition: fl_text_input_handler.cc:106
fl_key_event_hash
uint64_t fl_key_event_hash(FlKeyEvent *self)
Definition: fl_key_event.cc:114
fl_key_event_get_keycode
guint16 fl_key_event_get_keycode(FlKeyEvent *self)
Definition: fl_key_event.cc:89
compare_pending_by_hash
static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b)
Definition: fl_keyboard_handler.cc:244
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_keyboard_handler_sync_modifier_if_needed
void fl_keyboard_handler_sync_modifier_if_needed(FlKeyboardHandler *self, guint state, double event_time)
Definition: fl_keyboard_handler.cc:577
_FlKeyboardHandler::channel
FlMethodChannel * channel
Definition: fl_keyboard_handler.cc:205
fl_keyboard_view_delegate_get_messenger
FlBinaryMessenger * fl_keyboard_view_delegate_get_messenger(FlKeyboardViewDelegate *self)
Definition: fl_keyboard_view_delegate.cc:35
compare_pending_by_sequence_id
static gboolean compare_pending_by_sequence_id(gconstpointer a, gconstpointer b)
Definition: fl_keyboard_handler.cc:235
fl_keyboard_handler_class_init
static void fl_keyboard_handler_class_init(FlKeyboardHandlerClass *klass)
Definition: fl_keyboard_handler.cc:473
buffer
static const uint8_t buffer[]
Definition: fl_pixel_buffer_texture_test.cc:44
fl_keyboard_handler_init
static void fl_keyboard_handler_init(FlKeyboardHandler *self)
Definition: fl_keyboard_handler.cc:477
specified_logical_key
FlKeyEvent uint64_t specified_logical_key
Definition: fl_key_channel_responder.cc:119
fl_keyboard_pending_event_new
FlKeyboardPendingEvent * fl_keyboard_pending_event_new(FlKeyEvent *event, uint64_t sequence_id, size_t to_reply)
Definition: fl_keyboard_pending_event.cc:55
fl_keyboard_pending_event.h
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
_FlKeyboardHandler::view_delegate
FlKeyboardViewDelegate * view_delegate
Definition: fl_keyboard_handler.cc:166
fl_key_channel_responder.h
dispatch_to_responder
static void dispatch_to_responder(gpointer responder_data, gpointer foreach_data_ptr)
Definition: fl_keyboard_handler.cc:439
_FlKeyboardHandler::last_sequence_id
uint64_t last_sequence_id
Definition: fl_keyboard_handler.cc:186
fl_keyboard_view_delegate_send_key_event
void fl_keyboard_view_delegate_send_key_event(FlKeyboardViewDelegate *self, const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *user_data)
Definition: fl_keyboard_view_delegate.cc:14
fl_keyboard_view_delegate_get_keyboard_state
GHashTable * fl_keyboard_view_delegate_get_keyboard_state(FlKeyboardViewDelegate *self)
Definition: fl_keyboard_view_delegate.cc:67
get_logical_key_from_layout
static uint64_t get_logical_key_from_layout(FlKeyEvent *event, const DerivedLayout &layout)
Definition: fl_keyboard_handler.cc:92
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_keyboard_handler_new
FlKeyboardHandler * fl_keyboard_handler_new(FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
Definition: fl_keyboard_handler.cc:499
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlKeyboardHandlerUserData, fl_keyboard_handler_user_data, FL, KEYBOARD_HANDLER_USER_DATA, GObject)
_FlKeyboardHandler::pending_redispatches
GPtrArray * pending_redispatches
Definition: fl_keyboard_handler.cc:183
_FlKeyboardHandler
Definition: fl_keyboard_handler.cc:163
_FlKeyboardHandler::responder_list
GPtrArray * responder_list
Definition: fl_keyboard_handler.cc:171
G_DEFINE_TYPE
G_DEFINE_TYPE(FlKeyboardHandlerUserData, fl_keyboard_handler_user_data, G_TYPE_OBJECT) static void fl_keyboard_handler_user_data_dispose(GObject *object)
Definition: fl_keyboard_handler.cc:123
fl_keyboard_handler_dispose
static void fl_keyboard_handler_dispose(GObject *object)
Definition: fl_keyboard_handler.cc:449