KWin
Loading...
Searching...
No Matches
xcbutils.h
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2012, 2013 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#pragma once
10
11#include "effect/globals.h"
12#include "effect/xcb.h"
13#include "main.h"
14#include "utils/c_ptr.h"
15#include "utils/version.h"
16
17#include <QList>
18#include <QRect>
19#include <QRegion>
20
21#include <xcb/composite.h>
22#include <xcb/randr.h>
23#include <xcb/xcb.h>
24
25#include <xcb/shm.h>
26
28
29namespace KWin
30{
31
32namespace Xcb
33{
34
35typedef xcb_window_t WindowId;
36
37uint32_t KWIN_EXPORT toXNative(qreal value);
38QRect KWIN_EXPORT toXNative(const QRectF &value);
39qreal KWIN_EXPORT fromXNative(int value);
40QRectF KWIN_EXPORT fromXNative(const QRect &value);
41QSizeF KWIN_EXPORT fromXNative(const QSize &value);
42
47QRectF KWIN_EXPORT nativeFloor(const QRectF &value);
48
49// forward declaration of methods
50static void defineCursor(xcb_window_t window, xcb_cursor_t cursor);
51static void setInputFocus(xcb_window_t window, uint8_t revertTo = XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time = xTime());
52static void moveWindow(xcb_window_t window, const QPoint &pos);
53static void moveWindow(xcb_window_t window, uint32_t x, uint32_t y);
54static void lowerWindow(xcb_window_t window);
55static void selectInput(xcb_window_t window, uint32_t events);
56
182template<typename Reply,
183 typename Cookie,
184 typename... Args>
186{
190 typedef Reply reply_type;
194 typedef Cookie cookie_type;
199 typedef std::tuple<Args...> argument_types;
203 typedef Cookie (*request_func)(xcb_connection_t *, Args...);
207 typedef Reply *(*reply_func)(xcb_connection_t *, Cookie, xcb_generic_error_t **);
212 static constexpr std::size_t argumentCount = sizeof...(Args);
213};
214
220template<typename Reply,
221 typename Cookie>
222struct WrapperData<Reply, Cookie>
223{
224 typedef Reply reply_type;
225 typedef Cookie cookie_type;
226 typedef std::tuple<> argument_types;
227 typedef Cookie (*request_func)(xcb_connection_t *);
228 typedef Reply *(*reply_func)(xcb_connection_t *, Cookie, xcb_generic_error_t **);
229 static constexpr std::size_t argumentCount = 0;
230};
231
238template<typename Data>
240{
241public:
242 typedef typename Data::cookie_type Cookie;
243 typedef typename Data::reply_type Reply;
245 {
246 cleanup();
247 }
249 {
250 if (this != &other) {
251 // if we had managed a reply, free it
252 cleanup();
253 // copy members
254 m_retrieved = other.m_retrieved;
255 m_cookie = other.m_cookie;
256 m_window = other.m_window;
257 m_reply = other.m_reply;
258 // take over the responsibility for the reply pointer
259 takeFromOther(const_cast<AbstractWrapper &>(other));
260 }
261 return *this;
262 }
263
264 inline const Reply *operator->()
265 {
266 getReply();
267 return m_reply;
268 }
269 inline bool isNull()
270 {
271 getReply();
272 return m_reply == nullptr;
273 }
274 inline bool isNull() const
275 {
276 const_cast<AbstractWrapper *>(this)->getReply();
277 return m_reply == NULL;
278 }
279 inline operator bool()
280 {
281 return !isNull();
282 }
283 inline operator bool() const
284 {
285 return !isNull();
286 }
287 inline const Reply *data()
288 {
289 getReply();
290 return m_reply;
291 }
292 inline const Reply *data() const
293 {
294 const_cast<AbstractWrapper *>(this)->getReply();
295 return m_reply;
296 }
297 inline WindowId window() const
298 {
299 return m_window;
300 }
301 inline bool isRetrieved() const
302 {
303 return m_retrieved;
304 }
312 inline Reply *take()
313 {
314 getReply();
315 Reply *ret = m_reply;
316 m_reply = nullptr;
317 m_window = XCB_WINDOW_NONE;
318 return ret;
319 }
320
321protected:
323 : m_retrieved(false)
324 , m_window(XCB_WINDOW_NONE)
325 , m_reply(nullptr)
326 {
327 m_cookie.sequence = 0;
328 }
330 : m_retrieved(false)
331 , m_cookie(cookie)
332 , m_window(window)
333 , m_reply(nullptr)
334 {
335 }
336 explicit AbstractWrapper(const AbstractWrapper &other)
337 : m_retrieved(other.m_retrieved)
338 , m_cookie(other.m_cookie)
339 , m_window(other.m_window)
340 , m_reply(nullptr)
341 {
342 takeFromOther(const_cast<AbstractWrapper &>(other));
343 }
344 void getReply()
345 {
346 if (m_retrieved || !m_cookie.sequence) {
347 return;
348 }
349 m_reply = Data::replyFunc(connection(), m_cookie, nullptr);
350 m_retrieved = true;
351 }
352
353private:
354 inline void cleanup()
355 {
356 if (!m_retrieved && m_cookie.sequence) {
357 xcb_discard_reply(connection(), m_cookie.sequence);
358 } else if (m_reply) {
359 free(m_reply);
360 }
361 }
362 inline void takeFromOther(AbstractWrapper &other)
363 {
364 if (m_retrieved) {
365 m_reply = other.take();
366 } else {
367 // ensure that other object doesn't try to get the reply or discards it in the dtor
368 other.m_retrieved = true;
369 other.m_window = XCB_WINDOW_NONE;
370 }
371 }
372 bool m_retrieved;
373 Cookie m_cookie;
374 WindowId m_window;
375 Reply *m_reply;
376};
377
383template<typename T1, typename T2, std::size_t I>
385{
386 typedef typename std::tuple_element<I, T1>::type tuple1Type;
387 typedef typename std::tuple_element<I, T2>::type tuple2Type;
391 static constexpr bool value = std::is_same<tuple1Type, tuple2Type>::value && tupleCompare<T1, T2, I - 1>::value;
392};
393
397template<typename T1, typename T2>
398struct tupleCompare<T1, T2, 0>
399{
400 typedef typename std::tuple_element<0, T1>::type tuple1Type;
401 typedef typename std::tuple_element<0, T2>::type tuple2Type;
402 static constexpr bool value = std::is_same<tuple1Type, tuple2Type>::value;
403};
404
408template<typename Data, typename... Args>
409class Wrapper : public AbstractWrapper<Data>
410{
411public:
412 static_assert(!std::is_same<Data, Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type, Args...>>::value,
413 "Data template argument must be derived from WrapperData");
414 static_assert(std::is_base_of<Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type, Args...>, Data>::value,
415 "Data template argument must be derived from WrapperData");
416 static_assert(sizeof...(Args) == Data::argumentCount,
417 "Wrapper and WrapperData need to have same template argument count");
418 static_assert(tupleCompare<std::tuple<Args...>, typename Data::argument_types, sizeof...(Args) - 1>::value,
419 "Argument miss-match between Wrapper and WrapperData");
420 Wrapper() = default;
421 explicit Wrapper(Args... args)
422 : AbstractWrapper<Data>(XCB_WINDOW_NONE, Data::requestFunc(connection(), args...))
423 {
424 }
425 explicit Wrapper(xcb_window_t w, Args... args)
426 : AbstractWrapper<Data>(w, Data::requestFunc(connection(), args...))
427 {
428 }
429};
430
434template<typename Data, typename... Args>
435class Wrapper<Data, xcb_window_t, Args...> : public AbstractWrapper<Data>
436{
437public:
438 static_assert(!std::is_same<Data, Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type, xcb_window_t, Args...>>::value,
439 "Data template argument must be derived from WrapperData");
440 static_assert(std::is_base_of<Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type, xcb_window_t, Args...>, Data>::value,
441 "Data template argument must be derived from WrapperData");
442 static_assert(sizeof...(Args) + 1 == Data::argumentCount,
443 "Wrapper and WrapperData need to have same template argument count");
444 static_assert(tupleCompare<std::tuple<xcb_window_t, Args...>, typename Data::argument_types, sizeof...(Args)>::value,
445 "Argument miss-match between Wrapper and WrapperData");
446 Wrapper() = default;
447 explicit Wrapper(xcb_window_t w, Args... args)
448 : AbstractWrapper<Data>(w, Data::requestFunc(connection(), w, args...))
449 {
450 }
451};
452
458template<typename Data>
459class Wrapper<Data> : public AbstractWrapper<Data>
460{
461public:
462 static_assert(!std::is_same<Data, Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type>>::value,
463 "Data template argument must be derived from WrapperData");
464 static_assert(std::is_base_of<Xcb::WrapperData<typename Data::reply_type, typename Data::cookie_type>, Data>::value,
465 "Data template argument must be derived from WrapperData");
466 static_assert(Data::argumentCount == 0, "Wrapper for no arguments constructed with WrapperData with arguments");
467 explicit Wrapper()
468 : AbstractWrapper<Data>(XCB_WINDOW_NONE, Data::requestFunc(connection()))
469 {
470 }
471};
472
473class Atom
474{
475public:
476 explicit Atom(const QByteArray &name, bool onlyIfExists = false, xcb_connection_t *c = connection())
477 : m_connection(c)
478 , m_retrieved(false)
479 , m_cookie(xcb_intern_atom_unchecked(m_connection, onlyIfExists, name.length(), name.constData()))
480 , m_atom(XCB_ATOM_NONE)
481 , m_name(name)
482 {
483 }
484 Atom() = delete;
485 Atom(const Atom &) = delete;
486
488 {
489 if (!m_retrieved && m_cookie.sequence) {
490 xcb_discard_reply(m_connection, m_cookie.sequence);
491 }
492 }
493
494 operator xcb_atom_t() const
495 {
496 (const_cast<Atom *>(this))->getReply();
497 return m_atom;
498 }
499 bool isValid()
500 {
501 getReply();
502 return m_atom != XCB_ATOM_NONE;
503 }
504 bool isValid() const
505 {
506 (const_cast<Atom *>(this))->getReply();
507 return m_atom != XCB_ATOM_NONE;
508 }
509
510 inline const QByteArray &name() const
511 {
512 return m_name;
513 }
514
515 void getReply()
516 {
517 if (m_retrieved || !m_cookie.sequence) {
518 return;
519 }
520 UniqueCPtr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(m_connection, m_cookie, nullptr));
521 if (reply) {
522 m_atom = reply->atom;
523 }
524 m_retrieved = true;
525 }
526
527private:
528 xcb_connection_t *m_connection;
529 bool m_retrieved;
530 xcb_intern_atom_cookie_t m_cookie;
531 xcb_atom_t m_atom;
532 QByteArray m_name;
533};
534
553#define XCB_WRAPPER_DATA(__NAME__, __REQUEST__, ...) \
554 struct __NAME__ : public WrapperData<__REQUEST__##_reply_t, __REQUEST__##_cookie_t, __VA_ARGS__> \
555 { \
556 static constexpr request_func requestFunc = &__REQUEST__##_unchecked; \
557 static constexpr reply_func replyFunc = &__REQUEST__##_reply; \
558 };
559
572#define XCB_WRAPPER(__NAME__, __REQUEST__, ...) \
573 XCB_WRAPPER_DATA(__NAME__##Data, __REQUEST__, __VA_ARGS__) \
574 typedef Wrapper<__NAME__##Data, __VA_ARGS__> __NAME__;
575
576XCB_WRAPPER(WindowAttributes, xcb_get_window_attributes, xcb_window_t)
577XCB_WRAPPER(OverlayWindow, xcb_composite_get_overlay_window, xcb_window_t)
578
579XCB_WRAPPER_DATA(GeometryData, xcb_get_geometry, xcb_drawable_t)
580class WindowGeometry : public Wrapper<GeometryData, xcb_window_t>
581{
582public:
584 : Wrapper<GeometryData, xcb_window_t>()
585 {
586 }
587 explicit WindowGeometry(xcb_window_t window)
588 : Wrapper<GeometryData, xcb_window_t>(window)
589 {
590 }
591
592 inline QRectF rect()
593 {
594 const xcb_get_geometry_reply_t *geometry = data();
595 if (!geometry) {
596 return QRect();
597 }
598 return QRectF(Xcb::fromXNative(geometry->x), Xcb::fromXNative(geometry->y), Xcb::fromXNative(geometry->width), Xcb::fromXNative(geometry->height));
599 }
600
601 inline QSizeF size()
602 {
603 const xcb_get_geometry_reply_t *geometry = data();
604 if (!geometry) {
605 return QSize();
606 }
607 return QSizeF(Xcb::fromXNative(geometry->width), Xcb::fromXNative(geometry->height));
608 }
609};
610
611XCB_WRAPPER_DATA(TreeData, xcb_query_tree, xcb_window_t)
612class Tree : public Wrapper<TreeData, xcb_window_t>
613{
614public:
615 explicit Tree(WindowId window)
616 : Wrapper<TreeData, xcb_window_t>(window)
617 {
618 }
619
621 {
622 if (isNull() || data()->children_len == 0) {
623 return nullptr;
624 }
625 return xcb_query_tree_children(data());
626 }
627 inline xcb_window_t parent()
628 {
629 if (isNull()) {
630 return XCB_WINDOW_NONE;
631 }
632 return (*this)->parent;
633 }
634};
635
636XCB_WRAPPER(Pointer, xcb_query_pointer, xcb_window_t)
637
638struct CurrentInputData : public WrapperData<xcb_get_input_focus_reply_t, xcb_get_input_focus_cookie_t>
639{
640 static constexpr request_func requestFunc = &xcb_get_input_focus_unchecked;
641 static constexpr reply_func replyFunc = &xcb_get_input_focus_reply;
642};
643
644class CurrentInput : public Wrapper<CurrentInputData>
645{
646public:
649 {
650 }
651
652 inline xcb_window_t window()
653 {
654 if (isNull()) {
655 return XCB_WINDOW_NONE;
656 }
657 return (*this)->focus;
658 }
659};
660
661struct QueryKeymapData : public WrapperData<xcb_query_keymap_reply_t, xcb_query_keymap_cookie_t>
662{
663 static constexpr request_func requestFunc = &xcb_query_keymap_unchecked;
664 static constexpr reply_func replyFunc = &xcb_query_keymap_reply;
665};
666
667class QueryKeymap : public Wrapper<QueryKeymapData>
668{
669public:
672 {
673 }
674};
675
676struct ModifierMappingData : public WrapperData<xcb_get_modifier_mapping_reply_t, xcb_get_modifier_mapping_cookie_t>
677{
678 static constexpr request_func requestFunc = &xcb_get_modifier_mapping_unchecked;
679 static constexpr reply_func replyFunc = &xcb_get_modifier_mapping_reply;
680};
681
682class ModifierMapping : public Wrapper<ModifierMappingData>
683{
684public:
689
690 inline xcb_keycode_t *keycodes()
691 {
692 if (isNull()) {
693 return nullptr;
694 }
695 return xcb_get_modifier_mapping_keycodes(data());
696 }
697 inline int size()
698 {
699 if (isNull()) {
700 return 0;
701 }
702 return xcb_get_modifier_mapping_keycodes_length(data());
703 }
704};
705
706XCB_WRAPPER_DATA(PropertyData, xcb_get_property, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t)
707class Property : public Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t>
708{
709public:
711 : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t>()
712 , m_type(XCB_ATOM_NONE)
713 {
714 }
715 Property(const Property &other)
716 : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t>(other)
717 , m_type(other.m_type)
718 {
719 }
720 explicit Property(uint8_t _delete, xcb_window_t window, xcb_atom_t property, xcb_atom_t type, uint32_t long_offset, uint32_t long_length)
721 : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t>(window, _delete, window, property, type, long_offset, long_length)
722 , m_type(type)
723 {
724 }
726 {
728 m_type = other.m_type;
729 return *this;
730 }
731
744 template<typename T>
745 inline typename std::enable_if<!std::is_pointer<T>::value, T>::type value(T defaultValue = T(), bool *ok = nullptr)
746 {
747 return value<T>(sizeof(T) * 8, m_type, defaultValue, ok);
748 }
763 template<typename T>
764 inline typename std::enable_if<!std::is_pointer<T>::value, T>::type value(uint8_t format, xcb_atom_t type, T defaultValue = T(), bool *ok = nullptr)
765 {
766 T *reply = value<T *>(format, type, nullptr, ok);
767 if (!reply) {
768 return defaultValue;
769 }
770 return reply[0];
771 }
784 template<typename T>
785 inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(T defaultValue = nullptr, bool *ok = nullptr)
786 {
787 return value<T>(sizeof(typename std::remove_pointer<T>::type) * 8, m_type, defaultValue, ok);
788 }
807 template<typename T>
808 inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(uint8_t format, xcb_atom_t type, T defaultValue = nullptr, bool *ok = nullptr)
809 {
810 if (ok) {
811 *ok = false;
812 }
813 const PropertyData::reply_type *reply = data();
814 if (!reply) {
815 return defaultValue;
816 }
817 if (reply->type != type) {
818 return defaultValue;
819 }
820 if (reply->format != format) {
821 return defaultValue;
822 }
823
824 if (ok) {
825 *ok = true;
826 }
827 if (xcb_get_property_value_length(reply) == 0) {
828 return defaultValue;
829 }
830
831 return reinterpret_cast<T>(xcb_get_property_value(reply));
832 }
838 inline QByteArray toByteArray(uint8_t format = 8, xcb_atom_t type = XCB_ATOM_STRING, bool *ok = nullptr)
839 {
840 bool valueOk = false;
841 const char *reply = value<const char *>(format, type, nullptr, &valueOk);
842 if (ok) {
843 *ok = valueOk;
844 }
845
846 if (valueOk && !reply) {
847 return QByteArray("", 0); // valid, not null, but empty data
848 } else if (!valueOk) {
849 return QByteArray(); // Property not found, data empty and null
850 }
851 return QByteArray(reply, xcb_get_property_value_length(data()));
852 }
856 inline QByteArray toByteArray(bool *ok)
857 {
858 return toByteArray(8, m_type, ok);
859 }
876 inline bool toBool(uint8_t format = 32, xcb_atom_t type = XCB_ATOM_CARDINAL, bool *ok = nullptr)
877 {
878 bool *reply = value<bool *>(format, type, nullptr, ok);
879 if (!reply) {
880 return false;
881 }
882 if (data()->value_len != 1) {
883 if (ok) {
884 *ok = false;
885 }
886 return false;
887 }
888 return reply[0] != 0;
889 }
893 inline bool toBool(bool *ok)
894 {
895 return toBool(32, m_type, ok);
896 }
897
898private:
899 xcb_atom_t m_type;
900};
901
903{
904public:
905 StringProperty() = default;
906 explicit StringProperty(xcb_window_t w, xcb_atom_t p)
907 : Property(false, w, p, XCB_ATOM_STRING, 0, 10000)
908 {
909 }
910 operator QByteArray()
911 {
912 return toByteArray();
913 }
914};
915
916class TransientFor : public Property
917{
918public:
920 : Property(0, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 1)
921 {
922 }
923
929 inline bool getTransientFor(WindowId *prop)
930 {
931 WindowId *windows = value<WindowId *>();
932 if (!windows) {
933 return false;
934 }
935
936 *prop = *windows;
937 return true;
938 }
939};
940
942{
943public:
944 GeometryHints() = default;
945 void init(xcb_window_t window)
946 {
947 Q_ASSERT(window);
948 if (m_window) {
949 // already initialized
950 return;
951 }
952 m_window = window;
953 fetch();
954 }
955 void fetch()
956 {
957 if (!m_window) {
958 return;
959 }
960 m_sizeHints = nullptr;
961 m_hints = NormalHints(m_window);
962 }
963 void read()
964 {
965 m_sizeHints = m_hints.sizeHints();
966 }
967
968 bool hasPosition() const
969 {
971 }
972 bool hasSize() const
973 {
975 }
976 bool hasMinSize() const
977 {
978 return testFlag(NormalHints::SizeHints::MinSize);
979 }
980 bool hasMaxSize() const
981 {
982 return testFlag(NormalHints::SizeHints::MaxSize);
983 }
985 {
987 }
988 bool hasAspect() const
989 {
990 return testFlag(NormalHints::SizeHints::Aspect);
991 }
992 bool hasBaseSize() const
993 {
994 return testFlag(NormalHints::SizeHints::BaseSize);
995 }
996 bool hasWindowGravity() const
997 {
999 }
1000 QSizeF maxSize() const
1001 {
1002 if (!hasMaxSize()) {
1003 return QSize(INT_MAX, INT_MAX);
1004 }
1005 const QSize size(std::max(m_sizeHints->maxWidth, 1), std::max(m_sizeHints->maxHeight, 1));
1006 return fromXNative(size);
1007 }
1008 QSizeF minSize() const
1009 {
1010 if (!hasMinSize()) {
1011 // according to ICCCM 4.1.23 base size should be used as a fallback
1012 return baseSize();
1013 }
1014 const QSize size(m_sizeHints->minWidth, m_sizeHints->minHeight);
1015 return fromXNative(size);
1016 }
1017 QSizeF baseSize() const
1018 {
1019 // Note: not using minSize as fallback
1020 if (!hasBaseSize()) {
1021 return QSize(0, 0);
1022 }
1023 const QSize size(m_sizeHints->baseWidth, m_sizeHints->baseHeight);
1024 return fromXNative(size);
1025 }
1026 QSizeF resizeIncrements() const
1027 {
1028 if (!hasResizeIncrements()) {
1029 return fromXNative(QSize(1, 1));
1030 }
1031 return Xcb::fromXNative(QSize(std::max(m_sizeHints->widthInc, 1), std::max(m_sizeHints->heightInc, 1)));
1032 }
1033 xcb_gravity_t windowGravity() const
1034 {
1035 if (!hasWindowGravity()) {
1036 return XCB_GRAVITY_NORTH_WEST;
1037 }
1038 return xcb_gravity_t(m_sizeHints->winGravity);
1039 }
1040 QSize minAspect() const
1041 {
1042 if (!hasAspect()) {
1043 return QSize(1, INT_MAX);
1044 }
1045 // prevent division by zero
1046 return QSize(m_sizeHints->minAspect[0], std::max(m_sizeHints->minAspect[1], 1));
1047 }
1048 QSize maxAspect() const
1049 {
1050 if (!hasAspect()) {
1051 return QSize(INT_MAX, 1);
1052 }
1053 // prevent division by zero
1054 return QSize(m_sizeHints->maxAspect[0], std::max(m_sizeHints->maxAspect[1], 1));
1055 }
1056
1057private:
1061 class NormalHints : public Property
1062 {
1063 public:
1065 {
1078 qint32 flags = 0;
1079 qint32 pad[4] = {0, 0, 0, 0};
1080 qint32 minWidth = 0;
1081 qint32 minHeight = 0;
1082 qint32 maxWidth = 0;
1083 qint32 maxHeight = 0;
1084 qint32 widthInc = 0;
1085 qint32 heightInc = 0;
1086 qint32 minAspect[2] = {0, 0};
1087 qint32 maxAspect[2] = {0, 0};
1088 qint32 baseWidth = 0;
1089 qint32 baseHeight = 0;
1090 qint32 winGravity = 0;
1091 };
1092 explicit NormalHints()
1093 : Property(){};
1094 explicit NormalHints(WindowId window)
1095 : Property(0, window, XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS, 0, 18)
1096 {
1097 }
1098 inline SizeHints *sizeHints()
1099 {
1100 return value<SizeHints *>(32, XCB_ATOM_WM_SIZE_HINTS, nullptr);
1101 }
1102 };
1103 friend TestXcbSizeHints;
1104 bool testFlag(NormalHints::SizeHints::Flags flag) const
1105 {
1106 if (!m_window || !m_sizeHints) {
1107 return false;
1108 }
1109 return m_sizeHints->flags & flag;
1110 }
1111 xcb_window_t m_window = XCB_WINDOW_NONE;
1112 NormalHints m_hints;
1113 NormalHints::SizeHints *m_sizeHints = nullptr;
1114};
1115
1117{
1118public:
1119 MotifHints(xcb_atom_t atom)
1120 : m_atom(atom)
1121 {
1122 }
1123 void init(xcb_window_t window)
1124 {
1125 Q_ASSERT(window);
1126 if (m_window) {
1127 // already initialized
1128 return;
1129 }
1130 m_window = window;
1131 fetch();
1132 }
1133 void fetch()
1134 {
1135 if (!m_window) {
1136 return;
1137 }
1138 m_hints = nullptr;
1139 m_prop = Property(0, m_window, m_atom, m_atom, 0, 5);
1140 }
1141 void read()
1142 {
1143 m_hints = m_prop.value<MwmHints *>(32, m_atom, nullptr);
1144 }
1145 bool hasDecoration() const
1146 {
1147 if (!m_window || !m_hints) {
1148 return false;
1149 }
1150 return m_hints->flags & uint32_t(Hints::Decorations);
1151 }
1152 bool noBorder() const
1153 {
1154 if (!hasDecoration()) {
1155 return false;
1156 }
1157 return !m_hints->decorations;
1158 }
1159 bool resize() const
1160 {
1161 return testFunction(Functions::Resize);
1162 }
1163 bool move() const
1164 {
1165 return testFunction(Functions::Move);
1166 }
1167 bool minimize() const
1168 {
1169 return testFunction(Functions::Minimize);
1170 }
1171 bool maximize() const
1172 {
1173 return testFunction(Functions::Maximize);
1174 }
1175 bool close() const
1176 {
1177 return testFunction(Functions::Close);
1178 }
1179
1180private:
1181 struct MwmHints
1182 {
1183 uint32_t flags;
1184 uint32_t functions;
1185 uint32_t decorations;
1186 int32_t input_mode;
1187 uint32_t status;
1188 };
1189 enum class Hints {
1190 Functions = (1L << 0),
1191 Decorations = (1L << 1)
1192 };
1193 enum class Functions {
1194 All = (1L << 0),
1195 Resize = (1L << 1),
1196 Move = (1L << 2),
1197 Minimize = (1L << 3),
1198 Maximize = (1L << 4),
1199 Close = (1L << 5)
1200 };
1201 bool testFunction(Functions flag) const
1202 {
1203 if (!m_window || !m_hints) {
1204 return true;
1205 }
1206 if (!(m_hints->flags & uint32_t(Hints::Functions))) {
1207 return true;
1208 }
1209 // if MWM_FUNC_ALL is set, other flags say what to turn _off_
1210 const bool set_value = ((m_hints->functions & uint32_t(Functions::All)) == 0);
1211 if (m_hints->functions & uint32_t(flag)) {
1212 return set_value;
1213 }
1214 return !set_value;
1215 }
1216 xcb_window_t m_window = XCB_WINDOW_NONE;
1217 Property m_prop;
1218 xcb_atom_t m_atom;
1219 MwmHints *m_hints = nullptr;
1220};
1221
1222namespace RandR
1223{
1224XCB_WRAPPER(ScreenInfo, xcb_randr_get_screen_info, xcb_window_t)
1225
1226XCB_WRAPPER_DATA(ScreenResourcesData, xcb_randr_get_screen_resources, xcb_window_t)
1227class ScreenResources : public Wrapper<ScreenResourcesData, xcb_window_t>
1228{
1229public:
1230 explicit ScreenResources(WindowId window)
1231 : Wrapper<ScreenResourcesData, xcb_window_t>(window)
1232 {
1233 }
1234
1235 inline xcb_randr_crtc_t *crtcs()
1236 {
1237 if (isNull()) {
1238 return nullptr;
1239 }
1240 return xcb_randr_get_screen_resources_crtcs(data());
1241 }
1242 inline xcb_randr_mode_info_t *modes()
1243 {
1244 if (isNull()) {
1245 return nullptr;
1246 }
1247 return xcb_randr_get_screen_resources_modes(data());
1248 }
1249 inline uint8_t *names()
1250 {
1251 if (isNull()) {
1252 return nullptr;
1253 }
1254 return xcb_randr_get_screen_resources_names(data());
1255 }
1256};
1257
1258XCB_WRAPPER_DATA(CrtcGammaData, xcb_randr_get_crtc_gamma, xcb_randr_crtc_t)
1259class CrtcGamma : public Wrapper<CrtcGammaData, xcb_randr_crtc_t>
1260{
1261public:
1262 explicit CrtcGamma(xcb_randr_crtc_t c)
1263 : Wrapper<CrtcGammaData, xcb_randr_crtc_t>(c)
1264 {
1265 }
1266
1267 inline uint16_t *red()
1268 {
1269 return xcb_randr_get_crtc_gamma_red(data());
1270 }
1271 inline uint16_t *green()
1272 {
1273 return xcb_randr_get_crtc_gamma_green(data());
1274 }
1275 inline uint16_t *blue()
1276 {
1277 return xcb_randr_get_crtc_gamma_blue(data());
1278 }
1279};
1280
1281XCB_WRAPPER_DATA(CrtcInfoData, xcb_randr_get_crtc_info, xcb_randr_crtc_t, xcb_timestamp_t)
1282class CrtcInfo : public Wrapper<CrtcInfoData, xcb_randr_crtc_t, xcb_timestamp_t>
1283{
1284public:
1285 CrtcInfo() = default;
1286 CrtcInfo(const CrtcInfo &) = default;
1287 explicit CrtcInfo(xcb_randr_crtc_t c, xcb_timestamp_t t)
1288 : Wrapper<CrtcInfoData, xcb_randr_crtc_t, xcb_timestamp_t>(c, t)
1289 {
1290 }
1291
1292 inline QRect rect()
1293 {
1294 const CrtcInfoData::reply_type *info = data();
1295 if (!info || info->num_outputs == 0 || info->mode == XCB_NONE || info->status != XCB_RANDR_SET_CONFIG_SUCCESS) {
1296 return QRect();
1297 }
1298 return QRect(info->x, info->y, info->width, info->height);
1299 }
1300 inline xcb_randr_output_t *outputs()
1301 {
1302 const CrtcInfoData::reply_type *info = data();
1303 if (!info || info->num_outputs == 0 || info->mode == XCB_NONE || info->status != XCB_RANDR_SET_CONFIG_SUCCESS) {
1304 return nullptr;
1305 }
1306 return xcb_randr_get_crtc_info_outputs(info);
1307 }
1308};
1309
1310XCB_WRAPPER_DATA(OutputInfoData, xcb_randr_get_output_info, xcb_randr_output_t, xcb_timestamp_t)
1311class OutputInfo : public Wrapper<OutputInfoData, xcb_randr_output_t, xcb_timestamp_t>
1312{
1313public:
1314 OutputInfo() = default;
1315 OutputInfo(const OutputInfo &) = default;
1316 explicit OutputInfo(xcb_randr_output_t c, xcb_timestamp_t t)
1317 : Wrapper<OutputInfoData, xcb_randr_output_t, xcb_timestamp_t>(c, t)
1318 {
1319 }
1320
1321 inline QString name()
1322 {
1323 const OutputInfoData::reply_type *info = data();
1324 if (!info || info->num_crtcs == 0 || info->num_modes == 0 || info->status != XCB_RANDR_SET_CONFIG_SUCCESS) {
1325 return QString();
1326 }
1327 return QString::fromUtf8(reinterpret_cast<char *>(xcb_randr_get_output_info_name(info)), info->name_len);
1328 }
1329};
1330
1331XCB_WRAPPER_DATA(CurrentResourcesData, xcb_randr_get_screen_resources_current, xcb_window_t)
1332class CurrentResources : public Wrapper<CurrentResourcesData, xcb_window_t>
1333{
1334public:
1336 : Wrapper<CurrentResourcesData, xcb_window_t>(window)
1337 {
1338 }
1339
1340 inline xcb_randr_crtc_t *crtcs()
1341 {
1342 if (isNull()) {
1343 return nullptr;
1344 }
1345 return xcb_randr_get_screen_resources_current_crtcs(data());
1346 }
1347 inline xcb_randr_mode_info_t *modes()
1348 {
1349 if (isNull()) {
1350 return nullptr;
1351 }
1352 return xcb_randr_get_screen_resources_current_modes(data());
1353 }
1354};
1355
1356XCB_WRAPPER(SetCrtcConfig, xcb_randr_set_crtc_config, xcb_randr_crtc_t, xcb_timestamp_t, xcb_timestamp_t, int16_t, int16_t, xcb_randr_mode_t, uint16_t, uint32_t, const xcb_randr_output_t *)
1357
1358XCB_WRAPPER_DATA(OutputPropertyData, xcb_randr_get_output_property, xcb_randr_output_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t, uint8_t, uint8_t)
1363class OutputProperty : public Wrapper<OutputPropertyData, xcb_randr_output_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t, uint8_t, uint8_t>
1364{
1365public:
1366 OutputProperty() = default;
1367 explicit OutputProperty(xcb_randr_output_t output, xcb_atom_t property, xcb_atom_t type, uint32_t offset, uint32_t length, uint8_t _delete, uint8_t pending)
1368 : Wrapper(output, property, type, offset, length, _delete, pending)
1369 , m_type(type)
1370 {
1371 }
1372 template<typename T>
1373 inline typename std::enable_if<!std::is_pointer<T>::value, T>::type value(T defaultValue = T(), bool *ok = nullptr)
1374 {
1375 T *reply = value<T *>(sizeof(T) * 8, m_type, nullptr, ok);
1376 if (!reply) {
1377 return defaultValue;
1378 }
1379 return reply[0];
1380 }
1381 template<typename T>
1382 inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(T defaultValue = nullptr, bool *ok = nullptr)
1383 {
1384 return value<T>(sizeof(typename std::remove_pointer<T>::type) * 8, m_type, defaultValue, ok);
1385 }
1386 template<typename T>
1387 inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(uint8_t format, xcb_atom_t type, T defaultValue = nullptr, bool *ok = nullptr)
1388 {
1389 if (ok) {
1390 *ok = false;
1391 }
1392 const OutputPropertyData::reply_type *reply = data();
1393 if (!reply) {
1394 return defaultValue;
1395 }
1396 if (reply->type != type) {
1397 return defaultValue;
1398 }
1399 if (reply->format != format) {
1400 return defaultValue;
1401 }
1402
1403 if (ok) {
1404 *ok = true;
1405 }
1406 if (xcb_randr_get_output_property_data_length(reply) == 0) {
1407 return defaultValue;
1408 }
1409
1410 return reinterpret_cast<T>(xcb_randr_get_output_property_data(reply));
1411 }
1412 inline QByteArray toByteArray(uint8_t format = 8, xcb_atom_t type = XCB_ATOM_STRING, bool *ok = nullptr)
1413 {
1414 bool valueOk = false;
1415 const char *reply = value<const char *>(format, type, nullptr, &valueOk);
1416 if (ok) {
1417 *ok = valueOk;
1418 }
1419
1420 if (valueOk && !reply) {
1421 return QByteArray("", 0); // valid, not null, but empty data
1422 } else if (!valueOk) {
1423 return QByteArray(); // Property not found, data empty and null
1424 }
1425 return QByteArray(reply, xcb_randr_get_output_property_data_length(data()));
1426 }
1427 inline QByteArray toByteArray(bool *ok)
1428 {
1429 return toByteArray(8, m_type, ok);
1430 }
1431 inline bool toBool(uint8_t format = 32, xcb_atom_t type = XCB_ATOM_CARDINAL, bool *ok = nullptr)
1432 {
1433 bool *reply = value<bool *>(format, type, nullptr, ok);
1434 if (!reply) {
1435 return false;
1436 }
1437 if (data()->length != 1) {
1438 if (ok) {
1439 *ok = false;
1440 }
1441 return false;
1442 }
1443 return reply[0] != 0;
1444 }
1445 inline bool toBool(bool *ok)
1446 {
1447 return toBool(32, m_type, ok);
1448 }
1449
1450private:
1451 xcb_atom_t m_type;
1452};
1453}
1454
1456{
1457public:
1458 ExtensionData();
1464 QByteArray name;
1465 QList<QByteArray> opCodes;
1466 QList<QByteArray> errorCodes;
1467};
1468
1469class KWIN_EXPORT Extensions
1470{
1471public:
1472 bool isShapeAvailable() const
1473 {
1474 return m_shape.version > 0;
1475 }
1476 bool isShapeInputAvailable() const;
1477 int shapeNotifyEvent() const;
1478 bool hasShape(xcb_window_t w) const;
1479 bool isRandrAvailable() const
1480 {
1481 return m_randr.present;
1482 }
1483 int randrNotifyEvent() const;
1485 {
1486 return m_damage.present;
1487 }
1488 int damageNotifyEvent() const;
1490 {
1491 return m_composite.version > 0;
1492 }
1493 bool isCompositeOverlayAvailable() const;
1495 {
1496 return m_render.version > 0;
1497 }
1498 bool isFixesAvailable() const
1499 {
1500 return m_fixes.version > 0;
1501 }
1502 int fixesCursorNotifyEvent() const;
1503 int fixesSelectionNotifyEvent() const;
1504 bool isFixesRegionAvailable() const;
1505 bool isSyncAvailable() const
1506 {
1507 return m_sync.present;
1508 }
1509 int syncAlarmNotifyEvent() const;
1510 QList<ExtensionData> extensions() const;
1511 bool hasGlx() const
1512 {
1513 return m_glx.present;
1514 }
1515 int glxEventBase() const
1516 {
1517 return m_glx.eventBase;
1518 }
1519 int glxMajorOpcode() const
1520 {
1521 return m_glx.majorOpcode;
1522 }
1523
1524 static Extensions *self();
1525 static void destroy();
1526
1527private:
1528 Extensions();
1529 ~Extensions();
1530 void init();
1531 template<typename reply, typename T, typename F>
1532 void initVersion(T cookie, F f, ExtensionData *dataToFill);
1533 void extensionQueryReply(const xcb_query_extension_reply_t *extension, ExtensionData *dataToFill);
1534
1535 ExtensionData m_shape;
1536 ExtensionData m_randr;
1537 ExtensionData m_damage;
1538 ExtensionData m_composite;
1539 ExtensionData m_render;
1540 ExtensionData m_fixes;
1541 ExtensionData m_sync;
1542 ExtensionData m_glx;
1543
1544 static Extensions *s_self;
1545};
1546
1557{
1558public:
1571 Window(xcb_window_t window = XCB_WINDOW_NONE, bool destroy = true);
1580 Window(const QRectF &geometry, uint32_t mask = 0, const uint32_t *values = nullptr, xcb_window_t parent = rootWindow());
1590 Window(const QRectF &geometry, uint16_t windowClass, uint32_t mask = 0, const uint32_t *values = nullptr, xcb_window_t parent = rootWindow());
1591 Window(const Window &other) = delete;
1592 ~Window();
1593
1604 void create(const QRectF &geometry, uint32_t mask = 0, const uint32_t *values = nullptr, xcb_window_t parent = rootWindow());
1616 void create(const QRectF &geometry, uint16_t windowClass, uint32_t mask = 0, const uint32_t *values = nullptr, xcb_window_t parent = rootWindow());
1623 void reset(xcb_window_t window = XCB_WINDOW_NONE, bool destroy = true);
1627 bool isValid() const;
1628 inline const QRectF &geometry() const
1629 {
1630 return m_logicGeometry;
1631 }
1636 void setGeometry(const QRectF &geometry);
1637 void setGeometry(qreal x, qreal y, qreal width, qreal height);
1638 void move(const QPointF &pos);
1639 void move(qreal x, qreal y);
1640 void resize(const QSizeF &size);
1641 void resize(qreal width, qreal height);
1642 void raise();
1643 void lower();
1644 void map();
1645 void unmap();
1646 void reparent(xcb_window_t parent, qreal x = 0, qreal y = 0);
1647 void changeProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length,
1648 const void *data, uint8_t mode = XCB_PROP_MODE_REPLACE);
1649 void deleteProperty(xcb_atom_t property);
1650 void setBorderWidth(uint32_t width);
1651 void grabButton(uint8_t pointerMode, uint8_t keyboardmode,
1652 uint16_t modifiers = XCB_MOD_MASK_ANY,
1653 uint8_t button = XCB_BUTTON_INDEX_ANY,
1654 uint16_t eventMask = XCB_EVENT_MASK_BUTTON_PRESS,
1655 xcb_window_t confineTo = XCB_WINDOW_NONE,
1656 xcb_cursor_t cursor = XCB_CURSOR_NONE,
1657 bool ownerEvents = false);
1658 void ungrabButton(uint16_t modifiers = XCB_MOD_MASK_ANY, uint8_t button = XCB_BUTTON_INDEX_ANY);
1662 void clear();
1663 void setBackgroundPixmap(xcb_pixmap_t pixmap);
1664 void defineCursor(xcb_cursor_t cursor);
1665 void focus(uint8_t revertTo = XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time = XCB_TIME_CURRENT_TIME);
1666 void selectInput(uint32_t events);
1667 void kill();
1668 operator xcb_window_t() const;
1669
1670private:
1671 xcb_window_t doCreate(const QRectF &geometry, uint16_t windowClass, uint32_t mask = 0, const uint32_t *values = nullptr, xcb_window_t parent = rootWindow());
1672 void destroy();
1673 xcb_window_t m_window;
1674 bool m_destroy;
1675 QRectF m_logicGeometry;
1676};
1677
1678inline Window::Window(xcb_window_t window, bool destroy)
1679 : m_window(window)
1680 , m_destroy(destroy)
1681{
1682}
1683
1684inline Window::Window(const QRectF &geometry, uint32_t mask, const uint32_t *values, xcb_window_t parent)
1685 : m_window(doCreate(geometry, XCB_COPY_FROM_PARENT, mask, values, parent))
1686 , m_destroy(true)
1687{
1688}
1689
1690inline Window::Window(const QRectF &geometry, uint16_t windowClass, uint32_t mask, const uint32_t *values, xcb_window_t parent)
1691 : m_window(doCreate(geometry, windowClass, mask, values, parent))
1692 , m_destroy(true)
1693{
1694}
1695
1697{
1698 destroy();
1699}
1700
1701inline void Window::destroy()
1702{
1703 if (!isValid() || !m_destroy) {
1704 return;
1705 }
1706 xcb_destroy_window(connection(), m_window);
1707 m_window = XCB_WINDOW_NONE;
1708}
1709
1710inline bool Window::isValid() const
1711{
1712 return m_window != XCB_WINDOW_NONE;
1713}
1714
1715inline Window::operator xcb_window_t() const
1716{
1717 return m_window;
1718}
1719
1720inline void Window::create(const QRectF &geometry, uint16_t windowClass, uint32_t mask, const uint32_t *values, xcb_window_t parent)
1721{
1722 destroy();
1723 m_window = doCreate(geometry, windowClass, mask, values, parent);
1724}
1725
1726inline void Window::create(const QRectF &geometry, uint32_t mask, const uint32_t *values, xcb_window_t parent)
1727{
1728 create(geometry, XCB_COPY_FROM_PARENT, mask, values, parent);
1729}
1730
1731inline xcb_window_t Window::doCreate(const QRectF &geometry, uint16_t windowClass, uint32_t mask, const uint32_t *values, xcb_window_t parent)
1732{
1733 m_logicGeometry = geometry;
1734 xcb_window_t w = xcb_generate_id(connection());
1735 xcb_create_window(connection(), XCB_COPY_FROM_PARENT, w, parent,
1737 0, windowClass, XCB_COPY_FROM_PARENT, mask, values);
1738 return w;
1739}
1740
1741inline void Window::reset(xcb_window_t window, bool shouldDestroy)
1742{
1743 destroy();
1744 m_window = window;
1745 m_destroy = shouldDestroy;
1746}
1747
1748inline void Window::setGeometry(const QRectF &geometry)
1749{
1750 setGeometry(geometry.x(), geometry.y(), geometry.width(), geometry.height());
1751}
1752
1753inline void Window::setGeometry(qreal x, qreal y, qreal width, qreal height)
1754{
1755 m_logicGeometry.setRect(x, y, width, height);
1756 if (!isValid()) {
1757 return;
1758 }
1759 const uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
1760 const uint32_t values[] = {Xcb::toXNative(x), Xcb::toXNative(y), Xcb::toXNative(width), Xcb::toXNative(height)};
1761 xcb_configure_window(connection(), m_window, mask, values);
1762}
1763
1764inline void Window::move(const QPointF &pos)
1765{
1766 move(pos.x(), pos.y());
1767}
1768
1769inline void Window::move(qreal x, qreal y)
1770{
1771 m_logicGeometry.moveTo(x, y);
1772 if (!isValid()) {
1773 return;
1774 }
1775 moveWindow(m_window, x, y);
1776}
1777
1778inline void Window::resize(const QSizeF &size)
1779{
1780 resize(size.width(), size.height());
1781}
1782
1783inline void Window::resize(qreal width, qreal height)
1784{
1785 m_logicGeometry.setSize(QSizeF(width, height));
1786 if (!isValid()) {
1787 return;
1788 }
1789 const uint16_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
1790 const uint32_t values[] = {Xcb::toXNative(width), Xcb::toXNative(height)};
1791 xcb_configure_window(connection(), m_window, mask, values);
1792}
1793
1794inline void Window::raise()
1795{
1796 const uint32_t values[] = {XCB_STACK_MODE_ABOVE};
1797 xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_STACK_MODE, values);
1798}
1799
1800inline void Window::lower()
1801{
1802 lowerWindow(m_window);
1803}
1804
1805inline void Window::map()
1806{
1807 if (!isValid()) {
1808 return;
1809 }
1810 xcb_map_window(connection(), m_window);
1811}
1812
1813inline void Window::unmap()
1814{
1815 if (!isValid()) {
1816 return;
1817 }
1818 xcb_unmap_window(connection(), m_window);
1819}
1820
1821inline void Window::reparent(xcb_window_t parent, qreal x, qreal y)
1822{
1823 if (!isValid()) {
1824 return;
1825 }
1826 xcb_reparent_window(connection(), m_window, parent, Xcb::toXNative(x), Xcb::toXNative(y));
1827}
1828
1829inline void Window::changeProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length, const void *data, uint8_t mode)
1830{
1831 if (!isValid()) {
1832 return;
1833 }
1834 xcb_change_property(connection(), mode, m_window, property, type, format, length, data);
1835}
1836
1837inline void Window::deleteProperty(xcb_atom_t property)
1838{
1839 if (!isValid()) {
1840 return;
1841 }
1842 xcb_delete_property(connection(), m_window, property);
1843}
1844
1845inline void Window::setBorderWidth(uint32_t width)
1846{
1847 if (!isValid()) {
1848 return;
1849 }
1850 uint32_t _width = Xcb::toXNative(width);
1851 xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_BORDER_WIDTH, &_width);
1852}
1853
1854inline void Window::grabButton(uint8_t pointerMode, uint8_t keyboardmode, uint16_t modifiers,
1855 uint8_t button, uint16_t eventMask, xcb_window_t confineTo,
1856 xcb_cursor_t cursor, bool ownerEvents)
1857{
1858 if (!isValid()) {
1859 return;
1860 }
1861 xcb_grab_button(connection(), ownerEvents, m_window, eventMask,
1862 pointerMode, keyboardmode, confineTo, cursor, button, modifiers);
1863}
1864
1865inline void Window::ungrabButton(uint16_t modifiers, uint8_t button)
1866{
1867 if (!isValid()) {
1868 return;
1869 }
1870 xcb_ungrab_button(connection(), button, m_window, modifiers);
1871}
1872
1873inline void Window::clear()
1874{
1875 if (!isValid()) {
1876 return;
1877 }
1878 xcb_clear_area(connection(), false, m_window, 0, 0, 0, 0);
1879}
1880
1881inline void Window::setBackgroundPixmap(xcb_pixmap_t pixmap)
1882{
1883 if (!isValid()) {
1884 return;
1885 }
1886 const uint32_t values[] = {pixmap};
1887 xcb_change_window_attributes(connection(), m_window, XCB_CW_BACK_PIXMAP, values);
1888}
1889
1890inline void Window::defineCursor(xcb_cursor_t cursor)
1891{
1892 Xcb::defineCursor(m_window, cursor);
1893}
1894
1895inline void Window::focus(uint8_t revertTo, xcb_timestamp_t time)
1896{
1897 setInputFocus(m_window, revertTo, time);
1898}
1899
1900inline void Window::selectInput(uint32_t events)
1901{
1902 Xcb::selectInput(m_window, events);
1903}
1904
1905inline void Window::kill()
1906{
1907 xcb_kill_client(connection(), m_window);
1908}
1909
1910// helper functions
1911static inline void moveResizeWindow(WindowId window, const QRect &geometry)
1912{
1913 const uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
1914
1915 const uint32_t values[] = {Xcb::toXNative(geometry.x()), Xcb::toXNative(geometry.y()), Xcb::toXNative(geometry.width()), Xcb::toXNative(geometry.height())};
1916 xcb_configure_window(connection(), window, mask, values);
1917}
1918
1919static inline void moveWindow(xcb_window_t window, const QPoint &pos)
1920{
1921 moveWindow(window, pos.x(), pos.y());
1922}
1923
1924static inline void moveWindow(xcb_window_t window, uint32_t x, uint32_t y)
1925{
1926 const uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
1927 const uint32_t values[] = {Xcb::toXNative(x), Xcb::toXNative(y)};
1928 xcb_configure_window(connection(), window, mask, values);
1929}
1930
1931static inline void lowerWindow(xcb_window_t window)
1932{
1933 const uint32_t values[] = {XCB_STACK_MODE_BELOW};
1934 xcb_configure_window(connection(), window, XCB_CONFIG_WINDOW_STACK_MODE, values);
1935}
1936
1937static inline WindowId createInputWindow(const QRect &geometry, uint32_t mask, const uint32_t *values)
1938{
1939 WindowId window = xcb_generate_id(connection());
1940 xcb_create_window(connection(), 0, window, rootWindow(),
1941 geometry.x(), geometry.y(), geometry.width(), geometry.height(),
1942 0, XCB_WINDOW_CLASS_INPUT_ONLY,
1943 XCB_COPY_FROM_PARENT, mask, values);
1944 return window;
1945}
1946
1947static inline void restackWindows(const QList<xcb_window_t> &windows)
1948{
1949 if (windows.count() < 2) {
1950 // only one window, nothing to do
1951 return;
1952 }
1953 for (int i = 1; i < windows.count(); ++i) {
1954 const uint16_t mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
1955 const uint32_t stackingValues[] = {
1956 windows.at(i - 1),
1957 XCB_STACK_MODE_BELOW};
1958 xcb_configure_window(connection(), windows.at(i), mask, stackingValues);
1959 }
1960}
1961
1962static inline void restackWindowsWithRaise(const QList<xcb_window_t> &windows)
1963{
1964 if (windows.isEmpty()) {
1965 return;
1966 }
1967 const uint32_t values[] = {XCB_STACK_MODE_ABOVE};
1968 xcb_configure_window(connection(), windows.first(), XCB_CONFIG_WINDOW_STACK_MODE, values);
1969 restackWindows(windows);
1970}
1971
1972static xcb_screen_t *defaultScreen()
1973{
1974 return xcb_setup_roots_iterator(xcb_get_setup(connection())).data;
1975}
1976
1977static inline int defaultDepth()
1978{
1979 return defaultScreen()->root_depth;
1980}
1981
1982static inline xcb_rectangle_t fromQt(const QRect &rect)
1983{
1984 const QRect nativeRect = toXNative(rect);
1985 xcb_rectangle_t rectangle;
1986 rectangle.x = nativeRect.x();
1987 rectangle.y = nativeRect.y();
1988 rectangle.width = nativeRect.width();
1989 rectangle.height = nativeRect.height();
1990 return rectangle;
1991}
1992
1993static inline QList<xcb_rectangle_t> regionToRects(const QRegion &region)
1994{
1995 QList<xcb_rectangle_t> rects;
1996 rects.reserve(region.rectCount());
1997 for (const QRect &rect : region) {
1998 rects.append(Xcb::fromQt(rect));
1999 }
2000 return rects;
2001}
2002
2003static inline void defineCursor(xcb_window_t window, xcb_cursor_t cursor)
2004{
2005 xcb_change_window_attributes(connection(), window, XCB_CW_CURSOR, &cursor);
2006}
2007
2008static inline void setInputFocus(xcb_window_t window, uint8_t revertTo, xcb_timestamp_t time)
2009{
2010 xcb_set_input_focus(connection(), revertTo, window, time);
2011}
2012
2013static inline void setTransientFor(xcb_window_t window, xcb_window_t transient_for_window)
2014{
2015 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_TRANSIENT_FOR,
2016 XCB_ATOM_WINDOW, 32, 1, &transient_for_window);
2017}
2018
2019static inline void sync()
2020{
2021 auto *c = connection();
2022 const auto cookie = xcb_get_input_focus(c);
2023 xcb_generic_error_t *error = nullptr;
2024 UniqueCPtr<xcb_get_input_focus_reply_t> sync(xcb_get_input_focus_reply(c, cookie, &error));
2025 if (error) {
2026 free(error);
2027 }
2028}
2029
2030void selectInput(xcb_window_t window, uint32_t events)
2031{
2032 xcb_change_window_attributes(connection(), window, XCB_CW_EVENT_MASK, &events);
2033}
2034
2038class Shm
2039{
2040public:
2041 Shm();
2042 ~Shm();
2043 int shmId() const;
2044 void *buffer() const;
2045 xcb_shm_seg_t segment() const;
2046 bool isValid() const;
2047 uint8_t pixmapFormat() const;
2048
2049private:
2050 bool init();
2051 int m_shmId;
2052 void *m_buffer;
2053 xcb_shm_seg_t m_segment;
2054 bool m_valid;
2055 uint8_t m_pixmapFormat;
2056};
2057
2058inline void *Shm::buffer() const
2059{
2060 return m_buffer;
2061}
2062
2063inline bool Shm::isValid() const
2064{
2065 return m_valid;
2066}
2067
2068inline xcb_shm_seg_t Shm::segment() const
2069{
2070 return m_segment;
2071}
2072
2073inline int Shm::shmId() const
2074{
2075 return m_shmId;
2076}
2077
2078inline uint8_t Shm::pixmapFormat() const
2079{
2080 return m_pixmapFormat;
2081}
2082
2083inline static Version xServerVersion()
2084{
2085 if (xcb_connection_t *c = connection()) {
2086 auto setup = xcb_get_setup(c);
2087 const QByteArray vendorName(xcb_setup_vendor(setup), xcb_setup_vendor_length(setup));
2088 if (vendorName.contains("X.Org")) {
2089 const int release = setup->release_number;
2090 return Version(release / 10000000, (release / 100000) % 100, (release / 1000) % 100);
2091 }
2092 }
2093 return Version(0, 0, 0);
2094}
2095
2096} // namespace X11
2097
2098} // namespace KWin
bool resize
Definition window.h:443
bool move
Definition window.h:437
Abstract base class for the wrapper.
Definition xcbutils.h:240
AbstractWrapper(WindowId window, Cookie cookie)
Definition xcbutils.h:329
const Reply * data() const
Definition xcbutils.h:292
const Reply * data()
Definition xcbutils.h:287
Data::cookie_type Cookie
Definition xcbutils.h:242
WindowId window() const
Definition xcbutils.h:297
const Reply * operator->()
Definition xcbutils.h:264
AbstractWrapper(const AbstractWrapper &other)
Definition xcbutils.h:336
AbstractWrapper & operator=(const AbstractWrapper &other)
Definition xcbutils.h:248
Data::reply_type Reply
Definition xcbutils.h:243
Atom(const QByteArray &name, bool onlyIfExists=false, xcb_connection_t *c=connection())
Definition xcbutils.h:476
bool isValid() const
Definition xcbutils.h:504
Atom(const Atom &)=delete
const QByteArray & name() const
Definition xcbutils.h:510
void getReply()
Definition xcbutils.h:515
xcb_window_t window()
Definition xcbutils.h:652
QList< QByteArray > errorCodes
Definition xcbutils.h:1466
QList< QByteArray > opCodes
Definition xcbutils.h:1465
bool isShapeAvailable() const
Definition xcbutils.h:1472
int glxEventBase() const
Definition xcbutils.h:1515
bool isCompositeAvailable() const
Definition xcbutils.h:1489
int glxMajorOpcode() const
Definition xcbutils.h:1519
bool isSyncAvailable() const
Definition xcbutils.h:1505
bool isRandrAvailable() const
Definition xcbutils.h:1479
bool isRenderAvailable() const
Definition xcbutils.h:1494
bool hasGlx() const
Definition xcbutils.h:1511
bool isDamageAvailable() const
Definition xcbutils.h:1484
bool isFixesAvailable() const
Definition xcbutils.h:1498
bool hasMaxSize() const
Definition xcbutils.h:980
xcb_gravity_t windowGravity() const
Definition xcbutils.h:1033
bool hasMinSize() const
Definition xcbutils.h:976
QSizeF minSize() const
Definition xcbutils.h:1008
void init(xcb_window_t window)
Definition xcbutils.h:945
bool hasAspect() const
Definition xcbutils.h:988
QSizeF baseSize() const
Definition xcbutils.h:1017
QSize minAspect() const
Definition xcbutils.h:1040
QSize maxAspect() const
Definition xcbutils.h:1048
QSizeF resizeIncrements() const
Definition xcbutils.h:1026
bool hasBaseSize() const
Definition xcbutils.h:992
QSizeF maxSize() const
Definition xcbutils.h:1000
bool hasPosition() const
Definition xcbutils.h:968
bool hasResizeIncrements() const
Definition xcbutils.h:984
bool hasWindowGravity() const
Definition xcbutils.h:996
xcb_keycode_t * keycodes()
Definition xcbutils.h:690
bool close() const
Definition xcbutils.h:1175
bool resize() const
Definition xcbutils.h:1159
bool minimize() const
Definition xcbutils.h:1167
MotifHints(xcb_atom_t atom)
Definition xcbutils.h:1119
bool noBorder() const
Definition xcbutils.h:1152
bool hasDecoration() const
Definition xcbutils.h:1145
bool maximize() const
Definition xcbutils.h:1171
void init(xcb_window_t window)
Definition xcbutils.h:1123
bool move() const
Definition xcbutils.h:1163
QByteArray toByteArray(uint8_t format=8, xcb_atom_t type=XCB_ATOM_STRING, bool *ok=nullptr)
Reads the property as string and returns a QByteArray.
Definition xcbutils.h:838
Property(uint8_t _delete, xcb_window_t window, xcb_atom_t property, xcb_atom_t type, uint32_t long_offset, uint32_t long_length)
Definition xcbutils.h:720
QByteArray toByteArray(bool *ok)
Overloaded method for convenience.
Definition xcbutils.h:856
Property(const Property &other)
Definition xcbutils.h:715
std::enable_if< std::is_pointer< T >::value, T >::type value(uint8_t format, xcb_atom_t type, T defaultValue=nullptr, bool *ok=nullptr)
Reads the property as an array of T.
Definition xcbutils.h:808
std::enable_if<!std::is_pointer< T >::value, T >::type value(uint8_t format, xcb_atom_t type, T defaultValue=T(), bool *ok=nullptr)
Reads the property as a POD type.
Definition xcbutils.h:764
bool toBool(bool *ok)
Overloaded method for convenience.
Definition xcbutils.h:893
std::enable_if<!std::is_pointer< T >::value, T >::type value(T defaultValue=T(), bool *ok=nullptr)
Overloaded method for convenience.
Definition xcbutils.h:745
bool toBool(uint8_t format=32, xcb_atom_t type=XCB_ATOM_CARDINAL, bool *ok=nullptr)
Reads the property as a boolean value.
Definition xcbutils.h:876
Property & operator=(const Property &other)
Definition xcbutils.h:725
std::enable_if< std::is_pointer< T >::value, T >::type value(T defaultValue=nullptr, bool *ok=nullptr)
Overloaded method for convenience.
Definition xcbutils.h:785
CrtcGamma(xcb_randr_crtc_t c)
Definition xcbutils.h:1262
CrtcInfo(const CrtcInfo &)=default
xcb_randr_output_t * outputs()
Definition xcbutils.h:1300
CrtcInfo(xcb_randr_crtc_t c, xcb_timestamp_t t)
Definition xcbutils.h:1287
xcb_randr_mode_info_t * modes()
Definition xcbutils.h:1347
OutputInfo(xcb_randr_output_t c, xcb_timestamp_t t)
Definition xcbutils.h:1316
OutputInfo(const OutputInfo &)=default
bool toBool(uint8_t format=32, xcb_atom_t type=XCB_ATOM_CARDINAL, bool *ok=nullptr)
Definition xcbutils.h:1431
std::enable_if< std::is_pointer< T >::value, T >::type value(uint8_t format, xcb_atom_t type, T defaultValue=nullptr, bool *ok=nullptr)
Definition xcbutils.h:1387
QByteArray toByteArray(bool *ok)
Definition xcbutils.h:1427
QByteArray toByteArray(uint8_t format=8, xcb_atom_t type=XCB_ATOM_STRING, bool *ok=nullptr)
Definition xcbutils.h:1412
std::enable_if< std::is_pointer< T >::value, T >::type value(T defaultValue=nullptr, bool *ok=nullptr)
Definition xcbutils.h:1382
OutputProperty(xcb_randr_output_t output, xcb_atom_t property, xcb_atom_t type, uint32_t offset, uint32_t length, uint8_t _delete, uint8_t pending)
Definition xcbutils.h:1367
std::enable_if<!std::is_pointer< T >::value, T >::type value(T defaultValue=T(), bool *ok=nullptr)
Definition xcbutils.h:1373
xcb_randr_crtc_t * crtcs()
Definition xcbutils.h:1235
xcb_randr_mode_info_t * modes()
Definition xcbutils.h:1242
Small helper class to encapsulate SHM related functionality.
Definition xcbutils.h:2039
uint8_t pixmapFormat() const
Definition xcbutils.h:2078
void * buffer() const
Definition xcbutils.h:2058
int shmId() const
Definition xcbutils.h:2073
xcb_shm_seg_t segment() const
Definition xcbutils.h:2068
bool isValid() const
Definition xcbutils.h:2063
StringProperty(xcb_window_t w, xcb_atom_t p)
Definition xcbutils.h:906
bool getTransientFor(WindowId *prop)
Fill given window pointer with the WM_TRANSIENT_FOR property of a window.
Definition xcbutils.h:929
TransientFor(WindowId window)
Definition xcbutils.h:919
WindowId * children()
Definition xcbutils.h:620
Tree(WindowId window)
Definition xcbutils.h:615
xcb_window_t parent()
Definition xcbutils.h:627
WindowGeometry(xcb_window_t window)
Definition xcbutils.h:587
const QRectF & geometry() const
Definition xcbutils.h:1628
void setBorderWidth(uint32_t width)
Definition xcbutils.h:1845
void deleteProperty(xcb_atom_t property)
Definition xcbutils.h:1837
void resize(const QSizeF &size)
Definition xcbutils.h:1778
void grabButton(uint8_t pointerMode, uint8_t keyboardmode, uint16_t modifiers=XCB_MOD_MASK_ANY, uint8_t button=XCB_BUTTON_INDEX_ANY, uint16_t eventMask=XCB_EVENT_MASK_BUTTON_PRESS, xcb_window_t confineTo=XCB_WINDOW_NONE, xcb_cursor_t cursor=XCB_CURSOR_NONE, bool ownerEvents=false)
Definition xcbutils.h:1854
void reparent(xcb_window_t parent, qreal x=0, qreal y=0)
Definition xcbutils.h:1821
void defineCursor(xcb_cursor_t cursor)
Definition xcbutils.h:1890
void changeProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length, const void *data, uint8_t mode=XCB_PROP_MODE_REPLACE)
Definition xcbutils.h:1829
Window(const Window &other)=delete
void ungrabButton(uint16_t modifiers=XCB_MOD_MASK_ANY, uint8_t button=XCB_BUTTON_INDEX_ANY)
Definition xcbutils.h:1865
void create(const QRectF &geometry, uint32_t mask=0, const uint32_t *values=nullptr, xcb_window_t parent=rootWindow())
Definition xcbutils.h:1726
void selectInput(uint32_t events)
Definition xcbutils.h:1900
void setGeometry(const QRectF &geometry)
Definition xcbutils.h:1748
Window(xcb_window_t window=XCB_WINDOW_NONE, bool destroy=true)
Definition xcbutils.h:1678
void reset(xcb_window_t window=XCB_WINDOW_NONE, bool destroy=true)
Definition xcbutils.h:1741
void focus(uint8_t revertTo=XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time=XCB_TIME_CURRENT_TIME)
Definition xcbutils.h:1895
bool isValid() const
Definition xcbutils.h:1710
void move(const QPointF &pos)
Definition xcbutils.h:1764
void setBackgroundPixmap(xcb_pixmap_t pixmap)
Definition xcbutils.h:1881
Wrapper(xcb_window_t w, Args... args)
Definition xcbutils.h:447
Wrapper taking a WrapperData as first template argument and xcb request args as variadic args.
Definition xcbutils.h:410
Wrapper(Args... args)
Definition xcbutils.h:421
Wrapper(xcb_window_t w, Args... args)
Definition xcbutils.h:425
qreal fromXNative(int value)
Definition xcbutils.cpp:632
uint32_t toXNative(qreal value)
Definition xcbutils.cpp:618
QRectF nativeFloor(const QRectF &rect)
Definition xcbutils.cpp:652
xcb_window_t WindowId
Definition xcbutils.h:35
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
Session::Type type
Definition session.cpp:17
GLenum format
Definition gltexture.cpp:49
KWIN_EXPORT xcb_timestamp_t xTime()
Definition xcb.h:29
KWIN_EXPORT xcb_connection_t * connection()
Definition xcb.h:19
std::unique_ptr< T, CDeleter > UniqueCPtr
Definition c_ptr.h:28
static constexpr reply_func replyFunc
Definition xcbutils.h:679
static constexpr request_func requestFunc
Definition xcbutils.h:678
static constexpr reply_func replyFunc
Definition xcbutils.h:664
static constexpr request_func requestFunc
Definition xcbutils.h:663
Variadic template to wrap an xcb request.
Definition xcbutils.h:186
Cookie cookie_type
The type returned by the xcb request function.
Definition xcbutils.h:194
Reply reply_type
The type returned by the xcb reply function.
Definition xcbutils.h:190
xcb_query_keymap_reply_t *(* reply_func)(xcb_connection_t *, xcb_query_keymap_cookie_t, xcb_generic_error_t **)
The function pointer definition for the xcb reply function.
Definition xcbutils.h:207
Cookie(* request_func)(xcb_connection_t *, Args...)
The function pointer definition for the xcb request function.
Definition xcbutils.h:203
static constexpr std::size_t argumentCount
Number of variadic arguments.
Definition xcbutils.h:212
std::tuple< Args... > argument_types
Variadic arguments combined as a std::tuple.
Definition xcbutils.h:199
std::tuple_element< 0, T1 >::type tuple1Type
Definition xcbutils.h:400
std::tuple_element< 0, T2 >::type tuple2Type
Definition xcbutils.h:401
Template to compare the arguments of two std::tuple.
Definition xcbutils.h:385
static constexpr bool value
Definition xcbutils.h:391
std::tuple_element< I, T2 >::type tuple2Type
Definition xcbutils.h:387
std::tuple_element< I, T1 >::type tuple1Type
Definition xcbutils.h:386
#define XCB_WRAPPER_DATA(__NAME__, __REQUEST__,...)
Macro to create the WrapperData subclass.
Definition xcbutils.h:553
#define XCB_WRAPPER(__NAME__, __REQUEST__,...)
Macro to create Wrapper typedef and WrapperData.
Definition xcbutils.h:572