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

krfb

  • sources
  • kde-4.14
  • kdenetwork
  • krfb
  • framebuffers
  • x11
x11framebuffer.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 */
9 
10 #include "x11framebuffer.h"
11 #include "x11framebuffer.moc"
12 
13 #include <config-krfb.h>
14 
15 #include <QX11Info>
16 #include <QApplication>
17 #include <QDesktopWidget>
18 
19 #include <KApplication>
20 #include <KDebug>
21 
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 
25 #ifdef HAVE_XDAMAGE
26 #include <X11/extensions/Xdamage.h>
27 #endif
28 
29 #ifdef HAVE_XSHM
30 #include <sys/ipc.h>
31 #include <sys/shm.h>
32 #include <X11/extensions/XShm.h>
33 #endif
34 
35 class X11FrameBuffer::P
36 {
37 
38 public:
39 #ifdef HAVE_XDAMAGE
40  Damage damage;
41 #endif
42 #ifdef HAVE_XSHM
43  XShmSegmentInfo shminfo;
44 #endif
45 
46  XImage *framebufferImage;
47  XImage *updateTile;
48  EvWidget *ev;
49  bool useShm;
50  int xdamageBaseEvent;
51  bool running;
52 };
53 
54 X11FrameBuffer::X11FrameBuffer(WId id, QObject *parent)
55  : FrameBuffer(id, parent), d(new X11FrameBuffer::P)
56 {
57 #ifdef HAVE_XSHM
58  d->useShm = XShmQueryExtension(QX11Info::display());
59  kDebug() << "shm: " << d->useShm;
60 #else
61  d->useShm = false;
62 #endif
63  d->running = false;
64  d->framebufferImage = XGetImage(QX11Info::display(),
65  id,
66  0,
67  0,
68  QApplication::desktop()->width(), //arg, must get a widget ???
69  QApplication::desktop()->height(),
70  AllPlanes,
71  ZPixmap);
72 
73  if (d->useShm) {
74 #ifdef HAVE_XSHM
75  d->updateTile = XShmCreateImage(QX11Info::display(),
76  DefaultVisual(QX11Info::display(), 0),
77  d->framebufferImage->bits_per_pixel,
78  ZPixmap,
79  NULL,
80  &d->shminfo,
81  32,
82  32);
83  d->shminfo.shmid = shmget(IPC_PRIVATE,
84  d->updateTile->bytes_per_line * d->updateTile->height,
85  IPC_CREAT | 0777);
86 
87  d->shminfo.shmaddr = d->updateTile->data = (char *)
88  shmat(d->shminfo.shmid, 0, 0);
89  d->shminfo.readOnly = False;
90 
91  XShmAttach(QX11Info::display(), &d->shminfo);
92 #endif
93  } else {
94  ;
95  }
96 
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 << ")"
101  << endl;
102 
103  fb = d->framebufferImage->data;
104 #ifdef HAVE_XDAMAGE
105  d->ev = new EvWidget(this);
106  kapp->installX11EventFilter(d->ev);
107 #endif
108 }
109 
110 
111 X11FrameBuffer::~X11FrameBuffer()
112 {
113  XDestroyImage(d->framebufferImage);
114 #ifdef HAVE_XDAMAGE
115  kapp->removeX11EventFilter(d->ev);
116 #endif
117 #ifdef HAVE_XSHM
118  XShmDetach(QX11Info::display(), &d->shminfo);
119  XDestroyImage(d->updateTile);
120  shmdt(d->shminfo.shmaddr);
121  shmctl(d->shminfo.shmid, IPC_RMID, 0);
122 #endif
123  delete d;
124  fb = 0; // already deleted by XDestroyImage
125 }
126 
127 
128 int X11FrameBuffer::depth()
129 {
130  return d->framebufferImage->depth;
131 }
132 
133 int X11FrameBuffer::height()
134 {
135  return d->framebufferImage->height;
136 }
137 
138 int X11FrameBuffer::width()
139 {
140  return d->framebufferImage->width;
141 }
142 
143 int X11FrameBuffer::paddedWidth()
144 {
145  return d->framebufferImage->bytes_per_line;
146 }
147 
148 void X11FrameBuffer::getServerFormat(rfbPixelFormat &format)
149 {
150  format.bitsPerPixel = d->framebufferImage->bits_per_pixel;
151  format.depth = d->framebufferImage->depth;
152  format.trueColour = true;
153  format.bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ? true : false);
154 
155  if (format.bitsPerPixel == 8) {
156  format.redShift = 0;
157  format.greenShift = 3;
158  format.blueShift = 6;
159  format.redMax = 7;
160  format.greenMax = 7;
161  format.blueMax = 3;
162  } else {
163  format.redShift = 0;
164 
165  if (d->framebufferImage->red_mask)
166  while (!(d->framebufferImage->red_mask & (1 << format.redShift))) {
167  format.redShift++;
168  }
169 
170  format.greenShift = 0;
171 
172  if (d->framebufferImage->green_mask)
173  while (!(d->framebufferImage->green_mask & (1 << format.greenShift))) {
174  format.greenShift++;
175  }
176 
177  format.blueShift = 0;
178 
179  if (d->framebufferImage->blue_mask)
180  while (!(d->framebufferImage->blue_mask & (1 << format.blueShift))) {
181  format.blueShift++;
182  }
183 
184  format.redMax = d->framebufferImage->red_mask >> format.redShift;
185  format.greenMax = d->framebufferImage->green_mask >> format.greenShift;
186  format.blueMax = d->framebufferImage->blue_mask >> format.blueShift;
187  }
188 }
189 
190 void X11FrameBuffer::handleXDamage(XEvent *event)
191 {
192 #ifdef HAVE_XDAMAGE
193  XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
194  QRect r(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
195  tiles.append(r);
196 
197  /*if (!dev->more) {
198  XDamageSubtract(QX11Info::display(),d->damage, None, None);
199  }*/
200 #endif
201 }
202 
203 
204 void X11FrameBuffer::cleanupRects()
205 {
206 
207  QList<QRect> cpy = tiles;
208  bool inserted = false;
209  tiles.clear();
210 // kDebug() << "before cleanup: " << cpy.size();
211  foreach(const QRect & r, cpy) {
212  if (tiles.size() > 0) {
213  for (int i = 0; i < tiles.size(); i++) {
214  // kDebug() << r << tiles[i];
215  if (r.intersects(tiles[i])) {
216  tiles[i] |= r;
217  inserted = true;
218  break;
219  // kDebug() << "merged into " << tiles[i];
220  }
221  }
222 
223  if (!inserted) {
224  tiles.append(r);
225  // kDebug() << "appended " << r;
226  }
227  } else {
228  // kDebug() << "appended " << r;
229  tiles.append(r);
230  }
231  }
232 
233  for (int i = 0; i < tiles.size(); i++) {
234  tiles[i].adjust(-30, -30, 30, 30);
235 
236  if (tiles[i].top() < 0) {
237  tiles[i].setTop(0);
238  }
239 
240  if (tiles[i].left() < 0) {
241  tiles[i].setLeft(0);
242  }
243 
244  if (tiles[i].bottom() > d->framebufferImage->height) {
245  tiles[i].setBottom(d->framebufferImage->height);
246  }
247 
248  if (tiles[i].right() > d->framebufferImage->width) {
249  tiles[i].setRight(d->framebufferImage->width);
250  }
251  }
252 
253 // kDebug() << "after cleanup: " << tiles.size();
254 }
255 
256 void X11FrameBuffer::acquireEvents()
257 {
258 
259  XEvent ev;
260 
261  while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
262  handleXDamage(&ev);
263  }
264 
265  XDamageSubtract(QX11Info::display(), d->damage, None, None);
266 }
267 
268 QList< QRect > X11FrameBuffer::modifiedTiles()
269 {
270  QList<QRect> ret;
271 
272  if (!d->running) {
273  return ret;
274  }
275 
276  kapp->processEvents(); // try to make sure every damage event goes trough;
277  cleanupRects();
278  QRect gl;
279 
280  //d->useShm = false;
281  if (tiles.size() > 0) {
282  if (d->useShm) {
283 #ifdef HAVE_XSHM
284 
285  foreach(const QRect & r, tiles) {
286 // kDebug() << r;
287  gl |= r;
288  int y = r.y();
289  int x = r.x();
290 
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;
295  }
296 
297  if (x + d->updateTile->width > d->framebufferImage->width) {
298  x = d->framebufferImage->width - d->updateTile->width;
299  }
300 
301 // kDebug() << "x: " << x << " (" << r.x() << ") y: " << y << " (" << r.y() << ") " << r;
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;
306 
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;
311  }
312 
313  y += d->updateTile->height;
314  }
315 
316  x += d->updateTile->width;
317  y = r.y();
318  }
319  }
320 #endif
321  } else {
322  foreach(const QRect & r, tiles) {
323  XGetSubImage(QX11Info::display(),
324  win,
325  r.left(),
326  r.top(),
327  r.width(),
328  r.height(),
329  AllPlanes,
330  ZPixmap,
331  d->framebufferImage,
332  r.left(),
333  r.top()
334  );
335  }
336  }
337  }
338 
339 // kDebug() << "tot: " << gl;
340 // kDebug() << tiles.size();
341  ret = tiles;
342  tiles.clear();
343  return ret;
344 }
345 
346 void X11FrameBuffer::startMonitor()
347 {
348  d->running = true;
349 #ifdef HAVE_XDAMAGE
350  d->damage = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
351  XDamageSubtract(QX11Info::display(), d->damage, None, None);
352 #endif
353 }
354 
355 void X11FrameBuffer::stopMonitor()
356 {
357  d->running = false;
358 #ifdef HAVE_XDAMAGE
359  XDamageDestroy(QX11Info::display(), d->damage);
360 #endif
361 }
362 
363 
364 
365 EvWidget::EvWidget(X11FrameBuffer *x11fb)
366  : QWidget(0), fb(x11fb)
367 {
368 #ifdef HAVE_XDAMAGE
369  int er;
370  XDamageQueryExtension(QX11Info::display(), &xdamageBaseEvent, &er);
371 #endif
372 }
373 
374 bool EvWidget::x11Event(XEvent *event)
375 {
376 #ifdef HAVE_XDAMAGE
377 
378  if (event->type == xdamageBaseEvent + XDamageNotify) {
379  fb->handleXDamage(event);
380  return true;
381  }
382 
383 #endif
384  return false;
385 }
386 
387 
388 
QList::clear
void clear()
QWidget
FrameBuffer
Definition: framebuffer.h:27
EvWidget::EvWidget
EvWidget(X11FrameBuffer *x11fb)
Definition: x11framebuffer.cpp:365
QRect::right
int right() const
X11FrameBuffer::depth
virtual int depth()
Definition: x11framebuffer.cpp:128
QX11Info::display
Display * display()
QRect::intersects
bool intersects(const QRect &rectangle) const
QRect::height
int height() const
QRect::x
int x() const
QRect::y
int y() const
x11framebuffer.h
X11FrameBuffer::width
virtual int width()
Definition: x11framebuffer.cpp:138
rfbPixelFormat
Definition: rfbproto.h:148
QList::size
int size() const
QRect
rfbPixelFormat::blueMax
uint16_t blueMax
Definition: rfbproto.h:173
QList::append
void append(const T &value)
X11FrameBuffer::getServerFormat
virtual void getServerFormat(rfbPixelFormat &format)
Definition: x11framebuffer.cpp:148
rfbPixelFormat::redMax
uint16_t redMax
Definition: rfbproto.h:167
rfbPixelFormat::greenMax
uint16_t greenMax
Definition: rfbproto.h:171
EvWidget
Definition: x11framebuffer.h:17
QRect::top
int top() const
QObject
X11FrameBuffer::startMonitor
virtual void startMonitor()
Definition: x11framebuffer.cpp:346
QRect::left
int left() const
rfbPixelFormat::trueColour
uint8_t trueColour
Definition: rfbproto.h:160
X11FrameBuffer
Definition: x11framebuffer.h:35
QList< QRect >
FrameBuffer::tiles
QList< QRect > tiles
Definition: framebuffer.h:50
rfbPixelFormat::bigEndian
uint8_t bigEndian
Definition: rfbproto.h:154
X11FrameBuffer::X11FrameBuffer
X11FrameBuffer(WId id, QObject *parent=0)
Definition: x11framebuffer.cpp:54
X11FrameBuffer::modifiedTiles
virtual QList< QRect > modifiedTiles()
Definition: x11framebuffer.cpp:268
X11FrameBuffer::height
virtual int height()
Definition: x11framebuffer.cpp:133
X11FrameBuffer::stopMonitor
virtual void stopMonitor()
Definition: x11framebuffer.cpp:355
X11FrameBuffer::handleXDamage
void handleXDamage(XEvent *event)
Definition: x11framebuffer.cpp:190
QRect::width
int width() const
QApplication::desktop
QDesktopWidget * desktop()
rfbPixelFormat::bitsPerPixel
uint8_t bitsPerPixel
Definition: rfbproto.h:150
FrameBuffer::win
WId win
Definition: framebuffer.h:48
X11FrameBuffer::paddedWidth
virtual int paddedWidth()
Definition: x11framebuffer.cpp:143
rfbPixelFormat::blueShift
uint8_t blueShift
Definition: rfbproto.h:189
X11FrameBuffer::~X11FrameBuffer
~X11FrameBuffer()
Definition: x11framebuffer.cpp:111
QRect::bottom
int bottom() const
FrameBuffer::fb
char * fb
Definition: framebuffer.h:49
rfbPixelFormat::depth
uint8_t depth
Definition: rfbproto.h:152
rfbPixelFormat::redShift
uint8_t redShift
Definition: rfbproto.h:175
rfbPixelFormat::greenShift
uint8_t greenShift
Definition: rfbproto.h:187
EvWidget::x11Event
bool x11Event(XEvent *event)
Definition: x11framebuffer.cpp:374
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:29:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

krfb

Skip menu "krfb"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal