mirror of
https://github.com/KDE/krfb
synced 2026-07-01 07:31:16 -07:00
almost working
svn path=/trunk/kdenetwork/krfb/; revision=135195
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = lib krfb po doc include
|
||||
SUBDIRS = libvncserver krfb po doc
|
||||
|
||||
EXTRA_DIST = admin AUTHORS COPYING ChangeLog INSTALL README TODO NOTES \
|
||||
README_KDE3 krfb.lsm
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
For KDE 3.0, you need to do the following:
|
||||
|
||||
* the .ui files must be recompiled, you can enforce this by touching them:
|
||||
touch krfb/*.ui
|
||||
|
||||
* main.cpp and trayicon.cpp include the file kapp.h. It has been renamed to
|
||||
kapplication.h, so you must change the sources accordingly.
|
||||
|
||||
3.0 support has been removed for this release, but will re-appear soon.
|
||||
26
ROADMAP
Normal file
26
ROADMAP
Normal file
@@ -0,0 +1,26 @@
|
||||
Version 0.5 (2002/01/02): First release
|
||||
- first release
|
||||
- port x0rfbserver wiith simplified KDE/Qt interface
|
||||
|
||||
|
||||
Version 0.6 (2002/02/??): Improve RFB backend
|
||||
- improve RFB backend
|
||||
- replace x0rfbserver's encoders with those from TightVNCs WinVNC
|
||||
<- port ZLib and Tight encodings from TightVNCs WinVNC
|
||||
<- clip framebuffer updates to requested region
|
||||
<- rewrite Connection to use linked buffers
|
||||
<- knotify
|
||||
<- UI for multiple users (if libvncserver is chosen)
|
||||
|
||||
Version 0.7 (2002/??/??): Better integration with KDE, more end-user friendly
|
||||
- i18n
|
||||
- kded module or some other way to have a small module listening on the Rfb
|
||||
port (like inetd) that then starts KRfb
|
||||
- kcontrol module to configure the kded thing
|
||||
- on startup a dialog appears that allows the user to invite somebody
|
||||
else using email (and later other mechanisms). Dialog can be turned
|
||||
off, of course
|
||||
|
||||
Version 0.8 (2002/??/??):
|
||||
- docs
|
||||
|
||||
@@ -4,9 +4,15 @@ AM_INIT_AUTOMAKE(krfb,0.6)
|
||||
|
||||
AC_CHECK_HEADER(X11/extensions/XTest.h,
|
||||
[],
|
||||
AC_MSG_ERROR([XTest extension header not found]))
|
||||
AC_MSG_ERROR([XTest extension header not found / no xlib headers]))
|
||||
|
||||
AC_CHECK_HEADER(zlib.h,
|
||||
[],
|
||||
AC_MSG_ERROR([ZLib header not found]))
|
||||
|
||||
AC_CHECK_HEADER(jpeglib.h,
|
||||
[],
|
||||
AC_MSG_ERROR([libjpeg header not found]))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
METASOURCES = AUTO
|
||||
|
||||
bin_PROGRAMS = krfb
|
||||
krfb_SOURCES = rfbcontroller.cc configuration.cc trayicon.cpp XUpdateScanner.cc rfbconnection.cc main.cpp configurationdialog.ui newconnectiondialog.ui
|
||||
krfb_LDADD = ../lib/librfbserver.a -lz $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIBSOCKET)
|
||||
krfb_SOURCES = rfbcontroller.cc configuration.cc trayicon.cpp XUpdateScanner.cc main.cpp configurationdialog.ui newconnectiondialog.ui
|
||||
krfb_LDADD = ../libvncserver/libvncserver.a -lz -lpthread -ljpeg -lXtst $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIBSOCKET)
|
||||
|
||||
EXTRA_DIST = $(krfb_SOURCES) krfb.desktop lo32-app-krfb.png lo16-app-krfb.png rfbcontroller.h rfbconnection.h eyes-closed24.png eyes-open24.png XUpdateScanner.h trayicon.h configuration.h
|
||||
EXTRA_DIST = $(krfb_SOURCES) krfb.desktop lo32-app-krfb.png lo16-app-krfb.png rfbcontroller.h eyes-closed24.png eyes-open24.png XUpdateScanner.h trayicon.h configuration.h
|
||||
|
||||
install-data-local:
|
||||
$(mkinstalldirs) $(kde_appsdir)/Applications/
|
||||
@@ -35,10 +35,12 @@ KDE_ICON = krfb
|
||||
# kde_wallpaperdir Where general wallpapers should go to.
|
||||
|
||||
# set the include path for X, qt and KDE
|
||||
INCLUDES= $(all_includes) -I../include
|
||||
INCLUDES= $(all_includes) -I../libvncserver
|
||||
|
||||
# the library search path.
|
||||
krfb_LDFLAGS = $(all_libraries) $(KDE_RPATH) -lXtst
|
||||
krfb_LDFLAGS = $(all_libraries) $(KDE_RPATH)
|
||||
|
||||
CXXFLAGS = @CXXFLAGS@ -DQT_THREAD_SUPPORT
|
||||
|
||||
# Uncomment the following two lines if you add a ui.rc file for your application to make use of
|
||||
# KDE´s XML GUI builing
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
|
||||
#include "XUpdateScanner.h"
|
||||
|
||||
namespace rfb {
|
||||
|
||||
unsigned int scanlines[32] = { 0, 16, 8, 24,
|
||||
4, 20, 12, 28,
|
||||
10, 26, 18, 2,
|
||||
@@ -44,25 +42,29 @@ unsigned int scanlines[32] = { 0, 16, 8, 24,
|
||||
|
||||
XUpdateScanner::XUpdateScanner(Display *_dpy,
|
||||
Window _window,
|
||||
Framebuffer *_fb,
|
||||
unsigned char *_fb,
|
||||
int _width,
|
||||
int _height,
|
||||
int _bitsPerPixel,
|
||||
int _bytesPerLine,
|
||||
unsigned int _tileWidth,
|
||||
unsigned int _tileHeight,
|
||||
unsigned int _blockWidth,
|
||||
unsigned int _blockHeight) :
|
||||
unsigned int _tileHeight) :
|
||||
dpy(_dpy),
|
||||
window(_window),
|
||||
fb(_fb),
|
||||
width(_width),
|
||||
height(_height),
|
||||
bitsPerPixel(_bitsPerPixel),
|
||||
bytesPerLine(_bytesPerLine),
|
||||
tileWidth(_tileWidth),
|
||||
tileHeight(_tileHeight),
|
||||
blockWidth(_blockWidth),
|
||||
blockHeight(_blockHeight),
|
||||
count (0),
|
||||
scanline(NULL),
|
||||
tile(NULL)
|
||||
{
|
||||
tile = XShmCreateImage(dpy,
|
||||
DefaultVisual( dpy, 0 ),
|
||||
fb->pixelFormat.bits_per_pixel,
|
||||
bitsPerPixel,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&shminfo_tile,
|
||||
@@ -78,8 +80,8 @@ XUpdateScanner::XUpdateScanner(Display *_dpy,
|
||||
|
||||
XShmAttach(dpy, &shminfo_tile);
|
||||
|
||||
tilesX = (fb->width + tileWidth - 1) / tileWidth;
|
||||
tilesY = (fb->height + tileHeight - 1) / tileHeight;
|
||||
tilesX = (width + tileWidth - 1) / tileWidth;
|
||||
tilesY = (height + tileHeight - 1) / tileHeight;
|
||||
tileMap = new bool[tilesX * tilesY];
|
||||
|
||||
unsigned int i;
|
||||
@@ -88,11 +90,11 @@ XUpdateScanner::XUpdateScanner(Display *_dpy,
|
||||
|
||||
scanline = XShmCreateImage(dpy,
|
||||
DefaultVisual(dpy, 0),
|
||||
fb->pixelFormat.bits_per_pixel,
|
||||
bitsPerPixel,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&shminfo_scanline,
|
||||
fb->width,
|
||||
width,
|
||||
1);
|
||||
|
||||
shminfo_scanline.shmid = shmget(IPC_PRIVATE,
|
||||
@@ -122,8 +124,8 @@ XUpdateScanner::~XUpdateScanner()
|
||||
|
||||
void XUpdateScanner::copyTile(int x, int y)
|
||||
{
|
||||
unsigned int maxWidth = fb->width - x;
|
||||
unsigned int maxHeight = fb->height - y;
|
||||
unsigned int maxWidth = width - x;
|
||||
unsigned int maxHeight = height - y;
|
||||
if (maxWidth > tileWidth)
|
||||
maxWidth = tileWidth;
|
||||
if (maxHeight > tileHeight)
|
||||
@@ -136,13 +138,13 @@ void XUpdateScanner::copyTile(int x, int y)
|
||||
AllPlanes, ZPixmap, tile, 0, 0);
|
||||
}
|
||||
unsigned int line;
|
||||
int pixelsize = fb->pixelFormat.bits_per_pixel >> 3;
|
||||
int pixelsize = bitsPerPixel >> 3;
|
||||
unsigned char *src = (unsigned char*) tile->data;
|
||||
unsigned char *dest = fb->data + y * fb->bytesPerLine + x * pixelsize;
|
||||
unsigned char *dest = fb + y * bytesPerLine + x * pixelsize;
|
||||
for (line = 0; line < maxHeight; line++) {
|
||||
memcpy(dest, src, maxWidth * pixelsize );
|
||||
src += tile->bytes_per_line;
|
||||
dest += fb->bytesPerLine;
|
||||
dest += bytesPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,60 +161,51 @@ void XUpdateScanner::copyAllTiles()
|
||||
|
||||
}
|
||||
|
||||
void XUpdateScanner::initHint(Hint &hint)
|
||||
{
|
||||
hint.type = hintRefresh;
|
||||
hint.hint.refresh.x = 0;
|
||||
hint.hint.refresh.y = 0;
|
||||
hint.hint.refresh.width = 0;
|
||||
hint.hint.refresh.height = 0;
|
||||
}
|
||||
|
||||
void XUpdateScanner::createHintFromTile(int x, int y, Hint &hint)
|
||||
{
|
||||
unsigned int w = fb->width - x;
|
||||
unsigned int h = fb->height - y;
|
||||
unsigned int w = width - x;
|
||||
unsigned int h = height - y;
|
||||
if (w > tileWidth)
|
||||
w = tileWidth;
|
||||
if (h > tileHeight)
|
||||
h = tileHeight;
|
||||
|
||||
hint.hint.refresh.x = x;
|
||||
hint.hint.refresh.y = y;
|
||||
hint.hint.refresh.width = w;
|
||||
hint.hint.refresh.height = h;
|
||||
hint.x = x;
|
||||
hint.y = y;
|
||||
hint.w = w;
|
||||
hint.h = h;
|
||||
}
|
||||
|
||||
void XUpdateScanner::addTileToHint(int x, int y, Hint &hint)
|
||||
{
|
||||
unsigned int w = fb->width - x;
|
||||
unsigned int h = fb->height - y;
|
||||
unsigned int w = width - x;
|
||||
unsigned int h = height - y;
|
||||
if (w > tileWidth)
|
||||
w = tileWidth;
|
||||
if (h > tileHeight)
|
||||
h = tileHeight;
|
||||
|
||||
if (hint.hint.refresh.x > x) {
|
||||
hint.hint.refresh.width += hint.hint.refresh.x - x;
|
||||
hint.hint.refresh.x = x;
|
||||
if (hint.x > x) {
|
||||
hint.w += hint.x - x;
|
||||
hint.x = x;
|
||||
}
|
||||
|
||||
if (hint.hint.refresh.y > y) {
|
||||
hint.hint.refresh.height += hint.hint.refresh.y - y;
|
||||
hint.hint.refresh.y = y;
|
||||
if (hint.y > y) {
|
||||
hint.h += hint.y - y;
|
||||
hint.y = y;
|
||||
}
|
||||
|
||||
if ((hint.hint.refresh.x+hint.hint.refresh.width) < (x+w)) {
|
||||
hint.hint.refresh.width = (x+w) - hint.hint.refresh.x;
|
||||
if ((hint.x+hint.w) < (x+w)) {
|
||||
hint.w = (x+w) - hint.x;
|
||||
}
|
||||
|
||||
if ((hint.hint.refresh.y+hint.hint.refresh.height) < (y+h)) {
|
||||
hint.hint.refresh.height = (y+h) - hint.hint.refresh.y;
|
||||
if ((hint.y+hint.h) < (y+h)) {
|
||||
hint.h = (y+h) - hint.y;
|
||||
}
|
||||
}
|
||||
|
||||
void XUpdateScanner::flushHint(int x, int y, int &x0,
|
||||
Hint &hint, list<Hint> &hintList)
|
||||
Hint &hint, QList<Hint> &hintList)
|
||||
{
|
||||
if (x0 < 0)
|
||||
return;
|
||||
@@ -234,20 +227,18 @@ void XUpdateScanner::flushHint(int x, int y, int &x0,
|
||||
h++;
|
||||
}
|
||||
|
||||
hint.hint.refresh.height = h * tileHeight;
|
||||
if ((hint.hint.refresh.y + hint.hint.refresh.height) > fb->height)
|
||||
hint.hint.refresh.height = fb->height - hint.hint.refresh.y;
|
||||
hint.h = h * tileHeight;
|
||||
if ((hint.y + hint.h) > height)
|
||||
h = height - hint.y;
|
||||
|
||||
x0 = -1;
|
||||
|
||||
hintList.push_back(hint);
|
||||
initHint(hint);
|
||||
hintList.append(new Hint(hint));
|
||||
}
|
||||
|
||||
void XUpdateScanner::createHints(list<Hint> &hintList)
|
||||
void XUpdateScanner::createHints(QList<Hint> &hintList)
|
||||
{
|
||||
Hint hint;
|
||||
initHint(hint);
|
||||
int x0 = -1;
|
||||
|
||||
for (int y = 0; y < tilesY; y++) {
|
||||
@@ -272,7 +263,7 @@ void XUpdateScanner::createHints(list<Hint> &hintList)
|
||||
}
|
||||
}
|
||||
|
||||
void XUpdateScanner::searchUpdates(list<Hint> &hintList)
|
||||
void XUpdateScanner::searchUpdates(QList<Hint> &hintList)
|
||||
{
|
||||
count++;
|
||||
count %= 32;
|
||||
@@ -285,16 +276,16 @@ void XUpdateScanner::searchUpdates(list<Hint> &hintList)
|
||||
}
|
||||
|
||||
y = scanlines[count];
|
||||
while (y < fb->height) {
|
||||
while (y < height) {
|
||||
XShmGetImage(dpy, window, scanline, 0, y, AllPlanes);
|
||||
x = 0;
|
||||
while (x < fb->width) {
|
||||
int pixelsize = fb->pixelFormat.bits_per_pixel >> 3;
|
||||
while (x < width) {
|
||||
int pixelsize = bitsPerPixel >> 3;
|
||||
unsigned char *src = (unsigned char*) scanline->data +
|
||||
x * pixelsize;
|
||||
unsigned char *dest = fb->data +
|
||||
y * fb->bytesPerLine + x * pixelsize;
|
||||
int w = (x + 32) > fb->width ? (fb->width-x) : 32;
|
||||
unsigned char *dest = fb +
|
||||
y * bytesPerLine + x * pixelsize;
|
||||
int w = (x + 32) > width ? (width-x) : 32;
|
||||
if (memcmp(dest, src, w * pixelsize))
|
||||
tileMap[(x / tileWidth) +
|
||||
(y / tileHeight) * tilesX] = true;
|
||||
@@ -308,6 +299,5 @@ void XUpdateScanner::searchUpdates(list<Hint> &hintList)
|
||||
createHints(hintList);
|
||||
}
|
||||
|
||||
} // namespace rfb
|
||||
|
||||
|
||||
|
||||
@@ -21,41 +21,69 @@
|
||||
#ifndef _hexonet_rfb_XUpdateScanner_h_
|
||||
#define _hexonet_rfb_XUpdateScanner_h_
|
||||
|
||||
|
||||
#include "../include/rfbServer.h"
|
||||
|
||||
#include <qlist.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
|
||||
namespace rfb {
|
||||
class Hint {
|
||||
public:
|
||||
int x, y, w, h;
|
||||
|
||||
Hint() :
|
||||
x(0),
|
||||
y(0),
|
||||
w(0),
|
||||
h(0)
|
||||
{}
|
||||
Hint(Hint &h) :
|
||||
x(h.x),
|
||||
y(h.y),
|
||||
w(h.w),
|
||||
h(h.h)
|
||||
{
|
||||
}
|
||||
int left() {
|
||||
return x;
|
||||
}
|
||||
int right() {
|
||||
return x+w;
|
||||
}
|
||||
int top() {
|
||||
return y;
|
||||
}
|
||||
int bottom() {
|
||||
return y+h;
|
||||
}
|
||||
};
|
||||
|
||||
class XUpdateScanner
|
||||
{
|
||||
public:
|
||||
XUpdateScanner( Display *_dpy,
|
||||
Window _window,
|
||||
Framebuffer *_fb,
|
||||
unsigned char *_fb,
|
||||
int _width, int _height,
|
||||
int _bitsPerPixel, int _bytesPerLine,
|
||||
unsigned int _tileWidth = 32,
|
||||
unsigned int _tileHeight = 32,
|
||||
unsigned int _blockWidth = 9,
|
||||
unsigned int _blockHeight = 9);
|
||||
unsigned int _tileHeight = 32);
|
||||
|
||||
~XUpdateScanner();
|
||||
|
||||
void copyTile( int x, int y);
|
||||
void copyAllTiles();
|
||||
void searchUpdates( list< Hint > &hintList);
|
||||
void initHint(Hint &hint);
|
||||
void flushHint(int x, int y, int &x0, Hint &hint, list<Hint> &hintList);
|
||||
void createHints(list<Hint> &hintList);
|
||||
void searchUpdates( QList<Hint> &hintList);
|
||||
void flushHint(int x, int y, int &x0, Hint &hint, QList<Hint> &hintList);
|
||||
void createHints(QList<Hint> &hintList);
|
||||
void addTileToHint(int x, int y, Hint &hint);
|
||||
void createHintFromTile(int x, int y, Hint &hint);
|
||||
|
||||
Display *dpy;
|
||||
Window window;
|
||||
Framebuffer *fb;
|
||||
unsigned int tileWidth, tileHeight, blockWidth, blockHeight;
|
||||
unsigned char *fb;
|
||||
int width, height;
|
||||
int bitsPerPixel, bytesPerLine;
|
||||
unsigned int tileWidth, tileHeight;
|
||||
unsigned int count;
|
||||
|
||||
XImage *scanline;
|
||||
@@ -69,6 +97,4 @@ class XUpdateScanner
|
||||
};
|
||||
|
||||
|
||||
} // namespace rfb
|
||||
|
||||
#endif // _hexonet_rfb_XUpdateScanner_h_
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
#define VERSION "0.6"
|
||||
|
||||
static const char *description = I18N_NOOP("VNC-compatible server to share "
|
||||
@@ -137,9 +139,6 @@ int main(int argc, char *argv[])
|
||||
TrayIcon trayicon(new KAboutApplication(&aboutData), config);
|
||||
RFBController controller(config);
|
||||
|
||||
if (controller.state() == RFB_ERROR)
|
||||
return 1;
|
||||
|
||||
QObject::connect(&app, SIGNAL(lastWindowClosed()),
|
||||
&controller, SLOT(closeSession()));
|
||||
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
/***************************************************************************
|
||||
rfbconnection.cpp
|
||||
-------------------
|
||||
begin : Sun Dec 9 2001
|
||||
copyright : (C) 2001 by Tim Jansen
|
||||
email : tim@tjansen.de
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Contains portions & concept from rfb's x0rfbserver.cc
|
||||
* Copyright (C) 2000 heXoNet Support GmbH, D-66424 Homburg.
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rfbconnection.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <qapplication.h>
|
||||
#include <qtimer.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static XTestDisabler disabler;
|
||||
|
||||
RFBConnection::RFBConnection(Display *_dpy,
|
||||
int _fd,
|
||||
const QString &cpassword,
|
||||
bool _allowInput) :
|
||||
Server(),
|
||||
fd(_fd),
|
||||
buttonMask(0),
|
||||
allowInput(_allowInput),
|
||||
dpy(_dpy)
|
||||
{
|
||||
memcpy(password, "\0\0\0\0\0\0\0\0", 8);
|
||||
if (!cpassword.isNull())
|
||||
strncpy(password, cpassword.latin1(),
|
||||
(8 <= cpassword.length()) ? 8 : cpassword.length());
|
||||
|
||||
connection = new BufferedConnection(fd, 32768, 16384);
|
||||
|
||||
XTestGrabControl(dpy, true);
|
||||
disabler.disable = false;
|
||||
|
||||
createFramebuffer();
|
||||
|
||||
sendFirstHandshake(connection);
|
||||
}
|
||||
|
||||
RFBConnection::~RFBConnection() {
|
||||
destroyFramebuffer();
|
||||
delete connection;
|
||||
|
||||
disabler.disable = true;
|
||||
disabler.dpy = dpy;
|
||||
QTimer::singleShot(0, &disabler, SLOT(exec()));
|
||||
}
|
||||
|
||||
void RFBConnection::handleKeyEvent(KeyEvent &keyEvent) {
|
||||
if (!allowInput)
|
||||
return;
|
||||
KeyCode kc = XKeysymToKeycode(dpy, keyEvent.key);
|
||||
if (kc != NoSymbol)
|
||||
XTestFakeKeyEvent(dpy,
|
||||
XKeysymToKeycode( dpy, keyEvent.key ),
|
||||
keyEvent.down_flag,
|
||||
CurrentTime);
|
||||
}
|
||||
|
||||
void RFBConnection::handlePointerEvent(PointerEvent &pointerEvent) {
|
||||
if (!allowInput)
|
||||
return;
|
||||
XTestFakeMotionEvent(dpy,
|
||||
0,
|
||||
pointerEvent.x_position,
|
||||
pointerEvent.y_position,
|
||||
CurrentTime);
|
||||
int i = 1;
|
||||
while (i <= 5) {
|
||||
if ( (buttonMask & (1 << (i-1))) != (pointerEvent.button_mask & (1 << (i-1))) )
|
||||
XTestFakeButtonEvent( dpy, i,
|
||||
(pointerEvent.button_mask & (1 << (i-1)))? True : False,
|
||||
CurrentTime );
|
||||
i++;
|
||||
}
|
||||
buttonMask = pointerEvent.button_mask;
|
||||
}
|
||||
|
||||
void RFBConnection::createFramebuffer()
|
||||
{
|
||||
framebufferImage = XGetImage(dpy,
|
||||
QApplication::desktop()->winId(),
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(),
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
framebuffer = new Framebuffer();
|
||||
framebuffer->width = framebufferImage->width;
|
||||
framebuffer->height = framebufferImage->height;
|
||||
framebuffer->bytesPerLine = framebufferImage->bytes_per_line;
|
||||
framebuffer->data = (unsigned char*) framebufferImage->data;
|
||||
|
||||
framebuffer->pixelFormat.bits_per_pixel =
|
||||
framebufferImage->bits_per_pixel;
|
||||
framebuffer->pixelFormat.depth = framebufferImage->depth;
|
||||
framebuffer->pixelFormat.big_endian_flag =
|
||||
(framebufferImage->bitmap_bit_order == MSBFirst);
|
||||
framebuffer->pixelFormat.true_colour_flag = true;
|
||||
|
||||
if (framebuffer->pixelFormat.bits_per_pixel == 8) {
|
||||
framebuffer->pixelFormat.red_shift = 0;
|
||||
framebuffer->pixelFormat.green_shift = 2;
|
||||
framebuffer->pixelFormat.blue_shift = 5;
|
||||
framebuffer->pixelFormat.red_max = 3;
|
||||
framebuffer->pixelFormat.green_max = 7;
|
||||
framebuffer->pixelFormat.blue_max = 3;
|
||||
} else {
|
||||
framebuffer->pixelFormat.red_shift = 0;
|
||||
if ( framebufferImage->red_mask )
|
||||
while (!(framebufferImage->red_mask & (1 << framebuffer->pixelFormat.red_shift)))
|
||||
framebuffer->pixelFormat.red_shift++;
|
||||
framebuffer->pixelFormat.green_shift = 0;
|
||||
if (framebufferImage->green_mask)
|
||||
while (!(framebufferImage->green_mask & (1 << framebuffer->pixelFormat.green_shift)))
|
||||
framebuffer->pixelFormat.green_shift++;
|
||||
framebuffer->pixelFormat.blue_shift = 0;
|
||||
if (framebufferImage->blue_mask)
|
||||
while (!(framebufferImage->blue_mask & (1 << framebuffer->pixelFormat.blue_shift)))
|
||||
framebuffer->pixelFormat.blue_shift++;
|
||||
framebuffer->pixelFormat.red_max = framebufferImage->red_mask >> framebuffer->pixelFormat.red_shift;
|
||||
framebuffer->pixelFormat.green_max = framebufferImage->green_mask >> framebuffer->pixelFormat.green_shift;
|
||||
framebuffer->pixelFormat.blue_max = framebufferImage->blue_mask >> framebuffer->pixelFormat.blue_shift;
|
||||
}
|
||||
scanner = new XUpdateScanner( dpy, QApplication::desktop()->winId(), framebuffer );
|
||||
}
|
||||
|
||||
void RFBConnection::destroyFramebuffer()
|
||||
{
|
||||
delete scanner;
|
||||
delete framebuffer;
|
||||
XDestroyImage(framebufferImage);
|
||||
}
|
||||
|
||||
void RFBConnection::scanUpdates()
|
||||
{
|
||||
list<Hint> hintList;
|
||||
|
||||
scanner->searchUpdates(hintList);
|
||||
list<Hint>::iterator i;
|
||||
for (i = hintList.begin(); i != hintList.end(); i++)
|
||||
handleHint(*i);
|
||||
};
|
||||
|
||||
void RFBConnection::getServerInitialisation( ServerInitialisation &_serverInit )
|
||||
{
|
||||
Server::getServerInitialisation( _serverInit );
|
||||
_serverInit.name_length = strlen( getenv("HOSTNAME") );
|
||||
_serverInit.name_string = (CARD8 *) malloc( _serverInit.name_length + 1 );
|
||||
strcpy( (char*) _serverInit.name_string, getenv( "HOSTNAME" ) );
|
||||
}
|
||||
|
||||
XTestDisabler::XTestDisabler() :
|
||||
disable(false) {
|
||||
}
|
||||
|
||||
void XTestDisabler::exec() {
|
||||
if (disable)
|
||||
XTestDiscard(dpy);
|
||||
}
|
||||
|
||||
#include "rfbconnection.moc"
|
||||
@@ -1,90 +0,0 @@
|
||||
/***************************************************************************
|
||||
rfbconnection.h
|
||||
-------------------
|
||||
begin : Sun Dec 9 2001
|
||||
copyright : (C) 2001 by Tim Jansen
|
||||
email : tim@tjansen.de
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Contains portions & concept from rfb's x0rfbserver.cc
|
||||
* Copyright (C) 2000 heXoNet Support GmbH, D-66424 Homburg.
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef RFBCONNECTION_H
|
||||
#define RFBCONNECTION_H
|
||||
|
||||
// QT must be first because of conflicts with X11
|
||||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
|
||||
#include "XUpdateScanner.h"
|
||||
|
||||
#include "../include/rfbServer.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
/**
|
||||
* This is a port from x0rfbserver's BaseServer to KDE. It is called
|
||||
* RFBConnection because the original Server, despite its name, handles only
|
||||
* a single connection after it has been established. This class and its
|
||||
* connections are created and destroyed by RFBController. RFBController is the real
|
||||
* serverk, but I did not want to call it Server and create more confusion.
|
||||
* Unlike the original this one allows only one client, making stuff a little bit
|
||||
* simpler.
|
||||
* @author Tim Jansen
|
||||
*/
|
||||
class RFBConnection : public QObject, public Server {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RFBConnection(Display *dpy, int fd,
|
||||
const QString &cpassword,
|
||||
bool allowInput);
|
||||
virtual ~RFBConnection();
|
||||
virtual void handleKeyEvent(KeyEvent &keyEvent);
|
||||
virtual void handlePointerEvent(PointerEvent &pointerEvent);
|
||||
virtual void getServerInitialisation( ServerInitialisation &_serverInitialisation );
|
||||
void scanUpdates();
|
||||
|
||||
private:
|
||||
void createFramebuffer();
|
||||
void destroyFramebuffer();
|
||||
|
||||
int fd;
|
||||
int buttonMask;
|
||||
bool allowInput;
|
||||
|
||||
XUpdateScanner *scanner;
|
||||
|
||||
Display *dpy;
|
||||
XImage *framebufferImage;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class to calls XTestDiscard at idle time (because otherwise
|
||||
* it will not work with QT)
|
||||
*/
|
||||
class XTestDisabler : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
XTestDisabler();
|
||||
bool disable;
|
||||
Display *dpy;
|
||||
public slots:
|
||||
void exec();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,11 +6,6 @@
|
||||
email : tim@tjansen.de
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Contains portions & concept from rfb's x0rfbserver.cc
|
||||
* Copyright (C) 2000 heXoNet Support GmbH, D-66424 Homburg.
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -26,6 +21,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <kapp.h>
|
||||
#include <kdebug.h>
|
||||
#include <kmessagebox.h>
|
||||
#include <klocale.h>
|
||||
@@ -37,21 +33,78 @@
|
||||
#include <qglobal.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(x) Q_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#define IDLE_PAUSE (1000/50)
|
||||
|
||||
static XTestDisabler disabler;
|
||||
|
||||
// only one controller exists, so we can do this workaround for functions:
|
||||
static RFBController *self;
|
||||
|
||||
class AppLocker
|
||||
{
|
||||
public:
|
||||
AppLocker() {
|
||||
KApplication::kApplication()->lock();
|
||||
}
|
||||
|
||||
~AppLocker() {
|
||||
KApplication::kApplication()->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
static void keyboardHook(Bool down, KeySym keySym, rfbClientPtr cl)
|
||||
{
|
||||
AppLocker a;
|
||||
self->handleKeyEvent(down?true:false, keySym);
|
||||
}
|
||||
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
{
|
||||
AppLocker a;
|
||||
self->handlePointerEvent(bm, x, y);
|
||||
}
|
||||
|
||||
static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
|
||||
{
|
||||
AppLocker a;
|
||||
return self->handleNewClient(cl);
|
||||
}
|
||||
|
||||
static Bool passwordCheck(rfbClientPtr cl,
|
||||
char* encryptedPassword,
|
||||
int len)
|
||||
{
|
||||
AppLocker a;
|
||||
self->handleCheckPassword(encryptedPassword, len);
|
||||
}
|
||||
|
||||
static void clientGoneHook(rfbClientPtr cl)
|
||||
{
|
||||
AppLocker a;
|
||||
self->handleClientGone();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionDialog::closeEvent(QCloseEvent *)
|
||||
{
|
||||
emit closed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
RFBController::RFBController(Configuration *c) :
|
||||
configuration(c),
|
||||
socket(0),
|
||||
connection(0),
|
||||
idleUpdateScheduled(false)
|
||||
allowRemoteControl(false),
|
||||
connectionNum(0),
|
||||
configuration(c)
|
||||
{
|
||||
self = this;
|
||||
connect(dialog.acceptConnectionButton, SIGNAL(clicked()),
|
||||
SLOT(dialogAccepted()));
|
||||
connect(dialog.refuseConnectionButton, SIGNAL(clicked()),
|
||||
@@ -61,178 +114,302 @@ RFBController::RFBController(Configuration *c) :
|
||||
startServer();
|
||||
}
|
||||
|
||||
RFBController::~RFBController() {
|
||||
if (serversocket)
|
||||
delete serversocket;
|
||||
if (socket)
|
||||
delete socket;
|
||||
if (connection)
|
||||
delete connection;
|
||||
RFBController::~RFBController()
|
||||
{
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RFBController::startServer() {
|
||||
serversocket = new KServerSocket(configuration->port(), false);
|
||||
connect(serversocket, SIGNAL(accepted(KSocket*)), SLOT(accepted(KSocket*)));
|
||||
if (!serversocket->bindAndListen()) {
|
||||
delete serversocket;
|
||||
serversocket = 0;
|
||||
KMessageBox::error(0,
|
||||
i18n("KRfb Server cannot run, port %1 is already in use. ")
|
||||
.arg(configuration->port()),
|
||||
i18n("KRfb Error"));
|
||||
|
||||
|
||||
void RFBController::startServer(bool xtestGrab)
|
||||
{
|
||||
framebufferImage = XGetImage(qt_xdisplay(),
|
||||
QApplication::desktop()->winId(),
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(),
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
int w = framebufferImage->width;
|
||||
int h = framebufferImage->height;
|
||||
int bpp = framebufferImage->depth;
|
||||
char *fb = framebufferImage->data;
|
||||
|
||||
server = rfbGetScreen(0, 0, w, h,
|
||||
(bpp==4) ? 8 : 5,
|
||||
0, bpp);
|
||||
server->frameBuffer = fb;
|
||||
server->rfbPort = configuration->port();
|
||||
//server->udpPort = configuration->port();
|
||||
|
||||
server->kbdAddEvent = keyboardHook;
|
||||
server->ptrAddEvent = pointerHook;
|
||||
server->newClientHook = newClientHook;
|
||||
server->passwordCheck = passwordCheck;
|
||||
|
||||
scanner = new XUpdateScanner(qt_xdisplay(),
|
||||
QApplication::desktop()->winId(),
|
||||
(unsigned char*)fb,
|
||||
w, h, bpp, (bpp/8)*w);
|
||||
|
||||
rfbInitServer(server);
|
||||
state = RFB_WAITING;
|
||||
|
||||
if (xtestGrab) {
|
||||
disabler.disable = false;
|
||||
XTestGrabControl(qt_xdisplay(), true);
|
||||
}
|
||||
|
||||
rfbRunEventLoop(server, -1, TRUE);
|
||||
}
|
||||
|
||||
RFBState RFBController::state() {
|
||||
if (!serversocket)
|
||||
return RFB_ERROR;
|
||||
if (!socket)
|
||||
return RFB_WAITING;
|
||||
if (!connection)
|
||||
return RFB_CONNECTING;
|
||||
return RFB_CONNECTED;
|
||||
void RFBController::stopServer(bool xtestUngrab) {
|
||||
rfbScreenCleanup(server);
|
||||
state = RFB_STOPPED;
|
||||
delete scanner;
|
||||
|
||||
XDestroyImage(framebufferImage);
|
||||
|
||||
if (xtestUngrab) {
|
||||
disabler.disable = true;
|
||||
QTimer::singleShot(0, &disabler, SLOT(exec()));
|
||||
}
|
||||
}
|
||||
|
||||
void RFBController::rebind() {
|
||||
delete serversocket;
|
||||
startServer();
|
||||
stopServer(false);
|
||||
startServer(false);
|
||||
}
|
||||
|
||||
/* called when KServerSocket accepted a connection.
|
||||
Refuses the connection if there is already a connection.
|
||||
*/
|
||||
void RFBController::accepted(KSocket *s) {
|
||||
int sockFd = s->socket();
|
||||
if (sockFd < 0)
|
||||
kdError() << "Got negative socket (error)" << endl;
|
||||
|
||||
if (socket) {
|
||||
kdWarning() << "refuse 2nd connection" << endl;
|
||||
// TODO: send connection failed with reason
|
||||
delete s;
|
||||
void RFBController::acceptConnection(bool aRC) {
|
||||
if (state != RFB_CONNECTING)
|
||||
return;
|
||||
}
|
||||
|
||||
int one = 1;
|
||||
setsockopt(sockFd, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)&one, sizeof(one));
|
||||
fcntl(sockFd, F_SETFL, O_NONBLOCK);
|
||||
socket = s;
|
||||
allowRemoteControl = aRC;
|
||||
connectionNum++;
|
||||
idleTimer.start(IDLE_PAUSE);
|
||||
|
||||
if (configuration->askOnConnect()) {
|
||||
QString host, port;
|
||||
KExtendedSocket::resolve(KExtendedSocket::peerAddress(sockFd),
|
||||
host, port);
|
||||
dialog.ipLabel->setText(host);
|
||||
dialog.allowRemoteControlCB->setChecked(
|
||||
configuration->allowDesktopControl());
|
||||
dialog.setFixedSize(dialog.sizeHint());
|
||||
dialog.show();
|
||||
}
|
||||
else {
|
||||
acceptConnection(configuration->allowDesktopControl());
|
||||
}
|
||||
}
|
||||
|
||||
void RFBController::acceptConnection(bool allowDesktopControl) {
|
||||
KSocket *s = socket;
|
||||
connect(s, SIGNAL(readEvent(KSocket*)), SLOT(socketReadable()));
|
||||
connect(s, SIGNAL(writeEvent(KSocket*)), SLOT(socketWritable()));
|
||||
connect(s, SIGNAL(closeEvent(KSocket*)), SLOT(closeSession()));
|
||||
s->enableRead(true);
|
||||
s->enableWrite(true);
|
||||
connection = new RFBConnection(qt_xdisplay(), s->socket(),
|
||||
configuration->password(),
|
||||
allowDesktopControl);
|
||||
client->clientGoneHook = clientGoneHook;
|
||||
rfbStartOnHoldClient(client);
|
||||
|
||||
state = RFB_CONNECTED;
|
||||
emit sessionEstablished();
|
||||
}
|
||||
|
||||
void RFBController::idleSlot() {
|
||||
idleUpdateScheduled = false;
|
||||
if (connection) {
|
||||
connection->scanUpdates();
|
||||
connection->sendIncrementalFramebufferUpdate();
|
||||
connection->connection->write();
|
||||
checkWriteBuffer();
|
||||
}
|
||||
void RFBController::refuseConnection() {
|
||||
if (state != RFB_CONNECTING)
|
||||
return;
|
||||
rfbRefuseOnHoldClient(client);
|
||||
state = RFB_WAITING;
|
||||
}
|
||||
|
||||
void RFBController::checkWriteBuffer() {
|
||||
BufferedConnection *bc = connection->connection;
|
||||
bool bufferEmpty = !bc->hasSenderBufferData();
|
||||
socket->enableWrite(!bufferEmpty);
|
||||
if (bufferEmpty && !idleUpdateScheduled && connection) {
|
||||
QTimer::singleShot(0, this, SLOT(idleSlot()));
|
||||
idleUpdateScheduled = true;
|
||||
}
|
||||
void RFBController::connectionClosed()
|
||||
{
|
||||
idleTimer.stop();
|
||||
connectionNum--;
|
||||
state = RFB_WAITING;
|
||||
client = 0;
|
||||
emit sessionFinished();
|
||||
}
|
||||
|
||||
void RFBController::socketReadable() {
|
||||
if ((!socket) || (!connection))
|
||||
return;
|
||||
|
||||
BufferedConnection *bc = connection->connection;
|
||||
int count = bc->read();
|
||||
if (count < 0) {
|
||||
closeSession();
|
||||
return;
|
||||
}
|
||||
while (connection->currentState && bc->hasReceiverBufferData()) {
|
||||
connection->update();
|
||||
checkWriteBuffer();
|
||||
}
|
||||
|
||||
if (!connection->currentState) {
|
||||
closeSession();
|
||||
}
|
||||
void RFBController::closeConnection()
|
||||
{
|
||||
rfbCloseClient(client);
|
||||
}
|
||||
|
||||
void RFBController::socketWritable() {
|
||||
if ((!socket) || (!connection))
|
||||
return;
|
||||
void RFBController::idleSlot()
|
||||
{
|
||||
rfbUndrawCursor(server);
|
||||
|
||||
BufferedConnection *bc = connection->connection;
|
||||
int count = bc->write();
|
||||
if (count >= 0)
|
||||
checkWriteBuffer();
|
||||
else
|
||||
closeSession();
|
||||
QList<Hint> v;
|
||||
v.setAutoDelete(true);
|
||||
scanner->searchUpdates(v);
|
||||
|
||||
Hint *h;
|
||||
|
||||
for (h = v.first(); h != 0; h = v.next())
|
||||
rfbMarkRectAsModified(server, h->left(),
|
||||
h->top(),
|
||||
h->right(),
|
||||
h->bottom());
|
||||
|
||||
QPoint p = QCursor::pos();
|
||||
defaultPtrAddEvent(0, p.x(),p.y(), client);
|
||||
}
|
||||
|
||||
void RFBController::closeSession() {
|
||||
if (!socket)
|
||||
return;
|
||||
if (connection) {
|
||||
delete connection;
|
||||
connection = 0;
|
||||
emit sessionFinished();
|
||||
}
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
void RFBController::dialogAccepted() {
|
||||
if (!socket)
|
||||
return;
|
||||
ASSERT(!connection);
|
||||
|
||||
void RFBController::dialogAccepted()
|
||||
{
|
||||
dialog.hide();
|
||||
acceptConnection(dialog.allowRemoteControlCB->isChecked());
|
||||
}
|
||||
|
||||
void RFBController::dialogRefused() {
|
||||
if (!socket)
|
||||
return;
|
||||
ASSERT(!connection);
|
||||
|
||||
closeSocket();
|
||||
void RFBController::dialogRefused()
|
||||
{
|
||||
refuseConnection();
|
||||
dialog.hide();
|
||||
emit sessionRefused();
|
||||
}
|
||||
|
||||
void RFBController::closeSocket() {
|
||||
delete socket;
|
||||
socket = 0;
|
||||
bool RFBController::handleCheckPassword(const char *p, int len)
|
||||
{
|
||||
return TRUE;
|
||||
// TODO
|
||||
}
|
||||
|
||||
enum rfbNewClientAction RFBController::handleNewClient(rfbClientPtr cl)
|
||||
{
|
||||
int socket = cl->sock;
|
||||
|
||||
if ((connectionNum > 0) ||
|
||||
(state != RFB_WAITING))
|
||||
return RFB_CLIENT_REFUSE;
|
||||
|
||||
client = cl;
|
||||
|
||||
state = RFB_CONNECTING;
|
||||
|
||||
if (!configuration->askOnConnect()) {
|
||||
acceptConnection(configuration->allowDesktopControl());
|
||||
return RFB_CLIENT_ACCEPT;
|
||||
}
|
||||
|
||||
dialog.allowRemoteControlCB->setChecked(configuration->allowDesktopControl());
|
||||
// TODO: get & set client host name
|
||||
|
||||
dialog.show();
|
||||
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
|
||||
void RFBController::handleClientGone()
|
||||
{
|
||||
connectionClosed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define LEFTSHIFT 1
|
||||
#define RIGHTSHIFT 2
|
||||
#define ALTGR 4
|
||||
char ModifierState = 0;
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
|
||||
|
||||
void RFBController::tweakModifiers(char mod, bool down)
|
||||
{
|
||||
Display *dpy = qt_xdisplay();
|
||||
|
||||
bool isShift = ModifierState & (LEFTSHIFT|RIGHTSHIFT);
|
||||
if(mod < 0)
|
||||
return;
|
||||
|
||||
if(isShift && mod != 1) {
|
||||
if(ModifierState & LEFTSHIFT)
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
!down, CurrentTime);
|
||||
if(ModifierState & RIGHTSHIFT)
|
||||
XTestFakeKeyEvent(dpy, rightShiftCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if(!isShift && mod==1)
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
down, CurrentTime);
|
||||
|
||||
if(ModifierState&ALTGR && mod != 2)
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
!down, CurrentTime);
|
||||
if(!(ModifierState&ALTGR) && mod==2)
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
void RFBController::initKeycodes()
|
||||
{
|
||||
Display *dpy = qt_xdisplay();
|
||||
KeySym key,*keymap;
|
||||
int i,j,minkey,maxkey,syms_per_keycode;
|
||||
|
||||
memset(modifiers,-1,sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy,&minkey,&maxkey);
|
||||
keymap=XGetKeyboardMapping(dpy,minkey,(maxkey - minkey + 1),&syms_per_keycode);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++)
|
||||
for(j=0;j<syms_per_keycode;j++) {
|
||||
key=keymap[(i-minkey)*syms_per_keycode+j];
|
||||
if(key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
|
||||
keycodes[key]=i;
|
||||
modifiers[key]=j;
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy,XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy,XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy,XK_Mode_switch);
|
||||
|
||||
XFree ((char *)keymap);
|
||||
}
|
||||
|
||||
void RFBController::handleKeyEvent(bool down, KeySym keySym) {
|
||||
if (!allowRemoteControl)
|
||||
return;
|
||||
|
||||
Display *dpy = qt_xdisplay();
|
||||
|
||||
#define ADJUSTMOD(sym,state) \
|
||||
if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
|
||||
|
||||
ADJUSTMOD(XK_Shift_L,LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R,RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch,ALTGR);
|
||||
|
||||
if(keySym>=' ' && keySym<0x100) {
|
||||
KeyCode k;
|
||||
if (down)
|
||||
tweakModifiers(modifiers[keySym],True);
|
||||
//tweakModifiers(modifiers[keySym],down);
|
||||
//k = XKeysymToKeycode( dpy,keySym );
|
||||
k = keycodes[keySym];
|
||||
if(k!=NoSymbol)
|
||||
XTestFakeKeyEvent(dpy,k,down,CurrentTime);
|
||||
|
||||
/*XTestFakeKeyEvent(dpy,keycodes[keySym],down,CurrentTime);*/
|
||||
if (down)
|
||||
tweakModifiers(modifiers[keySym],False);
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode( dpy,keySym );
|
||||
if(k!=NoSymbol)
|
||||
XTestFakeKeyEvent(dpy,k,down,CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void RFBController::handlePointerEvent(int button_mask, int x, int y) {
|
||||
if (!allowRemoteControl)
|
||||
return;
|
||||
|
||||
Display *dpy = qt_xdisplay();
|
||||
XTestFakeMotionEvent(dpy, 0, x, y, CurrentTime);
|
||||
for(int i = 0; i < 5; i++)
|
||||
if ((buttonMask&(1<<i))!=(button_mask&(1<<i)))
|
||||
XTestFakeButtonEvent(dpy,
|
||||
i+1,
|
||||
(button_mask&(1<<i))?True:False,
|
||||
CurrentTime);
|
||||
|
||||
buttonMask = button_mask;
|
||||
}
|
||||
|
||||
|
||||
XTestDisabler::XTestDisabler() :
|
||||
disable(false) {
|
||||
}
|
||||
|
||||
void XTestDisabler::exec() {
|
||||
if (disable)
|
||||
XTestDiscard(qt_xdisplay());
|
||||
}
|
||||
|
||||
#include "rfbcontroller.moc"
|
||||
|
||||
@@ -25,17 +25,21 @@
|
||||
|
||||
#include "configuration.h"
|
||||
#include "newconnectiondialog.h"
|
||||
#include "XUpdateScanner.h"
|
||||
#include <ksock.h>
|
||||
#include <qobject.h>
|
||||
#include <qtimer.h>
|
||||
// rfbconnection must be last because of X11 headers
|
||||
#include "rfbconnection.h"
|
||||
#include "rfb.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
|
||||
|
||||
class QCloseEvent;
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
typedef enum {
|
||||
RFB_ERROR,
|
||||
RFB_STOPPED,
|
||||
RFB_WAITING,
|
||||
RFB_CONNECTING,
|
||||
RFB_CONNECTED
|
||||
@@ -65,11 +69,20 @@ public:
|
||||
RFBController(Configuration *c);
|
||||
virtual ~RFBController();
|
||||
|
||||
RFBState state();
|
||||
|
||||
RFBState state;
|
||||
|
||||
void acceptConnection(bool allowRemoteConnection);
|
||||
void refuseConnection();
|
||||
void connectionClosed();
|
||||
bool handleCheckPassword(const char *p, int len);
|
||||
void handleKeyEvent(bool down, KeySym keySym);
|
||||
void handlePointerEvent(int button_mask, int x, int y);
|
||||
enum rfbNewClientAction handleNewClient(rfbClientPtr cl);
|
||||
void handleClientGone();
|
||||
|
||||
public slots:
|
||||
void rebind();
|
||||
void closeSession();
|
||||
void closeConnection();
|
||||
|
||||
signals:
|
||||
void sessionEstablished();
|
||||
@@ -77,25 +90,45 @@ signals:
|
||||
void sessionRefused();
|
||||
|
||||
private:
|
||||
void startServer();
|
||||
void checkWriteBuffer();
|
||||
void acceptConnection(bool ask);
|
||||
void closeSocket();
|
||||
void startServer(bool xtestGrab = true);
|
||||
void stopServer(bool xtestUngrab = true);
|
||||
void tweakModifiers(char mod, bool down);
|
||||
void initKeycodes();
|
||||
|
||||
bool allowRemoteControl;
|
||||
int connectionNum;
|
||||
|
||||
QTimer idleTimer;
|
||||
Configuration *configuration;
|
||||
KServerSocket *serversocket;
|
||||
KSocket *socket;
|
||||
RFBConnection *connection;
|
||||
XUpdateScanner *scanner;
|
||||
ConnectionDialog dialog;
|
||||
bool idleUpdateScheduled;
|
||||
|
||||
rfbScreenInfoPtr server;
|
||||
rfbClientPtr client;
|
||||
|
||||
XImage *framebufferImage;
|
||||
int buttonMask;
|
||||
char modifiers[0x100];
|
||||
KeyCode keycodes[0x100], leftShiftCode, rightShiftCode, altGrCode;
|
||||
|
||||
private slots:
|
||||
void idleSlot();
|
||||
void accepted(KSocket*);
|
||||
void socketReadable();
|
||||
void socketWritable();
|
||||
void dialogAccepted();
|
||||
void dialogRefused();
|
||||
};
|
||||
|
||||
/*
|
||||
* Class to call XTestDiscard at idle time (because otherwise
|
||||
* it will not work with QT)
|
||||
*/
|
||||
class XTestDisabler : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
XTestDisabler();
|
||||
bool disable;
|
||||
Display *dpy;
|
||||
public slots:
|
||||
void exec();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user