mirror of
https://github.com/KDE/krfb
synced 2026-07-01 07:31:16 -07:00
Preliminary optional support for XDamage, checked both at compile and run time.
Uses less cpu than Qt approach, but visually sucks. I suspect there are too many updates sent to the client, I need to group the rects and create a bigger one when sending the event to the client. svn path=/trunk/KDE/kdenetwork/krfb/; revision=653073
This commit is contained in:
@@ -2,6 +2,7 @@ project(krfb)
|
||||
|
||||
|
||||
check_symbol_exists(rfbInitServer "rfb/rfb.h" HAVE_LIBVNCSERVER)
|
||||
macro_bool_to_01(X11_Xdamage_FOUND HAVE_XDAMAGE)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-krfb.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-krfb.h )
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}) # for config-krfb.h
|
||||
|
||||
@@ -23,6 +24,8 @@ set(krfb_SRCS
|
||||
connectioncontroller.cpp
|
||||
events.cpp
|
||||
framebuffer.cpp
|
||||
qtframebuffer.cpp
|
||||
x11framebuffer.cpp
|
||||
)
|
||||
|
||||
kde4_automoc(${krfb_SRCS})
|
||||
@@ -39,7 +42,7 @@ kde4_add_ui_files(krfb_SRCS connectionwidget.ui
|
||||
|
||||
kde4_add_executable(krfb ${krfb_SRCS})
|
||||
|
||||
target_link_libraries(krfb ${KDE4_KIO_LIBS} ${JPEG_LIBRARIES} ${SLP_LIBRARIES} ${LIBVNCSERVER_LIBRARIES})
|
||||
target_link_libraries(krfb ${KDE4_KIO_LIBS} ${JPEG_LIBRARIES} ${SLP_LIBRARIES} ${LIBVNCSERVER_LIBRARIES} ${X11_Xdamage_LIB})
|
||||
|
||||
install(TARGETS krfb DESTINATION ${BIN_INSTALL_DIR})
|
||||
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
|
||||
/* Define if SLP is available */
|
||||
#cmakedefine HAVE_SLP 1
|
||||
|
||||
/* Define if XDamage is available */
|
||||
#cmakedefine HAVE_XDAMAGE 1
|
||||
|
||||
@@ -78,9 +78,9 @@ enum rfbNewClientAction ConnectionController::handleNewClient()
|
||||
bool askOnConnect = KrfbConfig::askOnConnect();
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
|
||||
int socket = cl->sock;
|
||||
|
||||
#if 0
|
||||
int socket = cl->sock;
|
||||
// TODO: this drops the connection >.<
|
||||
QTcpSocket t;
|
||||
t.setSocketDescriptor(socket); //, QAbstractSocket::ConnectedState, QIODevice::NotOpen);
|
||||
|
||||
@@ -10,24 +10,25 @@
|
||||
#include "framebuffer.h"
|
||||
#include "framebuffer.moc"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QRegion>
|
||||
#include <QPixmap>
|
||||
#include <QBitmap>
|
||||
#include "config-krfb.h"
|
||||
|
||||
#include <QX11Info>
|
||||
|
||||
#include "qtframebuffer.h"
|
||||
#include "x11framebuffer.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
const int UPDATE_TIME = 500;
|
||||
|
||||
FrameBuffer::FrameBuffer(WId id, QObject *parent)
|
||||
: QObject(parent), win(id)
|
||||
{
|
||||
//TODO: implement reference counting to avoid update the screen
|
||||
// while no client is connected.
|
||||
|
||||
fbImage = QPixmap::grabWindow(win).toImage();
|
||||
fb = new char[fbImage.numBytes()];
|
||||
QTimer *t = new QTimer(this);
|
||||
connect(t, SIGNAL(timeout()), SLOT(updateFrameBuffer()));
|
||||
t->start(UPDATE_TIME);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,41 +42,6 @@ char * FrameBuffer::data()
|
||||
return fb;
|
||||
}
|
||||
|
||||
void FrameBuffer::updateFrameBuffer()
|
||||
{
|
||||
QImage img = QPixmap::grabWindow(win).toImage();
|
||||
QSize imgSize = img.size();
|
||||
|
||||
|
||||
// verify what part of the image need to be marked as changed
|
||||
// fbImage is the previous version of the image,
|
||||
// img is the current one
|
||||
|
||||
#if 0 // This is actually slower than updating the whole desktop...
|
||||
|
||||
QImage map(imgSize, QImage::Format_Mono);
|
||||
map.fill(0);
|
||||
|
||||
for (int x = 0; x < imgSize.width(); x++) {
|
||||
for (int y = 0; y < imgSize.height(); y++) {
|
||||
if (img.pixel(x,y) != fbImage.pixel(x,y)) {
|
||||
map.setPixel(x,y,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRegion r(QBitmap::fromImage(map));
|
||||
tiles = tiles + r.rects();
|
||||
|
||||
#else
|
||||
tiles.append(img.rect());
|
||||
#endif
|
||||
|
||||
memcpy(fb, (const char*)img.bits(), img.numBytes());
|
||||
fbImage = img;
|
||||
|
||||
}
|
||||
|
||||
QVector< QRect > & FrameBuffer::modifiedTiles()
|
||||
{
|
||||
return tiles;
|
||||
@@ -83,32 +49,37 @@ QVector< QRect > & FrameBuffer::modifiedTiles()
|
||||
|
||||
int FrameBuffer::width()
|
||||
{
|
||||
return fbImage.width();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FrameBuffer::height()
|
||||
{
|
||||
return fbImage.height();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FrameBuffer::getServerFormat(rfbPixelFormat & format)
|
||||
void FrameBuffer::getServerFormat(rfbPixelFormat &)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
format.trueColour = true;
|
||||
|
||||
format.bigEndian = false;
|
||||
format.redShift = 16;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 0;
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
}
|
||||
|
||||
int FrameBuffer::depth()
|
||||
{
|
||||
return fbImage.depth();
|
||||
return 32;
|
||||
}
|
||||
|
||||
FrameBuffer * FrameBuffer::getFrameBuffer(WId id, QObject * parent)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
int tmp, er;
|
||||
if (XDamageQueryExtension(QX11Info::display(), &tmp, &er)) {
|
||||
return new X11FrameBuffer(id, parent);
|
||||
}
|
||||
#endif
|
||||
return new QtFrameBuffer(id, parent);
|
||||
}
|
||||
|
||||
int FrameBuffer::paddedWidth()
|
||||
{
|
||||
return width() * depth() / 8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QImage>
|
||||
#include <QRect>
|
||||
#include <QVector>
|
||||
#include <QWidget>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class FrameBuffer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
@@ -24,26 +25,26 @@ class FrameBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~FrameBuffer();
|
||||
static FrameBuffer* getFrameBuffer(WId id, QObject *parent);
|
||||
|
||||
virtual ~FrameBuffer();
|
||||
|
||||
char * data();
|
||||
|
||||
QVector<QRect> &modifiedTiles();
|
||||
int width();
|
||||
int height();
|
||||
int depth();
|
||||
virtual int paddedWidth();
|
||||
virtual int width();
|
||||
virtual int height();
|
||||
virtual int depth();
|
||||
|
||||
void getServerFormat(rfbPixelFormat &format);
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateFrameBuffer();
|
||||
protected:
|
||||
explicit FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
private:
|
||||
WId win;
|
||||
char *fb;
|
||||
QImage fbImage;
|
||||
QVector<QRect> tiles;
|
||||
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "krfbserver.h"
|
||||
#include "krfbserver.moc"
|
||||
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
@@ -32,6 +31,9 @@
|
||||
#include "krfbconfig.h"
|
||||
#include "invitationmanager.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
static const char* cur=
|
||||
" "
|
||||
@@ -119,6 +121,7 @@ class KrfbServer::KrfbServerP {
|
||||
FrameBuffer *fb;
|
||||
QList< QPointer<ConnectionController> > controllers;
|
||||
rfbScreenInfoPtr screen;
|
||||
bool running;
|
||||
};
|
||||
|
||||
|
||||
@@ -134,7 +137,8 @@ KrfbServer::KrfbServer()
|
||||
:d(new KrfbServerP)
|
||||
{
|
||||
kDebug() << "starting " << endl;
|
||||
d->fb = new FrameBuffer(QApplication::desktop()->winId(), this);
|
||||
d->running = true;
|
||||
d->fb = FrameBuffer::getFrameBuffer(QApplication::desktop()->winId(), this);
|
||||
QTimer::singleShot(0, this, SLOT(startListening()));
|
||||
connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),SLOT(updatePassword()));
|
||||
|
||||
@@ -158,7 +162,7 @@ void KrfbServer::startListening()
|
||||
|
||||
rfbLogEnable(0);
|
||||
screen = rfbGetScreen(0, 0, w, h, 8, 3,depth / 8);
|
||||
screen->paddedWidthInBytes = w * 4;
|
||||
screen->paddedWidthInBytes = d->fb->paddedWidth();
|
||||
|
||||
d->fb->getServerFormat(screen->serverFormat);
|
||||
|
||||
@@ -192,7 +196,7 @@ void KrfbServer::startListening()
|
||||
disconnectAndQuit();
|
||||
};
|
||||
|
||||
while (true) {
|
||||
while (d->running) {
|
||||
foreach(QRect r, d->fb->modifiedTiles()) {
|
||||
rfbMarkRectAsModified(screen, r.top(), r.left(), r.left() + r.width(), r.top() + r.height());
|
||||
}
|
||||
@@ -200,6 +204,7 @@ void KrfbServer::startListening()
|
||||
rfbProcessEvents(screen, 100);
|
||||
qApp->processEvents();
|
||||
}
|
||||
rfbShutdownServer(screen, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +219,7 @@ void KrfbServer::enableDesktopControl(bool enable)
|
||||
|
||||
void KrfbServer::disconnectAndQuit()
|
||||
{
|
||||
// TODO: cleanup of existing connections
|
||||
d->running = false;
|
||||
emit quitApp();
|
||||
}
|
||||
|
||||
@@ -254,6 +259,19 @@ void KrfbServer::updatePassword()
|
||||
}
|
||||
}
|
||||
|
||||
bool KrfbServer::checkX11Capabilities() {
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
if ((!r) || (((majorv*1000)+minorv) < 2002)) {
|
||||
KMessageBox::error(0,
|
||||
i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
|
||||
i18n("Desktop Sharing Error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
~KrfbServer();
|
||||
|
||||
enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl);
|
||||
bool checkX11Capabilities();
|
||||
|
||||
signals:
|
||||
void sessionEstablished(QString);
|
||||
|
||||
11
main.cpp
11
main.cpp
@@ -40,6 +40,7 @@
|
||||
static const char description[] = I18N_NOOP("VNC-compatible server to share "
|
||||
"KDE desktops");
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
KAboutData aboutData( "krfb", I18N_NOOP("Desktop Sharing"),
|
||||
@@ -78,6 +79,9 @@ int main(int argc, char *argv[])
|
||||
TrayIcon trayicon(new ManageInvitationsDialog);
|
||||
|
||||
KrfbServer *server = KrfbServer::self(); // initialize the server manager
|
||||
if (!server->checkX11Capabilities()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
QObject::connect(&app, SIGNAL(lastWindowClosed()), // do not show passivepopup
|
||||
&trayicon, SLOT(prepareQuit()));
|
||||
@@ -97,13 +101,6 @@ int main(int argc, char *argv[])
|
||||
QObject::connect(server, SIGNAL(quitApp()),
|
||||
&app, SLOT(quit()));
|
||||
|
||||
//TODO: implement some error reporting mechanism between server and tray icon
|
||||
/*
|
||||
QObject::connect(&trayicon, SIGNAL(diconnectedMessageDisplayed()),
|
||||
&app, SLOT(quit()));
|
||||
QObject::connect(&server, SIGNAL(sessionRefused()),
|
||||
&app, SLOT(quit()));
|
||||
*/
|
||||
sigset_t sigs;
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGPIPE);
|
||||
|
||||
105
qtframebuffer.cpp
Normal file
105
qtframebuffer.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#include "qtframebuffer.h"
|
||||
#include "qtframebuffer.moc"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QRegion>
|
||||
#include <QPixmap>
|
||||
#include <QBitmap>
|
||||
|
||||
|
||||
const int UPDATE_TIME = 500;
|
||||
|
||||
QtFrameBuffer::QtFrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent)
|
||||
{
|
||||
fbImage = QPixmap::grabWindow(win).toImage();
|
||||
fb = new char[fbImage.numBytes()];
|
||||
QTimer *t = new QTimer(this);
|
||||
connect(t, SIGNAL(timeout()), SLOT(updateFrameBuffer()));
|
||||
t->start(UPDATE_TIME);
|
||||
}
|
||||
|
||||
|
||||
QtFrameBuffer::~QtFrameBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
int QtFrameBuffer::depth()
|
||||
{
|
||||
return fbImage.depth();
|
||||
}
|
||||
|
||||
int QtFrameBuffer::height()
|
||||
{
|
||||
return fbImage.height();
|
||||
}
|
||||
|
||||
int QtFrameBuffer::width()
|
||||
{
|
||||
return fbImage.width();
|
||||
}
|
||||
|
||||
void QtFrameBuffer::getServerFormat(rfbPixelFormat& format)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
format.trueColour = true;
|
||||
|
||||
format.bigEndian = false;
|
||||
format.redShift = 16;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 0;
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
}
|
||||
|
||||
void QtFrameBuffer::updateFrameBuffer()
|
||||
{
|
||||
QImage img = QPixmap::grabWindow(win).toImage();
|
||||
QSize imgSize = img.size();
|
||||
|
||||
|
||||
// verify what part of the image need to be marked as changed
|
||||
// fbImage is the previous version of the image,
|
||||
// img is the current one
|
||||
|
||||
#if 0 // This is actually slower than updating the whole desktop...
|
||||
|
||||
QImage map(imgSize, QImage::Format_Mono);
|
||||
map.fill(0);
|
||||
|
||||
for (int x = 0; x < imgSize.width(); x++) {
|
||||
for (int y = 0; y < imgSize.height(); y++) {
|
||||
if (img.pixel(x,y) != fbImage.pixel(x,y)) {
|
||||
map.setPixel(x,y,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRegion r(QBitmap::fromImage(map));
|
||||
tiles = tiles + r.rects();
|
||||
|
||||
#else
|
||||
tiles.append(img.rect());
|
||||
#endif
|
||||
|
||||
memcpy(fb, (const char*)img.bits(), img.numBytes());
|
||||
fbImage = img;
|
||||
|
||||
}
|
||||
|
||||
int QtFrameBuffer::paddedWidth()
|
||||
{
|
||||
return fbImage.width() * 4;
|
||||
}
|
||||
|
||||
41
qtframebuffer.h
Normal file
41
qtframebuffer.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#ifndef QTFRAMEBUFFER_H
|
||||
#define QTFRAMEBUFFER_H
|
||||
|
||||
#include <QImage>
|
||||
#include "framebuffer.h"
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class QtFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QtFrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~QtFrameBuffer();
|
||||
|
||||
virtual int depth();
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat& format);
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateFrameBuffer();
|
||||
|
||||
private:
|
||||
QImage fbImage;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -72,7 +72,7 @@ void TrayIcon::prepareQuit() {
|
||||
quitting = true;
|
||||
}
|
||||
|
||||
void TrayIcon::showConnectedMessage(QString host) {
|
||||
void TrayIcon::showConnectedMessage(const QString &host) {
|
||||
|
||||
setIcon(KIcon("eyes-open24"));
|
||||
KPassivePopup::message(i18n("Desktop Sharing"),
|
||||
|
||||
@@ -44,7 +44,7 @@ signals:
|
||||
|
||||
public Q_SLOTS:
|
||||
void prepareQuit();
|
||||
void showConnectedMessage(QString host);
|
||||
void showConnectedMessage(const QString &host);
|
||||
void showDisconnectedMessage();
|
||||
void setDesktopControlSetting(bool);
|
||||
void showManageInvitations();
|
||||
|
||||
175
x11framebuffer.cpp
Normal file
175
x11framebuffer.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#include "x11framebuffer.h"
|
||||
#include "x11framebuffer.moc"
|
||||
#include "config-krfb.h"
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include <KApplication>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
class X11FrameBuffer::P {
|
||||
|
||||
public:
|
||||
#ifdef HAVE_XDAMAGE
|
||||
Damage damage;
|
||||
#endif
|
||||
XImage *framebufferImage;
|
||||
EvWidget *ev;
|
||||
};
|
||||
|
||||
X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
|
||||
:FrameBuffer(id, parent), d(new X11FrameBuffer::P)
|
||||
{
|
||||
d->framebufferImage = XGetImage(QX11Info::display(),
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(), //arg, must get a widget ???
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
kDebug() << "Got image. bpp: " << d->framebufferImage->bits_per_pixel
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->bytes_per_line
|
||||
<< " (sent: " << d->framebufferImage->width * 4 << ")"
|
||||
<< endl;
|
||||
|
||||
fb = d->framebufferImage->data;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
d->ev = new EvWidget(this);
|
||||
d->damage = XDamageCreate(QX11Info::display(), id, XDamageReportRawRectangles);
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
kapp->installX11EventFilter(d->ev);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
X11FrameBuffer::~X11FrameBuffer()
|
||||
{
|
||||
XDestroyImage(d->framebufferImage);
|
||||
#ifdef HAVE_XDAMAGE
|
||||
kapp->removeX11EventFilter(d->ev);
|
||||
XDamageDestroy(QX11Info::display(),d->damage);
|
||||
#endif
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
int X11FrameBuffer::depth()
|
||||
{
|
||||
return d->framebufferImage->depth;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::height()
|
||||
{
|
||||
return d->framebufferImage->height;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::width()
|
||||
{
|
||||
return d->framebufferImage->width;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::paddedWidth()
|
||||
{
|
||||
return d->framebufferImage->bytes_per_line;
|
||||
}
|
||||
|
||||
void X11FrameBuffer::getServerFormat(rfbPixelFormat& format)
|
||||
{
|
||||
format.bitsPerPixel = d->framebufferImage->bits_per_pixel;
|
||||
format.depth = d->framebufferImage->depth;
|
||||
format.trueColour = true;
|
||||
format.bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ? true : false);
|
||||
|
||||
if ( format.bitsPerPixel == 8 ) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 3;
|
||||
format.blueShift = 6;
|
||||
format.redMax = 7;
|
||||
format.greenMax = 7;
|
||||
format.blueMax = 3;
|
||||
} else {
|
||||
format.redShift = 0;
|
||||
if ( d->framebufferImage->red_mask )
|
||||
while ( ! ( d->framebufferImage->red_mask & (1 << format.redShift) ) )
|
||||
format.redShift++;
|
||||
format.greenShift = 0;
|
||||
if ( d->framebufferImage->green_mask )
|
||||
while ( ! ( d->framebufferImage->green_mask & (1 << format.greenShift) ) )
|
||||
format.greenShift++;
|
||||
format.blueShift = 0;
|
||||
if ( d->framebufferImage->blue_mask )
|
||||
while ( ! ( d->framebufferImage->blue_mask & (1 << format.blueShift) ) )
|
||||
format.blueShift++;
|
||||
format.redMax = d->framebufferImage->red_mask >> format.redShift;
|
||||
format.greenMax = d->framebufferImage->green_mask >> format.greenShift;
|
||||
format.blueMax = d->framebufferImage->blue_mask >> format.blueShift;
|
||||
}
|
||||
}
|
||||
|
||||
void X11FrameBuffer::handleXDamage(XEvent * event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
|
||||
QRect r(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
|
||||
tiles.append(r);
|
||||
|
||||
XGetSubImage(QX11Info::display(),
|
||||
win,
|
||||
dev->area.x,
|
||||
dev->area.y,
|
||||
dev->area.width,
|
||||
dev->area.height,
|
||||
AllPlanes,
|
||||
ZPixmap,
|
||||
d->framebufferImage,
|
||||
dev->area.x,
|
||||
dev->area.y);
|
||||
|
||||
if (!dev->more) {
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
EvWidget::EvWidget(X11FrameBuffer * x11fb)
|
||||
:QWidget(0), fb(x11fb)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
int er;
|
||||
XDamageQueryExtension(QX11Info::display(), &xdamageBaseEvent, &er);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EvWidget::x11Event(XEvent * event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
if (event->type == xdamageBaseEvent+XDamageNotify) {
|
||||
fb->handleXDamage(event);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
54
x11framebuffer.h
Normal file
54
x11framebuffer.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; version 2
|
||||
of the License.
|
||||
*/
|
||||
#ifndef X11FRAMEBUFFER_H
|
||||
#define X11FRAMEBUFFER_H
|
||||
|
||||
#include <framebuffer.h>
|
||||
#include <QWidget>
|
||||
|
||||
class X11FrameBuffer;
|
||||
|
||||
class EvWidget: public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EvWidget(X11FrameBuffer *x11fb);
|
||||
|
||||
protected:
|
||||
bool x11Event ( XEvent * event );
|
||||
|
||||
private:
|
||||
X11FrameBuffer *fb;
|
||||
int xdamageBaseEvent;
|
||||
};
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class X11FrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
X11FrameBuffer(WId id, QObject* parent);
|
||||
|
||||
~X11FrameBuffer();
|
||||
|
||||
virtual int depth();
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat& format);
|
||||
|
||||
void handleXDamage( XEvent *event);
|
||||
private:
|
||||
class P;
|
||||
P * const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user