| Flutter Linux Embedder |

fl_windowing_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_windowing_handler.h"
6
7 #include "flutter/shell/platform/linux/fl_windowing_channel.h"
8 #include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
9
10 typedef struct {
11 GWeakRef engine;
12
13 FlWindowingChannel* channel;
14
15 GHashTable* windows_by_view_id;
16 } FlWindowingHandlerPrivate;
17
18 enum { SIGNAL_CREATE_WINDOW, LAST_SIGNAL };
19
20 static guint signals[LAST_SIGNAL];
21
22 G_DEFINE_TYPE_WITH_PRIVATE(FlWindowingHandler,
23 fl_windowing_handler,
24 G_TYPE_OBJECT)
25
26 typedef struct {
27 GtkWindow* window;
28 FlView* view;
29 guint first_frame_cb_id;
30 } WindowData;
31
32 static WindowData* window_data_new(GtkWindow* window, FlView* view) {
33 WindowData* data = g_new0(WindowData, 1);
34 data->window = GTK_WINDOW(g_object_ref(window));
35 data->view = FL_VIEW(g_object_ref(view));
36 return data;
37 }
38
39 static void window_data_free(WindowData* data) {
40 g_signal_handler_disconnect(data->view, data->first_frame_cb_id);
41 g_object_unref(data->window);
42 g_object_unref(data->view);
43 g_free(data);
44 }
45
46 // Called when the first frame is received.
47 static void first_frame_cb(FlView* view, WindowData* data) {
48 gtk_window_present(data->window);
49 }
50
51 static WindowData* get_window_data(FlWindowingHandler* self, int64_t view_id) {
52 FlWindowingHandlerPrivate* priv =
53 reinterpret_cast<FlWindowingHandlerPrivate*>(
54 fl_windowing_handler_get_instance_private(self));
55
56 return static_cast<WindowData*>(
57 g_hash_table_lookup(priv->windows_by_view_id, GINT_TO_POINTER(view_id)));
58 }
59
60 static GtkWindow* fl_windowing_handler_create_window(
61 FlWindowingHandler* handler,
62 FlView* view) {
63 GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
64 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
65
66 return GTK_WINDOW(window);
67 }
68
69 static FlMethodResponse* create_regular(FlWindowingSize* size,
70 FlWindowingSize* min_size,
71 FlWindowingSize* max_size,
72 const gchar* title,
73 FlWindowState state,
74 gpointer user_data) {
75 FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
76 FlWindowingHandlerPrivate* priv =
77 reinterpret_cast<FlWindowingHandlerPrivate*>(
78 fl_windowing_handler_get_instance_private(self));
79
80 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
81 if (engine == nullptr) {
82 return FL_METHOD_RESPONSE(
83 fl_method_error_response_new("Internal error", "No engine", nullptr));
84 }
85
86 FlView* view = fl_view_new_for_engine(engine);
87 gtk_widget_show(GTK_WIDGET(view));
88
89 GtkWindow* window;
90 g_signal_emit(self, signals[SIGNAL_CREATE_WINDOW], 0, view, &window);
91 if (window == nullptr) {
92 return FL_METHOD_RESPONSE(fl_method_error_response_new(
93 "Internal error", "Failed to create window", nullptr));
94 }
95
96 gtk_window_set_default_size(GTK_WINDOW(window), size->width, size->height);
97 if (title != nullptr) {
98 gtk_window_set_title(GTK_WINDOW(window), title);
99 }
100 switch (state) {
101 case FL_WINDOW_STATE_MAXIMIZED:
102 gtk_window_maximize(GTK_WINDOW(window));
103 break;
104 case FL_WINDOW_STATE_MINIMIZED:
105 gtk_window_iconify(GTK_WINDOW(window));
106 break;
107 case FL_WINDOW_STATE_RESTORED:
108 case FL_WINDOW_STATE_UNDEFINED:
109 break;
110 }
111
112 GdkGeometry geometry;
113 GdkWindowHints geometry_mask = static_cast<GdkWindowHints>(0);
114 if (min_size != nullptr) {
115 geometry.min_width = min_size->width;
116 geometry.min_height = min_size->height;
117 geometry_mask =
118 static_cast<GdkWindowHints>(geometry_mask | GDK_HINT_MIN_SIZE);
119 }
120 if (max_size != nullptr) {
121 geometry.max_width = max_size->width;
122 geometry.max_height = max_size->height;
123 geometry_mask =
124 static_cast<GdkWindowHints>(geometry_mask | GDK_HINT_MAX_SIZE);
125 }
126 if (geometry_mask != 0) {
127 gtk_window_set_geometry_hints(GTK_WINDOW(window), nullptr, &geometry,
128 geometry_mask);
129 }
130
131 WindowData* data = window_data_new(GTK_WINDOW(window), view);
132 data->first_frame_cb_id =
133 g_signal_connect(view, "first-frame", G_CALLBACK(first_frame_cb), data);
134
135 // Make the resources for the view so rendering can start.
136 // We'll show the view when we have the first frame.
137 gtk_widget_realize(GTK_WIDGET(view));
138
139 g_hash_table_insert(priv->windows_by_view_id,
140 GINT_TO_POINTER(fl_view_get_id(view)), data);
141
142 // We don't know the current size and dimensions, so just reflect back what
143 // was requested.
144 FlWindowingSize* initial_size = size;
145 FlWindowState initial_state = state;
146 if (initial_state == FL_WINDOW_STATE_UNDEFINED) {
147 initial_state = FL_WINDOW_STATE_RESTORED;
148 }
149
150 return fl_windowing_channel_make_create_regular_response(
151 fl_view_get_id(view), initial_size, initial_state);
152 }
153
154 static FlMethodResponse* modify_regular(int64_t view_id,
155 FlWindowingSize* size,
156 const gchar* title,
157 FlWindowState state,
158 gpointer user_data) {
159 FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
160
161 WindowData* data = get_window_data(self, view_id);
162 if (data == nullptr) {
163 return FL_METHOD_RESPONSE(fl_method_error_response_new(
164 "Bad Arguments", "No window with given view ID", nullptr));
165 }
166
167 if (size != nullptr) {
168 gtk_window_resize(data->window, size->width, size->height);
169 }
170
171 if (title != nullptr) {
172 gtk_window_set_title(data->window, title);
173 }
174
175 GdkWindowState window_state;
176 switch (state) {
177 case FL_WINDOW_STATE_RESTORED:
178 if (gtk_window_is_maximized(data->window)) {
179 gtk_window_unmaximize(data->window);
180 }
181 window_state =
182 gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(data->window)));
183 if (window_state & GDK_WINDOW_STATE_ICONIFIED) {
184 gtk_window_deiconify(data->window);
185 }
186 break;
187 case FL_WINDOW_STATE_MAXIMIZED:
188 gtk_window_maximize(data->window);
189 break;
190 case FL_WINDOW_STATE_MINIMIZED:
191 gtk_window_iconify(data->window);
192 break;
193 case FL_WINDOW_STATE_UNDEFINED:
194 break;
195 }
196
197 return fl_windowing_channel_make_modify_regular_response();
198 }
199
200 static FlMethodResponse* destroy_window(int64_t view_id, gpointer user_data) {
201 FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
202 FlWindowingHandlerPrivate* priv =
203 reinterpret_cast<FlWindowingHandlerPrivate*>(
204 fl_windowing_handler_get_instance_private(self));
205
206 WindowData* data = get_window_data(self, view_id);
207 if (data == nullptr) {
208 return FL_METHOD_RESPONSE(fl_method_error_response_new(
209 "Bad Arguments", "No window with given view ID", nullptr));
210 }
211
212 gtk_widget_destroy(GTK_WIDGET(data->window));
213
214 g_hash_table_remove(priv->windows_by_view_id, GINT_TO_POINTER(view_id));
215
216 return fl_windowing_channel_make_destroy_window_response();
217 }
218
219 static void fl_windowing_handler_dispose(GObject* object) {
220 FlWindowingHandler* self = FL_WINDOWING_HANDLER(object);
221 FlWindowingHandlerPrivate* priv =
222 reinterpret_cast<FlWindowingHandlerPrivate*>(
223 fl_windowing_handler_get_instance_private(self));
224
225 g_weak_ref_clear(&priv->engine);
226 g_clear_object(&priv->channel);
227 g_clear_pointer(&priv->windows_by_view_id, g_hash_table_unref);
228
229 G_OBJECT_CLASS(fl_windowing_handler_parent_class)->dispose(object);
230 }
231
232 static void fl_windowing_handler_class_init(FlWindowingHandlerClass* klass) {
233 G_OBJECT_CLASS(klass)->dispose = fl_windowing_handler_dispose;
234
235 klass->create_window = fl_windowing_handler_create_window;
236
237 signals[SIGNAL_CREATE_WINDOW] = g_signal_new(
238 "create-window", fl_windowing_handler_get_type(), G_SIGNAL_RUN_LAST,
239 G_STRUCT_OFFSET(FlWindowingHandlerClass, create_window),
240 g_signal_accumulator_first_wins, nullptr, nullptr, GTK_TYPE_WINDOW, 1,
241 fl_view_get_type());
242 }
243
244 static void fl_windowing_handler_init(FlWindowingHandler* self) {
245 FlWindowingHandlerPrivate* priv =
246 reinterpret_cast<FlWindowingHandlerPrivate*>(
247 fl_windowing_handler_get_instance_private(self));
248
249 priv->windows_by_view_id =
250 g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
251 reinterpret_cast<GDestroyNotify>(window_data_free));
252 }
253
254 static FlWindowingChannelVTable windowing_channel_vtable = {
255 .create_regular = create_regular,
256 .modify_regular = modify_regular,
257 .destroy_window = destroy_window,
258 };
259
260 FlWindowingHandler* fl_windowing_handler_new(FlEngine* engine) {
261 g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
262
263 FlWindowingHandler* self = FL_WINDOWING_HANDLER(
264 g_object_new(fl_windowing_handler_get_type(), nullptr));
265 FlWindowingHandlerPrivate* priv =
266 reinterpret_cast<FlWindowingHandlerPrivate*>(
267 fl_windowing_handler_get_instance_private(self));
268
269 g_weak_ref_init(&priv->engine, engine);
270 priv->channel = fl_windowing_channel_new(
271 fl_engine_get_binary_messenger(engine), &windowing_channel_vtable, self);
272
273 return self;
274 }
state
AtkStateType state
Definition: fl_accessible_node.cc:10
view
FlView * view
Definition: fl_application.cc:36
g_signal_emit
g_signal_emit(self, fl_application_signals[SIGNAL_CREATE_WINDOW], 0, view, &window)
window
return window
Definition: fl_application.cc:41
fl_engine_get_binary_messenger
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
Definition: fl_engine.cc:1281
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
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
priv
FlPixelBufferTexturePrivate * priv
Definition: fl_pixel_buffer_texture.cc:30
fl_view_new_for_engine
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition: fl_view.cc:772
fl_view_get_id
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition: fl_view.cc:793
fl_view.h
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49
fl_windowing_channel_make_modify_regular_response
FlMethodResponse * fl_windowing_channel_make_modify_regular_response()
Definition: fl_windowing_channel.cc:290
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
fl_windowing_channel_new
FlWindowingChannel * fl_windowing_channel_new(FlBinaryMessenger *messenger, FlWindowingChannelVTable *vtable, gpointer user_data)
Definition: fl_windowing_channel.cc:257
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
destroy_window
static FlMethodResponse * destroy_window(int64_t view_id, gpointer user_data)
Definition: fl_windowing_handler.cc:200
fl_windowing_handler_class_init
static void fl_windowing_handler_class_init(FlWindowingHandlerClass *klass)
Definition: fl_windowing_handler.cc:232
get_window_data
static WindowData * get_window_data(FlWindowingHandler *self, int64_t view_id)
Definition: fl_windowing_handler.cc:51
signals
static guint signals[LAST_SIGNAL]
Definition: fl_windowing_handler.cc:20
fl_windowing_handler_new
FlWindowingHandler * fl_windowing_handler_new(FlEngine *engine)
Definition: fl_windowing_handler.cc:260
WindowData
WindowData
Definition: fl_windowing_handler.cc:30
modify_regular
static FlMethodResponse * modify_regular(int64_t view_id, FlWindowingSize *size, const gchar *title, FlWindowState state, gpointer user_data)
Definition: fl_windowing_handler.cc:154
window_data_free
static void window_data_free(WindowData *data)
Definition: fl_windowing_handler.cc:39
fl_windowing_handler_dispose
static void fl_windowing_handler_dispose(GObject *object)
Definition: fl_windowing_handler.cc:219
create_regular
static FlMethodResponse * create_regular(FlWindowingSize *size, FlWindowingSize *min_size, FlWindowingSize *max_size, const gchar *title, FlWindowState state, gpointer user_data)
Definition: fl_windowing_handler.cc:69
LAST_SIGNAL
@ LAST_SIGNAL
Definition: fl_windowing_handler.cc:18
SIGNAL_CREATE_WINDOW
@ SIGNAL_CREATE_WINDOW
Definition: fl_windowing_handler.cc:18
first_frame_cb
static void first_frame_cb(FlView *view, WindowData *data)
Definition: fl_windowing_handler.cc:47
window_data_new
static WindowData * window_data_new(GtkWindow *window, FlView *view)
Definition: fl_windowing_handler.cc:32
fl_windowing_handler_init
static void fl_windowing_handler_init(FlWindowingHandler *self)
Definition: fl_windowing_handler.cc:244
windowing_channel_vtable
static FlWindowingChannelVTable windowing_channel_vtable
Definition: fl_windowing_handler.cc:254
fl_windowing_handler_create_window
static GtkWindow * fl_windowing_handler_create_window(FlWindowingHandler *handler, FlView *view)
Definition: fl_windowing_handler.cc:60
G_DEFINE_TYPE_WITH_PRIVATE
G_DEFINE_TYPE_WITH_PRIVATE(FlWindowingHandler, fl_windowing_handler, G_TYPE_OBJECT) typedef struct
Definition: fl_windowing_handler.cc:22
fl_windowing_handler.h
FlWindowingChannelVTable
Definition: fl_windowing_channel.h:40
FlWindowingChannelVTable::create_regular
FlMethodResponse *(* create_regular)(FlWindowingSize *size, FlWindowingSize *min_size, FlWindowingSize *max_size, const gchar *title, FlWindowState state, gpointer user_data)
Definition: fl_windowing_channel.h:41
FlWindowingHandlerPrivate
Definition: fl_windowing_handler.cc:10
FlWindowingHandlerPrivate::engine
GWeakRef engine
Definition: fl_windowing_handler.cc:11
FlWindowingHandlerPrivate::windows_by_view_id
GHashTable * windows_by_view_id
Definition: fl_windowing_handler.cc:15
FlWindowingHandlerPrivate::channel
FlWindowingChannel * channel
Definition: fl_windowing_handler.cc:13
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