1 /*
2 * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 *
6 */
7 #include "config.h"
8
9 #ifdef CAIRO_EGL_FOUND
10
11 #include <cairo/cairo-gl.h>
12 #include <wayland-egl.h>
13 #include "waylandeglwindow.h"
14 #include "wl_callback.h"
15
16 namespace fcitx {
17 namespace classicui {
WaylandEGLWindow(WaylandUI * ui)18 WaylandEGLWindow::WaylandEGLWindow(WaylandUI *ui)
19 : WaylandWindow(ui), window_(nullptr), cairoSurface_(nullptr) {}
20
~WaylandEGLWindow()21 WaylandEGLWindow::~WaylandEGLWindow() { destroyWindow(); }
22
createWindow()23 void WaylandEGLWindow::createWindow() { WaylandWindow::createWindow(); }
24
destroyWindow()25 void WaylandEGLWindow::destroyWindow() {
26 hide();
27 WaylandWindow::destroyWindow();
28 }
29
prerender()30 cairo_surface_t *WaylandEGLWindow::prerender() {
31 if (width_ == 0 || height_ == 0) {
32 hide();
33 return nullptr;
34 }
35
36 if (!window_) {
37 window_.reset(wl_egl_window_create(*surface_, width_, height_));
38 }
39 if (window_ && !eglSurface_) {
40 eglSurface_ = ui_->createEGLSurface(window_.get(), nullptr);
41 }
42 if (eglSurface_ && !cairoSurface_) {
43 cairoSurface_.reset(
44 ui_->createEGLCairoSurface(eglSurface_, width_, height_));
45 }
46 if (!cairoSurface_) {
47 return nullptr;
48 }
49 int width, height;
50 wl_egl_window_get_attached_size(window_.get(), &width, &height);
51 if (width != static_cast<int>(width_) ||
52 height != static_cast<int>(height_)) {
53 wl_egl_window_resize(window_.get(), width_, height_, 0, 0);
54 }
55 cairo_gl_surface_set_size(cairoSurface_.get(), width_, height_);
56 if (cairo_surface_status(cairoSurface_.get()) != CAIRO_STATUS_SUCCESS) {
57 return nullptr;
58 }
59
60 return cairoSurface_.get();
61 }
62
render()63 void WaylandEGLWindow::render() {
64 if (cairo_surface_status(cairoSurface_.get()) != CAIRO_STATUS_SUCCESS) {
65 return;
66 }
67 cairo_gl_surface_swapbuffers(cairoSurface_.get());
68 callback_.reset(surface_->frame());
69 callback_->done().connect([this](uint32_t) { callback_.reset(); });
70 }
71
hide()72 void WaylandEGLWindow::hide() {
73 cairoSurface_.reset();
74 if (eglSurface_) {
75 ui_->destroyEGLSurface(eglSurface_);
76 eglSurface_ = nullptr;
77 }
78 window_.reset();
79 surface_->attach(nullptr, 0, 0);
80 surface_->commit();
81 }
82 } // namespace classicui
83 } // namespace fcitx
84
85 #endif
86