• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

krfb

x11framebuffer.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
00003 
00004    This program is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 */
00009 
00010 #include "x11framebuffer.h"
00011 #include "x11framebuffer.moc"
00012 
00013 #include <config-krfb.h>
00014 
00015 #include <QX11Info>
00016 #include <QApplication>
00017 #include <QDesktopWidget>
00018 
00019 #include <KApplication>
00020 #include <KDebug>
00021 
00022 #include <X11/Xlib.h>
00023 #include <X11/Xutil.h>
00024 
00025 #ifdef HAVE_XDAMAGE
00026 #include <X11/extensions/Xdamage.h>
00027 #endif
00028 
00029 #ifdef HAVE_XSHM
00030 #include <sys/ipc.h>
00031 #include <sys/shm.h>
00032 #include <X11/extensions/XShm.h>
00033 #endif
00034 
00035 class X11FrameBuffer::P {
00036 
00037 public:
00038 #ifdef HAVE_XDAMAGE
00039     Damage damage;
00040 #endif
00041 #ifdef HAVE_XSHM
00042     XShmSegmentInfo shminfo;
00043 #endif
00044 
00045     XImage *framebufferImage;
00046     XImage *updateTile;
00047     EvWidget *ev;
00048     bool useShm;
00049     int xdamageBaseEvent;
00050     bool running;
00051 };
00052 
00053 X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
00054     :FrameBuffer(id, parent), d(new X11FrameBuffer::P)
00055 {
00056 #ifdef HAVE_XSHM
00057     d->useShm = XShmQueryExtension(QX11Info::display());
00058     kDebug() << "shm: " << d->useShm;
00059 #else
00060     d->useShm = false;
00061 #endif
00062     d->running = false;
00063     d->framebufferImage = XGetImage(QX11Info::display(),
00064                                     id,
00065                                     0,
00066                                     0,
00067                                     QApplication::desktop()->width(), //arg, must get a widget ???
00068                                     QApplication::desktop()->height(),
00069                                     AllPlanes,
00070                                     ZPixmap);
00071     if (d->useShm) {
00072 #ifdef HAVE_XSHM
00073         d->updateTile = XShmCreateImage(QX11Info::display(),
00074                                         DefaultVisual( QX11Info::display(), 0 ),
00075                                         d->framebufferImage->bits_per_pixel,
00076                                         ZPixmap,
00077                                         NULL,
00078                                         &d->shminfo,
00079                                         32,
00080                                         32);
00081         d->shminfo.shmid = shmget(IPC_PRIVATE,
00082                                   d->updateTile->bytes_per_line * d->updateTile->height,
00083                                   IPC_CREAT | 0777);
00084 
00085         d->shminfo.shmaddr = d->updateTile->data = (char *)
00086                 shmat(d->shminfo.shmid, 0, 0);
00087         d->shminfo.readOnly = False;
00088 
00089         XShmAttach(QX11Info::display(), &d->shminfo);
00090 #endif
00091     } else {
00092         ;
00093     }
00094     kDebug() << "Got image. bpp: " << d->framebufferImage->bits_per_pixel
00095             << ", depth: " << d->framebufferImage->depth
00096             << ", padded width: " << d->framebufferImage->bytes_per_line
00097             << " (sent: " << d->framebufferImage->width * 4 << ")"
00098             << endl;
00099 
00100     fb = d->framebufferImage->data;
00101 #ifdef HAVE_XDAMAGE
00102     d->ev = new EvWidget(this);
00103     kapp->installX11EventFilter(d->ev);
00104 #endif
00105 }
00106 
00107 
00108 X11FrameBuffer::~X11FrameBuffer()
00109 {
00110     XDestroyImage(d->framebufferImage);
00111 #ifdef HAVE_XDAMAGE
00112     kapp->removeX11EventFilter(d->ev);
00113 #endif
00114 #ifdef HAVE_XSHM
00115     XShmDetach(QX11Info::display(), &d->shminfo);
00116     XDestroyImage(d->updateTile);
00117     shmdt(d->shminfo.shmaddr);
00118     shmctl(d->shminfo.shmid, IPC_RMID, 0);
00119 #endif
00120     delete d;
00121     fb = 0; // already deleted by XDestroyImage
00122 }
00123 
00124 
00125 int X11FrameBuffer::depth()
00126 {
00127     return d->framebufferImage->depth;
00128 }
00129 
00130 int X11FrameBuffer::height()
00131 {
00132     return d->framebufferImage->height;
00133 }
00134 
00135 int X11FrameBuffer::width()
00136 {
00137     return d->framebufferImage->width;
00138 }
00139 
00140 int X11FrameBuffer::paddedWidth()
00141 {
00142     return d->framebufferImage->bytes_per_line;
00143 }
00144 
00145 void X11FrameBuffer::getServerFormat(rfbPixelFormat& format)
00146 {
00147     format.bitsPerPixel = d->framebufferImage->bits_per_pixel;
00148     format.depth = d->framebufferImage->depth;
00149     format.trueColour = true;
00150     format.bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ? true : false);
00151 
00152     if ( format.bitsPerPixel == 8 ) {
00153         format.redShift = 0;
00154         format.greenShift = 3;
00155         format.blueShift = 6;
00156         format.redMax   = 7;
00157         format.greenMax = 7;
00158         format.blueMax  = 3;
00159     } else {
00160         format.redShift = 0;
00161         if ( d->framebufferImage->red_mask )
00162             while ( ! ( d->framebufferImage->red_mask & (1 << format.redShift) ) )
00163                 format.redShift++;
00164         format.greenShift = 0;
00165         if ( d->framebufferImage->green_mask )
00166             while ( ! ( d->framebufferImage->green_mask & (1 << format.greenShift) ) )
00167                 format.greenShift++;
00168         format.blueShift = 0;
00169         if ( d->framebufferImage->blue_mask )
00170             while ( ! ( d->framebufferImage->blue_mask & (1 << format.blueShift) ) )
00171                 format.blueShift++;
00172         format.redMax   = d->framebufferImage->red_mask   >> format.redShift;
00173         format.greenMax = d->framebufferImage->green_mask >> format.greenShift;
00174         format.blueMax  = d->framebufferImage->blue_mask  >> format.blueShift;
00175     }
00176 }
00177 
00178 void X11FrameBuffer::handleXDamage(XEvent * event)
00179 {
00180 #ifdef HAVE_XDAMAGE
00181     XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
00182     QRect r(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
00183     tiles.append(r);
00184 
00185     /*if (!dev->more) {
00186         XDamageSubtract(QX11Info::display(),d->damage, None, None);
00187     }*/
00188 #endif
00189 }
00190 
00191 
00192 void X11FrameBuffer::cleanupRects() {
00193 
00194     QList<QRect> cpy = tiles;
00195     bool inserted = false;
00196     tiles.clear();
00197 //     kDebug() << "before cleanup: " << cpy.size();
00198     foreach (const QRect &r, cpy) {
00199         if (tiles.size() > 0) {
00200             for(int i = 0; i < tiles.size(); i++) {
00201     //             kDebug() << r << tiles[i];
00202                 if (r.intersects(tiles[i])) {
00203                     tiles[i] |= r;
00204                     inserted = true;
00205                     break;
00206     //                 kDebug() << "merged into " << tiles[i];
00207                 }
00208             }
00209             if (!inserted) {
00210                 tiles.append(r);
00211     //             kDebug() << "appended " << r;
00212             }
00213         } else {
00214     //         kDebug() << "appended " << r;
00215             tiles.append(r);
00216         }
00217     }
00218     for(int i = 0; i < tiles.size(); i++) {
00219         tiles[i].adjust(-30,-30,30,30);
00220         if (tiles[i].top() < 0){
00221             tiles[i].setTop(0);
00222         }
00223         if (tiles[i].left() < 0){
00224             tiles[i].setLeft(0);
00225         }
00226         if (tiles[i].bottom() > d->framebufferImage->height) {
00227             tiles[i].setBottom(d->framebufferImage->height);
00228         }
00229         if (tiles[i].right() > d->framebufferImage->width) {
00230             tiles[i].setRight(d->framebufferImage->width);
00231         }
00232     }
00233 //     kDebug() << "after cleanup: " << tiles.size();
00234 }
00235 
00236 void X11FrameBuffer::acquireEvents() {
00237 
00238     XEvent ev;
00239     while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent+XDamageNotify, &ev)) {
00240         handleXDamage(&ev);
00241     }
00242     XDamageSubtract(QX11Info::display(),d->damage, None, None);
00243 }
00244 
00245 QList< QRect > X11FrameBuffer::modifiedTiles()
00246 {
00247     QList<QRect> ret;
00248     if (!d->running) return ret;
00249     kapp->processEvents(); // try to make sure every damage event goes trough;
00250     cleanupRects();
00251     QRect gl;
00252     //d->useShm = false;
00253     if (tiles.size()  > 0) {
00254         if (d->useShm) {
00255 #ifdef HAVE_XSHM
00256 
00257             foreach(const QRect &r, tiles) {
00258 //                 kDebug() << r;
00259                 gl |= r;
00260                 int y = r.y();
00261                 int x = r.x();
00262                 while (x < r.right() ) {
00263                     while (y < r.bottom() ) {
00264                         if (y+d->updateTile->height > d->framebufferImage->height) {
00265                             y = d->framebufferImage->height - d->updateTile->height;
00266                         }
00267                         if (x+d->updateTile->width > d->framebufferImage->width) {
00268                             x = d->framebufferImage->width - d->updateTile->width;
00269                         }
00270 //                         kDebug() << "x: " << x << " (" << r.x() << ") y: " << y << " (" << r.y() << ") " << r;
00271                         XShmGetImage(QX11Info::display(), win, d->updateTile, x, y, AllPlanes);
00272                         int pxsize =  d->framebufferImage->bits_per_pixel / 8;
00273                         char *dest = fb + ((d->framebufferImage->bytes_per_line * y) + (x*pxsize));
00274                         char *src = d->updateTile->data;
00275                         for (int i = 0; i < d->updateTile->height; i++) {
00276                             memcpy(dest, src, d->updateTile->bytes_per_line);
00277                             dest += d->framebufferImage->bytes_per_line;
00278                             src += d->updateTile->bytes_per_line;
00279                         }
00280                         y += d->updateTile->height;
00281                     }
00282                     x += d->updateTile->width;
00283                     y = r.y();
00284                 }
00285             }
00286 #endif
00287         } else {
00288             foreach(const QRect &r, tiles) {
00289                 XGetSubImage(QX11Info::display(),
00290                     win,
00291                     r.left(),
00292                     r.top(),
00293                     r.width(),
00294                     r.height(),
00295                     AllPlanes,
00296                     ZPixmap,
00297                     d->framebufferImage,
00298                     r.left(),
00299                     r.top()
00300                     );
00301             }
00302         }
00303     }
00304 //     kDebug() << "tot: " << gl;
00305 //     kDebug() << tiles.size();
00306     ret = tiles;
00307     tiles.clear();
00308     return ret;
00309 }
00310 
00311 void X11FrameBuffer::startMonitor()
00312 {
00313     d->running = true;
00314 #ifdef HAVE_XDAMAGE
00315     d->damage = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
00316     XDamageSubtract(QX11Info::display(),d->damage, None, None);
00317 #endif
00318 }
00319 
00320 void X11FrameBuffer::stopMonitor()
00321 {
00322     d->running = false;
00323 #ifdef HAVE_XDAMAGE
00324     XDamageDestroy(QX11Info::display(),d->damage);
00325 #endif
00326 }
00327 
00328 
00329 
00330 EvWidget::EvWidget(X11FrameBuffer * x11fb)
00331     :QWidget(0), fb(x11fb)
00332 {
00333 #ifdef HAVE_XDAMAGE
00334     int er;
00335     XDamageQueryExtension(QX11Info::display(), &xdamageBaseEvent, &er);
00336 #endif
00337 }
00338 
00339 bool EvWidget::x11Event(XEvent * event)
00340 {
00341 #ifdef HAVE_XDAMAGE
00342     if (event->type == xdamageBaseEvent+XDamageNotify) {
00343         fb->handleXDamage(event);
00344         return true;
00345     }
00346 #endif
00347     return false;
00348 }
00349 
00350 
00351 

krfb

Skip menu "krfb"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal