Flutter Linux Embedder
fl_text_input_handler_test.cc File Reference
#include <utility>
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
#include "flutter/shell/platform/linux/fl_text_input_handler.h"
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"
#include "flutter/shell/platform/linux/testing/mock_gtk.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

Go to the source code of this file.

Classes

struct  InputConfig
 
struct  EditingState
 
struct  EditingDelta
 

Functions

static FlValuebuild_map (std::map< const gchar *, FlValue * > args)
 
static FlValuebuild_list (std::vector< FlValue * > args)
 
static FlValuebuild_input_config (InputConfig config)
 
static FlValuebuild_editing_state (EditingState state)
 
static FlValuebuild_editing_delta (EditingDelta delta)
 
static void set_client (FlMockBinaryMessenger *messenger, InputConfig config)
 
static void set_editing_state (FlMockBinaryMessenger *messenger, EditingState state)
 
static void send_key_event (FlTextInputHandler *handler, gint keyval, gint state=0)
 
 TEST (FlTextInputHandlerTest, MessageHandler)
 
 TEST (FlTextInputHandlerTest, SetClient)
 
 TEST (FlTextInputHandlerTest, Show)
 
 TEST (FlTextInputHandlerTest, Hide)
 
 TEST (FlTextInputHandlerTest, ClearClient)
 
 TEST (FlTextInputHandlerTest, PerformAction)
 
 TEST (FlTextInputHandlerTest, MultilineWithSendAction)
 
 TEST (FlTextInputHandlerTest, MoveCursor)
 
 TEST (FlTextInputHandlerTest, Select)
 
 TEST (FlTextInputHandlerTest, Composing)
 
 TEST (FlTextInputHandlerTest, SurroundingText)
 
 TEST (FlTextInputHandlerTest, SetMarkedTextRect)
 
 TEST (FlTextInputHandlerTest, TextInputTypeNone)
 
 TEST (FlTextInputHandlerTest, TextEditingDelta)
 
 TEST (FlTextInputHandlerTest, ComposingDelta)
 
 TEST (FlTextInputHandlerTest, NonComposingDelta)
 
 TEST (FlTextInputHandlerTest, InputPurposeNumber)
 
 TEST (FlTextInputHandlerTest, InputPurposePhone)
 
 TEST (FlTextInputHandlerTest, InputPurposeEmail)
 
 TEST (FlTextInputHandlerTest, InputPurposeUrl)
 
 TEST (FlTextInputHandlerTest, InputPurposePassword)
 
 TEST (FlTextInputHandlerTest, InputPurposeName)
 
 TEST (FlTextInputHandlerTest, InputHintsAddress)
 
 TEST (FlTextInputHandlerTest, InputHintsMultiline)
 
 TEST (FlTextInputHandlerTest, InputHintsWebSearch)
 
 TEST (FlTextInputHandlerTest, InputHintsTwitter)
 
 TEST (FlTextInputHandlerTest, DefaultInputPurposeAndHints)
 
 TEST (FlTextInputHandlerTest, UpdateConfig)
 

Function Documentation

◆ build_editing_delta()

static FlValue* build_editing_delta ( EditingDelta  delta)
static

Definition at line 85 of file fl_text_input_handler_test.cc.

85  {
86  return build_map({
87  {"oldText", fl_value_new_string(delta.old_text)},
88  {"deltaText", fl_value_new_string(delta.delta_text)},
89  {"deltaStart", fl_value_new_int(delta.delta_start)},
90  {"deltaEnd", fl_value_new_int(delta.delta_end)},
91  {"selectionBase", fl_value_new_int(delta.selection_base)},
92  {"selectionExtent", fl_value_new_int(delta.selection_extent)},
93  {"selectionAffinity", fl_value_new_string("TextAffinity.downstream")},
94  {"selectionIsDirectional", fl_value_new_bool(false)},
95  {"composingBase", fl_value_new_int(delta.composing_base)},
96  {"composingExtent", fl_value_new_int(delta.composing_extent)},
97  });
98 }
static FlValue * build_map(std::map< const gchar *, FlValue * > args)
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262

References build_map(), EditingDelta::composing_base, EditingDelta::composing_extent, EditingDelta::delta_end, EditingDelta::delta_start, EditingDelta::delta_text, fl_value_new_bool(), fl_value_new_int(), fl_value_new_string(), EditingDelta::old_text, EditingDelta::selection_base, and EditingDelta::selection_extent.

Referenced by TEST().

◆ build_editing_state()

static FlValue* build_editing_state ( EditingState  state)
static

Definition at line 62 of file fl_text_input_handler_test.cc.

62  {
63  return build_map({
64  {"text", fl_value_new_string(state.text)},
65  {"selectionBase", fl_value_new_int(state.selection_base)},
66  {"selectionExtent", fl_value_new_int(state.selection_extent)},
67  {"selectionAffinity", fl_value_new_string("TextAffinity.downstream")},
68  {"selectionIsDirectional", fl_value_new_bool(false)},
69  {"composingBase", fl_value_new_int(state.composing_base)},
70  {"composingExtent", fl_value_new_int(state.composing_extent)},
71  });
72 }

References build_map(), EditingState::composing_base, EditingState::composing_extent, fl_value_new_bool(), fl_value_new_int(), fl_value_new_string(), EditingState::selection_base, EditingState::selection_extent, and EditingState::text.

Referenced by set_editing_state(), and TEST().

◆ build_input_config()

static FlValue* build_input_config ( InputConfig  config)
static

Definition at line 41 of file fl_text_input_handler_test.cc.

41  {
42  return build_list({
44  build_map({
45  {"inputAction", fl_value_new_string(config.input_action)},
46  {"inputType", build_map({
47  {"name", fl_value_new_string(config.input_type)},
48  })},
49  {"enableDeltaModel", fl_value_new_bool(config.enable_delta_model)},
50  }),
51  });
52 }
static FlValue * build_list(std::vector< FlValue * > args)
const gchar * input_action

References build_list(), build_map(), InputConfig::client_id, InputConfig::enable_delta_model, fl_value_new_bool(), fl_value_new_int(), fl_value_new_string(), InputConfig::input_action, and InputConfig::input_type.

Referenced by set_client().

◆ build_list()

static FlValue* build_list ( std::vector< FlValue * >  args)
static

Definition at line 26 of file fl_text_input_handler_test.cc.

26  {
28  for (auto it = args.begin(); it != args.end(); ++it) {
30  }
31  return value;
32 }
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint8_t value
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:349
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:600
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42

References args, fl_value_append_take(), fl_value_new_list(), and value.

Referenced by build_input_config(), and TEST().

◆ build_map()

static FlValue* build_map ( std::map< const gchar *, FlValue * >  args)
static

