11 #include "x11framebuffer.moc"
13 #include <config-krfb.h>
16 #include <QApplication>
17 #include <QDesktopWidget>
19 #include <KApplication>
23 #include <X11/Xutil.h>
26 #include <X11/extensions/Xdamage.h>
32 #include <X11/extensions/XShm.h>
35 class X11FrameBuffer::P
43 XShmSegmentInfo shminfo;
46 XImage *framebufferImage;
58 d->useShm = XShmQueryExtension(QX11Info::display());
59 kDebug() <<
"shm: " << d->useShm;
64 d->framebufferImage = XGetImage(QX11Info::display(),
68 QApplication::desktop()->
width(),
69 QApplication::desktop()->
height(),
75 d->updateTile = XShmCreateImage(QX11Info::display(),
76 DefaultVisual(QX11Info::display(), 0),
77 d->framebufferImage->bits_per_pixel,
83 d->shminfo.shmid = shmget(IPC_PRIVATE,
84 d->updateTile->bytes_per_line * d->updateTile->height,
87 d->shminfo.shmaddr = d->updateTile->data = (
char *)
88 shmat(d->shminfo.shmid, 0, 0);
89 d->shminfo.readOnly = False;
91 XShmAttach(QX11Info::display(), &d->shminfo);
97 kDebug() <<
"Got image. bpp: " << d->framebufferImage->bits_per_pixel
98 <<
", depth: " << d->framebufferImage->depth
99 <<
", padded width: " << d->framebufferImage->bytes_per_line
100 <<
" (sent: " << d->framebufferImage->width * 4 <<
")"
103 fb = d->framebufferImage->data;
106 kapp->installX11EventFilter(d->ev);
113 XDestroyImage(d->framebufferImage);
115 kapp->removeX11EventFilter(d->ev);
118 XShmDetach(QX11Info::display(), &d->shminfo);
119 XDestroyImage(d->updateTile);
120 shmdt(d->shminfo.shmaddr);
121 shmctl(d->shminfo.shmid, IPC_RMID, 0);
130 return d->framebufferImage->depth;
135 return d->framebufferImage->height;
140 return d->framebufferImage->width;
145 return d->framebufferImage->bytes_per_line;
150 format.
bitsPerPixel = d->framebufferImage->bits_per_pixel;
151 format.
depth = d->framebufferImage->depth;
153 format.
bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ?
true :
false);
165 if (d->framebufferImage->red_mask)
166 while (!(d->framebufferImage->red_mask & (1 << format.
redShift))) {
172 if (d->framebufferImage->green_mask)
173 while (!(d->framebufferImage->green_mask & (1 << format.
greenShift))) {
179 if (d->framebufferImage->blue_mask)
180 while (!(d->framebufferImage->blue_mask & (1 << format.
blueShift))) {
193 XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
194 QRect r(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
204 void X11FrameBuffer::cleanupRects()
207 QList<QRect> cpy =
tiles;
208 bool inserted =
false;
211 foreach(
const QRect & r, cpy) {
212 if (
tiles.size() > 0) {
213 for (
int i = 0; i <
tiles.size(); i++) {
215 if (r.intersects(
tiles[i])) {
233 for (
int i = 0; i <
tiles.size(); i++) {
234 tiles[i].adjust(-30, -30, 30, 30);
236 if (
tiles[i].top() < 0) {
240 if (
tiles[i].left() < 0) {
244 if (
tiles[i].bottom() > d->framebufferImage->height) {
245 tiles[i].setBottom(d->framebufferImage->height);
248 if (
tiles[i].right() > d->framebufferImage->width) {
249 tiles[i].setRight(d->framebufferImage->width);
256 void X11FrameBuffer::acquireEvents()
261 while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
265 XDamageSubtract(QX11Info::display(), d->damage, None, None);
276 kapp->processEvents();
281 if (
tiles.size() > 0) {
285 foreach(
const QRect & r,
tiles) {
291 while (x < r.right()) {
292 while (y < r.bottom()) {
293 if (y + d->updateTile->height > d->framebufferImage->height) {
294 y = d->framebufferImage->height - d->updateTile->height;
297 if (x + d->updateTile->width > d->framebufferImage->width) {
298 x = d->framebufferImage->width - d->updateTile->width;
302 XShmGetImage(QX11Info::display(),
win, d->updateTile, x, y, AllPlanes);
303 int pxsize = d->framebufferImage->bits_per_pixel / 8;
304 char *dest =
fb + ((d->framebufferImage->bytes_per_line * y) + (x * pxsize));
305 char *src = d->updateTile->data;
307 for (
int i = 0; i < d->updateTile->height; i++) {
308 memcpy(dest, src, d->updateTile->bytes_per_line);
309 dest += d->framebufferImage->bytes_per_line;
310 src += d->updateTile->bytes_per_line;
313 y += d->updateTile->height;
316 x += d->updateTile->width;
322 foreach(
const QRect & r,
tiles) {
323 XGetSubImage(QX11Info::display(),
350 d->damage = XDamageCreate(QX11Info::display(),
win, XDamageReportRawRectangles);
351 XDamageSubtract(QX11Info::display(), d->damage, None, None);
359 XDamageDestroy(QX11Info::display(), d->damage);
370 XDamageQueryExtension(QX11Info::display(), &xdamageBaseEvent, &er);
378 if (event->type == xdamageBaseEvent + XDamageNotify) {
virtual void getServerFormat(rfbPixelFormat &format)
virtual void startMonitor()
X11FrameBuffer(WId id, QObject *parent=0)
virtual QList< QRect > modifiedTiles()
virtual void stopMonitor()
void handleXDamage(XEvent *event)
virtual int paddedWidth()