Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_json_method_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_json_method_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_key_event_plugin.cc
FILE: ../../../flutter/shell/platform/linux/fl_key_event_plugin.h
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_method_call.cc
Expand Down
1 change: 1 addition & 0 deletions shell/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ source_set("flutter_linux") {
"fl_engine.cc",
"fl_json_message_codec.cc",
"fl_json_method_codec.cc",
"fl_key_event_plugin.cc",
"fl_message_codec.cc",
"fl_method_call.cc",
"fl_method_channel.cc",
Expand Down
255 changes: 255 additions & 0 deletions shell/platform/linux/fl_key_event_plugin.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
// 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.

#include "flutter/shell/platform/linux/fl_key_event_plugin.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"

static constexpr char kChannelName[] = "flutter/keyevent";
static constexpr char kTypeKey[] = "type";
static constexpr char kTypeValueUp[] = "keyup";
static constexpr char kTypeValueDown[] = "keydown";
static constexpr char kKeymapKey[] = "keymap";
static constexpr char kKeyCodeKey[] = "keyCode";
static constexpr char kScanCodeKey[] = "scanCode";
static constexpr char kModifiersKey[] = "modifiers";
static constexpr char kToolkitKey[] = "toolkit";
static constexpr char kUnicodeScalarValuesKey[] = "unicodeScalarValues";

static constexpr char kGLFWToolkit[] = "glfw";
static constexpr char kLinuxKeymap[] = "linux";

struct _FlKeyEventPlugin {
GObject parent_instance;

FlBasicMessageChannel* channel;
};

G_DEFINE_TYPE(FlKeyEventPlugin, fl_key_event_plugin, G_TYPE_OBJECT)

// Converts a Gdk key code to its GLFW equivalent.
// TODO(robert-ancell) Create a "gtk" toolkit in Flutter so we don't have to
// convert values. https://github.com/flutter/flutter/issues/57603
static int gdk_keyval_to_glfw_key_code(guint keyval) {
switch (keyval) {
case GDK_KEY_space:
return 32;
case GDK_KEY_apostrophe:
return 39;
case GDK_KEY_comma:
return 44;
case GDK_KEY_minus:
return 45;
case GDK_KEY_period:
return 46;
case GDK_KEY_slash:
return 47;
case GDK_KEY_0:
return 48;
case GDK_KEY_1:
return 49;
case GDK_KEY_2:
return 50;
case GDK_KEY_3:
return 51;
case GDK_KEY_4:
return 52;
case GDK_KEY_5:
return 53;
case GDK_KEY_6:
return 54;
case GDK_KEY_7:
return 55;
case GDK_KEY_8:
return 56;
case GDK_KEY_9:
return 57;
case GDK_KEY_semicolon:
return 59;
case GDK_KEY_equal:
return 61;
case GDK_KEY_a:
return 65;
case GDK_KEY_b:
return 66;
case GDK_KEY_c:
return 67;
case GDK_KEY_d:
return 68;
case GDK_KEY_e:
return 69;
case GDK_KEY_f:
return 70;
case GDK_KEY_g:
return 71;
case GDK_KEY_h:
return 72;
case GDK_KEY_i:
return 73;
case GDK_KEY_j:
return 74;
case GDK_KEY_k:
return 75;
case GDK_KEY_l:
return 76;
case GDK_KEY_m:
return 77;
case GDK_KEY_n:
return 78;
case GDK_KEY_o:
return 79;
case GDK_KEY_p:
return 80;
case GDK_KEY_q:
return 81;
case GDK_KEY_r:
return 82;
case GDK_KEY_s:
return 83;
case GDK_KEY_t:
return 84;
case GDK_KEY_u:
return 85;
case GDK_KEY_v:
return 86;
case GDK_KEY_w:
return 87;
case GDK_KEY_x:
return 88;
case GDK_KEY_y:
return 89;
case GDK_KEY_z:
return 90;
case GDK_KEY_bracketleft:
return 91;
case GDK_KEY_bracketright:
return 92;
case GDK_KEY_grave:
return 96;
case GDK_KEY_Escape:
return 256;
case GDK_KEY_Return:
return 257;
case GDK_KEY_Tab:
return 258;
case GDK_KEY_BackSpace:
return 259;
case GDK_KEY_Insert:
return 260;
case GDK_KEY_Delete:
return 261;
case GDK_KEY_Right:
return 262;
case GDK_KEY_Left:
return 263;
case GDK_KEY_Down:
return 264;
case GDK_KEY_Up:
return 265;
case GDK_KEY_Page_Up:
return 266;
case GDK_KEY_Page_Down:
return 267;
case GDK_KEY_Home:
return 268;
case GDK_KEY_End:
return 269;
case GDK_KEY_Shift_L:
return 340;
case GDK_KEY_Control_L:
return 341;
case GDK_KEY_Alt_L:
return 342;
case GDK_KEY_Super_L:
return 343;
case GDK_KEY_Shift_R:
return 344;
case GDK_KEY_Control_R:
return 345;
case GDK_KEY_Alt_R:
return 346;
case GDK_KEY_Super_R:
return 347;
default:
return 0;
}
}

// Converts a Gdk key state to its GLFW equivalent.
int64_t gdk_state_to_glfw_modifiers(guint8 state) {
int64_t modifiers = 0;

if ((state & GDK_SHIFT_MASK) != 0)
modifiers |= 0x0001;
if ((state & GDK_CONTROL_MASK) != 0)
modifiers |= 0x0002;
if ((state & GDK_MOD1_MASK) != 0)
modifiers |= 0x0004;
if ((state & GDK_SUPER_MASK) != 0)
modifiers |= 0x0008;

return modifiers;
}

static void fl_key_event_plugin_dispose(GObject* object) {
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(object);

g_clear_object(&self->channel);

G_OBJECT_CLASS(fl_key_event_plugin_parent_class)->dispose(object);
}

static void fl_key_event_plugin_class_init(FlKeyEventPluginClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_key_event_plugin_dispose;
}

static void fl_key_event_plugin_init(FlKeyEventPlugin* self) {}

FlKeyEventPlugin* fl_key_event_plugin_new(FlBinaryMessenger* messenger) {
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);

FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(
g_object_new(fl_key_event_plugin_get_type(), nullptr));

g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
self->channel = fl_basic_message_channel_new(messenger, kChannelName,
FL_MESSAGE_CODEC(codec));

return self;
}

void fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
GdkEventKey* event) {
g_return_if_fail(FL_IS_KEY_EVENT_PLUGIN(self));
g_return_if_fail(event != nullptr);

const gchar* type;
if (event->type == GDK_KEY_PRESS)
type = kTypeValueDown;
else if (event->type == GDK_KEY_RELEASE)
type = kTypeValueUp;
else
return;

int64_t scan_code = event->hardware_keycode;
int64_t key_code = gdk_keyval_to_glfw_key_code(event->keyval);
int64_t modifiers = gdk_state_to_glfw_modifiers(event->state);
int64_t unicodeScalarValues = gdk_keyval_to_unicode(event->keyval);

g_autoptr(FlValue) message = fl_value_new_map();
fl_value_set_string_take(message, kTypeKey, fl_value_new_string(type));
fl_value_set_string_take(message, kKeymapKey,
fl_value_new_string(kLinuxKeymap));
fl_value_set_string_take(message, kScanCodeKey, fl_value_new_int(scan_code));
fl_value_set_string_take(message, kToolkitKey,
fl_value_new_string(kGLFWToolkit));
fl_value_set_string_take(message, kKeyCodeKey, fl_value_new_int(key_code));
fl_value_set_string_take(message, kModifiersKey, fl_value_new_int(modifiers));
if (unicodeScalarValues != 0)
fl_value_set_string_take(message, kUnicodeScalarValuesKey,
fl_value_new_int(unicodeScalarValues));

fl_basic_message_channel_send(self->channel, message, nullptr, nullptr,
nullptr);
}
49 changes: 49 additions & 0 deletions shell/platform/linux/fl_key_event_plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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 FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_

#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"

#include <gdk/gdk.h>

G_BEGIN_DECLS

G_DECLARE_FINAL_TYPE(FlKeyEventPlugin,
fl_key_event_plugin,
FL,
KEY_EVENT_PLUGIN,
GObject);

/**
* FlKeyEventPlugin:
*
* #FlKeyEventPlugin is a plugin that implements the shell side
* of SystemChannels.keyEvent from the Flutter services library.
*/

/**
* fl_key_event_plugin_new:
* @messenger: an #FlBinaryMessenger.
*
* Creates a #FlKeyEventPlugin.
*
* Returns: a new #FlKeyEventPlugin.
*/
FlKeyEventPlugin* fl_key_event_plugin_new(FlBinaryMessenger* messenger);

/**
* fl_key_event_plugin_send_key_event:
* @plugin: an #FlKeyEventPlugin.
* @event: a #GdkEventKey.
*
* Sends a key event to Flutter.
*/
void fl_key_event_plugin_send_key_event(FlKeyEventPlugin* plugin,
GdkEventKey* event);

G_END_DECLS

#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_
Loading