Definition at line 18 of file fl_text_input_handler_test.cc.

18  {
20  for (auto it = args.begin(); it != args.end(); ++it) {
21  fl_value_set_string_take(value, it->first, it->second);
22  }
23  return value;
24 }
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366

References args, fl_value_new_map(), fl_value_set_string_take(), and value.

Referenced by build_editing_delta(), build_editing_state(), build_input_config(), and TEST().

◆ send_key_event()

static void send_key_event ( FlTextInputHandler *  handler,
gint  keyval,
gint  state = 0 
)
static

Definition at line 143 of file fl_text_input_handler_test.cc.

145  {
146  GdkEvent* gdk_event = gdk_event_new(GDK_KEY_PRESS);
147  gdk_event->key.keyval = keyval;
148  gdk_event->key.state = state;
149  g_autoptr(FlKeyEvent) key_event = fl_key_event_new_from_gdk_event(gdk_event);
150  fl_text_input_handler_filter_keypress(handler, key_event);
151 }
g_autoptr(FlEngine) engine
FlKeyEvent * fl_key_event_new_from_gdk_event(GdkEvent *event)
Definition: fl_key_event.cc:53
gboolean fl_text_input_handler_filter_keypress(FlTextInputHandler *self, FlKeyEvent *event)

References fl_key_event_new_from_gdk_event(), fl_text_input_handler_filter_keypress(), and g_autoptr().

Referenced by TEST().

◆ set_client()

static void set_client ( FlMockBinaryMessenger *  messenger,
InputConfig  config 
)
static

Definition at line 100 of file fl_text_input_handler_test.cc.

100  {
101  gboolean called = FALSE;
103  fl_mock_binary_messenger_invoke_json_method(
104  messenger, "flutter/textinput", "TextInput.setClient", args,
105  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
106  gpointer user_data) {
107  gboolean* called = static_cast<gboolean*>(user_data);
108  *called = TRUE;
109 
110  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
111 
112  g_autoptr(FlValue) expected_result = fl_value_new_null();
114  FL_METHOD_SUCCESS_RESPONSE(response)),
115  expected_result));
116  },
117  &called);
118  EXPECT_TRUE(called);
119 }
const char FlTextDirection FlAssertiveness gpointer user_data
return TRUE
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
static FlValue * build_input_config(InputConfig config)
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:471

References args, build_input_config(), fl_method_success_response_get_result(), fl_value_equal(), fl_value_new_null(), g_autoptr(), TRUE, and user_data.

Referenced by TEST().

◆ set_editing_state()

static void set_editing_state ( FlMockBinaryMessenger *  messenger,
EditingState  state 
)
static

Definition at line 121 of file fl_text_input_handler_test.cc.

122  {
123  gboolean called = FALSE;
125  fl_mock_binary_messenger_invoke_json_method(
126  messenger, "flutter/textinput", "TextInput.setEditingState", args,
127  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
128  gpointer user_data) {
129  gboolean* called = static_cast<gboolean*>(user_data);
130  *called = TRUE;
131 
132  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
133 
134  g_autoptr(FlValue) expected_result = fl_value_new_null();
136  FL_METHOD_SUCCESS_RESPONSE(response)),
137  expected_result));
138  },
139  &called);
140  EXPECT_TRUE(called);
141 }
static FlValue * build_editing_state(EditingState state)

References args, build_editing_state(), fl_method_success_response_get_result(), fl_value_equal(), fl_value_new_null(), g_autoptr(), TRUE, and user_data.

Referenced by TEST().

◆ TEST() [1/28]

TEST ( FlTextInputHandlerTest  ,
ClearClient   
)

Definition at line 242 of file fl_text_input_handler_test.cc.

242  {
243  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
244  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
245 
246  g_autoptr(FlTextInputHandler) handler =
247  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
248  EXPECT_NE(handler, nullptr);
249 
250  gboolean called = FALSE;
251  fl_mock_binary_messenger_invoke_json_method(
252  messenger, "flutter/textinput", "TextInput.clearClient", nullptr,
253  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
254  gpointer user_data) {
255  gboolean* called = static_cast<gboolean*>(user_data);
256  *called = TRUE;
257 
258  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
259 
260  g_autoptr(FlValue) expected_result = fl_value_new_null();
262  FL_METHOD_SUCCESS_RESPONSE(response)),
263  expected_result));
264  },
265  &called);
266  EXPECT_TRUE(called);
267 
268  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
269 }
void fl_binary_messenger_shutdown(FlBinaryMessenger *self)
FlTextInputHandler * fl_text_input_handler_new(FlBinaryMessenger *messenger)

References fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_null(), g_autoptr(), TRUE, and user_data.

◆ TEST() [2/28]

TEST ( FlTextInputHandlerTest  ,
Composing   
)

Definition at line 519 of file fl_text_input_handler_test.cc.

519  {
520  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
521  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
522 
523  g_autoptr(FlTextInputHandler) handler =
524  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
525  EXPECT_NE(handler, nullptr);
526 
527  // update
528  EXPECT_CALL(mock_gtk, gtk_im_context_get_preedit_string(
529  ::testing::_, ::testing::A<gchar**>(), ::testing::_,
530  ::testing::A<gint*>()))
531  .WillOnce(
532  ::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter")),
533  ::testing::SetArgPointee<3>(0)));
534 
535  int call_count = 0;
536  fl_mock_binary_messenger_set_json_method_channel(
537  messenger, "flutter/textinput",
538  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
539  FlValue* args, gpointer user_data) {
540  int* call_count = static_cast<int*>(user_data);
541 
542  EXPECT_STREQ(name, "TextInputClient.updateEditingState");
543  g_autoptr(FlValue) expected_args = nullptr;
544  switch (*call_count) {
545  case 0:
546  expected_args = build_list({
547  fl_value_new_int(-1), // client_id
549  .text = "Flutter",
550  .selection_base = 0,
551  .selection_extent = 0,
552  .composing_base = 0,
553  .composing_extent = 7,
554  }),
555  });
556  break;
557  case 1:
558  // commit
559  expected_args = build_list({
560  fl_value_new_int(-1), // client_id
562  .text = "engine",
563  .selection_base = 6,
564  .selection_extent = 6,
565  }),
566  });
567  break;
568  case 2:
569  // end
570  expected_args = build_list({
571  fl_value_new_int(-1), // client_id
573  .text = "engine",
574  .selection_base = 6,
575  .selection_extent = 6,
576  }),
577  });
578  break;
579  default:
580  g_assert_not_reached();
581  break;
582  }
583  EXPECT_TRUE(fl_value_equal(args, expected_args));
584  (*call_count)++;
585 
586  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
587  },
588  &call_count);
589 
590  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
591  "preedit-start", nullptr);
592  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
593  "preedit-changed", nullptr);
594  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
595  "engine", nullptr);
596  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
597  "preedit-end", nullptr);
598  EXPECT_EQ(call_count, 3);
599 
600  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
601 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
GtkIMContext * fl_text_input_handler_get_im_context(FlTextInputHandler *self)

References args, build_editing_state(), build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_get_im_context(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), and user_data.

◆ TEST() [3/28]

TEST ( FlTextInputHandlerTest  ,
ComposingDelta   
)

Definition at line 866 of file fl_text_input_handler_test.cc.

866  {
867  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
868  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
869 
870  g_autoptr(FlTextInputHandler) handler =
871  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
872  EXPECT_NE(handler, nullptr);
873 
874  // set config
875  set_client(messenger, {
876  .client_id = 1,
877  .enable_delta_model = true,
878  });
879 
880  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
881  "preedit-start", nullptr);
882 
883  // update
884  EXPECT_CALL(mock_gtk, gtk_im_context_get_preedit_string(
885  ::testing::_, ::testing::A<gchar**>(), ::testing::_,
886  ::testing::A<gint*>()))
887  .WillOnce(
888  ::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter ")),
889  ::testing::SetArgPointee<3>(8)));
890 
891  int call_count = 0;
892  fl_mock_binary_messenger_set_json_method_channel(
893  messenger, "flutter/textinput",
894  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
895  FlValue* args, gpointer user_data) {
896  int* call_count = static_cast<int*>(user_data);
897 
898  EXPECT_STREQ(name, "TextInputClient.updateEditingStateWithDeltas");
899  g_autoptr(FlValue) expected_args = nullptr;
900  switch (*call_count) {
901  case 0:
902  expected_args = build_list({
903  fl_value_new_int(1), // client_id
904  build_map({{
905  "deltas",
906  build_list({
908  .old_text = "",
909  .delta_text = "Flutter ",
910  .delta_start = 0,
911  .delta_end = 0,
912  .selection_base = 8,
913  .selection_extent = 8,
914  .composing_base = 0,
915  .composing_extent = 8,
916  }),
917  }),
918  }}),
919  });
920  break;
921  case 1:
922  // commit
923  expected_args = build_list({
924  fl_value_new_int(1), // client_id
925  build_map({{
926  "deltas",
927  build_list({
929  .old_text = "Flutter ",
930  .delta_text = "Flutter engine",
931  .delta_start = 0,
932  .delta_end = 8,
933  .selection_base = 14,
934  .selection_extent = 14,
935  .composing_base = -1,
936  .composing_extent = -1,
937  }),
938  }),
939  }}),
940  });
941  break;
942  case 2:
943  // end
944  expected_args = build_list({
945  fl_value_new_int(1), // client_id
946  build_map({{
947  "deltas",
948  build_list({
950  .old_text = "Flutter engine",
951  .selection_base = 14,
952  .selection_extent = 14,
953  }),
954  }),
955  }}),
956  });
957  break;
958  default:
959  g_assert_not_reached();
960  break;
961  }
962  EXPECT_TRUE(fl_value_equal(args, expected_args));
963  (*call_count)++;
964 
965  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
966  },
967  &call_count);
968 
969  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
970  "preedit-changed", nullptr);
971  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
972  "Flutter engine", nullptr);
973  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
974  "preedit-end", nullptr);
975  EXPECT_EQ(call_count, 3);
976 
977  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
978 }
static void set_client(FlMockBinaryMessenger *messenger, InputConfig config)
static FlValue * build_editing_delta(EditingDelta delta)

References args, build_editing_delta(), build_list(), build_map(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_get_im_context(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), set_client(), and user_data.

◆ TEST() [4/28]

TEST ( FlTextInputHandlerTest  ,
DefaultInputPurposeAndHints   
)

Definition at line 1415 of file fl_text_input_handler_test.cc.

1415  {
1416  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1417  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1418 
1419  g_autoptr(FlTextInputHandler) handler =
1420  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1421  EXPECT_NE(handler, nullptr);
1422 
1423  EXPECT_CALL(mock_gtk,
1424  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1425  GTK_INPUT_PURPOSE_FREE_FORM));
1426  EXPECT_CALL(mock_gtk,
1427  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1428  GTK_INPUT_HINT_NONE));
1429 
1430  set_client(messenger, {
1431  .client_id = 1,
1432  .input_type = "TextInputType.text",
1433  });
1434 
1435  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1436 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [5/28]

TEST ( FlTextInputHandlerTest  ,
Hide   
)

Definition at line 211 of file fl_text_input_handler_test.cc.

211  {
212  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
213  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
214 
215  g_autoptr(FlTextInputHandler) handler =
216  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
217  EXPECT_NE(handler, nullptr);
218 
219  EXPECT_CALL(mock_gtk, gtk_im_context_focus_out);
220 
221  gboolean called = FALSE;
222  fl_mock_binary_messenger_invoke_json_method(
223  messenger, "flutter/textinput", "TextInput.hide", nullptr,
224  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
225  gpointer user_data) {
226  gboolean* called = static_cast<gboolean*>(user_data);
227  *called = TRUE;
228 
229  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
230 
231  g_autoptr(FlValue) expected_result = fl_value_new_null();
233  FL_METHOD_SUCCESS_RESPONSE(response)),
234  expected_result));
235  },
236  &called);
237  EXPECT_TRUE(called);
238 
239  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
240 }

References fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_null(), g_autoptr(), TRUE, and user_data.

◆ TEST() [6/28]

TEST ( FlTextInputHandlerTest  ,
InputHintsAddress   
)

Definition at line 1319 of file fl_text_input_handler_test.cc.

1319  {
1320  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1321  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1322 
1323  g_autoptr(FlTextInputHandler) handler =
1324  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1325  EXPECT_NE(handler, nullptr);
1326 
1327  EXPECT_CALL(mock_gtk,
1328  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1329  GTK_INPUT_PURPOSE_FREE_FORM));
1330  EXPECT_CALL(mock_gtk,
1331  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1332  GTK_INPUT_HINT_UPPERCASE_WORDS));
1333 
1334  set_client(messenger, {
1335  .client_id = 1,
1336  .input_type = "TextInputType.address",
1337  });
1338 
1339  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1340 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [7/28]

TEST ( FlTextInputHandlerTest  ,
InputHintsMultiline   
)

Definition at line 1342 of file fl_text_input_handler_test.cc.

