| Flutter Linux Embedder |

fl_windowing_channel.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_windowing_channel.h"
6
7 #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
8 #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
9
10 static constexpr char kChannelName[] = "flutter/windowing";
11 static constexpr char kBadArgumentsError[] = "Bad Arguments";
12
13 static constexpr char kCreateRegularMethod[] = "createRegular";
14 static constexpr char kModifyRegularMethod[] = "modifyRegular";
15 static constexpr char kDestroyWindowMethod[] = "destroyWindow";
16
17 static constexpr char kSizeKey[] = "size";
18 static constexpr char kMinSizeKey[] = "minSize";
19 static constexpr char kMaxSizeKey[] = "maxSize";
20 static constexpr char kTitleKey[] = "title";
21 static constexpr char kStateKey[] = "state";
22 static constexpr char kViewIdKey[] = "viewId";
23
24 struct _FlWindowingChannel {
25 GObject parent_instance;
26
27 FlMethodChannel* channel;
28
29 // Handlers for incoming method calls.
30 FlWindowingChannelVTable* vtable;
31
32 // User data to pass to method call handlers.
33 gpointer user_data;
34 };
35
36 G_DEFINE_TYPE(FlWindowingChannel, fl_windowing_channel, G_TYPE_OBJECT)
37
38 // Returns TRUE if [args] is a valid size argument.
39 static gboolean is_valid_size_argument(FlValue* value) {
40 return fl_value_get_type(value) == FL_VALUE_TYPE_LIST &&
41 fl_value_get_length(value) == 2 &&
42 fl_value_get_type(fl_value_get_list_value(value, 0)) ==
43 FL_VALUE_TYPE_FLOAT &&
44 fl_value_get_type(fl_value_get_list_value(value, 1)) ==
45 FL_VALUE_TYPE_FLOAT;
46 }
47
48 G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlWindowingSize, g_free)
49
50 static FlWindowingSize* parse_size_value(FlValue* value) {
51 FlWindowingSize* size = g_new0(FlWindowingSize, 1);
52 size->width = fl_value_get_float(fl_value_get_list_value(value, 0));
53 size->height = fl_value_get_float(fl_value_get_list_value(value, 1));
54 return size;
55 }
56
57 static gboolean parse_window_state_value(FlValue* value, FlWindowState* state) {
58 if (fl_value_get_type(value) != FL_VALUE_TYPE_STRING) {
59 return FALSE;
60 }
61
62 const gchar* text = fl_value_get_string(value);
63 if (strcmp(text, "WindowState.restored") == 0) {
64 *state = FL_WINDOW_STATE_RESTORED;
65 return TRUE;
66 } else if (strcmp(text, "WindowState.maximized") == 0) {
67 *state = FL_WINDOW_STATE_MAXIMIZED;
68 return TRUE;
69 } else if (strcmp(text, "WindowState.minimized") == 0) {
70 *state = FL_WINDOW_STATE_MINIMIZED;
71 return TRUE;
72 }
73
74 return FALSE;
75 }
76
77 static const gchar* window_state_to_string(FlWindowState state) {
78 switch (state) {
79 case FL_WINDOW_STATE_UNDEFINED:
80 return nullptr;
81 case FL_WINDOW_STATE_RESTORED:
82 return "WindowState.restored";
83 case FL_WINDOW_STATE_MAXIMIZED:
84 return "WindowState.maximized";
85 case FL_WINDOW_STATE_MINIMIZED:
86 return "WindowState.minimized";
87 }
88
89 return nullptr;
90 }
91
92 // Called when a regular window should be created.
93 static FlMethodResponse* create_regular(FlWindowingChannel* self,
94 FlValue* args) {
95 if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
96 return FL_METHOD_RESPONSE(fl_method_error_response_new(
97 kBadArgumentsError, "Argument map missing or malformed", nullptr));
98 }
99
100 FlValue* size_value = fl_value_lookup_string(args, kSizeKey);
101 if (size_value == nullptr || !is_valid_size_argument(size_value)) {
102 return FL_METHOD_RESPONSE(fl_method_error_response_new(
103 kBadArgumentsError, "Missing/invalid size argument", nullptr));
104 }
105 g_autoptr(FlWindowingSize) size = parse_size_value(size_value);
106
107 FlValue* min_size_value = fl_value_lookup_string(args, kMinSizeKey);
108 g_autoptr(FlWindowingSize) min_size = nullptr;
109 if (min_size_value != nullptr) {
110 if (!is_valid_size_argument(min_size_value)) {
111 return FL_METHOD_RESPONSE(fl_method_error_response_new(
112 kBadArgumentsError, "Invalid minSize argument", nullptr));
113 }
114 min_size = parse_size_value(min_size_value);
115 }
116
117 FlValue* max_size_value = fl_value_lookup_string(args, kMaxSizeKey);
118 g_autoptr(FlWindowingSize) max_size = nullptr;
119 if (max_size_value != nullptr) {
120 if (!is_valid_size_argument(max_size_value)) {
121 return FL_METHOD_RESPONSE(fl_method_error_response_new(
122 kBadArgumentsError, "Invalid maxSize argument", nullptr));
123 }
124 max_size = parse_size_value(max_size_value);
125 }
126
127 FlValue* title_value = fl_value_lookup_string(args, kTitleKey);
128 const gchar* title = nullptr;
129 if (title_value != nullptr) {
130 if (fl_value_get_type(title_value) != FL_VALUE_TYPE_STRING) {
131 return FL_METHOD_RESPONSE(fl_method_error_response_new(
132 kBadArgumentsError, "Invalid title argument", nullptr));
133 }
134 title = fl_value_get_string(title_value);
135 }
136 FlWindowState state = FL_WINDOW_STATE_UNDEFINED;
137 FlValue* state_value = fl_value_lookup_string(args, kStateKey);
138 if (state_value != nullptr) {
139 if (!parse_window_state_value(state_value, &state)) {
140 return FL_METHOD_RESPONSE(fl_method_error_response_new(
141 kBadArgumentsError, "Invalid state argument", nullptr));
142 }
143 }
144
145 return self->vtable->create_regular(size, min_size, max_size, title, state,
146 self->user_data);
147 }
148
149 // Called when a regular window should be created.
150 static FlMethodResponse* modify_regular(FlWindowingChannel* self,
151 FlValue* args) {
152 if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
153 return FL_METHOD_RESPONSE(fl_method_error_response_new(
154 kBadArgumentsError, "Argument map missing or malformed", nullptr));
155 }
156
157 FlValue* view_id_value = fl_value_lookup_string(args, kViewIdKey);
158 if (view_id_value == nullptr ||
159 fl_value_get_type(view_id_value) != FL_VALUE_TYPE_INT) {
160 return FL_METHOD_RESPONSE(fl_method_error_response_new(
161 kBadArgumentsError, "Missing/invalid viewId argument", nullptr));
162 }
163 int64_t view_id = fl_value_get_int(view_id_value);
164
165 g_autoptr(FlWindowingSize) size = nullptr;
166 FlValue* size_value = fl_value_lookup_string(args, kSizeKey);
167 if (size_value != nullptr) {
168 if (!is_valid_size_argument(size_value)) {
169 return FL_METHOD_RESPONSE(fl_method_error_response_new(
170 kBadArgumentsError, "Invalid size argument", nullptr));
171 }
172 size = parse_size_value(size_value);
173 }
174 FlValue* title_value = fl_value_lookup_string(args, kTitleKey);
175 const gchar* title = nullptr;
176 if (title_value != nullptr) {
177 if (fl_value_get_type(title_value) != FL_VALUE_TYPE_STRING) {
178 return FL_METHOD_RESPONSE(fl_method_error_response_new(
179 kBadArgumentsError, "Invalid title argument", nullptr));
180 }
181 title = fl_value_get_string(title_value);
182 }
183 FlWindowState state = FL_WINDOW_STATE_UNDEFINED;
184 FlValue* state_value = fl_value_lookup_string(args, kStateKey);
185 if (state_value != nullptr) {
186 if (!parse_window_state_value(state_value, &state)) {
187 return FL_METHOD_RESPONSE(fl_method_error_response_new(
188 kBadArgumentsError, "Invalid state argument", nullptr));
189 }
190 }
191
192 return self->vtable->modify_regular(view_id, size, title, state,
193 self->user_data);
194 }
195
196 // Called when a window should be destroyed.
197 static FlMethodResponse* destroy_window(FlWindowingChannel* self,
198 FlValue* args) {
199 if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
200 return FL_METHOD_RESPONSE(fl_method_error_response_new(
201 kBadArgumentsError, "Argument map missing or malformed", nullptr));
202 }
203
204 FlValue* view_id_value = fl_value_lookup_string(args, kViewIdKey);
205 if (view_id_value == nullptr ||
206 fl_value_get_type(view_id_value) != FL_VALUE_TYPE_INT) {
207 return FL_METHOD_RESPONSE(fl_method_error_response_new(
208 kBadArgumentsError, "Missing/invalid viewId argument", nullptr));
209 }
210 int64_t view_id = fl_value_get_int(view_id_value);
211
212 return self->vtable->destroy_window(view_id, self->user_data);
213 }
214
215 // Called when a method call is received from Flutter.
216 static void method_call_cb(FlMethodChannel* channel,
217 FlMethodCall* method_call,
218 gpointer user_data) {
219 FlWindowingChannel* self = FL_WINDOWING_CHANNEL(user_data);
220
221 const gchar* method = fl_method_call_get_name(method_call);
222 FlValue* args = fl_method_call_get_args(method_call);
223 g_autoptr(FlMethodResponse) response = nullptr;
224
225 if (strcmp(method, kCreateRegularMethod) == 0) {
226 response = create_regular(self, args);
227 } else if (strcmp(method, kModifyRegularMethod) == 0) {
228 response = modify_regular(self, args);
229 } else if (strcmp(method, kDestroyWindowMethod) == 0) {
230 response = destroy_window(self, args);
231 } else {
232 response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
233 }
234
235 if (response != nullptr) {
236 g_autoptr(GError) error = nullptr;
237 if (!fl_method_call_respond(method_call, response, &error)) {
238 g_warning("Failed to send method call response: %s", error->message);
239 }
240 }
241 }
242
243 static void fl_windowing_channel_dispose(GObject* object) {
244 FlWindowingChannel* self = FL_WINDOWING_CHANNEL(object);
245
246 g_clear_object(&self->channel);
247
248 G_OBJECT_CLASS(fl_windowing_channel_parent_class)->dispose(object);
249 }
250
251 static void fl_windowing_channel_class_init(FlWindowingChannelClass* klass) {
252 G_OBJECT_CLASS(klass)->dispose = fl_windowing_channel_dispose;
253 }
254
255 static void fl_windowing_channel_init(FlWindowingChannel* self) {}
256
257 FlWindowingChannel* fl_windowing_channel_new(FlBinaryMessenger* messenger,
258 FlWindowingChannelVTable* vtable,
259 gpointer user_data) {
260 FlWindowingChannel* self = FL_WINDOWING_CHANNEL(
261 g_object_new(fl_windowing_channel_get_type(), nullptr));
262
263 self->vtable = vtable;
264 self->user_data = user_data;
265
266 g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
267 self->channel =
268 fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
269 fl_method_channel_set_method_call_handler(self->channel, method_call_cb, self,
270 nullptr);
271
272 return self;
273 }
274
275 FlMethodResponse* fl_windowing_channel_make_create_regular_response(
276 int64_t view_id,
277 FlWindowingSize* size,
278 FlWindowState state) {
279 g_autoptr(FlValue) result = fl_value_new_map();
280 fl_value_set_string_take(result, kViewIdKey, fl_value_new_int(view_id));
281 g_autoptr(FlValue) size_value = fl_value_new_list();
282 fl_value_append_take(size_value, fl_value_new_float(size->width));
283 fl_value_append_take(size_value, fl_value_new_float(size->height));
284 fl_value_set_string(result, kSizeKey, size_value);
285 fl_value_set_string_take(result, kStateKey,
286 fl_value_new_string(window_state_to_string(state)));
287 return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
288 }
289
290 FlMethodResponse* fl_windowing_channel_make_modify_regular_response() {
291 return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
292 }
293
294 FlMethodResponse* fl_windowing_channel_make_destroy_window_response() {
295 return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
296 }
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
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_method_call_get_name
G_MODULE_EXPORT const gchar * fl_method_call_get_name(FlMethodCall *self)
Definition: fl_method_call.cc:67
fl_method_call_get_args
G_MODULE_EXPORT FlValue * fl_method_call_get_args(FlMethodCall *self)
Definition: fl_method_call.cc:72
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_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
fl_method_channel.h
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
fl_method_error_response_new
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
Definition: fl_method_response.cc:144
fl_method_success_response_new
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
Definition: fl_method_response.cc:126
fl_method_not_implemented_response_new
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
Definition: fl_method_response.cc:179
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_standard_method_codec_new
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
Definition: fl_standard_method_codec.cc:291
fl_standard_method_codec.h
fl_value_set_string
G_MODULE_EXPORT void fl_value_set_string(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:639
fl_value_new_float
G_MODULE_EXPORT FlValue * fl_value_new_float(double value)
Definition: fl_value.cc:269
fl_value_lookup_string
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:811
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
fl_value_get_list_value
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:776
fl_value_get_int
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:668
fl_value_new_string
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
fl_value_new_list
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:349
fl_value_append_take
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:600
fl_value_get_string
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
fl_value_get_float
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition: fl_value.cc:675
fl_value_get_length
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:724
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:68
FL_VALUE_TYPE_INT
@ FL_VALUE_TYPE_INT
Definition: fl_value.h:66
FL_VALUE_TYPE_LIST
@ FL_VALUE_TYPE_LIST
Definition: fl_value.h:73
FL_VALUE_TYPE_MAP
@ FL_VALUE_TYPE_MAP
Definition: fl_value.h:74
FL_VALUE_TYPE_FLOAT
@ FL_VALUE_TYPE_FLOAT
Definition: fl_value.h:67
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49
method_call_cb
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
Definition: fl_windowing_channel.cc:216
destroy_window
static FlMethodResponse * destroy_window(FlWindowingChannel *self, FlValue *args)
Definition: fl_windowing_channel.cc:197
fl_windowing_channel_class_init
static void fl_windowing_channel_class_init(FlWindowingChannelClass *klass)
Definition: fl_windowing_channel.cc:251
kStateKey
static constexpr char kStateKey[]
Definition: fl_windowing_channel.cc:21
kCreateRegularMethod
static constexpr char kCreateRegularMethod[]
Definition: fl_windowing_channel.cc:13
kMaxSizeKey
static constexpr char kMaxSizeKey[]
Definition: fl_windowing_channel.cc:19
kViewIdKey
static constexpr char kViewIdKey[]
Definition: fl_windowing_channel.cc:22
fl_windowing_channel_init
static void fl_windowing_channel_init(FlWindowingChannel *self)
Definition: fl_windowing_channel.cc:255
kSizeKey
static constexpr char kSizeKey[]
Definition: fl_windowing_channel.cc:17
kDestroyWindowMethod
static constexpr char kDestroyWindowMethod[]
Definition: fl_windowing_channel.cc:15
kMinSizeKey
static constexpr char kMinSizeKey[]
Definition: fl_windowing_channel.cc:18
fl_windowing_channel_make_modify_regular_response
FlMethodResponse * fl_windowing_channel_make_modify_regular_response()
Definition: fl_windowing_channel.cc:290
kChannelName
static constexpr char kChannelName[]
Definition: fl_windowing_channel.cc:10
is_valid_size_argument
static gboolean is_valid_size_argument(FlValue *value)
Definition: fl_windowing_channel.cc:39
parse_window_state_value
static gboolean parse_window_state_value(FlValue *value, FlWindowState *state)
Definition: fl_windowing_channel.cc:57
kTitleKey
static constexpr char kTitleKey[]
Definition: fl_windowing_channel.cc:20
fl_windowing_channel_make_create_regular_response
FlMethodResponse * fl_windowing_channel_make_create_regular_response(int64_t view_id, FlWindowingSize *size, FlWindowState state)
Definition: fl_windowing_channel.cc:275
kModifyRegularMethod
static constexpr char kModifyRegularMethod[]
Definition: fl_windowing_channel.cc:14
fl_windowing_channel_new
FlWindowingChannel * fl_windowing_channel_new(FlBinaryMessenger *messenger, FlWindowingChannelVTable *vtable, gpointer user_data)
Definition: fl_windowing_channel.cc:257
kBadArgumentsError
static constexpr char kBadArgumentsError[]
Definition: fl_windowing_channel.cc:11
modify_regular
static FlMethodResponse * modify_regular(FlWindowingChannel *self, FlValue *args)
Definition: fl_windowing_channel.cc:150
create_regular
static FlMethodResponse * create_regular(FlWindowingChannel *self, FlValue *args)
Definition: fl_windowing_channel.cc:93
window_state_to_string
static const gchar * window_state_to_string(FlWindowState state)
Definition: fl_windowing_channel.cc:77
fl_windowing_channel_dispose
static void fl_windowing_channel_dispose(GObject *object)
Definition: fl_windowing_channel.cc:243
parse_size_value
static FlWindowingSize * parse_size_value(FlValue *value)
Definition: fl_windowing_channel.cc:50
fl_windowing_channel_make_destroy_window_response
FlMethodResponse * fl_windowing_channel_make_destroy_window_response()
Definition: fl_windowing_channel.cc:294
fl_windowing_channel.h
FlWindowState
FlWindowState
Definition: fl_windowing_channel.h:20
FL_WINDOW_STATE_UNDEFINED
@ FL_WINDOW_STATE_UNDEFINED
Definition: fl_windowing_channel.h:21
FL_WINDOW_STATE_MINIMIZED
@ FL_WINDOW_STATE_MINIMIZED
Definition: fl_windowing_channel.h:24
FL_WINDOW_STATE_MAXIMIZED
@ FL_WINDOW_STATE_MAXIMIZED
Definition: fl_windowing_channel.h:23
FL_WINDOW_STATE_RESTORED
@ FL_WINDOW_STATE_RESTORED
Definition: fl_windowing_channel.h:22
_FlWindowingChannel
Definition: fl_windowing_channel.cc:24
_FlWindowingChannel::parent_instance
GObject parent_instance
Definition: fl_windowing_channel.cc:25
_FlWindowingChannel::user_data
gpointer user_data
Definition: fl_windowing_channel.cc:33
_FlWindowingChannel::vtable
FlWindowingChannelVTable * vtable
Definition: fl_windowing_channel.cc:30
_FlWindowingChannel::channel
FlMethodChannel * channel
Definition: fl_windowing_channel.cc:27
FlWindowingChannelVTable
Definition: fl_windowing_channel.h:40
FlWindowingSize
Definition: fl_windowing_channel.h:28
FlWindowingSize::height
double height
Definition: fl_windowing_channel.h:30
FlWindowingSize::width
double width
Definition: fl_windowing_channel.h:29