|
5 | 5 | #include "fl_renderer_x11.h"
|
6 | 6 | #ifdef GDK_WINDOWING_X11
|
7 | 7 |
|
| 8 | +#include <X11/X.h> |
| 9 | + |
8 | 10 | #include "flutter/shell/platform/linux/egl_utils.h"
|
9 | 11 |
|
10 | 12 | struct _FlRendererX11 {
|
11 | 13 | FlRenderer parent_instance;
|
| 14 | + |
| 15 | + // Connection to the X server. |
| 16 | + Display* display; |
12 | 17 | };
|
13 | 18 |
|
14 | 19 | G_DEFINE_TYPE(FlRendererX11, fl_renderer_x11, fl_renderer_get_type())
|
15 | 20 |
|
| 21 | +static void fl_renderer_x11_dispose(GObject* object) { |
| 22 | + FlRendererX11* self = FL_RENDERER_X11(object); |
| 23 | + |
| 24 | + if (self->display != nullptr) { |
| 25 | + XCloseDisplay(self->display); |
| 26 | + self->display = nullptr; |
| 27 | + } |
| 28 | + |
| 29 | + G_OBJECT_CLASS(fl_renderer_x11_parent_class)->dispose(object); |
| 30 | +} |
| 31 | + |
16 | 32 | // Implements FlRenderer::setup_window_attr.
|
17 | 33 | static gboolean fl_renderer_x11_setup_window_attr(
|
18 | 34 | FlRenderer* renderer,
|
@@ -50,11 +66,17 @@ static gboolean fl_renderer_x11_setup_window_attr(
|
50 | 66 |
|
51 | 67 | // Implements FlRenderer::create_display.
|
52 | 68 | static EGLDisplay fl_renderer_x11_create_display(FlRenderer* renderer) {
|
53 |
| - // Note the use of EGL_DEFAULT_DISPLAY rather than sharing the existing |
54 |
| - // display connection from GTK. This is because this EGL display is going to |
55 |
| - // be accessed by a thread from Flutter. The GTK/X11 display connection is not |
56 |
| - // thread safe and would cause a crash. |
57 |
| - return eglGetDisplay(EGL_DEFAULT_DISPLAY); |
| 69 | + FlRendererX11* self = FL_RENDERER_X11(renderer); |
| 70 | + |
| 71 | + // Create a dedicated connection to the X server because the EGL calls are |
| 72 | + // made from Flutter on a different thread to GTK. Re-using the existing |
| 73 | + // GTK X11 connection would crash as Xlib is not thread safe. |
| 74 | + if (self->display == nullptr) { |
| 75 | + Display* display = gdk_x11_get_default_xdisplay(); |
| 76 | + self->display = XOpenDisplay(DisplayString(display)); |
| 77 | + } |
| 78 | + |
| 79 | + return eglGetDisplay(self->display); |
58 | 80 | }
|
59 | 81 |
|
60 | 82 | // Implements FlRenderer::create_surfaces.
|
@@ -99,6 +121,7 @@ static gboolean fl_renderer_x11_create_surfaces(FlRenderer* renderer,
|
99 | 121 | }
|
100 | 122 |
|
101 | 123 | static void fl_renderer_x11_class_init(FlRendererX11Class* klass) {
|
| 124 | + G_OBJECT_CLASS(klass)->dispose = fl_renderer_x11_dispose; |
102 | 125 | FL_RENDERER_CLASS(klass)->setup_window_attr =
|
103 | 126 | fl_renderer_x11_setup_window_attr;
|
104 | 127 | FL_RENDERER_CLASS(klass)->create_display = fl_renderer_x11_create_display;
|
|
0 commit comments