1342  {
1343  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1344  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1345 
1346  g_autoptr(FlTextInputHandler) handler =
1347  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1348  EXPECT_NE(handler, nullptr);
1349 
1350  EXPECT_CALL(mock_gtk,
1351  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1352  GTK_INPUT_PURPOSE_FREE_FORM));
1353  EXPECT_CALL(
1354  mock_gtk,
1355  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1356  static_cast<gint>(GTK_INPUT_HINT_SPELLCHECK |
1357  GTK_INPUT_HINT_UPPERCASE_SENTENCES)));
1358 
1359  set_client(messenger, {
1360  .client_id = 1,
1361  .input_type = "TextInputType.multiline",
1362  });
1363 
1364  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1365 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [8/28]

TEST ( FlTextInputHandlerTest  ,
InputHintsTwitter   
)

Definition at line 1390 of file fl_text_input_handler_test.cc.

1390  {
1391  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1392  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1393 
1394  g_autoptr(FlTextInputHandler) handler =
1395  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1396  EXPECT_NE(handler, nullptr);
1397 
1398  EXPECT_CALL(mock_gtk,
1399  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1400  GTK_INPUT_PURPOSE_FREE_FORM));
1401  EXPECT_CALL(
1402  mock_gtk,
1403  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1404  static_cast<gint>(GTK_INPUT_HINT_SPELLCHECK |
1405  GTK_INPUT_HINT_UPPERCASE_SENTENCES)));
1406 
1407  set_client(messenger, {
1408  .client_id = 1,
1409  .input_type = "TextInputType.twitter",
1410  });
1411 
1412  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1413 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [9/28]

TEST ( FlTextInputHandlerTest  ,
InputHintsWebSearch   
)

Definition at line 1367 of file fl_text_input_handler_test.cc.

1367  {
1368  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1369  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1370 
1371  g_autoptr(FlTextInputHandler) handler =
1372  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1373  EXPECT_NE(handler, nullptr);
1374 
1375  EXPECT_CALL(mock_gtk,
1376  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1377  GTK_INPUT_PURPOSE_FREE_FORM));
1378  EXPECT_CALL(mock_gtk,
1379  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1380  GTK_INPUT_HINT_LOWERCASE));
1381 
1382  set_client(messenger, {
1383  .client_id = 1,
1384  .input_type = "TextInputType.webSearch",
1385  });
1386 
1387  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1388 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [10/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposeEmail   
)

Definition at line 1227 of file fl_text_input_handler_test.cc.

1227  {
1228  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1229  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1230 
1231  g_autoptr(FlTextInputHandler) handler =
1232  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1233  EXPECT_NE(handler, nullptr);
1234 
1235  EXPECT_CALL(mock_gtk,
1236  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1237  GTK_INPUT_PURPOSE_EMAIL));
1238  EXPECT_CALL(mock_gtk,
1239  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1240  GTK_INPUT_HINT_NONE));
1241 
1242  set_client(messenger, {
1243  .client_id = 1,
1244  .input_type = "TextInputType.emailAddress",
1245  });
1246 
1247  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1248 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [11/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposeName   
)

Definition at line 1296 of file fl_text_input_handler_test.cc.

1296  {
1297  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1298  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1299 
1300  g_autoptr(FlTextInputHandler) handler =
1301  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1302  EXPECT_NE(handler, nullptr);
1303 
1304  EXPECT_CALL(mock_gtk,
1305  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1306  GTK_INPUT_PURPOSE_NAME));
1307  EXPECT_CALL(mock_gtk,
1308  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1309  GTK_INPUT_HINT_UPPERCASE_WORDS));
1310 
1311  set_client(messenger, {
1312  .client_id = 1,
1313  .input_type = "TextInputType.name",
1314  });
1315 
1316  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1317 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [12/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposeNumber   
)

Definition at line 1181 of file fl_text_input_handler_test.cc.

1181  {
1182  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1183  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1184 
1185  g_autoptr(FlTextInputHandler) handler =
1186  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1187  EXPECT_NE(handler, nullptr);
1188 
1189  EXPECT_CALL(mock_gtk,
1190  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1191  GTK_INPUT_PURPOSE_NUMBER));
1192  EXPECT_CALL(mock_gtk,
1193  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1194  GTK_INPUT_HINT_NONE));
1195 
1196  set_client(messenger, {
1197  .client_id = 1,
1198  .input_type = "TextInputType.number",
1199  });
1200 
1201  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1202 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [13/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposePassword   
)

Definition at line 1273 of file fl_text_input_handler_test.cc.

1273  {
1274  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1275  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1276 
1277  g_autoptr(FlTextInputHandler) handler =
1278  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1279  EXPECT_NE(handler, nullptr);
1280 
1281  EXPECT_CALL(mock_gtk,
1282  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1283  GTK_INPUT_PURPOSE_PASSWORD));
1284  EXPECT_CALL(mock_gtk,
1285  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1286  GTK_INPUT_HINT_NONE));
1287 
1288  set_client(messenger, {
1289  .client_id = 1,
1290  .input_type = "TextInputType.visiblePassword",
1291  });
1292 
1293  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1294 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [14/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposePhone   
)

Definition at line 1204 of file fl_text_input_handler_test.cc.

1204  {
1205  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1206  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1207 
1208  g_autoptr(FlTextInputHandler) handler =
1209  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1210  EXPECT_NE(handler, nullptr);
1211 
1212  EXPECT_CALL(mock_gtk,
1213  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1214  GTK_INPUT_PURPOSE_PHONE));
1215  EXPECT_CALL(mock_gtk,
1216  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1217  GTK_INPUT_HINT_NONE));
1218 
1219  set_client(messenger, {
1220  .client_id = 1,
1221  .input_type = "TextInputType.phone",
1222  });
1223 
1224  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1225 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [15/28]

TEST ( FlTextInputHandlerTest  ,
InputPurposeUrl   
)

Definition at line 1250 of file fl_text_input_handler_test.cc.

1250  {
1251  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1252  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1253 
1254  g_autoptr(FlTextInputHandler) handler =
1255  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1256  EXPECT_NE(handler, nullptr);
1257 
1258  EXPECT_CALL(mock_gtk,
1259  g_object_set(::testing::_, ::testing::StrEq("input-purpose"),
1260  GTK_INPUT_PURPOSE_URL));
1261  EXPECT_CALL(mock_gtk,
1262  g_object_set(::testing::_, ::testing::StrEq("input-hints"),
1263  GTK_INPUT_HINT_NONE));
1264 
1265  set_client(messenger, {
1266  .client_id = 1,
1267  .input_type = "TextInputType.url",
1268  });
1269 
1270  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1271 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [16/28]

TEST ( FlTextInputHandlerTest  ,
MessageHandler   
)

Definition at line 153 of file fl_text_input_handler_test.cc.

153  {
154  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
155  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
156 
157  g_autoptr(FlTextInputHandler) handler =
158  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
159  EXPECT_NE(handler, nullptr);
160 
161  EXPECT_TRUE(
162  fl_mock_binary_messenger_has_handler(messenger, "flutter/textinput"));
163 
164  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
165 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), and g_autoptr().

◆ TEST() [17/28]

TEST ( FlTextInputHandlerTest  ,
MoveCursor   
)

Definition at line 389 of file fl_text_input_handler_test.cc.

389  {
390  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
391  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
392 
393  g_autoptr(FlTextInputHandler) handler =
394  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
395  EXPECT_NE(handler, nullptr);
396 
397  set_client(messenger, {.client_id = 1});
398  set_editing_state(messenger, {
399  .text = "Flutter",
400  .selection_base = 4,
401  .selection_extent = 4,
402  });
403 
404  int call_count = 0;
405  fl_mock_binary_messenger_set_json_method_channel(
406  messenger, "flutter/textinput",
407  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
408  FlValue* args, gpointer user_data) {
409  int* call_count = static_cast<int*>(user_data);
410 
411  EXPECT_STREQ(name, "TextInputClient.updateEditingState");
412  g_autoptr(FlValue) expected_args = nullptr;
413  switch (*call_count) {
414  case 0:
415  // move cursor to beginning
416  expected_args = build_list({
417  fl_value_new_int(1), // client_id
419  .text = "Flutter",
420  .selection_base = 0,
421  .selection_extent = 0,
422  }),
423  });
424  break;
425  case 1:
426  // move cursor to end
427  expected_args = build_list({
428  fl_value_new_int(1), // client_id
430  .text = "Flutter",
431  .selection_base = 7,
432  .selection_extent = 7,
433  }),
434  });
435  break;
436  default:
437  g_assert_not_reached();
438  break;
439  }
440  EXPECT_TRUE(fl_value_equal(args, expected_args));
441  (*call_count)++;
442 
443  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
444  },
445  &call_count);
446 
447  send_key_event(handler, GDK_KEY_Home);
448  send_key_event(handler, GDK_KEY_End);
449  EXPECT_EQ(call_count, 2);
450 
451  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
452 }
static void send_key_event(FlTextInputHandler *handler, gint keyval, gint state=0)
static void set_editing_state(FlMockBinaryMessenger *messenger, EditingState state)

References args, build_editing_state(), build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), and user_data.

◆ TEST() [18/28]

TEST ( FlTextInputHandlerTest  ,
MultilineWithSendAction   
)

Definition at line 331 of file fl_text_input_handler_test.cc.

331  {
332  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
333  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
334 
335  g_autoptr(FlTextInputHandler) handler =
336  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
337  EXPECT_NE(handler, nullptr);
338 
339  set_client(messenger, {
340  .client_id = 1,
341  .input_type = "TextInputType.multiline",
342  .input_action = "TextInputAction.send",
343  });
344  set_editing_state(messenger, {
345  .text = "Flutter",
346  .selection_base = 7,
347  .selection_extent = 7,
348  });
349 
350  // Because the input action is not set to TextInputAction.newline, the next
351  // expected call is "TextInputClient.performAction". If the input action was
352  // set to TextInputAction.newline the next call would be
353  // "TextInputClient.updateEditingState" (this case is tested in the test named
354  // 'PerformAction').
355  int call_count = 0;
356  fl_mock_binary_messenger_set_json_method_channel(
357  messenger, "flutter/textinput",
358  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
359  FlValue* args, gpointer user_data) {
360  int* call_count = static_cast<int*>(user_data);
361 
362  EXPECT_STREQ(name, "TextInputClient.performAction");
363  g_autoptr(FlValue) expected_args = nullptr;
364  switch (*call_count) {
365  case 0:
366  // Perform action.
367  expected_args = build_list({
368  fl_value_new_int(1), // client_id
369  fl_value_new_string("TextInputAction.send"),
370  });
371  break;
372  default:
373  g_assert_not_reached();
374  break;
375  }
376  EXPECT_TRUE(fl_value_equal(args, expected_args));
377  (*call_count)++;
378 
379  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
380  },
381  &call_count);
382 
383  send_key_event(handler, GDK_KEY_Return);
384  EXPECT_EQ(call_count, 1);
385 
386  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
387 }

References args, build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), fl_value_new_string(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), and user_data.

◆ TEST() [19/28]

TEST ( FlTextInputHandlerTest  ,
NonComposingDelta   
)

Definition at line 980 of file fl_text_input_handler_test.cc.

