dont deadlock while receiving events
This commit is contained in:
		
							parent
							
								
									0b5710da3e
								
							
						
					
					
						commit
						7298730969
					
				| @ -66,6 +66,12 @@ | ||||
|             <arg name="tag" type="int"/> | ||||
|             <arg name="active" type="int"/> | ||||
|             <arg name="num_clients" type="int"/> | ||||
|             <arg name="urgent" type="int"/> | ||||
|         </event> | ||||
| 
 | ||||
|         <event name="frame"> | ||||
|             <description summary="sent after all other events have been sent. allows for atomic updates."> | ||||
|             </description> | ||||
|         </event> | ||||
|     </interface> | ||||
| </protocol> | ||||
|  | ||||
							
								
								
									
										46
									
								
								src/bar.cpp
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								src/bar.cpp
									
									
									
									
									
								
							| @ -27,25 +27,25 @@ static QFont getFont() | ||||
|     font.setBold(fontBold); | ||||
|     return font; | ||||
| } | ||||
| static QFont font = getFont(); | ||||
| static QFontMetrics fontMetrics = QFontMetrics {font}; | ||||
| 
 | ||||
| Bar::Bar(const wl_output *output) | ||||
|     : _font {getFont()} | ||||
|     , _fontMetrics {_font} | ||||
| { | ||||
|     _surface = wl_compositor_create_surface(compositor); | ||||
|     _layerSurface = zwlr_layer_shell_v1_get_layer_surface(wlrLayerShell, | ||||
|         _surface, nullptr, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "net.tapesoftware.Somebar"); | ||||
|     zwlr_layer_surface_v1_add_listener(_layerSurface, &_layerSurfaceListener, this); | ||||
|     _surface.reset(wl_compositor_create_surface(compositor)); | ||||
|     _layerSurface.reset(zwlr_layer_shell_v1_get_layer_surface(wlrLayerShell, | ||||
|         _surface.get(), nullptr, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "net.tapesoftware.Somebar")); | ||||
|     zwlr_layer_surface_v1_add_listener(_layerSurface.get(), &_layerSurfaceListener, this); | ||||
|     auto anchor = topbar ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; | ||||
|     zwlr_layer_surface_v1_set_anchor(_layerSurface, | ||||
|     zwlr_layer_surface_v1_set_anchor(_layerSurface.get(), | ||||
|         anchor | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); | ||||
| 
 | ||||
|     auto barSize = _fontMetrics.ascent() + _fontMetrics.descent() + paddingY * 2; | ||||
|     _textY = _fontMetrics.ascent() + paddingY; | ||||
|     auto barSize = fontMetrics.ascent() + fontMetrics.descent() + paddingY * 2; | ||||
|     _textY = fontMetrics.ascent() + paddingY; | ||||
| 
 | ||||
|     zwlr_layer_surface_v1_set_size(_layerSurface, 0, barSize); | ||||
|     zwlr_layer_surface_v1_set_exclusive_zone(_layerSurface, barSize); | ||||
|     wl_surface_commit(_surface); | ||||
|     zwlr_layer_surface_v1_set_size(_layerSurface.get(), 0, barSize); | ||||
|     zwlr_layer_surface_v1_set_exclusive_zone(_layerSurface.get(), barSize); | ||||
|     wl_surface_commit(_surface.get()); | ||||
| 
 | ||||
|     for (auto tag : tagNames) { | ||||
|         _tags.push_back({ tag, false }); | ||||
| @ -54,11 +54,7 @@ Bar::Bar(const wl_output *output) | ||||
|     _status = "Status"; | ||||
| } | ||||
| 
 | ||||
| Bar::~Bar() | ||||
| { | ||||
|     wl_surface_destroy(_surface); | ||||
|     zwlr_layer_surface_v1_destroy(_layerSurface); | ||||
| } | ||||
| const wl_surface* Bar::surface() const { return _surface.get(); } | ||||
| 
 | ||||
| void Bar::click(int x, int) | ||||
| { | ||||
| @ -75,9 +71,9 @@ void Bar::invalidate() | ||||
| { | ||||
|     if (_invalid) return; | ||||
|     _invalid = true; | ||||
|     auto frame = wl_surface_frame(_surface); | ||||
|     auto frame = wl_surface_frame(_surface.get()); | ||||
|     wl_callback_add_listener(frame, &_frameListener, this); | ||||
|     wl_surface_commit(_surface); | ||||
|     wl_surface_commit(_surface.get()); | ||||
| } | ||||
| 
 | ||||
| void Bar::setStatus(const QString &status) | ||||
| @ -88,7 +84,7 @@ void Bar::setStatus(const QString &status) | ||||
| 
 | ||||
| void Bar::layerSurfaceConfigure(uint32_t serial, uint32_t width, uint32_t height) | ||||
| { | ||||
|     zwlr_layer_surface_v1_ack_configure(_layerSurface, serial); | ||||
|     zwlr_layer_surface_v1_ack_configure(_layerSurface.get(), serial); | ||||
|     _bufs.emplace(width, height, WL_SHM_FORMAT_XRGB8888); | ||||
|     render(); | ||||
| } | ||||
| @ -105,7 +101,7 @@ void Bar::render() | ||||
|     auto painter = QPainter {&img}; | ||||
|     _painter = &painter; | ||||
|     _x = 0; | ||||
|     painter.setFont(_font); | ||||
|     painter.setFont(font); | ||||
| 
 | ||||
|     setColorScheme(colorActive); | ||||
|     painter.fillRect(0, 0, img.width(), img.height(), painter.brush()); | ||||
| @ -115,9 +111,9 @@ void Bar::render() | ||||
|     renderStatus(); | ||||
|      | ||||
|     _painter = nullptr; | ||||
|     wl_surface_attach(_surface, _bufs->buffer(), 0, 0); | ||||
|     wl_surface_damage(_surface, 0, 0, INT_MAX, INT_MAX); | ||||
|     wl_surface_commit(_surface); | ||||
|     wl_surface_attach(_surface.get(), _bufs->buffer(), 0, 0); | ||||
|     wl_surface_damage(_surface.get(), 0, 0, INT_MAX, INT_MAX); | ||||
|     wl_surface_commit(_surface.get()); | ||||
|     _bufs->flip(); | ||||
|     _invalid = false; | ||||
| } | ||||
| @ -156,5 +152,5 @@ void Bar::renderStatus() | ||||
| 
 | ||||
| int Bar::textWidth(const QString &text) | ||||
| { | ||||
|     return _fontMetrics.size(Qt::TextSingleLine, text).width(); | ||||
|     return fontMetrics.size(Qt::TextSingleLine, text).width(); | ||||
| } | ||||
|  | ||||
| @ -22,11 +22,9 @@ class Bar { | ||||
|     static const zwlr_layer_surface_v1_listener _layerSurfaceListener; | ||||
|     static const wl_callback_listener _frameListener; | ||||
| 
 | ||||
|     wl_surface *_surface {nullptr}; | ||||
|     zwlr_layer_surface_v1 *_layerSurface {nullptr}; | ||||
|     wl_unique_ptr<wl_surface> _surface; | ||||
|     wl_unique_ptr<zwlr_layer_surface_v1> _layerSurface; | ||||
|     QPainter *_painter {nullptr}; | ||||
|     QFont _font; | ||||
|     QFontMetrics _fontMetrics; | ||||
|     std::optional<ShmBuffer> _bufs; | ||||
|     int _textY, _x; | ||||
|     bool _invalid {false}; | ||||
| @ -45,7 +43,7 @@ class Bar { | ||||
|     void invalidate(); | ||||
| public: | ||||
|     explicit Bar(const wl_output *output); | ||||
|     const wl_surface* surface() const; | ||||
|     void setStatus(const QString &status); | ||||
|     void click(int x, int y); | ||||
|     ~Bar(); | ||||
| }; | ||||
|  | ||||
| @ -3,10 +3,12 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| #include <wayland-client.h> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <QColor> | ||||
| #include <QString> | ||||
| #include "wlr-layer-shell-unstable-v1-client-protocol.h" | ||||
| #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" | ||||
| 
 | ||||
| extern wl_display *display; | ||||
| extern wl_compositor *compositor; | ||||
| @ -17,3 +19,17 @@ extern std::vector<QString> tagNames; | ||||
| struct ColorScheme { | ||||
|     QColor fg, bg; | ||||
| }; | ||||
| 
 | ||||
| // wayland smart pointers
 | ||||
| template<typename T> | ||||
| struct wl_deleter; | ||||
| #define WL_DELETER(type, fn) template<> struct wl_deleter<type> { void operator()(type *v) { if(v) fn(v); } } | ||||
| 
 | ||||
| template<typename T> | ||||
| using wl_unique_ptr = std::unique_ptr<T, wl_deleter<T>>; | ||||
| 
 | ||||
| WL_DELETER(wl_surface, wl_surface_destroy); | ||||
| WL_DELETER(zwlr_layer_surface_v1, zwlr_layer_surface_v1_destroy); | ||||
| WL_DELETER(wl_buffer, wl_buffer_destroy); | ||||
| WL_DELETER(wl_output, wl_output_release); | ||||
| WL_DELETER(znet_tapesoftware_dwl_wm_monitor_v1, znet_tapesoftware_dwl_wm_monitor_v1_release); | ||||
|  | ||||
							
								
								
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -24,8 +24,8 @@ | ||||
| 
 | ||||
| struct Monitor { | ||||
|     uint32_t name; | ||||
|     wl_output *wlOutput; | ||||
|     znet_tapesoftware_dwl_wm_monitor_v1 *dwlMonitor; | ||||
|     wl_unique_ptr<wl_output> wlOutput; | ||||
|     wl_unique_ptr<znet_tapesoftware_dwl_wm_monitor_v1> dwlMonitor; | ||||
|     std::optional<Bar> bar; | ||||
| }; | ||||
| 
 | ||||
| @ -42,8 +42,8 @@ wl_shm *shm; | ||||
| zwlr_layer_shell_v1 *wlrLayerShell; | ||||
| znet_tapesoftware_dwl_wm_v1 *dwlWm; | ||||
| std::vector<QString> tagNames; | ||||
| static bool ready; | ||||
| static std::vector<Monitor> monitors; | ||||
| static std::optional<Bar> bar; | ||||
| static std::string statusFifoName; | ||||
| static int statusFifoFd {-1}; | ||||
| static int statusFifoWriter {-1}; | ||||
| @ -57,7 +57,7 @@ static const struct xdg_wm_base_listener xdgWmBaseListener = { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct PointerState { | ||||
| struct SeatState { | ||||
|     wl_pointer *pointer; | ||||
|     wl_surface *cursorSurface; | ||||
|     wl_cursor_image *cursorImage; | ||||
| @ -65,33 +65,40 @@ struct PointerState { | ||||
|     int x, y; | ||||
|     bool leftButtonClick; | ||||
| }; | ||||
| static PointerState pointerState; | ||||
| static SeatState seatState; | ||||
| static Bar* barFromSurface(const wl_surface *surface) | ||||
| { | ||||
|     auto fbar = std::find_if(begin(monitors), end(monitors), [surface](const Monitor &mon) { | ||||
|         return mon.bar && mon.bar->surface() == surface; | ||||
|     }); | ||||
|     return fbar != end(monitors) && fbar->bar ? &*fbar->bar : nullptr; | ||||
| } | ||||
| static const struct wl_pointer_listener pointerListener = { | ||||
|     .enter = [](void*, wl_pointer *pointer, uint32_t serial, | ||||
|                 wl_surface*, wl_fixed_t x, wl_fixed_t y) | ||||
|                 wl_surface *surface, wl_fixed_t x, wl_fixed_t y) | ||||
|     { | ||||
|         pointerState.focusedBar = &bar.value(); | ||||
|         wl_pointer_set_cursor(pointer, serial, pointerState.cursorSurface, | ||||
|             pointerState.cursorImage->hotspot_x, pointerState.cursorImage->hotspot_y); | ||||
|         seatState.focusedBar = barFromSurface(surface); | ||||
|         wl_pointer_set_cursor(pointer, serial, seatState.cursorSurface, | ||||
|             seatState.cursorImage->hotspot_x, seatState.cursorImage->hotspot_y); | ||||
|     }, | ||||
|     .leave = [](void*, wl_pointer*, uint32_t serial, wl_surface*) { | ||||
|         pointerState.focusedBar = nullptr; | ||||
|         seatState.focusedBar = nullptr; | ||||
|     }, | ||||
|     .motion = [](void*, wl_pointer*, uint32_t, wl_fixed_t x, wl_fixed_t y) { | ||||
|         pointerState.x = wl_fixed_to_int(x); | ||||
|         pointerState.y = wl_fixed_to_int(y); | ||||
|         seatState.x = wl_fixed_to_int(x); | ||||
|         seatState.y = wl_fixed_to_int(y); | ||||
|     }, | ||||
|     .button = [](void*, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) { | ||||
|         if (button == BTN_LEFT) { | ||||
|             pointerState.leftButtonClick = pressed == WL_POINTER_BUTTON_STATE_PRESSED; | ||||
|             seatState.leftButtonClick = pressed == WL_POINTER_BUTTON_STATE_PRESSED; | ||||
|         } | ||||
|     }, | ||||
|     .axis = [](void*, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { }, | ||||
|     .frame = [](void*, wl_pointer*) { | ||||
|         if (!pointerState.focusedBar) return; | ||||
|         if (pointerState.leftButtonClick) { | ||||
|             pointerState.leftButtonClick = false; | ||||
|             pointerState.focusedBar->click(pointerState.x, pointerState.y); | ||||
|         if (!seatState.focusedBar) return; | ||||
|         if (seatState.leftButtonClick) { | ||||
|             seatState.leftButtonClick = false; | ||||
|             seatState.focusedBar->click(seatState.x, seatState.y); | ||||
|         } | ||||
|     }, | ||||
|     .axis_source = [](void*, wl_pointer*, uint32_t) { }, | ||||
| @ -103,16 +110,16 @@ static wl_seat *seat; | ||||
| static const struct wl_seat_listener seatListener = { | ||||
|     [](void*, wl_seat*, uint32_t cap) | ||||
|     { | ||||
|         if (!pointerState.pointer && WL_SEAT_CAPABILITY_POINTER) { | ||||
|         if (!seatState.pointer && WL_SEAT_CAPABILITY_POINTER) { | ||||
|             auto cursorTheme = wl_cursor_theme_load(NULL, 24, shm); | ||||
|             auto cursorImage = wl_cursor_theme_get_cursor(cursorTheme, "left_ptr")->images[0]; | ||||
|             pointerState.cursorImage = cursorImage; | ||||
|             pointerState.cursorSurface = wl_compositor_create_surface(compositor); | ||||
|             wl_surface_attach(pointerState.cursorSurface, | ||||
|             seatState.cursorImage = cursorImage; | ||||
|             seatState.cursorSurface = wl_compositor_create_surface(compositor); | ||||
|             wl_surface_attach(seatState.cursorSurface, | ||||
|                 wl_cursor_image_get_buffer(cursorImage), 0, 0); | ||||
|             wl_surface_commit(pointerState.cursorSurface); | ||||
|             pointerState.pointer = wl_seat_get_pointer(seat); | ||||
|             wl_pointer_add_listener(pointerState.pointer, &pointerListener, nullptr); | ||||
|             wl_surface_commit(seatState.cursorSurface); | ||||
|             seatState.pointer = wl_seat_get_pointer(seat); | ||||
|             wl_pointer_add_listener(seatState.pointer, &pointerListener, nullptr); | ||||
|         } | ||||
|     }, | ||||
|     [](void*, wl_seat*, const char *name) { } | ||||
| @ -125,21 +132,26 @@ static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = { | ||||
| }; | ||||
| 
 | ||||
| static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorListener { | ||||
|     .tag = [](void*, znet_tapesoftware_dwl_wm_monitor_v1*, int tag, int active, int numClients) { | ||||
|         printf("tag %s: active=%d, num_clients=%d\n", qPrintable(tagNames[tag]), active, numClients); | ||||
|     .tag = [](void*, znet_tapesoftware_dwl_wm_monitor_v1*, int tag, int active, int numClients, int urgent) { | ||||
|         printf("tag %s: active=%d, num_clients=%d, urgent=%d\n", qPrintable(tagNames[tag]), active, numClients, urgent); | ||||
|     }, | ||||
|     .frame = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*) { | ||||
|         auto mon = static_cast<Monitor*>(mv); | ||||
|         if (!mon->bar) { | ||||
|             mon->bar.emplace(mon->wlOutput.get()); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static void setupOutput(Monitor &monitor) { | ||||
|     monitor.dwlMonitor = znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput); | ||||
|     znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor, &dwlWmMonitorListener, &monitor); | ||||
|     monitor.bar.emplace(monitor.wlOutput); | ||||
| static void setupMonitor(Monitor &monitor) { | ||||
|     monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get())); | ||||
|     znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); | ||||
| } | ||||
| 
 | ||||
| static void onOutput(int name, wl_output *output) { | ||||
|     auto& monitor = monitors.emplace_back(name, output); | ||||
|     if (dwlWm) { | ||||
|         setupOutput(monitor); | ||||
| static void onOutput(uint32_t name, wl_output *output) { | ||||
|     auto& m = monitors.emplace_back(Monitor {name, wl_unique_ptr<wl_output> {output}}); | ||||
|     if (ready) { | ||||
|         setupMonitor(m); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -153,10 +165,9 @@ static void onReady() | ||||
|     requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1"); | ||||
|     setupStatusFifo(); | ||||
|     wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc.
 | ||||
|     ready = true; | ||||
|     for (auto& monitor : monitors) { | ||||
|         auto monitor = znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, output); | ||||
|         printf("created monitor %p for output %p\n", monitor, output); | ||||
|         bar.emplace(output); | ||||
|         setupMonitor(monitor); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -198,8 +209,10 @@ static void onStatus() | ||||
|     char buffer[512]; | ||||
|     auto n = read(statusFifoFd, buffer, sizeof(buffer)); | ||||
|     auto str = QString::fromUtf8(buffer, n); | ||||
|     if (bar) { | ||||
|         bar->setStatus(str); | ||||
|     for (auto &monitor : monitors) { | ||||
|         if (monitor.bar) { | ||||
|             monitor.bar->setStatus(str); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -230,13 +243,23 @@ static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, co | ||||
|         wl_seat_add_listener(seat, &seatListener, nullptr); | ||||
|     } | ||||
|     if (wl_output *output; reg.handle(output, wl_output_interface, 1)) { | ||||
|         outputs.push_back(output); | ||||
|         onOutput(name, output); | ||||
|     } | ||||
|     if (reg.handle(dwlWm, znet_tapesoftware_dwl_wm_v1_interface, 1)) { | ||||
|         znet_tapesoftware_dwl_wm_v1_add_listener(dwlWm, &dwlWmListener, nullptr); | ||||
|     } | ||||
| } | ||||
| static const struct wl_registry_listener registry_listener = { registryHandleGlobal, nullptr }; | ||||
| static void registryHandleRemove(void*, wl_registry *registry, uint32_t name) | ||||
| { | ||||
|     auto it = std::find_if(begin(monitors), end(monitors), [name](const Monitor &m) { return m.name == name; }); | ||||
|     if (it != end(monitors)) { | ||||
|         monitors.erase(it); | ||||
|     } | ||||
| } | ||||
| static const struct wl_registry_listener registry_listener = { | ||||
|     .global = registryHandleGlobal, | ||||
|     .global_remove = registryHandleRemove, | ||||
| }; | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| @ -273,7 +296,14 @@ int main(int argc, char **argv) | ||||
| 
 | ||||
|     QSocketNotifier displayReadNotifier(wl_display_get_fd(display), QSocketNotifier::Read); | ||||
|     displayReadNotifier.setEnabled(true); | ||||
|     QObject::connect(&displayReadNotifier, &QSocketNotifier::activated, [=]() { wl_display_dispatch(display); }); | ||||
|     QObject::connect(&displayReadNotifier, &QSocketNotifier::activated, [=]() { | ||||
|         auto res = wl_display_dispatch(display); | ||||
|         if (res < 0) { | ||||
|             perror("wl_display_dispatch"); | ||||
|             cleanup(); | ||||
|             exit(1); | ||||
|         } | ||||
|     }); | ||||
|     displayWriteNotifier = new QSocketNotifier(wl_display_get_fd(display), QSocketNotifier::Write); | ||||
|     displayWriteNotifier->setEnabled(false); | ||||
|     QObject::connect(displayWriteNotifier, &QSocketNotifier::activated, waylandWriteReady); | ||||
|  | ||||
| @ -22,20 +22,21 @@ ShmBuffer::ShmBuffer(int w, int h, wl_shm_format format) | ||||
|     close(fd); | ||||
|     for (auto i=0; i<n; i++) { | ||||
|         auto offset = oneSize*i; | ||||
|         auto buffer = wl_shm_pool_create_buffer(pool, offset, width, height, stride, format); | ||||
|         _buffers[i] = { ptr+offset, buffer }; | ||||
|         _buffers[i] = { | ||||
|             ptr+offset, | ||||
|             wl_unique_ptr<wl_buffer> { wl_shm_pool_create_buffer(pool, offset, width, height, stride, format) }, | ||||
|         }; | ||||
|     } | ||||
|     wl_shm_pool_destroy(pool); | ||||
| } | ||||
| 
 | ||||
| ShmBuffer::~ShmBuffer() | ||||
| { | ||||
|     munmap(_buffers[0].data, _totalSize); | ||||
|     for (auto i=0; i<n; i++) { | ||||
|         wl_buffer_destroy(_buffers[i].buffer); | ||||
|     if (_buffers[0].data) { | ||||
|         munmap(_buffers[0].data, _totalSize); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint8_t* ShmBuffer::data() const { return _buffers[_current].data; } | ||||
| wl_buffer* ShmBuffer::buffer() const { return _buffers[_current].buffer; } | ||||
| wl_buffer* ShmBuffer::buffer() const { return _buffers[_current].buffer.get(); } | ||||
| void ShmBuffer::flip() { _current = 1-_current; } | ||||
|  | ||||
| @ -4,22 +4,29 @@ | ||||
| #pragma once | ||||
| #include <array> | ||||
| #include <wayland-client.h> | ||||
| #include "common.hpp" | ||||
| 
 | ||||
| // double buffered shm
 | ||||
| // format is must be 32-bit
 | ||||
| class ShmBuffer { | ||||
|     struct Buf { | ||||
|         uint8_t *data {nullptr}; | ||||
|         wl_buffer *buffer {nullptr}; | ||||
|         wl_unique_ptr<wl_buffer> buffer; | ||||
|     }; | ||||
|     std::array<Buf, 2> _buffers; | ||||
|     int _current {0}; | ||||
|     size_t _totalSize {0}; | ||||
| public: | ||||
|     int width, height, stride; | ||||
| 
 | ||||
|     explicit ShmBuffer(int width, int height, wl_shm_format format); | ||||
|     ShmBuffer(const ShmBuffer&) = delete; | ||||
|     ShmBuffer(ShmBuffer&&) = default; | ||||
|     ShmBuffer& operator=(const ShmBuffer&) = delete; | ||||
|     ShmBuffer& operator=(ShmBuffer&&) = default; | ||||
|     ~ShmBuffer(); | ||||
| 
 | ||||
|     uint8_t* data() const; | ||||
|     wl_buffer* buffer() const; | ||||
|     void flip(); | ||||
|     ~ShmBuffer(); | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user