GCC Code Coverage Report


Directory: ./
File: backends/xrandr/xcbwrapper.h
Date: 2023-04-20 22:59:23
Exec Total Coverage
Lines: 0 34 0.0%
Branches: 0 10 0.0%

Line Branch Exec Source
1 /********************************************************************
2 K Win - the KDE window manager
3 This file is part of the KDE project.
4
5 Copyright (C) 2012, 2013 Martin Gräßlin <mgraesslin@kde.org>
6 Copyright (C) 2015 Daniel Vrátil <dvratil@redhat.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *********************************************************************/
21 #pragma once
22
23 #include <functional>
24 #include <type_traits>
25
26 #include <QScopedPointer>
27
28 #include <xcb/randr.h>
29 #include <xcb/xcb.h>
30
31 namespace XCB
32 {
33
34 template<typename T>
35 using ScopedPointer = QScopedPointer<T, QScopedPointerPodDeleter>;
36
37 xcb_connection_t* connection();
38 void closeConnection();
39 xcb_screen_t* screenOfDisplay(xcb_connection_t* c, int screen);
40
41 struct GrabServer {
42 GrabServer();
43 ~GrabServer();
44 };
45
46 template<typename Reply,
47 typename Cookie,
48 typename ReplyFunc,
49 ReplyFunc replyFunc,
50 typename RequestFunc,
51 RequestFunc requestFunc,
52 typename... RequestFuncArgs>
53 class Wrapper
54 {
55 public:
56 Wrapper()
57 : m_retrieved(false)
58 , m_window(XCB_WINDOW_NONE)
59 , m_reply(nullptr)
60 {
61 m_cookie.sequence = 0;
62 }
63 explicit Wrapper(const RequestFuncArgs&... args)
64 : m_retrieved(false)
65 , m_cookie(requestFunc(connection(), args...))
66 , m_window(requestWindow<RequestFuncArgs...>(args...))
67 , m_reply(nullptr)
68 {
69 }
70 explicit Wrapper(const Wrapper& other)
71 : m_retrieved(other.m_retrieved)
72 , m_cookie(other.m_cookie)
73 , m_window(other.m_window)
74 , m_reply(nullptr)
75 {
76 takeFromOther(const_cast<Wrapper&>(other));
77 }
78 virtual ~Wrapper()
79 {
80 cleanup();
81 }
82 inline Wrapper& operator=(const Wrapper& other)
83 {
84 if (this != &other) {
85 // if we had managed a reply, free it
86 cleanup();
87 // copy members
88 m_retrieved = other.m_retrieved;
89 m_cookie = other.m_cookie;
90 m_window = other.m_window;
91 m_reply = other.m_reply;
92 // take over the responsibility for the reply pointer
93 takeFromOther(const_cast<Wrapper&>(other));
94 }
95 return *this;
96 }
97
98 inline operator const Reply*() const
99 {
100 getReply();
101 return m_reply;
102 }
103 inline const Reply* operator->() const
104 {
105 getReply();
106 return m_reply;
107 }
108 inline bool isNull() const
109 {
110 getReply();
111 return m_reply == nullptr;
112 }
113 inline operator bool() const
114 {
115 return !isNull();
116 }
117 inline const Reply* data() const
118 {
119 getReply();
120 return m_reply;
121 }
122 inline xcb_window_t window() const
123 {
124 return m_window;
125 }
126 inline bool isRetrieved() const
127 {
128 return m_retrieved;
129 }
130 /**
131 * Returns the value of the reply pointer referenced by this object. The reply pointer of
132 * this object will be reset to null. Calling any method which requires the reply to be valid
133 * will crash.
134 *
135 * Callers of this function take ownership of the pointer.
136 **/
137 inline Reply* take()
138 {
139 getReply();
140 Reply* ret = m_reply;
141 m_reply = nullptr;
142 m_window = XCB_WINDOW_NONE;
143 return ret;
144 }
145
146 protected:
147 void getReply() const
148 {
149 if (m_retrieved || !m_cookie.sequence) {
150 return;
151 }
152 m_reply = replyFunc(connection(), m_cookie, nullptr);
153 m_retrieved = true;
154 }
155
156 private:
157 inline void cleanup()
158 {
159 if (!m_retrieved && m_cookie.sequence) {
160 xcb_discard_reply(connection(), m_cookie.sequence);
161 } else if (m_reply) {
162 free(m_reply);
163 }
164 }
165 inline void takeFromOther(Wrapper& other)
166 {
167 if (m_retrieved) {
168 m_reply = other.take();
169 } else {
170 // ensure that other object doesn't try to get the reply or discards it in the dtor
171 other.m_retrieved = true;
172 other.m_window = XCB_WINDOW_NONE;
173 }
174 }
175 template<typename... Args>
176 constexpr xcb_window_t requestWindow(const Args&... args) const
177 {
178 return std::is_same<typename std::tuple_element<0, std::tuple<Args...>>::type,
179 xcb_window_t>::value
180 ? std::get<0>(std::tuple<Args...>(args...))
181 : static_cast<xcb_window_t>(XCB_WINDOW_NONE);
182 }
183
184 mutable bool m_retrieved;
185 Cookie m_cookie;
186 xcb_window_t m_window;
187 mutable Reply* m_reply;
188 };
189
190 #define XCB_DECLARE_TYPE(name, xcb_request, ...) \
191 typedef Wrapper<xcb_request##_reply_t, \
192 xcb_request##_cookie_t, \
193 decltype(&xcb_request##_reply), \
194 xcb_request##_reply, \
195 decltype(&xcb_request), \
196 xcb_request, \
197 ##__VA_ARGS__> \
198 name
199
200 XCB_DECLARE_TYPE(ScreenInfo, xcb_randr_get_screen_info, xcb_window_t);
201
202 XCB_DECLARE_TYPE(ScreenSize, xcb_randr_get_screen_size_range, xcb_window_t);
203
204 XCB_DECLARE_TYPE(PrimaryOutput, xcb_randr_get_output_primary, xcb_window_t);
205
206 XCB_DECLARE_TYPE(InternAtom, xcb_intern_atom, uint8_t, uint16_t, const char*);
207
208 XCB_DECLARE_TYPE(OutputInfo, xcb_randr_get_output_info, xcb_randr_output_t, xcb_timestamp_t);
209
210 XCB_DECLARE_TYPE(CRTCInfo, xcb_randr_get_crtc_info, xcb_randr_crtc_t, xcb_timestamp_t);
211
212 XCB_DECLARE_TYPE(AtomName, xcb_get_atom_name, xcb_atom_t);
213
214 }
215