980  {
981  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
982  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
983 
984  g_autoptr(FlTextInputHandler) handler =
985  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
986  EXPECT_NE(handler, nullptr);
987 
988  // set config
989  set_client(messenger, {
990  .client_id = 1,
991  .enable_delta_model = true,
992  });
993 
994  int call_count = 0;
995  fl_mock_binary_messenger_set_json_method_channel(
996  messenger, "flutter/textinput",
997  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
998  FlValue* args, gpointer user_data) {
999  int* call_count = static_cast<int*>(user_data);
1000 
1001  EXPECT_STREQ(name, "TextInputClient.updateEditingStateWithDeltas");
1002  g_autoptr(FlValue) expected_args = nullptr;
1003  switch (*call_count) {
1004  case 0:
1005  // commit F
1006  expected_args = build_list({
1007  fl_value_new_int(1), // client_id
1008  build_map({{
1009  "deltas",
1010  build_list({
1012  .old_text = "",
1013  .delta_text = "F",
1014  .delta_start = 0,
1015  .delta_end = 0,
1016  .selection_base = 1,
1017  .selection_extent = 1,
1018  .composing_base = -1,
1019  .composing_extent = -1,
1020  }),
1021  }),
1022  }}),
1023  });
1024  break;
1025  case 1:
1026  // commit l
1027  expected_args = build_list({
1028  fl_value_new_int(1), // client_id
1029  build_map({{
1030  "deltas",
1031  build_list({
1033  .old_text = "F",
1034  .delta_text = "l",
1035  .delta_start = 1,
1036  .delta_end = 1,
1037  .selection_base = 2,
1038  .selection_extent = 2,
1039  .composing_base = -1,
1040  .composing_extent = -1,
1041  }),
1042  }),
1043  }}),
1044  });
1045  break;
1046  case 2:
1047  // commit u
1048  expected_args = build_list({
1049  fl_value_new_int(1), // client_id
1050  build_map({{
1051  "deltas",
1052  build_list({
1054  .old_text = "Fl",
1055  .delta_text = "u",
1056  .delta_start = 2,
1057  .delta_end = 2,
1058  .selection_base = 3,
1059  .selection_extent = 3,
1060  .composing_base = -1,
1061  .composing_extent = -1,
1062  }),
1063  }),
1064  }}),
1065  });
1066  break;
1067  case 3:
1068  // commit t
1069  expected_args = build_list({
1070  fl_value_new_int(1), // client_id
1071  build_map({{
1072  "deltas",
1073  build_list({
1075  .old_text = "Flu",
1076  .delta_text = "t",
1077  .delta_start = 3,
1078  .delta_end = 3,
1079  .selection_base = 4,
1080  .selection_extent = 4,
1081  .composing_base = -1,
1082  .composing_extent = -1,
1083  }),
1084  }),
1085  }}),
1086  });
1087  break;
1088  case 4:
1089  // commit t again
1090  expected_args = build_list({
1091  fl_value_new_int(1), // client_id
1092  build_map({{
1093  "deltas",
1094  build_list({
1096  .old_text = "Flut",
1097  .delta_text = "t",
1098  .delta_start = 4,
1099  .delta_end = 4,
1100  .selection_base = 5,
1101  .selection_extent = 5,
1102  .composing_base = -1,
1103  .composing_extent = -1,
1104  }),
1105  }),
1106  }}),
1107  });
1108  break;
1109  case 5:
1110  // commit e
1111  expected_args = build_list({
1112  fl_value_new_int(1), // client_id
1113  build_map({{
1114  "deltas",
1115  build_list({
1117  .old_text = "Flutt",
1118  .delta_text = "e",
1119  .delta_start = 5,
1120  .delta_end = 5,
1121  .selection_base = 6,
1122  .selection_extent = 6,
1123  .composing_base = -1,
1124  .composing_extent = -1,
1125  }),
1126  }),
1127  }}),
1128  });
1129  break;
1130  case 6:
1131  // commit r
1132  expected_args = build_list({
1133  fl_value_new_int(1), // client_id
1134  build_map({{
1135  "deltas",
1136  build_list({
1138  .old_text = "Flutte",
1139  .delta_text = "r",
1140  .delta_start = 6,
1141  .delta_end = 6,
1142  .selection_base = 7,
1143  .selection_extent = 7,
1144  .composing_base = -1,
1145  .composing_extent = -1,
1146  }),
1147  }),
1148  }}),
1149  });
1150  break;
1151  default:
1152  g_assert_not_reached();
1153  break;
1154  }
1155  EXPECT_TRUE(fl_value_equal(args, expected_args));
1156  (*call_count)++;
1157 
1158  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
1159  },
1160  &call_count);
1161 
1162  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1163  "F", nullptr);
1164  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1165  "l", nullptr);
1166  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1167  "u", nullptr);
1168  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1169  "t", nullptr);
1170  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1171  "t", nullptr);
1172  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1173  "e", nullptr);
1174  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
1175  "r", nullptr);
1176  EXPECT_EQ(call_count, 7);
1177 
1178  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1179 }

References args, build_editing_delta(), build_list(), build_map(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_get_im_context(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), set_client(), and user_data.

◆ TEST() [20/28]

TEST ( FlTextInputHandlerTest  ,
PerformAction   
)

Definition at line 271 of file fl_text_input_handler_test.cc.

271  {
272  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
273  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
274 
275  g_autoptr(FlTextInputHandler) handler =
276  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
277  EXPECT_NE(handler, nullptr);
278 
279  set_client(messenger, {
280  .client_id = 1,
281  .input_type = "TextInputType.multiline",
282  .input_action = "TextInputAction.newline",
283  });
284  set_editing_state(messenger, {
285  .text = "Flutter",
286  .selection_base = 7,
287  .selection_extent = 7,
288  });
289 
290  // Client will update editing state and perform action
291  int call_count = 0;
292  fl_mock_binary_messenger_set_json_method_channel(
293  messenger, "flutter/textinput",
294  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
295  FlValue* args, gpointer user_data) {
296  int* call_count = static_cast<int*>(user_data);
297 
298  if (strcmp(name, "TextInputClient.updateEditingState") == 0) {
299  g_autoptr(FlValue) expected_args = build_list({
300  fl_value_new_int(1), // client_id
302  .text = "Flutter\n",
303  .selection_base = 8,
304  .selection_extent = 8,
305  }),
306  });
307  EXPECT_TRUE(fl_value_equal(args, expected_args));
308  EXPECT_EQ(*call_count, 0);
309  (*call_count)++;
310  } else if (strcmp(name, "TextInputClient.performAction") == 0) {
311  g_autoptr(FlValue) expected_args = build_list({
312  fl_value_new_int(1), // client_id
313  fl_value_new_string("TextInputAction.newline"),
314  });
315  EXPECT_TRUE(fl_value_equal(args, expected_args));
316  EXPECT_EQ(*call_count, 1);
317  (*call_count)++;
318  }
319 
320  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
321  },
322  &call_count);
323 
324  send_key_event(handler, GDK_KEY_Return);
325  EXPECT_EQ(call_count, 2);
326 
327  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
328 }

References args, build_editing_state(), build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), fl_value_new_string(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), and user_data.

◆ TEST() [21/28]

TEST ( FlTextInputHandlerTest  ,
Select   
)

Definition at line 454 of file fl_text_input_handler_test.cc.

454  {
455  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
456  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
457 
458  g_autoptr(FlTextInputHandler) handler =
459  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
460  EXPECT_NE(handler, nullptr);
461 
462  set_client(messenger, {.client_id = 1});
463  set_editing_state(messenger, {
464  .text = "Flutter",
465  .selection_base = 4,
466  .selection_extent = 4,
467  });
468 
469  int call_count = 0;
470  fl_mock_binary_messenger_set_json_method_channel(
471  messenger, "flutter/textinput",
472  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
473  FlValue* args, gpointer user_data) {
474  int* call_count = static_cast<int*>(user_data);
475 
476  EXPECT_STREQ(name, "TextInputClient.updateEditingState");
477  g_autoptr(FlValue) expected_args = nullptr;
478  switch (*call_count) {
479  case 0:
480  // select to end
481  expected_args = build_list({
482  fl_value_new_int(1), // client_id
484  .text = "Flutter",
485  .selection_base = 4,
486  .selection_extent = 7,
487  }),
488  });
489  break;
490  case 1:
491  // select to beginning
492  expected_args = build_list({
493  fl_value_new_int(1), // client_id
495  .text = "Flutter",
496  .selection_base = 4,
497  .selection_extent = 0,
498  }),
499  });
500  break;
501  default:
502  g_assert_not_reached();
503  break;
504  }
505  EXPECT_TRUE(fl_value_equal(args, expected_args));
506  (*call_count)++;
507 
508  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
509  },
510  &call_count);
511 
512  send_key_event(handler, GDK_KEY_End, GDK_SHIFT_MASK);
513  send_key_event(handler, GDK_KEY_Home, GDK_SHIFT_MASK);
514  EXPECT_EQ(call_count, 2);
515 
516  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
517 }

