1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include "CommitTiming.hpp"
#include "core/Compositor.hpp"
#include "../managers/eventLoop/EventLoopManager.hpp"
#include "../managers/eventLoop/EventLoopTimer.hpp"
CCommitTimerResource::CCommitTimerResource(UP<CWpCommitTimerV1>&& resource_, SP<CWLSurfaceResource> surface) : m_resource(std::move(resource_)), m_surface(surface) {
if UNLIKELY (!m_resource->resource())
return;
m_resource->setData(this);
m_resource->setDestroy([this](CWpCommitTimerV1* r) { PROTO::commitTiming->destroyResource(this); });
m_resource->setOnDestroy([this](CWpCommitTimerV1* r) { PROTO::commitTiming->destroyResource(this); });
m_resource->setSetTimestamp([this](CWpCommitTimerV1* r, uint32_t tvHi, uint32_t tvLo, uint32_t tvNsec) {
if (!m_surface) {
r->error(WP_COMMIT_TIMER_V1_ERROR_SURFACE_DESTROYED, "Surface was gone");
return;
}
if (m_surface->m_pending.pendingTimeout.has_value()) {
r->error(WP_COMMIT_TIMER_V1_ERROR_TIMESTAMP_EXISTS, "Timestamp is already set");
return;
}
const auto delay = Time::till({.tv_sec = (((uint64_t)tvHi) << 32) | (uint64_t)tvLo, .tv_nsec = tvNsec});
if (delay.count() <= 0) {
m_surface->m_pending.pendingTimeout.reset();
} else
m_surface->m_pending.pendingTimeout = delay;
});
m_listeners.surfaceStateCommit = m_surface->m_events.stateCommit2.listen([this](auto state) {
if (!state || !state->pendingTimeout.has_value() || !m_surface || m_surface->isTearing())
return;
m_surface->m_stateQueue.lock(state, LOCK_REASON_TIMER);
if (!state->timer) {
state->timer = makeShared<CEventLoopTimer>(
state->pendingTimeout,
[this, state](SP<CEventLoopTimer> self, void* data) {
if (!m_surface || !state)
return;
m_surface->m_stateQueue.unlock(state, LOCK_REASON_TIMER);
},
nullptr);
g_pEventLoopManager->addTimer(state->timer);
} else
state->timer->updateTimeout(state->pendingTimeout);
state->pendingTimeout.reset();
});
}
bool CCommitTimerResource::good() {
return m_resource->resource();
}
CCommitTimingManagerResource::CCommitTimingManagerResource(UP<CWpCommitTimingManagerV1>&& resource_) : m_resource(std::move(resource_)) {
if UNLIKELY (!m_resource->resource())
return;
m_resource->setData(this);
m_resource->setDestroy([this](CWpCommitTimingManagerV1* r) { PROTO::commitTiming->destroyResource(this); });
m_resource->setOnDestroy([this](CWpCommitTimingManagerV1* r) { PROTO::commitTiming->destroyResource(this); });
m_resource->setGetTimer([](CWpCommitTimingManagerV1* r, uint32_t id, wl_resource* surfResource) {
if (!surfResource) {
r->error(-1, "No resource for commit timing");
return;
}
auto surf = CWLSurfaceResource::fromResource(surfResource);
if (!surf) {
r->error(-1, "No surface for commit timing");
return;
}
if (surf->m_commitTimer) {
r->error(WP_COMMIT_TIMING_MANAGER_V1_ERROR_COMMIT_TIMER_EXISTS, "Surface already has a commit timing");
return;
}
const auto& RESOURCE = PROTO::commitTiming->m_timers.emplace_back(makeUnique<CCommitTimerResource>(makeUnique<CWpCommitTimerV1>(r->client(), r->version(), id), surf));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::commitTiming->m_timers.pop_back();
return;
}
surf->m_commitTimer = RESOURCE;
});
}
CCommitTimingManagerResource::~CCommitTimingManagerResource() {
;
}
bool CCommitTimingManagerResource::good() {
return m_resource->resource();
}
CCommitTimingProtocol::CCommitTimingProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
void CCommitTimingProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
const auto RESOURCE = m_managers.emplace_back(makeUnique<CCommitTimingManagerResource>(makeUnique<CWpCommitTimingManagerV1>(client, ver, id))).get();
if (!RESOURCE->good()) {
wl_client_post_no_memory(client);
m_managers.pop_back();
return;
}
}
void CCommitTimingProtocol::destroyResource(CCommitTimingManagerResource* res) {
std::erase_if(m_managers, [&](const auto& other) { return other.get() == res; });
}
void CCommitTimingProtocol::destroyResource(CCommitTimerResource* res) {
std::erase_if(m_timers, [&](const auto& other) { return other.get() == res; });
}
|