Qt 4.8
qxcbwindowsurface.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qxcbwindowsurface.h"
43 
44 #include "qxcbconnection.h"
45 #include "qxcbscreen.h"
46 #include "qxcbwindow.h"
47 
48 #include <xcb/shm.h>
49 #include <xcb/xcb_image.h>
50 
51 #include <sys/ipc.h>
52 #include <sys/shm.h>
53 
54 #include <stdio.h>
55 
56 #include <qdebug.h>
57 #include <qpainter.h>
58 
59 class QXcbShmImage : public QXcbObject
60 {
61 public:
64 
65  QImage *image() { return &m_qimage; }
66 
67  void put(xcb_window_t window, const QPoint &dst, const QRect &source);
68  void preparePaint(const QRegion &region);
69 
70 private:
71  void destroy();
72 
73  xcb_shm_segment_info_t m_shm_info;
74 
75  xcb_image_t *m_xcb_image;
76 
78 
79  xcb_gcontext_t m_gc;
80  xcb_window_t m_gc_window;
81 
83 };
84 
86  : QXcbObject(screen->connection())
87  , m_gc(0)
88  , m_gc_window(0)
89 {
91  m_xcb_image = xcb_image_create_native(xcb_connection(),
92  size.width(),
93  size.height(),
94  XCB_IMAGE_FORMAT_Z_PIXMAP,
95  depth,
96  0,
97  ~0,
98  0);
99 
100  m_shm_info.shmid = shmget (IPC_PRIVATE,
101  m_xcb_image->stride * m_xcb_image->height, IPC_CREAT|0600);
102 
103  m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat (m_shm_info.shmid, 0, 0);
104  m_shm_info.shmseg = xcb_generate_id(xcb_connection());
105 
106  xcb_generic_error_t *error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false));
107  if (error) {
108  qWarning() << "QXcbWindowSurface: Unable to attach to shared memory segment";
109  free(error);
110  }
111 
112  if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1)
113  qWarning() << "QXcbWindowSurface: Error while marking the shared memory segment to be destroyed";
114 
115  m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
116 }
117 
119 {
120  Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
121  xcb_image_destroy(m_xcb_image);
122  shmdt(m_shm_info.shmaddr);
123  shmctl(m_shm_info.shmid, IPC_RMID, 0);
124  if (m_gc)
125  Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
126 }
127 
128 void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source)
129 {
131  if (m_gc_window != window) {
132  if (m_gc)
133  Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
134 
135  m_gc = xcb_generate_id(xcb_connection());
136  Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, 0, 0));
137 
139  }
140 
142  xcb_image_shm_put(xcb_connection(),
143  window,
144  m_gc,
145  m_xcb_image,
146  m_shm_info,
147  source.x(),
148  source.y(),
149  target.x(),
150  target.y(),
151  source.width(),
152  source.height(),
153  false);
155 
156  m_dirty = m_dirty | source;
157 
158  xcb_flush(xcb_connection());
160 }
161 
163 {
164  // to prevent X from reading from the image region while we're writing to it
165  if (m_dirty.intersects(region)) {
166  connection()->sync();
167  m_dirty = QRegion();
168  }
169 }
170 
172  : QWindowSurface(widget, setDefaultSurface)
173  , m_image(0)
174  , m_syncingResize(false)
175 {
176  QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget));
177  setConnection(screen->connection());
178 }
179 
181 {
182  delete m_image;
183 }
184 
186 {
187  return m_image->image();
188 }
189 
191 {
192  m_image->preparePaint(region);
193 
194  if (m_image->image()->hasAlphaChannel()) {
195  QPainter p(m_image->image());
197  const QVector<QRect> rects = region.rects();
198  const QColor blank = Qt::transparent;
199  for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
200  p.fillRect(*it, blank);
201  }
202  }
203 }
204 
206 {
207 }
208 
210 {
211  QRect bounds = region.boundingRect();
212 
213  if (size().isEmpty() || !geometry().contains(bounds))
214  return;
215 
217 
218  QXcbWindow *window = static_cast<QXcbWindow *>(widget->window()->platformWindow());
219 
220  extern QWidgetData* qt_widget_data(QWidget *);
221  QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft();
222 
223  QVector<QRect> rects = region.rects();
224  for (int i = 0; i < rects.size(); ++i)
225  m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset));
226 
228 
229  if (m_syncingResize) {
230  xcb_flush(xcb_connection());
231  connection()->sync();
232  m_syncingResize = false;
233  window->updateSyncRequestCounter();
234  }
235 }
236 
238 {
239  if (size == QWindowSurface::size())
240  return;
241 
243  QWindowSurface::resize(size);
244 
246  QXcbWindow* win = static_cast<QXcbWindow *>(window()->platformWindow());
247 
248  delete m_image;
249  m_image = new QXcbShmImage(screen, size, win->depth(), win->format());
251 
252  m_syncingResize = true;
253 }
254 
255 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
256 
257 bool QXcbWindowSurface::scroll(const QRegion &area, int dx, int dy)
258 {
259  if (m_image->image()->isNull())
260  return false;
261 
262  m_image->preparePaint(area);
263 
264  const QVector<QRect> rects = area.rects();
265  for (int i = 0; i < rects.size(); ++i)
266  qt_scrollRectInImage(*m_image->image(), rects.at(i), QPoint(dx, dy));
267 
268  return true;
269 }
270 
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
QRect geometry() const
Returns the currently allocated area on the screen.
Format
The following image formats are available in Qt.
Definition: qimage.h:91
void beginPaint(const QRegion &)
This function is called before painting onto the surface begins, with the region in which the paintin...
QPointer< QWidget > widget
QXcbWindowSurface(QWidget *widget, bool setDefaultSurface=true)
xcb_gcontext_t m_gc
QRect rect(const QWidget *widget) const
Returns the rectangle for widget in the coordinates of this window surface.
#define it(className, varName)
#define error(msg)
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
xcb_connection_t * xcb_connection() const
Definition: qxcbobject.h:56
void endPaint(const QRegion &)
This function is called after painting onto the surface has ended, with the region in which the paint...
QXcbShmImage * m_image
void put(xcb_window_t window, const QPoint &dst, const QRect &source)
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
void preparePaint(const QRegion &region)
void setConnection(QXcbConnection *connection)
Definition: qxcbobject.h:52
QRect translated(int dx, int dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:328
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
virtual QPoint offset(const QWidget *widget) const
Returns the offset of widget in the coordinates of this window surface.
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
Definition: qimage.cpp:6495
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
unsigned char quint8
Definition: qglobal.h:934
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QXcbConnection * connection() const
Definition: qxcbobject.h:53
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:250
xcb_shm_segment_info_t m_shm_info
unsigned char uchar
Definition: qglobal.h:994
NSWindow * window
int width() const
Returns the width.
Definition: qsize.h:126
xcb_image_t * m_xcb_image
static bool isEmpty(const char *str)
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned int uint
Definition: qglobal.h:996
void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
static QPlatformScreen * platformScreenForWidget(const QWidget *widget)
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
xcb_window_t m_gc_window
QRect wrect
Definition: qwidget.h:145
QImage::Format format() const
Definition: qxcbwindow.h:79
The QWindowSurface class provides the drawing area for top-level windows.
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
Definition: qpainter.cpp:2422
iterator begin()
Returns an STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:247
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
xcb_window_t window() const
Definition: qxcbwindow.h:77
#define Q_XCB_CALL(x)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
#define Q_XCB_NOOP(c)
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
bool scroll(const QRegion &area, int dx, int dy)
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative...
QWidget * window() const
Returns the window for this widget, i.e.
Definition: qwidget.cpp:4492
bool intersects(const QRegion &r) const
Returns true if this region intersects with region, otherwise returns false.
Definition: qregion.cpp:766
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
void resize(const QSize &size)
uint depth() const
Definition: qxcbwindow.h:78
Q_GUI_EXPORT QWidgetData * qt_qwidget_data(QWidget *widget)
Definition: qwidget.cpp:12915
void flush(QWidget *widget, const QRegion &region, const QPoint &offset)
Flushes the given region from the specified widget onto the screen.
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format)
QWidget * window() const
Returns a pointer to the top-level window associated with this surface.
static int area(const QSize &s)
Definition: qicon.cpp:155
QPaintDevice * paintDevice()
Implement this function to return the appropriate paint device.
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
void updateSyncRequestCounter()
Definition: qxcbwindow.cpp:705