References args, build_editing_state(), build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), and user_data.

◆ TEST() [22/28]

TEST ( FlTextInputHandlerTest  ,
SetClient   
)

Definition at line 167 of file fl_text_input_handler_test.cc.

167  {
168  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
169  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
170 
171  g_autoptr(FlTextInputHandler) handler =
172  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
173  EXPECT_NE(handler, nullptr);
174 
175  set_client(messenger, {.client_id = 1});
176 
177  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
178 }

References fl_binary_messenger_shutdown(), fl_text_input_handler_new(), g_autoptr(), and set_client().

◆ TEST() [23/28]

TEST ( FlTextInputHandlerTest  ,
SetMarkedTextRect   
)

Definition at line 668 of file fl_text_input_handler_test.cc.

668  {
669  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
670  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
671 
672  g_autoptr(FlTextInputHandler) handler =
673  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
674  EXPECT_NE(handler, nullptr);
675 
676  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
677  "preedit-start", nullptr);
678 
679  // set editable size and transform
680  g_autoptr(FlValue) size_and_transform = build_map({
681  {
682  "transform",
683  build_list({
693  fl_value_new_float(10),
694  fl_value_new_float(11),
695  fl_value_new_float(12),
696  fl_value_new_float(13),
697  fl_value_new_float(14),
698  fl_value_new_float(15),
699  fl_value_new_float(16),
700  }),
701  },
702  });
703  gboolean called = FALSE;
704  fl_mock_binary_messenger_invoke_json_method(
705  messenger, "flutter/textinput", "TextInput.setEditableSizeAndTransform",
706  size_and_transform,
707  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
708  gpointer user_data) {
709  gboolean* called = static_cast<gboolean*>(user_data);
710  *called = TRUE;
711 
712  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
713 
714  g_autoptr(FlValue) expected_result = fl_value_new_null();
716  FL_METHOD_SUCCESS_RESPONSE(response)),
717  expected_result));
718  },
719  &called);
720  EXPECT_TRUE(called);
721 
722  EXPECT_CALL(mock_gtk, gtk_widget_translate_coordinates(
723  ::testing::_, ::testing::_, ::testing::Eq(27),
724  ::testing::Eq(32), ::testing::_, ::testing::_))
725  .WillOnce(::testing::DoAll(::testing::SetArgPointee<4>(123),
726  ::testing::SetArgPointee<5>(456),
727  ::testing::Return(true)));
728 
729  EXPECT_CALL(mock_gtk, gtk_im_context_set_cursor_location(
730  ::testing::_,
731  ::testing::Pointee(::testing::AllOf(
732  ::testing::Field(&GdkRectangle::x, 123),
733  ::testing::Field(&GdkRectangle::y, 456),
734  ::testing::Field(&GdkRectangle::width, 0),
735  ::testing::Field(&GdkRectangle::height, 0)))));
736 
737  // set marked text rect
738  g_autoptr(FlValue) rect = build_map({
739  {"x", fl_value_new_float(1)},
740  {"y", fl_value_new_float(2)},
741  {"width", fl_value_new_float(3)},
742  {"height", fl_value_new_float(4)},
743  });
744  called = FALSE;
745  fl_mock_binary_messenger_invoke_json_method(
746  messenger, "flutter/textinput", "TextInput.setMarkedTextRect", rect,
747  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
748  gpointer user_data) {
749  gboolean* called = static_cast<gboolean*>(user_data);
750  *called = TRUE;
751 
752  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
753 
754  g_autoptr(FlValue) expected_result = fl_value_new_null();
756  FL_METHOD_SUCCESS_RESPONSE(response)),
757  expected_result));
758  },
759  &called);
760  EXPECT_TRUE(called);
761 
762  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
763 }
self height
self width
G_MODULE_EXPORT FlValue * fl_value_new_float(double value)
Definition: fl_value.cc:269

References build_list(), build_map(), fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_text_input_handler_get_im_context(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_float(), fl_value_new_null(), g_autoptr(), height, TRUE, user_data, and width.

◆ TEST() [24/28]

TEST ( FlTextInputHandlerTest  ,
Show   
)

Definition at line 180 of file fl_text_input_handler_test.cc.

180  {
181  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
182  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
183 
184  g_autoptr(FlTextInputHandler) handler =
185  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
186  EXPECT_NE(handler, nullptr);
187 
188  EXPECT_CALL(mock_gtk, gtk_im_context_focus_in);
189 
190  gboolean called = FALSE;
191  fl_mock_binary_messenger_invoke_json_method(
192  messenger, "flutter/textinput", "TextInput.show", nullptr,
193  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
194  gpointer user_data) {
195  gboolean* called = static_cast<gboolean*>(user_data);
196  *called = TRUE;
197 
198  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
199 
200  g_autoptr(FlValue) expected_result = fl_value_new_null();
202  FL_METHOD_SUCCESS_RESPONSE(response)),
203  expected_result));
204  },
205  &called);
206  EXPECT_TRUE(called);
207 
208  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
209 }

References fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_null(), g_autoptr(), TRUE, and user_data.

◆ TEST() [25/28]

TEST ( FlTextInputHandlerTest  ,
SurroundingText   
)

Definition at line 603 of file fl_text_input_handler_test.cc.

603  {
604  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
605  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
606 
607  g_autoptr(FlTextInputHandler) handler =
608  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
609  EXPECT_NE(handler, nullptr);
610 
611  set_client(messenger, {.client_id = 1});
612  set_editing_state(messenger, {
613  .text = "Flutter",
614  .selection_base = 3,
615  .selection_extent = 3,
616  });
617 
618  // retrieve
619  EXPECT_CALL(mock_gtk, gtk_im_context_set_surrounding(
620  ::testing::_, ::testing::StrEq("Flutter"), -1, 3));
621 
622  gboolean retrieved = false;
623  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
624  "retrieve-surrounding", &retrieved, nullptr);
625  EXPECT_TRUE(retrieved);
626 
627  int call_count = 0;
628  fl_mock_binary_messenger_set_json_method_channel(
629  messenger, "flutter/textinput",
630  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
631  FlValue* args, gpointer user_data) {
632  int* call_count = static_cast<int*>(user_data);
633 
634  EXPECT_STREQ(name, "TextInputClient.updateEditingState");
635  g_autoptr(FlValue) expected_args = nullptr;
636  switch (*call_count) {
637  case 0:
638  // delete
639  expected_args = build_list({
640  fl_value_new_int(1), // client_id
642  .text = "Flutr",
643  .selection_base = 3,
644  .selection_extent = 3,
645  }),
646  });
647  break;
648  default:
649  g_assert_not_reached();
650  break;
651  }
652  EXPECT_TRUE(fl_value_equal(args, expected_args));
653  (*call_count)++;
654 
655  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
656  },
657  &call_count);
658 
659  gboolean deleted = false;
660  g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
661  "delete-surrounding", 1, 2, &deleted, nullptr);
662  EXPECT_TRUE(deleted);
663  EXPECT_EQ(call_count, 1);
664 
665  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
666 }

