Changeset View
Changeset View
Standalone View
Standalone View
overlaywindow.cpp
- This file was copied to plugins/platforms/x11/standalone/overlaywindow_x11.cpp.
Show All 14 Lines | |||||
15 | GNU General Public License for more details. | 15 | GNU General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | 20 | | |||
21 | #include "overlaywindow.h" | 21 | #include "overlaywindow.h" | ||
22 | 22 | | |||
23 | #include "kwinglobals.h" | | |||
24 | #include "screens.h" | | |||
25 | #include "utils.h" | | |||
26 | #include "xcbutils.h" | | |||
27 | | ||||
28 | #include "assert.h" | | |||
29 | | ||||
30 | #include <QVector> | | |||
31 | | ||||
32 | #include <xcb/composite.h> | | |||
33 | #include <xcb/shape.h> | | |||
34 | #if XCB_COMPOSITE_MAJOR_VERSION > 0 || XCB_COMPOSITE_MINOR_VERSION >= 3 | | |||
35 | #define KWIN_HAVE_XCOMPOSITE_OVERLAY | | |||
36 | #endif | | |||
37 | | ||||
38 | namespace KWin { | 23 | namespace KWin { | ||
39 | OverlayWindow::OverlayWindow() | 24 | OverlayWindow::OverlayWindow() | ||
40 | : m_visible(true) | | |||
41 | , m_shown(false) | | |||
42 | , m_window(XCB_WINDOW_NONE) | | |||
43 | { | 25 | { | ||
44 | } | 26 | } | ||
45 | 27 | | |||
46 | OverlayWindow::~OverlayWindow() | 28 | OverlayWindow::~OverlayWindow() | ||
47 | { | 29 | { | ||
48 | } | 30 | } | ||
49 | 31 | | |||
50 | bool OverlayWindow::create() | | |||
51 | { | | |||
52 | assert(m_window == XCB_WINDOW_NONE); | | |||
53 | if (!Xcb::Extensions::self()->isCompositeOverlayAvailable()) | | |||
54 | return false; | | |||
55 | if (!Xcb::Extensions::self()->isShapeInputAvailable()) // needed in setupOverlay() | | |||
56 | return false; | | |||
57 | #ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY | | |||
58 | Xcb::OverlayWindow overlay(rootWindow()); | | |||
59 | if (overlay.isNull()) { | | |||
60 | return false; | | |||
61 | } | | |||
62 | m_window = overlay->overlay_win; | | |||
63 | if (m_window == XCB_WINDOW_NONE) | | |||
64 | return false; | | |||
65 | resize(screens()->size()); | | |||
66 | return true; | | |||
67 | #else | | |||
68 | return false; | | |||
69 | #endif | | |||
70 | } | | |||
71 | | ||||
72 | void OverlayWindow::setup(xcb_window_t window) | | |||
73 | { | | |||
74 | assert(m_window != XCB_WINDOW_NONE); | | |||
75 | assert(Xcb::Extensions::self()->isShapeInputAvailable()); | | |||
76 | setNoneBackgroundPixmap(m_window); | | |||
77 | m_shape = QRegion(); | | |||
78 | const QSize &s = screens()->size(); | | |||
79 | setShape(QRect(0, 0, s.width(), s.height())); | | |||
80 | if (window != XCB_WINDOW_NONE) { | | |||
81 | setNoneBackgroundPixmap(window); | | |||
82 | setupInputShape(window); | | |||
83 | } | | |||
84 | const uint32_t eventMask = XCB_EVENT_MASK_VISIBILITY_CHANGE; | | |||
85 | xcb_change_window_attributes(connection(), m_window, XCB_CW_EVENT_MASK, &eventMask); | | |||
86 | } | | |||
87 | | ||||
88 | void OverlayWindow::setupInputShape(xcb_window_t window) | | |||
89 | { | | |||
90 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, window, 0, 0, 0, NULL); | | |||
91 | } | | |||
92 | | ||||
93 | void OverlayWindow::setNoneBackgroundPixmap(xcb_window_t window) | | |||
94 | { | | |||
95 | const uint32_t mask = XCB_BACK_PIXMAP_NONE; | | |||
96 | xcb_change_window_attributes(connection(), window, XCB_CW_BACK_PIXMAP, &mask); | | |||
97 | } | | |||
98 | | ||||
99 | void OverlayWindow::show() | | |||
100 | { | | |||
101 | assert(m_window != XCB_WINDOW_NONE); | | |||
102 | if (m_shown) | | |||
103 | return; | | |||
104 | xcb_map_subwindows(connection(), m_window); | | |||
105 | xcb_map_window(connection(), m_window); | | |||
106 | m_shown = true; | | |||
107 | } | | |||
108 | | ||||
109 | void OverlayWindow::hide() | | |||
110 | { | | |||
111 | assert(m_window != XCB_WINDOW_NONE); | | |||
112 | xcb_unmap_window(connection(), m_window); | | |||
113 | m_shown = false; | | |||
114 | const QSize &s = screens()->size(); | | |||
115 | setShape(QRect(0, 0, s.width(), s.height())); | | |||
116 | } | | |||
117 | | ||||
118 | void OverlayWindow::setShape(const QRegion& reg) | | |||
119 | { | | |||
120 | // Avoid setting the same shape again, it causes flicker (apparently it is not a no-op | | |||
121 | // and triggers something). | | |||
122 | if (reg == m_shape) | | |||
123 | return; | | |||
124 | QVector< QRect > rects = reg.rects(); | | |||
125 | xcb_rectangle_t *xrects = new xcb_rectangle_t[rects.count()]; | | |||
126 | for (int i = 0; | | |||
127 | i < rects.count(); | | |||
128 | ++i) { | | |||
129 | xrects[ i ].x = rects[ i ].x(); | | |||
130 | xrects[ i ].y = rects[ i ].y(); | | |||
131 | xrects[ i ].width = rects[ i ].width(); | | |||
132 | xrects[ i ].height = rects[ i ].height(); | | |||
133 | } | | |||
134 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, | | |||
135 | m_window, 0, 0, rects.count(), xrects); | | |||
136 | delete[] xrects; | | |||
137 | setupInputShape(m_window); | | |||
138 | m_shape = reg; | | |||
139 | } | | |||
140 | | ||||
141 | void OverlayWindow::resize(const QSize &size) | | |||
142 | { | | |||
143 | assert(m_window != XCB_WINDOW_NONE); | | |||
144 | const uint32_t geometry[2] = { | | |||
145 | static_cast<uint32_t>(size.width()), | | |||
146 | static_cast<uint32_t>(size.height()) | | |||
147 | }; | | |||
148 | xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, geometry); | | |||
149 | setShape(QRegion(0, 0, size.width(), size.height())); | | |||
150 | } | | |||
151 | | ||||
152 | bool OverlayWindow::isVisible() const | | |||
153 | { | | |||
154 | return m_visible; | | |||
155 | } | | |||
156 | | ||||
157 | void OverlayWindow::setVisibility(bool visible) | | |||
158 | { | | |||
159 | m_visible = visible; | | |||
160 | } | | |||
161 | | ||||
162 | void OverlayWindow::destroy() | | |||
163 | { | | |||
164 | if (m_window == XCB_WINDOW_NONE) | | |||
165 | return; | | |||
166 | // reset the overlay shape | | |||
167 | const QSize &s = screens()->size(); | | |||
168 | xcb_rectangle_t rec = { 0, 0, static_cast<uint16_t>(s.width()), static_cast<uint16_t>(s.height()) }; | | |||
169 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); | | |||
170 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); | | |||
171 | #ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY | | |||
172 | xcb_composite_release_overlay_window(connection(), m_window); | | |||
173 | #endif | | |||
174 | m_window = XCB_WINDOW_NONE; | | |||
175 | m_shown = false; | | |||
176 | } | | |||
177 | | ||||
178 | xcb_window_t OverlayWindow::window() const | | |||
179 | { | | |||
180 | return m_window; | | |||
181 | } | | |||
182 | | ||||
183 | } // namespace KWin | 32 | } // namespace KWin |