Wayland cOMPositor written in C++ using Louvre.
1/* ========================================================================
2 *
3 * Filename: WOutput.cpp
4 * Description: W Compositor output class definitions
5 * GitHub Repo: https://github.com/diego-est/womp
6 * Author: Diego A. Estrada Rivera
7 * License: GPL-3.0
8 *
9 * ======================================================================== */
10#include "WOutput.hpp"
11#include "WCompositor.hpp"
12#include "WSurface.hpp"
13#include "WTopBar.hpp"
14#include "global.hpp"
15#include "prelude.hpp"
16#include <LCompositor.h>
17#include <LCursor.h>
18#include <LDNDManager.h>
19#include <LLog.h>
20#include <LOpenGL.h>
21#include <LPainter.h>
22#include <LSeat.h>
23#include <LTexture.h>
24#include <LTextureView.h>
25#include <memory>
26
27WOutput::WOutput() noexcept
28{
29}
30
31void WOutput::initializeGL() noexcept
32{
33 wallpaperView = std::make_unique<LTextureView>(
34 nullptr, &G::compositor()->backgroundLayer);
35
36 /*
37 * TextureView's have a default nullptr translucent region, which means
38 * they are considered completely translucent by the scene. However,
39 * setting an empty LRegion (not nullptr) indicates to the scene that
40 * the view is completely opaque.
41 */
42 let emptyRegion = LRegion();
43 wallpaperView->setTranslucentRegion(&emptyRegion);
44
45 updateWallpaper();
46 topBar = std::make_unique<WTopBar>(this);
47 G::scene()->handleInitializeGL(this);
48 repaint();
49}
50
51void WOutput::moveGL() noexcept
52{
53 wallpaperView->setPos(pos());
54 topBar->update();
55 G::scene()->handleMoveGL(this);
56 repaint();
57}
58
59void WOutput::resizeGL() noexcept
60{
61 updateWallpaper();
62 topBar->update();
63 G::scene()->handleResizeGL(this);
64 repaint();
65}
66
67void WOutput::paintGL() noexcept
68{
69 // check if HW cursor is supported
70 if (cursor()->hasHardwareSupport(this)) {
71 G::compositor()->softwareCursor.setTexture(nullptr);
72 } else {
73 G::compositor()->softwareCursor.setTexture(cursor()->texture());
74 G::compositor()->softwareCursor.setPos(cursor()->rect().pos());
75 G::compositor()->softwareCursor.setDstSize(
76 cursor()->rect().size());
77 G::compositor()->softwareCursor.setVisible(cursor()->visible());
78 }
79 topBar->update();
80 G::scene()->handlePaintGL(this);
81}
82
83void WOutput::uninitializeGL() noexcept
84{
85 /*
86 * set minimized output to nullptr to prevent the compositor from
87 * crashing when a surface is unminimized and
88 * WSurface::minimizeChanged() is triggered
89 */
90 for (let surface : G::surfaces())
91 if (surface->minimizedOutput == this)
92 surface->minimizedOutput = nullptr;
93
94 G::scene()->handleUninitializeGL(this);
95
96 if (wallpaperView->texture())
97 delete wallpaperView->texture();
98}
99
100void WOutput::updateWallpaper() const noexcept
101{
102 if (wallpaperView->texture()) {
103 // if the current wallpaper size is equal to the output size
104 // then the output simply changed its scale
105 if (wallpaperView->texture()->sizeB() == sizeB()) {
106 wallpaperView->setBufferScale(scale());
107 wallpaperView->setPos(pos());
108 return;
109 }
110
111 delete wallpaperView->texture();
112 }
113
114 // load the original wallpaper
115 let originalWallpaper = std::unique_ptr<LTexture>(LOpenGL::loadTexture(
116 "/home/Michorron/Media/Pictures/Wallpapers/bliss.jpg"));
117
118 if (originalWallpaper == nullptr) {
119 LLog::error("[louvre-example] Failed to load wallpaper.");
120 return;
121 }
122
123 let srcRect = calculateWallpaperRect(originalWallpaper->sizeB());
124
125 // copy the srcRect of the originall wallpaper and scale it to match the
126 // output buffer size
127 wallpaperView->setTexture(originalWallpaper->copyB(sizeB(), srcRect));
128
129 // set the buffer scale of the wallpaper view to match the output scale
130 wallpaperView->setBufferScale(scale());
131
132 // delete the original wallpaper texture since we are using the scaled
133 // copy
134 wallpaperView->setPos(pos());
135}
136
137void WOutput::damageRenderingTest() noexcept
138{
139 painter()->clearScreen();
140 G::scene()->handlePaintGL(this);
141
142 var damage = LRegion();
143 damage.addRect(rect());
144 setBufferDamage(damage);
145}
146fn WOutput::calculateWallpaperRect(
147 LSize const& originalWallpaperSize) const noexcept -> LRect
148{
149 var srcRect = LRect(0);
150
151 let scaledWidth =
152 F32(size().w() * originalWallpaperSize.h()) / F32(size().h());
153
154 // if the scaled width is greater than or equal to the output's width,
155 // we clip the texture's left and right sides.
156 if (scaledWidth >= originalWallpaperSize.w()) {
157 srcRect.setH(originalWallpaperSize.h());
158 srcRect.setW((originalWallpaperSize.h() * size().w()) /
159 size().h());
160 srcRect.setY((originalWallpaperSize.w() - srcRect.w()) / 2.0);
161 } else { // otherwise clip the texture's top and bottom sides
162 srcRect.setW(originalWallpaperSize.w());
163 srcRect.setH(originalWallpaperSize.h() * size().h() /
164 size().w());
165 srcRect.setY((originalWallpaperSize.h() - srcRect.h()) / 2.0);
166 }
167
168 return srcRect;
169}