References args, build_editing_state(), build_list(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_get_im_context(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), set_client(), set_editing_state(), and user_data.

◆ TEST() [26/28]

TEST ( FlTextInputHandlerTest  ,
TextEditingDelta   
)

Definition at line 802 of file fl_text_input_handler_test.cc.

802  {
803  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
804  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
805 
806  g_autoptr(FlTextInputHandler) handler =
807  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
808  EXPECT_NE(handler, nullptr);
809 
810  set_client(messenger, {
811  .client_id = 1,
812  .enable_delta_model = true,
813  });
814  set_editing_state(messenger, {
815  .text = "Flutter",
816  .selection_base = 7,
817  .selection_extent = 7,
818  });
819 
820  // update editing state with deltas
821  int call_count = 0;
822  fl_mock_binary_messenger_set_json_method_channel(
823  messenger, "flutter/textinput",
824  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
825  FlValue* args, gpointer user_data) {
826  int* call_count = static_cast<int*>(user_data);
827 
828  EXPECT_STREQ(name, "TextInputClient.updateEditingStateWithDeltas");
829  g_autoptr(FlValue) expected_args = nullptr;
830  switch (*call_count) {
831  case 0:
832  expected_args = build_list({
833  fl_value_new_int(1), // client_id
834  build_map({{
835  "deltas",
836  build_list({
838  .old_text = "Flutter",
839  .delta_text = "Flutter",
840  .delta_start = 7,
841  .delta_end = 7,
842  .selection_base = 0,
843  .selection_extent = 0,
844  }),
845  }),
846  }}),
847  });
848  break;
849  default:
850  g_assert_not_reached();
851  break;
852  }
853  EXPECT_TRUE(fl_value_equal(args, expected_args));
854  (*call_count)++;
855 
856  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
857  },
858  &call_count);
859 
860  send_key_event(handler, GDK_KEY_Home);
861  EXPECT_EQ(call_count, 1);
862 
863  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
864 }

References args, build_editing_delta(), build_list(), build_map(), fl_binary_messenger_shutdown(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_int(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), and user_data.

◆ TEST() [27/28]

TEST ( FlTextInputHandlerTest  ,
TextInputTypeNone   
)

Definition at line 765 of file fl_text_input_handler_test.cc.

765  {
766  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
767  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
768 
769  g_autoptr(FlTextInputHandler) handler =
770  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
771  EXPECT_NE(handler, nullptr);
772 
773  set_client(messenger, {
774  .client_id = 1,
775  .input_type = "TextInputType.none",
776  });
777 
778  EXPECT_CALL(mock_gtk, gtk_im_context_focus_in).Times(0);
779  EXPECT_CALL(mock_gtk, gtk_im_context_focus_out);
780 
781  gboolean called = FALSE;
782  fl_mock_binary_messenger_invoke_json_method(
783  messenger, "flutter/textinput", "TextInput.show", nullptr,
784  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
785  gpointer user_data) {
786  gboolean* called = static_cast<gboolean*>(user_data);
787  *called = TRUE;
788 
789  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
790 
791  g_autoptr(FlValue) expected_result = fl_value_new_null();
793  FL_METHOD_SUCCESS_RESPONSE(response)),
794  expected_result));
795  },
796  &called);
797  EXPECT_TRUE(called);
798 
799  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
800 }

References fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_null(), g_autoptr(), set_client(), TRUE, and user_data.

◆ TEST() [28/28]

TEST ( FlTextInputHandlerTest  ,
UpdateConfig   
)

Definition at line 1438 of file fl_text_input_handler_test.cc.

1438  {
1439  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
1440  ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
1441 
1442  g_autoptr(FlTextInputHandler) handler =
1443  fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
1444  EXPECT_NE(handler, nullptr);
1445 
1446  set_client(messenger, {
1447  .client_id = 1,
1448  .input_action = "TextInputAction.none",
1449  });
1450 
1451  // Update config with a different input action
1452  gboolean called = FALSE;
1453  g_autoptr(FlValue) config = build_map({
1454  {"inputAction", fl_value_new_string("TextInputAction.send")},
1455  {"inputType", build_map({
1456  {"name", fl_value_new_string("TextInputType.text")},
1457  })},
1458  {"enableDeltaModel", fl_value_new_bool(false)},
1459  });
1460  fl_mock_binary_messenger_invoke_json_method(
1461  messenger, "flutter/textinput", "TextInput.updateConfig", config,
1462  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
1463  gpointer user_data) {
1464  gboolean* called = static_cast<gboolean*>(user_data);
1465  *called = TRUE;
1466 
1467  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
1468 
1469  g_autoptr(FlValue) expected_result = fl_value_new_null();
1471  FL_METHOD_SUCCESS_RESPONSE(response)),
1472  expected_result));
1473  },
1474  &called);
1475  EXPECT_TRUE(called);
1476 
1477  set_editing_state(messenger, {
1478  .text = "Flutter",
1479  .selection_base = 7,
1480  .selection_extent = 7,
1481  });
1482 
1483  // Verify the action was updated by checking perform action call
1484  int call_count = 0;
1485  fl_mock_binary_messenger_set_json_method_channel(
1486  messenger, "flutter/textinput",
1487  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
1488  FlValue* args, gpointer user_data) {
1489  int* call_count = static_cast<int*>(user_data);
1490 
1491  EXPECT_STREQ(name, "TextInputClient.performAction");
1492  g_autoptr(FlValue) expected_args = build_list({
1493  fl_value_new_int(1), // client_id
1494  fl_value_new_string("TextInputAction.send"),
1495  });
1496  EXPECT_TRUE(fl_value_equal(args, expected_args));
1497  (*call_count)++;
1498 
1499  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
1500  },
1501  &call_count);
1502 
1503  send_key_event(handler, GDK_KEY_Return);
1504  EXPECT_EQ(call_count, 1);
1505 
1506  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
1507 }

References args, build_list(), build_map(), fl_binary_messenger_shutdown(), fl_method_success_response_get_result(), fl_method_success_response_new(), fl_text_input_handler_new(), fl_value_equal(), fl_value_new_bool(), fl_value_new_int(), fl_value_new_null(), fl_value_new_string(), g_autoptr(), send_key_event(), set_client(), set_editing_state(), TRUE, and user_data.