Changeset View
Changeset View
Standalone View
Standalone View
backends/xrandr/xrandroutput.cpp
Show All 10 Lines | |||||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * | ||
13 | * Lesser General Public License for more details. * | 13 | * Lesser General Public License for more details. * | ||
14 | * * | 14 | * * | ||
15 | * You should have received a copy of the GNU Lesser General Public * | 15 | * You should have received a copy of the GNU Lesser General Public * | ||
16 | * License along with this library; if not, write to the Free Software * | 16 | * License along with this library; if not, write to the Free Software * | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | ||
18 | *************************************************************************************/ | 18 | *************************************************************************************/ | ||
19 | | ||||
20 | #include "xrandroutput.h" | 19 | #include "xrandroutput.h" | ||
21 | #include "xrandrmode.h" | 20 | | ||
22 | #include "xrandrconfig.h" | | |||
23 | #include "xrandr.h" | | |||
24 | #include "output.h" | | |||
25 | #include "config.h" | 21 | #include "config.h" | ||
22 | #include "xrandr.h" | ||||
23 | #include "xrandrconfig.h" | ||||
24 | #include "xrandrmode.h" | ||||
26 | #include "../utils.h" | 25 | #include "../utils.h" | ||
27 | 26 | | |||
28 | #include <QRect> | | |||
29 | | ||||
30 | Q_DECLARE_METATYPE(QList<int>) | 27 | Q_DECLARE_METATYPE(QList<int>) | ||
31 | 28 | | |||
32 | XRandROutput::XRandROutput(xcb_randr_output_t id, XRandRConfig *config) | 29 | XRandROutput::XRandROutput(xcb_randr_output_t id, XRandRConfig *config) | ||
33 | : QObject(config) | 30 | : QObject(config) | ||
34 | , m_config(config) | 31 | , m_config(config) | ||
35 | , m_id(id) | 32 | , m_id(id) | ||
36 | , m_type(KScreen::Output::Unknown) | | |||
37 | , m_primary(false) | 33 | , m_primary(false) | ||
34 | , m_type(KScreen::Output::Unknown) | ||||
38 | , m_crtc(nullptr) | 35 | , m_crtc(nullptr) | ||
39 | { | 36 | { | ||
40 | init(); | 37 | init(); | ||
41 | } | 38 | } | ||
42 | 39 | | |||
43 | XRandROutput::~XRandROutput() | 40 | XRandROutput::~XRandROutput() | ||
44 | { | 41 | { | ||
45 | } | 42 | } | ||
Show All 38 Lines | 80 | { | |||
84 | return m_crtc ? QString::number(m_crtc->mode()) : QString(); | 81 | return m_crtc ? QString::number(m_crtc->mode()) : QString(); | ||
85 | } | 82 | } | ||
86 | 83 | | |||
87 | XRandRMode* XRandROutput::currentMode() const | 84 | XRandRMode* XRandROutput::currentMode() const | ||
88 | { | 85 | { | ||
89 | if (!m_crtc) { | 86 | if (!m_crtc) { | ||
90 | return nullptr; | 87 | return nullptr; | ||
91 | } | 88 | } | ||
89 | | ||||
92 | unsigned int modeId = m_crtc->mode(); | 90 | unsigned int modeId = m_crtc->mode(); | ||
93 | if (!m_modes.contains(modeId)) { | 91 | if (!m_modes.contains(modeId)) { | ||
94 | return nullptr; | 92 | return nullptr; | ||
95 | } | 93 | } | ||
96 | 94 | | |||
97 | return m_modes[modeId]; | 95 | return m_modes[modeId]; | ||
98 | } | 96 | } | ||
99 | 97 | | |||
100 | KScreen::Output::Rotation XRandROutput::rotation() const | 98 | KScreen::Output::Rotation XRandROutput::rotation() const | ||
101 | { | 99 | { | ||
102 | return static_cast<KScreen::Output::Rotation>(m_crtc ? m_crtc->rotation() : XCB_RANDR_ROTATION_ROTATE_0); | 100 | return static_cast<KScreen::Output::Rotation>(m_crtc ? m_crtc->rotation() : | ||
101 | XCB_RANDR_ROTATION_ROTATE_0); | ||||
103 | } | 102 | } | ||
104 | 103 | | |||
105 | QByteArray XRandROutput::edid() const | 104 | QByteArray XRandROutput::edid() const | ||
106 | { | 105 | { | ||
107 | if (m_edid.isNull()) { | 106 | if (m_edid.isNull()) { | ||
108 | m_edid = XRandR::outputEdid(m_id); | 107 | m_edid = XRandR::outputEdid(m_id); | ||
109 | } | 108 | } | ||
110 | return m_edid; | 109 | return m_edid; | ||
111 | } | 110 | } | ||
112 | 111 | | |||
113 | XRandRCrtc* XRandROutput::crtc() const | 112 | XRandRCrtc* XRandROutput::crtc() const | ||
114 | { | 113 | { | ||
115 | return m_crtc; | 114 | return m_crtc; | ||
116 | } | 115 | } | ||
117 | 116 | | |||
118 | void XRandROutput::update() | 117 | void XRandROutput::update() | ||
119 | { | 118 | { | ||
120 | init(); | 119 | init(); | ||
121 | } | 120 | } | ||
122 | 121 | | |||
123 | void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, bool primary) | 122 | void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, | ||
123 | bool primary) | ||||
124 | { | 124 | { | ||
125 | qCDebug(KSCREEN_XRANDR) << "XRandROutput" << m_id << "update"; | 125 | qCDebug(KSCREEN_XRANDR) << "XRandROutput" << m_id << "update" << "\n" | ||
126 | qCDebug(KSCREEN_XRANDR) << "\tm_connected:" << m_connected; | 126 | << "\tm_connected:" << m_connected << "\n" | ||
127 | qCDebug(KSCREEN_XRANDR) << "\tm_crtc" << m_crtc; | 127 | << "\tm_crtc" << m_crtc << "\n" | ||
128 | qCDebug(KSCREEN_XRANDR) << "\tCRTC:" << crtc; | 128 | << "\tCRTC:" << crtc << "\n" | ||
129 | qCDebug(KSCREEN_XRANDR) << "\tMODE:" << mode; | 129 | << "\tMODE:" << mode << "\n" | ||
130 | qCDebug(KSCREEN_XRANDR) << "\tConnection:" << conn; | 130 | << "\tConnection:" << conn << "\n" | ||
131 | qCDebug(KSCREEN_XRANDR) << "\tPrimary:" << primary; | 131 | << "\tPrimary:" << primary; | ||
132 | 132 | | |||
133 | // Connected or disconnected | 133 | // Connected or disconnected | ||
134 | if (isConnected() != (conn == XCB_RANDR_CONNECTION_CONNECTED)) { | 134 | if (isConnected() != (conn == XCB_RANDR_CONNECTION_CONNECTED)) { | ||
135 | if (conn == XCB_RANDR_CONNECTION_CONNECTED) { | 135 | if (conn == XCB_RANDR_CONNECTION_CONNECTED) { | ||
136 | // New monitor has been connected, refresh everything | 136 | // New monitor has been connected, refresh everything | ||
137 | init(); | 137 | init(); | ||
138 | } else { | 138 | } else { | ||
139 | // Disconnected | 139 | // Disconnected | ||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Line(s) | 188 | { | |||
189 | XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME); | 189 | XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME); | ||
190 | Q_ASSERT(outputInfo); | 190 | Q_ASSERT(outputInfo); | ||
191 | if (!outputInfo) { | 191 | if (!outputInfo) { | ||
192 | return; | 192 | return; | ||
193 | } | 193 | } | ||
194 | 194 | | |||
195 | XCB::PrimaryOutput primary(XRandR::rootWindow()); | 195 | XCB::PrimaryOutput primary(XRandR::rootWindow()); | ||
196 | 196 | | |||
197 | m_name = QString::fromUtf8((const char *) xcb_randr_get_output_info_name(outputInfo.data()), outputInfo->name_len); | 197 | m_name = QString::fromUtf8((const char *) xcb_randr_get_output_info_name(outputInfo.data()), | ||
198 | outputInfo->name_len); | ||||
198 | m_type = fetchOutputType(m_id, m_name); | 199 | m_type = fetchOutputType(m_id, m_name); | ||
199 | m_icon = QString(); | 200 | m_icon = QString(); | ||
200 | m_connected = (xcb_randr_connection_t) outputInfo->connection; | 201 | m_connected = (xcb_randr_connection_t) outputInfo->connection; | ||
201 | m_primary = (primary->output == m_id); | 202 | m_primary = (primary->output == m_id); | ||
203 | | ||||
202 | xcb_randr_output_t *clones = xcb_randr_get_output_info_clones(outputInfo.data()); | 204 | xcb_randr_output_t *clones = xcb_randr_get_output_info_clones(outputInfo.data()); | ||
203 | for (int i = 0; i < outputInfo->num_clones; ++i) { | 205 | for (int i = 0; i < outputInfo->num_clones; ++i) { | ||
204 | m_clones.append(clones[i]); | 206 | m_clones.append(clones[i]); | ||
205 | } | 207 | } | ||
208 | | ||||
206 | m_widthMm = outputInfo->mm_width; | 209 | m_widthMm = outputInfo->mm_width; | ||
207 | m_heightMm = outputInfo->mm_height; | 210 | m_heightMm = outputInfo->mm_height; | ||
211 | | ||||
208 | m_crtc = m_config->crtc(outputInfo->crtc); | 212 | m_crtc = m_config->crtc(outputInfo->crtc); | ||
209 | if (m_crtc) { | 213 | if (m_crtc) { | ||
210 | m_crtc->connectOutput(m_id); | 214 | m_crtc->connectOutput(m_id); | ||
211 | } | 215 | } | ||
212 | m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); | 216 | m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); | ||
213 | 217 | | |||
214 | updateModes(outputInfo); | 218 | updateModes(outputInfo); | ||
215 | } | 219 | } | ||
216 | 220 | | |||
217 | void XRandROutput::updateModes(const XCB::OutputInfo &outputInfo) | 221 | void XRandROutput::updateModes(const XCB::OutputInfo &outputInfo) | ||
218 | { | 222 | { | ||
219 | /* Init modes */ | 223 | /* Init modes */ | ||
220 | XCB::ScopedPointer<xcb_randr_get_screen_resources_reply_t> screenResources(XRandR::screenResources()); | 224 | XCB::ScopedPointer<xcb_randr_get_screen_resources_reply_t> | ||
225 | screenResources(XRandR::screenResources()); | ||||
226 | | ||||
221 | Q_ASSERT(screenResources); | 227 | Q_ASSERT(screenResources); | ||
222 | if (!screenResources) { | 228 | if (!screenResources) { | ||
223 | return; | 229 | return; | ||
224 | } | 230 | } | ||
225 | xcb_randr_mode_info_t *modes = xcb_randr_get_screen_resources_modes(screenResources.data()); | 231 | xcb_randr_mode_info_t *modes = xcb_randr_get_screen_resources_modes(screenResources.data()); | ||
226 | xcb_randr_mode_t *outputModes = xcb_randr_get_output_info_modes(outputInfo.data()); | 232 | xcb_randr_mode_t *outputModes = xcb_randr_get_output_info_modes(outputInfo.data()); | ||
227 | 233 | | |||
228 | m_preferredModes.clear(); | 234 | m_preferredModes.clear(); | ||
Show All 13 Lines | 240 | for (int j = 0; j < screenResources->num_modes; ++j) { | |||
242 | if (i < outputInfo->num_preferred) { | 248 | if (i < outputInfo->num_preferred) { | ||
243 | m_preferredModes.append(QString::number(mode->id())); | 249 | m_preferredModes.append(QString::number(mode->id())); | ||
244 | } | 250 | } | ||
245 | break; | 251 | break; | ||
246 | } | 252 | } | ||
247 | } | 253 | } | ||
248 | } | 254 | } | ||
249 | 255 | | |||
250 | KScreen::Output::Type XRandROutput::fetchOutputType(xcb_randr_output_t outputId, const QString &name) | 256 | KScreen::Output::Type XRandROutput::fetchOutputType(xcb_randr_output_t outputId, | ||
257 | const QString &name) | ||||
251 | { | 258 | { | ||
252 | QString type = QString::fromUtf8(typeFromProperty(outputId)); | 259 | QString type = QString::fromUtf8(typeFromProperty(outputId)); | ||
253 | if (type.isEmpty()) { | 260 | if (type.isEmpty()) { | ||
254 | type = name; | 261 | type = name; | ||
255 | } | 262 | } | ||
256 | 263 | | |||
257 | return Utils::guessOutputType(type, name); | 264 | return Utils::guessOutputType(type, name); | ||
258 | } | 265 | } | ||
259 | 266 | | |||
260 | QByteArray XRandROutput::typeFromProperty(xcb_randr_output_t outputId) | 267 | QByteArray XRandROutput::typeFromProperty(xcb_randr_output_t outputId) | ||
261 | { | 268 | { | ||
262 | QByteArray type; | 269 | QByteArray type; | ||
263 | 270 | | |||
264 | XCB::InternAtom atomType(true, 13, "ConnectorType"); | 271 | XCB::InternAtom atomType(true, 13, "ConnectorType"); | ||
265 | if (!atomType) { | 272 | if (!atomType) { | ||
266 | return type; | 273 | return type; | ||
267 | } | 274 | } | ||
268 | 275 | | |||
269 | char *connectorType; | | |||
270 | | ||||
271 | auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType->atom, | 276 | auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType->atom, | ||
272 | XCB_ATOM_ANY, 0, 100, false, false); | 277 | XCB_ATOM_ANY, 0, 100, false, false); | ||
273 | XCB::ScopedPointer<xcb_randr_get_output_property_reply_t> reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, nullptr)); | 278 | XCB::ScopedPointer<xcb_randr_get_output_property_reply_t> | ||
279 | reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, nullptr)); | ||||
274 | if (!reply) { | 280 | if (!reply) { | ||
275 | return type; | 281 | return type; | ||
276 | } | 282 | } | ||
277 | 283 | | |||
278 | if (!(reply->type == XCB_ATOM_ATOM && reply->format == 32 && reply->num_items == 1)) { | 284 | if (!(reply->type == XCB_ATOM_ATOM && reply->format == 32 && reply->num_items == 1)) { | ||
279 | return type; | 285 | return type; | ||
280 | } | 286 | } | ||
281 | 287 | | |||
282 | const uint8_t *prop = xcb_randr_get_output_property_data(reply.data()); | 288 | const uint8_t *prop = xcb_randr_get_output_property_data(reply.data()); | ||
283 | XCB::AtomName atomName(*reinterpret_cast<const xcb_atom_t*>(prop)); | 289 | XCB::AtomName atomName(*reinterpret_cast<const xcb_atom_t*>(prop)); | ||
284 | if (!atomName) { | 290 | if (!atomName) { | ||
285 | return type; | 291 | return type; | ||
286 | } | 292 | } | ||
287 | 293 | | |||
288 | connectorType = xcb_get_atom_name_name(atomName); | 294 | char *connectorType = xcb_get_atom_name_name(atomName); | ||
289 | if (!connectorType) { | 295 | if (!connectorType) { | ||
290 | return type; | 296 | return type; | ||
291 | } | 297 | } | ||
292 | 298 | | |||
293 | type = connectorType; | 299 | type = connectorType; | ||
294 | return type; | 300 | return type; | ||
295 | } | 301 | } | ||
296 | 302 | | |||
▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines |