Compare commits
128 Commits
v4.13.80
...
Applicatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7968886f15 | ||
|
|
786fb279f1 | ||
|
|
c0dbc82627 | ||
|
|
4f0ca5a73d | ||
|
|
eb6bc85a6a | ||
|
|
69aa649d9c | ||
|
|
1fb61059a7 | ||
|
|
0689b72f38 | ||
|
|
4564c91b64 | ||
|
|
01ec550abf | ||
|
|
47c40225fd | ||
|
|
f131f7ddba | ||
|
|
b2cb3e8204 | ||
|
|
c92ef2f230 | ||
|
|
b2fe612ec4 | ||
|
|
831ec6c9be | ||
|
|
4b01a1cac7 | ||
|
|
09b643f5cb | ||
|
|
77ef270323 | ||
|
|
e487c45f34 | ||
|
|
2a60739a16 | ||
|
|
8eecd9097e | ||
|
|
e3b9a0b30a | ||
|
|
6561a9db15 | ||
|
|
c0ceb8a83d | ||
|
|
f107a73d28 | ||
|
|
4974154cc3 | ||
|
|
05dc124c8b | ||
|
|
b960bb4ba4 | ||
|
|
f702422c9d | ||
|
|
27e48f1114 | ||
|
|
9e77d1f5ac | ||
|
|
c12697e23f | ||
|
|
3ce5047a6f | ||
|
|
60b6f7b86b | ||
|
|
b1f1a2f8d6 | ||
|
|
ee863548d9 | ||
|
|
ccc9ed069f | ||
|
|
8c7138b592 | ||
|
|
364cee9ba2 | ||
|
|
215d20c004 | ||
|
|
315b401227 | ||
|
|
9289a22d8a | ||
|
|
d529e22430 | ||
|
|
b6fbb67af1 | ||
|
|
da4de72d55 | ||
|
|
b3e1624469 | ||
|
|
aa80d3915d | ||
|
|
0b210563cb | ||
|
|
b4713d4755 | ||
|
|
34d9387aa0 | ||
|
|
eb7caf8594 | ||
|
|
e761ee832e | ||
|
|
699d7f9a27 | ||
|
|
43083c52dc | ||
|
|
903692c299 | ||
|
|
2885bf2c5a | ||
|
|
6544fd56e9 | ||
|
|
3fc2398707 | ||
|
|
c1efd7158f | ||
|
|
cbc43a390f | ||
|
|
631d3c85ac | ||
|
|
ae15751847 | ||
|
|
f1a3e2b31c | ||
|
|
b95a5b285d | ||
|
|
0ee5738bf5 | ||
|
|
5195783757 | ||
|
|
1b6702167d | ||
|
|
8b7fcb023d | ||
|
|
65595722bd | ||
|
|
916ffb525a | ||
|
|
ee5cb9eaf5 | ||
|
|
ecb9fb8ee0 | ||
|
|
2c317584b9 | ||
|
|
c98d1d7676 | ||
|
|
def5195e63 | ||
|
|
510e5f8d52 | ||
|
|
964386e2a6 | ||
|
|
0d500c00ba | ||
|
|
07439f6408 | ||
|
|
aa0e358136 | ||
|
|
7c175bbc6e | ||
|
|
405bec30f6 | ||
|
|
464cbd8573 | ||
|
|
c1904c41c7 | ||
|
|
17752eba7c | ||
|
|
f4b4fe0f34 | ||
|
|
ac6f4ca3ed | ||
|
|
d2d49abf23 | ||
|
|
396e277113 | ||
|
|
ab7ed1c006 | ||
|
|
1c9db8798e | ||
|
|
a2b1c5e0b5 | ||
|
|
f95fafe5a7 | ||
|
|
3a9f58f12e | ||
|
|
74b4d19a35 | ||
|
|
c0f1b1ebb4 | ||
|
|
d306c6c73d | ||
|
|
8d1abb3a8f | ||
|
|
f15490d58a | ||
|
|
c83182f8d3 | ||
|
|
e0dc5b3a51 | ||
|
|
5948ee69c2 | ||
|
|
e443b13227 | ||
|
|
ff2d0d999d | ||
|
|
0b9ed26137 | ||
|
|
05b6105be8 | ||
|
|
6d5e2bc356 | ||
|
|
10176b9e01 | ||
|
|
9bb8e28eeb | ||
|
|
56e1804b23 | ||
|
|
82707732d3 | ||
|
|
e63fb3f0b1 | ||
|
|
a45aa4a16b | ||
|
|
535e474cbd | ||
|
|
2448d9e944 | ||
|
|
74683e0a02 | ||
|
|
87f2742fcc | ||
|
|
6306bf85cf | ||
|
|
cb43be430c | ||
|
|
97beca4d9c | ||
|
|
ad800f12fc | ||
|
|
9db3ae6629 | ||
|
|
b6b20c84e8 | ||
|
|
0bff5df104 | ||
|
|
1c85dc7d85 | ||
|
|
83767fea93 | ||
|
|
8597d3c4a7 |
4
.reviewboardrc
Normal file
@@ -0,0 +1,4 @@
|
||||
REPOSITORY = "git://anongit.kde.org/krfb"
|
||||
REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
|
||||
TARGET_PEOPLE = "whiting"
|
||||
|
||||
@@ -1,51 +1,66 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
project(krfb)
|
||||
|
||||
if(NOT INSIDE_KDENETWORK)
|
||||
message("Not building inside KDENetwork, loading KDE CMake Macros.")
|
||||
include(FeatureSummary)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core DBus Widgets X11Extras)
|
||||
|
||||
find_package(KDE4 REQUIRED)
|
||||
find_package(ECM 1.7.0 NO_MODULE REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
|
||||
include(KDE4Defaults)
|
||||
include(MacroLibrary)
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(ECMInstallIcons)
|
||||
include(ECMAddAppIcon)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckPrototypeExists)
|
||||
include(CheckTypeSize)
|
||||
find_package(KF5 REQUIRED COMPONENTS
|
||||
I18n
|
||||
Completion
|
||||
Config
|
||||
CoreAddons
|
||||
Crash
|
||||
DBusAddons
|
||||
DNSSD
|
||||
DocTools
|
||||
Notifications
|
||||
Wallet
|
||||
WidgetsAddons
|
||||
XmlGui
|
||||
)
|
||||
|
||||
set(CMAKE_REQUIRED_DEFINITIONS ${_KDE4_PLATFORM_DEFINITIONS})
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${KDEWIN32_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${KDEWIN32_INCLUDES})
|
||||
endif(WIN32)
|
||||
add_definitions(${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS} ${KDE4_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
|
||||
endif(NOT INSIDE_KDENETWORK)
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
find_package(XCB REQUIRED COMPONENTS
|
||||
XCB
|
||||
RENDER
|
||||
SHAPE
|
||||
XFIXES
|
||||
DAMAGE
|
||||
SHM
|
||||
IMAGE
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${KDEWIN32_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${KDEWIN32_INCLUDES})
|
||||
endif(WIN32)
|
||||
|
||||
add_definitions(${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} )
|
||||
|
||||
set(IS_KTP_INTERNAL_MODULE TRUE)
|
||||
set(CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
|
||||
${CMAKE_MODULE_PATH}
|
||||
)
|
||||
|
||||
macro_optional_find_package(TelepathyQt4)
|
||||
macro_log_feature(TelepathyQt4_FOUND "telepathy-qt" "Telepathy Qt Bindings" "http://telepathy.freedesktop.org" FALSE "0.9" "Needed to build Telepathy Tubes support.")
|
||||
find_package(LibVNCServer REQUIRED)
|
||||
|
||||
macro_optional_find_package(KTp)
|
||||
macro_log_feature(KTP_FOUND "KTP" "KDE Telepathy" "https://projects.kde.org/projects/extragear/network/telepathy" FALSE "" "Needed to build KDE IM Contacts Display in KRFB.")
|
||||
|
||||
macro_bool_to_01(X11_Xdamage_FOUND HAVE_XDAMAGE)
|
||||
macro_bool_to_01(X11_XShm_FOUND HAVE_XSHM)
|
||||
|
||||
include_directories ("${CMAKE_CURRENT_BINARY_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb/ui"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/libvncserver/"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libvncserver/"
|
||||
)
|
||||
|
||||
if(Q_WS_X11)
|
||||
@@ -54,11 +69,8 @@ if(Q_WS_X11)
|
||||
endif(NOT X11_XTest_FOUND)
|
||||
endif(Q_WS_X11)
|
||||
|
||||
add_subdirectory(libvncserver)
|
||||
add_subdirectory(krfb)
|
||||
add_subdirectory (framebuffers)
|
||||
add_subdirectory(framebuffers)
|
||||
add_subdirectory(doc)
|
||||
|
||||
if (NOT INSIDE_KDENETWORK)
|
||||
macro_display_feature_log()
|
||||
endif ()
|
||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# Try to find the KTp library
|
||||
# KTP_FOUND
|
||||
# KTP_INCLUDE_DIR
|
||||
# KTP_LIBRARIES
|
||||
# KTP_MODELS_LIBRARIES
|
||||
# KTP_WIDGETS_LIBRARIES
|
||||
|
||||
# Copyright (c) 2011, Dario Freddi <drf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
if (NOT IS_KTP_INTERNAL_MODULE)
|
||||
message (FATAL_ERROR "KTp can be used just from internal components at this time")
|
||||
endif (NOT IS_KTP_INTERNAL_MODULE)
|
||||
|
||||
SET (KTP_FIND_REQUIRED ${KTp_FIND_REQUIRED})
|
||||
if (KTP_INCLUDE_DIRS AND KTP_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
set(KTP_FIND_QUIETLY TRUE)
|
||||
endif (KTP_INCLUDE_DIRS AND KTP_LIBRARIES)
|
||||
|
||||
find_path(KTP_INCLUDE_DIR
|
||||
NAMES KTp/presence.h
|
||||
PATHS ${KDE4_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
find_library(KTP_LIBRARIES NAMES ktpcommoninternalsprivate )
|
||||
find_library(KTP_MODELS_LIBRARIES NAMES ktpmodelsprivate )
|
||||
find_library(KTP_WIDGETS_LIBRARIES NAMES ktpwidgetsprivate )
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(KTp DEFAULT_MSG
|
||||
KTP_LIBRARIES
|
||||
KTP_MODELS_LIBRARIES
|
||||
KTP_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(KTP_INCLUDE_DIRS KTP_LIBRARIES)
|
||||
41
cmake/modules/FindLibVNCServer.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
# cmake macro to test LIBVNCSERVER LIB
|
||||
|
||||
# Copyright (c) 2006, Alessandro Praduroux <pradu@pradu.it>
|
||||
# Copyright (c) 2007, Urs Wolfer <uwolfer @ kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
INCLUDE(CheckStructHasMember)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(LIBVNCSERVER_FIND_QUIETLY TRUE)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
FIND_PATH(LIBVNCSERVER_INCLUDE_DIR rfb/rfb.h)
|
||||
|
||||
FIND_LIBRARY(LIBVNCSERVER_LIBRARIES NAMES vncserver libvncserver)
|
||||
|
||||
# libvncserver and libvncclient are in the same package, so it does
|
||||
# not make sense to add a new cmake script for finding libvncclient.
|
||||
# instead just find the libvncclient also in this file.
|
||||
FIND_PATH(LIBVNCCLIENT_INCLUDE_DIR rfb/rfbclient.h)
|
||||
FIND_LIBRARY(LIBVNCCLIENT_LIBRARIES NAMES vncclient libvncclient)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
SET(CMAKE_REQUIRED_INCLUDES "${LIBVNCSERVER_INCLUDE_DIR}" "${CMAKE_REQUIRED_INCLUDES}")
|
||||
CHECK_STRUCT_HAS_MEMBER("struct _rfbClient" GotXCutText rfb/rfbclient.h LIBVNCSERVER_FOUND)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
IF (LIBVNCSERVER_FOUND)
|
||||
IF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found LibVNCServer: ${LIBVNCSERVER_LIBRARIES}")
|
||||
ENDIF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
ELSE (LIBVNCSERVER_FOUND)
|
||||
IF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could NOT find acceptable version of LibVNCServer (version 0.9 or later required).")
|
||||
ENDIF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
ENDIF (LIBVNCSERVER_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(LIBVNCSERVER_INCLUDE_DIR LIBVNCSERVER_LIBRARIES)
|
||||
@@ -1,2 +1,2 @@
|
||||
########### install files ###############
|
||||
kde4_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR krfb)
|
||||
kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR krfb)
|
||||
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 45 KiB |
@@ -1,22 +1,11 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
|
||||
<!ENTITY kappname "&krfb;">
|
||||
<!ENTITY package "kdenetwork">
|
||||
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [
|
||||
<!ENTITY % addindex "IGNORE">
|
||||
<!ENTITY % English "INCLUDE"> <!-- ONLY If you are writing non-English
|
||||
original documentation, change
|
||||
the language here -->
|
||||
|
||||
<!-- Do not define any other entities; instead, use the entities
|
||||
from entities/general.entities and $LANG/user.entities. -->
|
||||
<!ENTITY % English "INCLUDE">
|
||||
]>
|
||||
<!-- Based on kdoctemplate v0.9 January 10 2003 -->
|
||||
|
||||
<book id="krfb" lang="&language;">
|
||||
|
||||
<!-- This header contains all of the meta-information for the document such
|
||||
as Authors, publish date, the abstract, and Keywords -->
|
||||
|
||||
<bookinfo>
|
||||
<title>The &krfb; Handbook</title>
|
||||
|
||||
@@ -32,21 +21,11 @@ as Authors, publish date, the abstract, and Keywords -->
|
||||
<year>2003</year>
|
||||
<holder>&Brad.Hards;</holder>
|
||||
</copyright>
|
||||
<!-- Translators: put here the copyright notice of the translation -->
|
||||
|
||||
<legalnotice>&FDLNotice;</legalnotice>
|
||||
|
||||
<!-- Date and version information of the documentation
|
||||
Don't forget to include this last date and this last revision number, we
|
||||
need them for translation coordination !
|
||||
Please respect the format of the date (YYYY-MM-DD) and of the version
|
||||
(V.MM.LL), it could be used by automation scripts.
|
||||
Do NOT change these in the translation. -->
|
||||
|
||||
<date>2013-06-19</date>
|
||||
<releaseinfo>&kde; 4.11</releaseinfo>
|
||||
|
||||
<!-- Abstract about this handbook -->
|
||||
<date>2016-07-25</date>
|
||||
<releaseinfo>5.0 (Applications 16.08)</releaseinfo>
|
||||
|
||||
<abstract>
|
||||
<para>
|
||||
@@ -56,10 +35,6 @@ view or even control the desktop.
|
||||
</para>
|
||||
</abstract>
|
||||
|
||||
<!-- This is a set of Keywords for indexing by search engines.
|
||||
Please at least include KDE, the KDE package it is in, the name
|
||||
of your application, and a few relevant keywords. -->
|
||||
|
||||
<keywordset>
|
||||
<keyword>KDE</keyword>
|
||||
<keyword>kdenetwork</keyword>
|
||||
@@ -75,23 +50,9 @@ Please at least include KDE, the KDE package it is in, the name
|
||||
|
||||
</bookinfo>
|
||||
|
||||
<!-- The contents of the documentation begin here. Label
|
||||
each chapter so with the id attribute. This is necessary for two reasons: it
|
||||
allows you to easily reference the chapter from other chapters of your
|
||||
document, and if there is no ID, the name of the generated HTML files will vary
|
||||
from time to time making it hard to manage for maintainers and for the CVS
|
||||
system. Any chapter labelled (OPTIONAL) may be left out at the author's
|
||||
discretion. Other chapters should not be left out in order to maintain a
|
||||
consistent documentation style across all KDE apps. -->
|
||||
|
||||
<chapter id="introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<!-- The introduction chapter contains a brief introduction for the
|
||||
application that explains what it does and where to report
|
||||
problems. Basically a long version of the abstract. Don't include a
|
||||
revision history. (see installation appendix comment) -->
|
||||
|
||||
<para>
|
||||
&krfb; is a server application that allows you to share your current
|
||||
session with a user on another machine, who can use a <acronym>VNC</acronym> client to
|
||||
@@ -165,10 +126,8 @@ use &krfb; over other links, but performance is unlikely to be as good.
|
||||
<chapter id="using-krfb">
|
||||
<title>Using &krfb;</title>
|
||||
|
||||
<!-- This chapter should tell the user how to use your app. You should use as
|
||||
many sections (Chapter, Sect1, Sect3, etc...) as is necessary to fully document
|
||||
your application. -->
|
||||
|
||||
<sect1 id="main-windw">
|
||||
<title>&krfb; Main Window</title>
|
||||
<para>
|
||||
It is very easy to use &krfb; - it has a simple interface, as shown in
|
||||
the screenshot below.
|
||||
@@ -189,64 +148,69 @@ the screenshot below.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you want to allow someone to access your desktop, you can create
|
||||
an personal invitation using the <guibutton>New Personal
|
||||
Invitation...</guibutton> button, which will bring up a window
|
||||
containing the information needed to access your desktop. An example
|
||||
is shown below.
|
||||
When you want to allow someone to access your desktop, you have to
|
||||
enable the checkbox <guilabel>Enable Desktop Sharing</guilabel>,
|
||||
which will start the server.
|
||||
</para>
|
||||
|
||||
<sect2 id="connection-details">
|
||||
<title>Connection Details</title>
|
||||
|
||||
<para>
|
||||
The <guilabel>Address</guilabel> contains the address of your
|
||||
computer and the port number, separated by a colon.
|
||||
The address is just a hint - you can use any address that can
|
||||
reach your computer. &krfb; tries to guess your address from your
|
||||
network configuration, but does not always succeed in doing so.
|
||||
If your computer is behind a firewall it may have a different
|
||||
address or be unreachable for other computers.
|
||||
</para>
|
||||
<para>
|
||||
You can change the port on the <guilabel>Network</guilabel>
|
||||
page in the configuration dialog.
|
||||
</para>
|
||||
<para>
|
||||
The next field is prefilled with an automatically generated password.
|
||||
Click in the icon at the right of the field to change the password.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="unattended-access">
|
||||
<title>Unattended Access</title>
|
||||
|
||||
<para>
|
||||
Any remote user with the desktop sharing password will have to be authenticated.
|
||||
If unattended access is activated, and the remote user provides the password
|
||||
for unattended mode, desktop sharing access will be granted without explicit
|
||||
confirmation.
|
||||
</para>
|
||||
<para>
|
||||
By default the password for this mode is empty, to change that click on
|
||||
the button and enter a password.
|
||||
</para>
|
||||
<para>
|
||||
If unattended access is allowed, then you should probably specify a
|
||||
password.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<screenshot>
|
||||
<screeninfo>Example &krfb; personal invitation</screeninfo>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="personal_invitation.png" format="PNG"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>Example &krfb; personal invitation</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
If the machine is a server and you are using &krfb; for remote
|
||||
administration, you probably want to use unattended access.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To increase security, the invitation is only valid for an
|
||||
hour after it is created, and of course the person connecting has to
|
||||
have the correct password.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="transfer-login-information">
|
||||
<title>Transfer Login Information</title>
|
||||
|
||||
<para>
|
||||
Since you may want to invite someone to access your desktop by email,
|
||||
&krfb; can create invitations as email messages. You can create such
|
||||
an invitation using the <guibutton>New Email Invitation...</guibutton>
|
||||
button on the &krfb; main window. This will usually bring up an email
|
||||
message that looks like the following, ready for you to type in the
|
||||
email address of the person you are sending the invitation to.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<screenshot>
|
||||
<screeninfo>Example &krfb; email invitation</screeninfo>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="email_invitation.png" format="PNG"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>Example &krfb; email invitation</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
&krfb; will warn you about the security implications of sending this
|
||||
information across an insecure link. You must heed those warnings.
|
||||
&krfb; has no invitation feature any more as in previous versions.
|
||||
So you have to transfer the login information yourself using email
|
||||
or a personal invitation.
|
||||
</para>
|
||||
<para>
|
||||
If you cannot encrypt the email (or otherwise secure the link),
|
||||
sending invitations by email is a very serious security risk, since
|
||||
sending a password by email is a very serious security risk, since
|
||||
anyone can read the password and address from the email as it passes
|
||||
over the network. This means that they can potentially take control of
|
||||
your machine.
|
||||
@@ -255,33 +219,32 @@ your machine.
|
||||
If you cannot encrypt the email message, it may be better to use a
|
||||
personal invitation, telephone the person you are giving access to,
|
||||
verify the identity of that person, and provide the required
|
||||
invitation information that way.
|
||||
information that way.
|
||||
</para>
|
||||
</warning>
|
||||
|
||||
<sect1 id="krfb-managing-invitations">
|
||||
<title>Managing &krfb; invitations</title>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Having created an invitation (either a personal invitation or one that
|
||||
was sent by email), &krfb; main window allows you to delete existing
|
||||
invitations. To just delete one of the invitations, select it with the
|
||||
mouse (it should become highlighted), and then select
|
||||
the <guibutton>Delete</guibutton>. To delete all invitations, just
|
||||
select the <guibutton>Delete All</guibutton> button.
|
||||
&krfb; uses the normal <acronym>RFB</acronym> password system, which does not transfer
|
||||
your password in the clear across the network. Instead, it uses a
|
||||
challenge-response system. This is reasonably secure, as long as the
|
||||
password is securely guarded.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
</sect2>
|
||||
|
||||
<sect1 id="krfb-qit">
|
||||
<sect2 id="krfb-qqit">
|
||||
<title>Quit &krfb;</title>
|
||||
|
||||
<para>
|
||||
If you close the &krfb; main window the server keeps running, which is
|
||||
indicated by an icon in the system tray.
|
||||
To stop &krfb; right click on the icon in the systems tray and select
|
||||
If you close the &krfb; main window by clicking on the window close icon or using the
|
||||
shortcut <keycombo action="simul">&Alt;<keycap>F4</keycap></keycombo> the server
|
||||
keeps running, which is indicated by an icon in the system tray.
|
||||
To stop &krfb; either use <menuchoice><guimenu>File</guimenu><guimenuitem>Quit</guimenuitem></menuchoice>
|
||||
in the main window or right click on the icon in the system tray and select
|
||||
<guimenuitem>Quit</guimenuitem>.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
@@ -290,7 +253,7 @@ To stop &krfb; right click on the icon in the systems tray and select
|
||||
<para>
|
||||
In addition to the main &krfb; interface shown and described above,
|
||||
you can also control &krfb; using the
|
||||
<guibutton>Configure...</guibutton> on the &krfb; main window. The &krfb;
|
||||
<guimenuitem>Configure...</guimenuitem> on the &krfb; main window. The &krfb;
|
||||
configuration has two pages, as shown in the screenshot below:
|
||||
</para>
|
||||
|
||||
@@ -314,8 +277,8 @@ The <guilabel>Network</guilabel> page allows control over the port that
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Announce service on the network</guilabel> checkbox
|
||||
controls whether &krfb; announces invitations over the network using
|
||||
The <guilabel>Announce service on the local network</guilabel> checkbox
|
||||
controls whether &krfb; announces the service over the local network using
|
||||
Service Location Protocol. This is normally a good idea, but only
|
||||
works really well with a Service Location Protocol aware client, such
|
||||
as &krdc;.
|
||||
@@ -323,8 +286,8 @@ as &krdc;.
|
||||
|
||||
<para>
|
||||
If you select the <guilabel>Use default port</guilabel> checkbox,
|
||||
then &krfb; will locate a suitable port, and invitations will match
|
||||
this port. If you deselect this checkbox, you can specify a particular
|
||||
then &krfb; will locate a suitable port.
|
||||
If you deselect this checkbox, you can specify a particular
|
||||
port. Specifying a particular port may be useful if you are using
|
||||
port-forwarding on the firewall. Note that if Service Location
|
||||
Protocol is turned on, this will automatically deal with identifying
|
||||
@@ -332,8 +295,8 @@ the correct port.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Security</guilabel> page allows you configure settings
|
||||
related to access to the &krfb; server.
|
||||
The <guilabel>Security</guilabel> page allows you to configure whether the
|
||||
person connecting to the &krfb; server can control the desktop, or only view.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -350,41 +313,15 @@ related to access to the &krfb; server.
|
||||
</screenshot>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Allow uninvited connections</guilabel> check box controls
|
||||
whether &krfb; allows connection without an invitation. If uninvited
|
||||
connections are allowed, then you should probably specify a
|
||||
password. You can also use the check boxes here to choose whether you
|
||||
have to confirm the connection before it proceeds, and whether the
|
||||
person connecting can control the desktop, or only view.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the machine is a workstation, and you choose to allow uninvited
|
||||
connections, you probably want to select the <guilabel>Ask
|
||||
before accepting connections </guilabel>. Conversely, if the
|
||||
machine is a server and you are using &krfb; for remote
|
||||
administration, you probably want to deselect this option.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
&krfb; uses the normal <acronym>RFB</acronym> password system, which does not transfer
|
||||
your password in the clear across the network. Instead, it uses a
|
||||
challenge-response system. This is reasonably secure, as long as the
|
||||
password is securely guarded.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="krfb-connection">
|
||||
<title>What happens when someone connects to &krfb;</title>
|
||||
<title>Connecting to &krfb;</title>
|
||||
|
||||
<para>
|
||||
When someone connects to &krfb; on your machine, you will get a pop-up
|
||||
notification that looks like the following screenshot, unless you are
|
||||
accepting uninvited connections without warning.
|
||||
accepting unattended access without confirmation.
|
||||
</para>
|
||||
<para>
|
||||
<screenshot>
|
||||
@@ -402,8 +339,8 @@ accepting uninvited connections without warning.
|
||||
|
||||
<para>
|
||||
If you <guibutton>Accept Connection</guibutton>, the client can
|
||||
proceed to authenticate (which requires the correct password for a
|
||||
personal invitation or email invitation). If you <guibutton>Refuse
|
||||
proceed to authenticate, which requires the correct password for a
|
||||
login. If you <guibutton>Refuse
|
||||
Connection</guibutton>, then the attempt to connect will be terminated.
|
||||
</para>
|
||||
|
||||
@@ -413,23 +350,11 @@ mouse</guilabel> check box determines whether this client can only
|
||||
observe, or can take control of your machine.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the client connection is successful, and used the password from a
|
||||
personal invitation or email invitation, then that invitation is
|
||||
deleted and cannot be used again. You will also get a small pop-up
|
||||
window in the dock, that shows that the connection has been made.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="credits">
|
||||
|
||||
<!-- Include credits for the programmers, documentation writers, and
|
||||
contributors here. The license for your software should then be included below
|
||||
the credits with a reference to the appropriate license file included in the KDE
|
||||
distribution. -->
|
||||
|
||||
<title>Credits and License</title>
|
||||
|
||||
<para>
|
||||
@@ -458,33 +383,6 @@ Documentation Copyright © 2003 &Brad.Hards; &Brad.Hards.mail;
|
||||
|
||||
</chapter>
|
||||
|
||||
<appendix id="installation">
|
||||
<title>Installation</title>
|
||||
|
||||
<sect1 id="getting-krfb">
|
||||
<title>How to obtain &krfb;</title>
|
||||
|
||||
<!-- This first entity contains boiler plate for applications that are
|
||||
part of KDE CVS. You should remove it if you are releasing your
|
||||
application -->
|
||||
|
||||
&install.intro.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="compilation">
|
||||
<title>Compilation and Installation</title>
|
||||
|
||||
<!-- This entity contains the boilerplate text for standard -->
|
||||
<!-- compilation instructions. If your application requires any -->
|
||||
<!-- special handling, remove it, and replace with your own text. -->
|
||||
|
||||
&install.compile.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
|
||||
&documentation.index;
|
||||
</book>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 33 KiB |
@@ -1,3 +1,5 @@
|
||||
add_subdirectory (qt)
|
||||
add_subdirectory (x11)
|
||||
|
||||
if (${XCB_DAMAGE_FOUND} AND ${XCB_SHM_FOUND} AND ${XCB_IMAGE_FOUND})
|
||||
add_subdirectory (xcb)
|
||||
endif()
|
||||
|
||||
@@ -7,22 +7,18 @@ set (krfb_framebuffer_qt_SRCS
|
||||
qtframebufferplugin.cpp
|
||||
)
|
||||
|
||||
kde4_add_plugin (krfb_framebuffer_qt
|
||||
add_library(krfb_framebuffer_qt
|
||||
MODULE
|
||||
${krfb_framebuffer_qt_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_framebuffer_qt
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${KDE4_KDEUI_LIBS}
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
KF5::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_qt
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
|
||||
install (FILES krfb_framebuffer_qt.desktop
|
||||
DESTINATION ${SERVICES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=Qt based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema Qt de buffer pa KRfb
|
||||
Comment[ast]=Búfer de cuadros basáu en Qt pa KRfb.
|
||||
Comment[bg]=Основан на Qt фреймбуфер за KRfb.
|
||||
Comment[bs]=Kadrobafer za KRfb na osnovu Qt
|
||||
Comment[ca]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[bs]=Kadrobafer za KRfb na osnovu Qt.
|
||||
Comment[ca]=«Framebuffer» basat en les Qt per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en les Qt per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na Qt pro KRfb.
|
||||
Comment[da]=Qt-baseret framebuffer til KRfb.
|
||||
Comment[de]=Qt-basierter Framebuffer für KRfb
|
||||
@@ -49,11 +49,11 @@ Comment[x-test]=xxQt based Framebuffer for KRfb.xx
|
||||
Comment[zh_CN]=基于 Qt 的 KRfb 帧缓冲机制
|
||||
Comment[zh_TW]=KRfb 的 Qt-based Framebuffer
|
||||
Name=Qt Framebuffer for KRfb
|
||||
Name[ast]=Esquema Qt de buffer pa KRfb
|
||||
Name[ast]=Búfer de cuadros Qt pa KRfb
|
||||
Name[bg]=Qt фреймбуфер за KRfb
|
||||
Name[bs]=Qt-ov kadrobafer za KRFB
|
||||
Name[ca]=«Framebuffer» Qt per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» Qt per al KRfb.
|
||||
Name[ca]=«Framebuffer» de les Qt per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» de les Qt per al KRfb.
|
||||
Name[cs]=Qt Framebuffer pro KRfb
|
||||
Name[da]=Qt-framebuffer til KRfb
|
||||
Name[de]=Qt-Framebuffer für KRfb
|
||||
|
||||
81
framebuffers/qt/krfb_framebuffer_qt.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "Qt based Framebuffer for KRfb.",
|
||||
"Description[ast]": "Búfer de cuadros basáu en Qt pa KRfb.",
|
||||
"Description[ca@valencia]": "«Framebuffer» basat en les Qt per al KRfb.",
|
||||
"Description[ca]": "«Framebuffer» basat en les Qt per al KRfb.",
|
||||
"Description[cs]": "Framebuffer založený na Qt pro KRfb.",
|
||||
"Description[da]": "Qt-baseret framebuffer til KRfb.",
|
||||
"Description[de]": "Qt-basierter Framebuffer für KRfb",
|
||||
"Description[el]": "Μνήμη ανανέωσης βίντεο με βάση τhn Qt για το KRfb.",
|
||||
"Description[es]": "Framebuffer basado en Qt para KRfb.",
|
||||
"Description[et]": "KRfb Qt põhine kaadripuhver",
|
||||
"Description[fi]": "QT-perustainen Kehyspuskuri KRfb:lle",
|
||||
"Description[fr]": "Tampon d'images utilisant Qt pour KRfb.",
|
||||
"Description[gl]": "Framebuffer baseado en Qt para KRfb.",
|
||||
"Description[ia]": "Framebuffer basate sur Qt per KRfb",
|
||||
"Description[it]": "Framebuffer basato su Qt per KRfb.",
|
||||
"Description[ko]": "KRfb용 Qt 기반 프레임버퍼입니다.",
|
||||
"Description[nl]": "Op Qt gebaseerd framebuffer voor KRfb.",
|
||||
"Description[nn]": "Qt-basert biletbuffer for KRfb.",
|
||||
"Description[pl]": "Bufor ramki na podstawie Qt dla KRfb.",
|
||||
"Description[pt]": "'Framebuffer' baseado no Qt para o KRfb.",
|
||||
"Description[pt_BR]": "Framebuffer baseado no Qt para o KRfb.",
|
||||
"Description[ru]": "Буфер кадров для KRfb на базе Qt",
|
||||
"Description[sk]": "Framebuffer založený na Qt pre KRfb.",
|
||||
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na Qt",
|
||||
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu Qt‑u",
|
||||
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu Qt‑u",
|
||||
"Description[sr]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sv]": "X11-rambuffert för Krfb.",
|
||||
"Description[tr]": "KRfb için Qt tabanlı Çerçeve tamponu.",
|
||||
"Description[uk]": "Заснований на Qt буфер кадрів для KRfb.",
|
||||
"Description[x-test]": "xxQt based Framebuffer for KRfb.xx",
|
||||
"Description[zh_CN]": "KRfb 的基于 Qt 的帧缓冲。",
|
||||
"Description[zh_TW]": "KRfb 的 Qt-based Framebuffer",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "qt",
|
||||
"License": "GPL",
|
||||
"Name": "Qt Framebuffer for KRfb",
|
||||
"Name[ast]": "Búfer de cuadros Qt pa KRfb",
|
||||
"Name[ca@valencia]": "«Framebuffer» de les Qt per al KRfb.",
|
||||
"Name[ca]": "«Framebuffer» de les Qt per al KRfb.",
|
||||
"Name[cs]": "Qt Framebuffer pro KRfb",
|
||||
"Name[da]": "Qt-framebuffer til KRfb",
|
||||
"Name[de]": "Qt-Framebuffer für KRfb",
|
||||
"Name[el]": "Μνήμη ανανέωσης βίντεο Qt για το KRfb",
|
||||
"Name[es]": "Framebuffer de Qt para KRfb",
|
||||
"Name[et]": "KRfb Qt kaadripuhver",
|
||||
"Name[fi]": "QT-kehyspuskuri KRfb:lle",
|
||||
"Name[fr]": "Tampon d'images Qt pour KRfb",
|
||||
"Name[gl]": "Framebuffer de Qt para KRfb",
|
||||
"Name[ia]": "Framebuffer Qt per KRfb",
|
||||
"Name[it]": "Framebuffer Qt per KRfb",
|
||||
"Name[ko]": "KRfb용 Qt 프레임버퍼",
|
||||
"Name[nl]": "Qt-framebuffer voor KRfb",
|
||||
"Name[nn]": "Qt-biletbuffer for KRfb",
|
||||
"Name[pl]": "Bufor ramki Qt dla KRfb",
|
||||
"Name[pt]": "'Framebuffer' do Qt para o KRfb",
|
||||
"Name[pt_BR]": "Framebuffer do Qt para o KRfb",
|
||||
"Name[ru]": "Буфер кадров Qt для KRfb",
|
||||
"Name[sk]": "Qt Framebuffer pre KRfb",
|
||||
"Name[sl]": "Slikovni medpomnilnik Qt za KRfb",
|
||||
"Name[sr@ijekavian]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sr@ijekavianlatin]": "Qt‑ov kadrobafer za KRFB",
|
||||
"Name[sr@latin]": "Qt‑ov kadrobafer za KRFB",
|
||||
"Name[sr]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sv]": "X11-rambuffert för Krfb",
|
||||
"Name[tr]": "KRfb için Qt Çerçeve tamponu",
|
||||
"Name[uk]": "Буфер кадрів на Qt для KRfb",
|
||||
"Name[x-test]": "xxQt Framebuffer for KRfbxx",
|
||||
"Name[zh_CN]": "KRfb 的 Qt 帧缓冲",
|
||||
"Name[zh_TW]": "Krfb 的 Qt Framebuffer",
|
||||
"ServiceTypes": [
|
||||
"krfb/framebuffer"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <QRegion>
|
||||
#include <QPixmap>
|
||||
#include <QBitmap>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
|
||||
const int UPDATE_TIME = 500;
|
||||
@@ -21,16 +23,25 @@ const int UPDATE_TIME = 500;
|
||||
QtFrameBuffer::QtFrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent)
|
||||
{
|
||||
fbImage = QPixmap::grabWindow(win).toImage();
|
||||
fb = new char[fbImage.numBytes()];
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
if (screen) {
|
||||
primaryScreen = screen;
|
||||
fbImage = screen->grabWindow(win).toImage();
|
||||
fb = new char[fbImage.byteCount()];
|
||||
} else {
|
||||
fb = Q_NULLPTR;
|
||||
primaryScreen = Q_NULLPTR;
|
||||
}
|
||||
|
||||
t = new QTimer(this);
|
||||
connect(t, SIGNAL(timeout()), SLOT(updateFrameBuffer()));
|
||||
connect(t, &QTimer::timeout, this, &QtFrameBuffer::updateFrameBuffer);
|
||||
}
|
||||
|
||||
|
||||
QtFrameBuffer::~QtFrameBuffer()
|
||||
{
|
||||
delete [] fb;
|
||||
if (fb)
|
||||
delete [] fb;
|
||||
fb = 0;
|
||||
}
|
||||
|
||||
@@ -66,7 +77,9 @@ void QtFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
|
||||
void QtFrameBuffer::updateFrameBuffer()
|
||||
{
|
||||
QImage img = QPixmap::grabWindow(win).toImage();
|
||||
if (!fb || !primaryScreen) return;
|
||||
QImage img = primaryScreen->grabWindow(win).toImage();
|
||||
#if 0 // This is actually slower than updating the whole desktop...
|
||||
QSize imgSize = img.size();
|
||||
|
||||
|
||||
@@ -74,8 +87,6 @@ void QtFrameBuffer::updateFrameBuffer()
|
||||
// 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);
|
||||
|
||||
@@ -94,7 +105,7 @@ void QtFrameBuffer::updateFrameBuffer()
|
||||
tiles.append(img.rect());
|
||||
#endif
|
||||
|
||||
memcpy(fb, (const char *)img.bits(), img.numBytes());
|
||||
memcpy(fb, (const char *)img.bits(), img.byteCount());
|
||||
fbImage = img;
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "framebuffer.h"
|
||||
|
||||
class QTimer;
|
||||
class QScreen;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
@@ -25,13 +26,13 @@ public:
|
||||
|
||||
~QtFrameBuffer();
|
||||
|
||||
virtual int depth();
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
virtual void startMonitor();
|
||||
virtual void stopMonitor();
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateFrameBuffer();
|
||||
@@ -39,6 +40,7 @@ public Q_SLOTS:
|
||||
private:
|
||||
QImage fbImage;
|
||||
QTimer *t;
|
||||
QScreen *primaryScreen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
#include "qtframebuffer.h"
|
||||
|
||||
#include <KGenericFactory>
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(QtFrameBufferPluginFactory, "krfb_framebuffer_qt.json",
|
||||
registerPlugin<QtFrameBufferPlugin>();)
|
||||
|
||||
QtFrameBufferPlugin::QtFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
@@ -39,9 +41,5 @@ FrameBuffer *QtFrameBufferPlugin::frameBuffer(WId id)
|
||||
return new QtFrameBuffer(id);
|
||||
}
|
||||
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<QtFrameBufferPlugin>();) \
|
||||
K_EXPORT_PLUGIN(factory("krfb_framebuffer_qt"))
|
||||
|
||||
|
||||
#include "qtframebufferplugin.moc"
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
#include <kdemacros.h>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
@@ -37,7 +35,7 @@ public:
|
||||
QtFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~QtFrameBufferPlugin();
|
||||
|
||||
virtual FrameBuffer *frameBuffer(WId id);
|
||||
FrameBuffer *frameBuffer(WId id) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QtFrameBufferPlugin)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_x11_SRCS
|
||||
x11framebuffer.cpp
|
||||
x11framebufferplugin.cpp
|
||||
)
|
||||
|
||||
kde4_add_plugin (krfb_framebuffer_x11
|
||||
${krfb_framebuffer_x11_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_framebuffer_x11
|
||||
${KDE4_KDEUI_LIBS}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
${X11_Xext_LIB}
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_x11
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install (FILES krfb_framebuffer_x11.desktop
|
||||
DESTINATION ${SERVICES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
/* 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; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "x11framebuffer.h"
|
||||
#include "x11framebuffer.moc"
|
||||
|
||||
#include <config-krfb.h>
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include <KApplication>
|
||||
#include <KDebug>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#endif
|
||||
|
||||
class X11FrameBuffer::P
|
||||
{
|
||||
|
||||
public:
|
||||
#ifdef HAVE_XDAMAGE
|
||||
Damage damage;
|
||||
#endif
|
||||
#ifdef HAVE_XSHM
|
||||
XShmSegmentInfo shminfo;
|
||||
#endif
|
||||
|
||||
XImage *framebufferImage;
|
||||
XImage *updateTile;
|
||||
EvWidget *ev;
|
||||
bool useShm;
|
||||
int xdamageBaseEvent;
|
||||
bool running;
|
||||
};
|
||||
|
||||
X11FrameBuffer::X11FrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent), d(new X11FrameBuffer::P)
|
||||
{
|
||||
#ifdef HAVE_XSHM
|
||||
d->useShm = XShmQueryExtension(QX11Info::display());
|
||||
kDebug() << "shm: " << d->useShm;
|
||||
#else
|
||||
d->useShm = false;
|
||||
#endif
|
||||
d->running = false;
|
||||
d->framebufferImage = XGetImage(QX11Info::display(),
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(), //arg, must get a widget ???
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
d->updateTile = XShmCreateImage(QX11Info::display(),
|
||||
DefaultVisual(QX11Info::display(), 0),
|
||||
d->framebufferImage->bits_per_pixel,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&d->shminfo,
|
||||
32,
|
||||
32);
|
||||
d->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
d->updateTile->bytes_per_line * d->updateTile->height,
|
||||
IPC_CREAT | 0777);
|
||||
|
||||
d->shminfo.shmaddr = d->updateTile->data = (char *)
|
||||
shmat(d->shminfo.shmid, 0, 0);
|
||||
d->shminfo.readOnly = False;
|
||||
|
||||
XShmAttach(QX11Info::display(), &d->shminfo);
|
||||
#endif
|
||||
} else {
|
||||
;
|
||||
}
|
||||
|
||||
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);
|
||||
kapp->installX11EventFilter(d->ev);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
X11FrameBuffer::~X11FrameBuffer()
|
||||
{
|
||||
XDestroyImage(d->framebufferImage);
|
||||
#ifdef HAVE_XDAMAGE
|
||||
kapp->removeX11EventFilter(d->ev);
|
||||
#endif
|
||||
#ifdef HAVE_XSHM
|
||||
XShmDetach(QX11Info::display(), &d->shminfo);
|
||||
XDestroyImage(d->updateTile);
|
||||
shmdt(d->shminfo.shmaddr);
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, 0);
|
||||
#endif
|
||||
delete d;
|
||||
fb = 0; // already deleted by XDestroyImage
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
/*if (!dev->more) {
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
}*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void X11FrameBuffer::cleanupRects()
|
||||
{
|
||||
|
||||
QList<QRect> cpy = tiles;
|
||||
bool inserted = false;
|
||||
tiles.clear();
|
||||
// kDebug() << "before cleanup: " << cpy.size();
|
||||
foreach(const QRect & r, cpy) {
|
||||
if (tiles.size() > 0) {
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
// kDebug() << r << tiles[i];
|
||||
if (r.intersects(tiles[i])) {
|
||||
tiles[i] |= r;
|
||||
inserted = true;
|
||||
break;
|
||||
// kDebug() << "merged into " << tiles[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
tiles.append(r);
|
||||
// kDebug() << "appended " << r;
|
||||
}
|
||||
} else {
|
||||
// kDebug() << "appended " << r;
|
||||
tiles.append(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
tiles[i].adjust(-30, -30, 30, 30);
|
||||
|
||||
if (tiles[i].top() < 0) {
|
||||
tiles[i].setTop(0);
|
||||
}
|
||||
|
||||
if (tiles[i].left() < 0) {
|
||||
tiles[i].setLeft(0);
|
||||
}
|
||||
|
||||
if (tiles[i].bottom() > d->framebufferImage->height) {
|
||||
tiles[i].setBottom(d->framebufferImage->height);
|
||||
}
|
||||
|
||||
if (tiles[i].right() > d->framebufferImage->width) {
|
||||
tiles[i].setRight(d->framebufferImage->width);
|
||||
}
|
||||
}
|
||||
|
||||
// kDebug() << "after cleanup: " << tiles.size();
|
||||
}
|
||||
|
||||
void X11FrameBuffer::acquireEvents()
|
||||
{
|
||||
|
||||
XEvent ev;
|
||||
|
||||
while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
|
||||
handleXDamage(&ev);
|
||||
}
|
||||
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
}
|
||||
|
||||
QList< QRect > X11FrameBuffer::modifiedTiles()
|
||||
{
|
||||
QList<QRect> ret;
|
||||
|
||||
if (!d->running) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
kapp->processEvents(); // try to make sure every damage event goes trough;
|
||||
cleanupRects();
|
||||
QRect gl;
|
||||
|
||||
//d->useShm = false;
|
||||
if (tiles.size() > 0) {
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
|
||||
foreach(const QRect & r, tiles) {
|
||||
// kDebug() << r;
|
||||
gl |= r;
|
||||
int y = r.y();
|
||||
int x = r.x();
|
||||
|
||||
while (x < r.right()) {
|
||||
while (y < r.bottom()) {
|
||||
if (y + d->updateTile->height > d->framebufferImage->height) {
|
||||
y = d->framebufferImage->height - d->updateTile->height;
|
||||
}
|
||||
|
||||
if (x + d->updateTile->width > d->framebufferImage->width) {
|
||||
x = d->framebufferImage->width - d->updateTile->width;
|
||||
}
|
||||
|
||||
// kDebug() << "x: " << x << " (" << r.x() << ") y: " << y << " (" << r.y() << ") " << r;
|
||||
XShmGetImage(QX11Info::display(), win, d->updateTile, x, y, AllPlanes);
|
||||
int pxsize = d->framebufferImage->bits_per_pixel / 8;
|
||||
char *dest = fb + ((d->framebufferImage->bytes_per_line * y) + (x * pxsize));
|
||||
char *src = d->updateTile->data;
|
||||
|
||||
for (int i = 0; i < d->updateTile->height; i++) {
|
||||
memcpy(dest, src, d->updateTile->bytes_per_line);
|
||||
dest += d->framebufferImage->bytes_per_line;
|
||||
src += d->updateTile->bytes_per_line;
|
||||
}
|
||||
|
||||
y += d->updateTile->height;
|
||||
}
|
||||
|
||||
x += d->updateTile->width;
|
||||
y = r.y();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
foreach(const QRect & r, tiles) {
|
||||
XGetSubImage(QX11Info::display(),
|
||||
win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
AllPlanes,
|
||||
ZPixmap,
|
||||
d->framebufferImage,
|
||||
r.left(),
|
||||
r.top()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// kDebug() << "tot: " << gl;
|
||||
// kDebug() << tiles.size();
|
||||
ret = tiles;
|
||||
tiles.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11FrameBuffer::startMonitor()
|
||||
{
|
||||
d->running = true;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
d->damage = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11FrameBuffer::stopMonitor()
|
||||
{
|
||||
d->running = false;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageDestroy(QX11Info::display(), d->damage);
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/* 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; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#ifndef KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_X11_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 = 0);
|
||||
|
||||
~X11FrameBuffer();
|
||||
|
||||
virtual QList<QRect> modifiedTiles();
|
||||
virtual int depth();
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
virtual void startMonitor();
|
||||
virtual void stopMonitor();
|
||||
|
||||
|
||||
void handleXDamage(XEvent *event);
|
||||
private:
|
||||
void cleanupRects();
|
||||
void acquireEvents();
|
||||
|
||||
class P;
|
||||
P *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "x11framebufferplugin.h"
|
||||
|
||||
#include "x11framebuffer.h"
|
||||
|
||||
#include <KGenericFactory>
|
||||
|
||||
|
||||
X11FrameBufferPlugin::X11FrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
X11FrameBufferPlugin::~X11FrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *X11FrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
return new X11FrameBuffer(id);
|
||||
}
|
||||
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<X11FrameBufferPlugin>();) \
|
||||
K_EXPORT_PLUGIN(factory("krfb_framebuffer_x11"))
|
||||
|
||||
|
||||
#include "x11framebufferplugin.moc"
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
#include <kdemacros.h>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class X11FrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
X11FrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~X11FrameBufferPlugin();
|
||||
|
||||
virtual FrameBuffer *frameBuffer(WId id);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(X11FrameBufferPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
28
framebuffers/xcb/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_xcb_SRCS
|
||||
xcb_framebufferplugin.cpp
|
||||
xcb_framebuffer.cpp
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_xcb MODULE ${krfb_framebuffer_xcb_SRCS})
|
||||
|
||||
target_link_libraries (krfb_framebuffer_xcb
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
XCB::XCB
|
||||
XCB::RENDER
|
||||
XCB::SHAPE
|
||||
XCB::XFIXES
|
||||
XCB::DAMAGE
|
||||
XCB::SHM
|
||||
XCB::IMAGE
|
||||
KF5::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_xcb
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
@@ -1,11 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=X11 XDamage/XShm based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema de buffer pa KRfb basáu en XDamage/XShm
|
||||
Comment[ast]=Búfer de cuadros basáu en XDamage/XShm de X11 pa KRfb.
|
||||
Comment[bg]=Основан на X11 XDamage/XShm фреймбуфер за KRfb.
|
||||
Comment[bs]=X11 XDamage/XShm baziran framebafer za KRfb.
|
||||
Comment[ca]=«Framebuffer» basat en XDamage/XShmQt de l'X11 per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en XDamage/XShmQt de l'X11 per al KRfb.
|
||||
Comment[ca]=«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na X11 XDamage/XShm pro KRfb.
|
||||
Comment[da]=X11 XDamage/XShm-baseret framebuffer til KRfb.
|
||||
Comment[de]=X11 XDamage/XShm-basierter Framebuffer für KRfb.
|
||||
@@ -17,7 +17,7 @@ Comment[eu]=X11 XDamage/XShm oinarritutako KRfb-ren irteerako bideoa.
|
||||
Comment[fi]=X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.
|
||||
Comment[fr]=Sortie vidéo fondée sur X11 « XDamage / XShm » pour Krfb.
|
||||
Comment[ga]=Maolán fráma le haghaidh KRfb, bunaithe ar X11 XDamage/XShm
|
||||
Comment[gl]=Framebuffer baseado en Xll XDamage/Xshm para XRfb.
|
||||
Comment[gl]=Framebuffer baseado en X11 XDamage/Xshm para XRfb.
|
||||
Comment[hr]=Međuspreminik okvira baziran na X11 XDamage/XShm za KRfb.
|
||||
Comment[hu]=X11 XDamage/XShm-alapú framebuffer a Krfb-hez.
|
||||
Comment[ia]=Framebuffer basate sur X11 XDamage/XShm per KRfb.
|
||||
@@ -49,11 +49,11 @@ Comment[x-test]=xxX11 XDamage/XShm based Framebuffer for KRfb.xx
|
||||
Comment[zh_CN]=基于 X11 XDamage/XShm 扩展的 KRfb 帧缓冲机制。
|
||||
Comment[zh_TW]=KRfb 的 X11 XDamage/XShm based Framebuffer
|
||||
Name=X11 Framebuffer for KRfb
|
||||
Name[ast]=Buffer de X11 pa KRfb
|
||||
Name[ast]=Búfer de cuadros de X11 pa KRfb
|
||||
Name[bg]=X11 фреймбуфер за KRfb
|
||||
Name[bs]=X11 frame bafer za KRfb
|
||||
Name[ca]=«Framebuffer» de l'X11 per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» de l'X11 per al KRfb.
|
||||
Name[ca]=«Framebuffer» del X11 per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» del X11 per al KRfb.
|
||||
Name[cs]=X11 Framebuffer pro KRfb
|
||||
Name[da]=X11-framebuffer til KRfb
|
||||
Name[de]=X11-Framebuffer für KRfb
|
||||
@@ -99,8 +99,8 @@ Name[zh_TW]=KRfb 的 X11 Framebuffer
|
||||
Type=Service
|
||||
ServiceTypes=krfb/framebuffer
|
||||
|
||||
X-KDE-Library=krfb_framebuffer_x11
|
||||
X-KDE-PluginInfo-Name=x11
|
||||
X-KDE-Library=krfb_framebuffer_xcb
|
||||
X-KDE-PluginInfo-Name=xcb
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://www.kde.org
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
81
framebuffers/xcb/krfb_framebuffer_xcb.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "X11 XDamage/XShm based Framebuffer for KRfb.",
|
||||
"Description[ast]": "Búfer de cuadros basáu en XDamage/XShm de X11 pa KRfb.",
|
||||
"Description[ca@valencia]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
|
||||
"Description[ca]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
|
||||
"Description[cs]": "Framebuffer založený na X11 XDamage/XShm pro KRfb.",
|
||||
"Description[da]": "X11 XDamage/XShm-baseret framebuffer til KRfb.",
|
||||
"Description[de]": "X11 XDamage/XShm-basierter Framebuffer für KRfb.",
|
||||
"Description[el]": "Μνήμη ανανέωσης βίντεο με βάση το X11 XDamage/XShm για το KRfb.",
|
||||
"Description[es]": "Framebuffer basado en XDamage/XShm de X11 para KRfb.",
|
||||
"Description[et]": "KRfb X11 XDamage/XShm põhine kaadripuhver",
|
||||
"Description[fi]": "X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.",
|
||||
"Description[fr]": "Tampon d'images utilisant XDamage/XShm de X11 pour KRfb.",
|
||||
"Description[gl]": "Framebuffer baseado en X11 XDamage/Xshm para XRfb.",
|
||||
"Description[ia]": "Framebuffer basate sur X11 XDamage/XShm per KRfb.",
|
||||
"Description[it]": "Framebuffer basato su XDamage/XShm di X11 per KRfb.",
|
||||
"Description[ko]": "KRfb용 X11 XDamage/XShm 기반 프레임버퍼입니다.",
|
||||
"Description[nl]": "Op X11 XDamage/XShm gebaseerd framebuffer voor KRfb.",
|
||||
"Description[nn]": "X11 XDamage/XShm-basert biletbuffer for KRfb.",
|
||||
"Description[pl]": "Bufor ramki na podstawie X11 XDamage/XShm dla KRfb.",
|
||||
"Description[pt]": "'Framebuffer' do X11, baseado no XDamage/XShm, para o KRfb.",
|
||||
"Description[pt_BR]": "Framebuffer baseado no XDamage/XShm do X11 para o KRfb.",
|
||||
"Description[ru]": "Буфер кадров для KRfb на базе X11 XDamage/XShm",
|
||||
"Description[sk]": "Framebuffer založený na X11 XDamage/XShm pre KRfb.",
|
||||
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na X11 XDamage/XShm",
|
||||
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.",
|
||||
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
|
||||
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
|
||||
"Description[sr]": "Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.",
|
||||
"Description[sv]": "X11 XDamage/XShm-baserad rambuffert för Krfb.",
|
||||
"Description[tr]": "KRfb için X11 XDamage/XShm tabanlı Çerçeve tamponu.",
|
||||
"Description[uk]": "Заснований на XDamage/XShm X11 буфер кадрів для KRfb.",
|
||||
"Description[x-test]": "xxX11 XDamage/XShm based Framebuffer for KRfb.xx",
|
||||
"Description[zh_CN]": "KRfb 的基于 X11 XDamage/XShm 的帧缓冲。",
|
||||
"Description[zh_TW]": "KRfb 的 X11 XDamage/XShm based Framebuffer",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "xcb",
|
||||
"License": "GPL",
|
||||
"Name": "X11 Framebuffer for KRfb",
|
||||
"Name[ast]": "Búfer de cuadros de X11 pa KRfb",
|
||||
"Name[ca@valencia]": "«Framebuffer» del X11 per al KRfb.",
|
||||
"Name[ca]": "«Framebuffer» del X11 per al KRfb.",
|
||||
"Name[cs]": "X11 Framebuffer pro KRfb",
|
||||
"Name[da]": "X11-framebuffer til KRfb",
|
||||
"Name[de]": "X11-Framebuffer für KRfb",
|
||||
"Name[el]": "Μνήμη ανανέωσης βίντεο X11 για το KRfb.",
|
||||
"Name[es]": "Framebuffer X11 para KRfb",
|
||||
"Name[et]": "KRfb X11 kaadripuhver",
|
||||
"Name[fi]": "X11-kehyspuskuri KRfb:lle",
|
||||
"Name[fr]": "Tampon d'images X11 pour KRfb",
|
||||
"Name[gl]": "Framebuffer de X11 para KRfb",
|
||||
"Name[ia]": "Framebuffer X11 per KRfb",
|
||||
"Name[it]": "Framebuffer X11 per KRfb",
|
||||
"Name[ko]": "KRfb용 X11 프레임버퍼",
|
||||
"Name[nl]": "X11 framebuffer voor KRfb",
|
||||
"Name[nn]": "X11-biletbuffer for KRfb",
|
||||
"Name[pl]": "Bufor ramki X11 dla KRfb",
|
||||
"Name[pt]": "'Framebuffer' do X11 para o KRfb",
|
||||
"Name[pt_BR]": "Framebuffer do X11 para o KRfb",
|
||||
"Name[ru]": "Буфер кадров X11 для KRfb",
|
||||
"Name[sk]": "X11 Framebuffer pre KRfb",
|
||||
"Name[sl]": "Slikovni medpomnilnik X11 za KRfb",
|
||||
"Name[sr@ijekavian]": "Икс11 кадробафер за КРФБ.",
|
||||
"Name[sr@ijekavianlatin]": "X11 kadrobafer za KRFB.",
|
||||
"Name[sr@latin]": "X11 kadrobafer za KRFB.",
|
||||
"Name[sr]": "Икс11 кадробафер за КРФБ.",
|
||||
"Name[sv]": "X11-rambuffert för Krfb",
|
||||
"Name[tr]": "KRfb için X11 Çerçeve tamponu",
|
||||
"Name[uk]": "Буфер кадрів X11 для KRfb",
|
||||
"Name[x-test]": "xxX11 Framebuffer for KRfbxx",
|
||||
"Name[zh_CN]": "XRfb 的 X11 帧缓冲",
|
||||
"Name[zh_TW]": "KRfb 的 X11 Framebuffer",
|
||||
"ServiceTypes": [
|
||||
"krfb/framebuffer"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
685
framebuffers/xcb/xcb_framebuffer.cpp
Normal file
@@ -0,0 +1,685 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2017 Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
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 "xcb_framebuffer.h"
|
||||
#include "xcb_framebuffer.moc"
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
#include <xcb/damage.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QCoreApplication>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
class KrfbXCBEventFilter: public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
KrfbXCBEventFilter(XCBFrameBuffer *owner);
|
||||
|
||||
public:
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
|
||||
|
||||
public:
|
||||
int xdamageBaseEvent;
|
||||
int xdamageBaseError;
|
||||
int xshmBaseEvent;
|
||||
int xshmBaseError;
|
||||
bool xshmAvail;
|
||||
XCBFrameBuffer *fb_owner;
|
||||
};
|
||||
|
||||
|
||||
|
||||
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
|
||||
xdamageBaseEvent(0), xdamageBaseError(0),
|
||||
xshmBaseEvent(0), xshmBaseError(0), xshmAvail(false),
|
||||
fb_owner(owner)
|
||||
{
|
||||
const xcb_query_extension_reply_t *xdamage_data = xcb_get_extension_data(
|
||||
QX11Info::connection(), &xcb_damage_id);
|
||||
if (xdamage_data) {
|
||||
// also query extension version!
|
||||
// ATTENTION: if we don't do that, xcb_damage_create() will always FAIL!
|
||||
xcb_damage_query_version_reply_t *xdamage_version = xcb_damage_query_version_reply(
|
||||
QX11Info::connection(),
|
||||
xcb_damage_query_version(
|
||||
QX11Info::connection(),
|
||||
XCB_DAMAGE_MAJOR_VERSION,
|
||||
XCB_DAMAGE_MINOR_VERSION),
|
||||
NULL);
|
||||
if (!xdamage_version) {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get XDamage extension version!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
qDebug() << "xcb framebuffer: XDamage extension version:" <<
|
||||
xdamage_version->major_version << "." << xdamage_version->minor_version;
|
||||
#endif
|
||||
|
||||
free(xdamage_version);
|
||||
|
||||
xdamageBaseEvent = xdamage_data->first_event;
|
||||
xdamageBaseError = xdamage_data->first_error;
|
||||
|
||||
// XShm presence is optional. If it is present, all image getting
|
||||
// operations will be faster, without XShm it will only be slower.
|
||||
const xcb_query_extension_reply_t *xshm_data = xcb_get_extension_data(
|
||||
QX11Info::connection(), &xcb_shm_id);
|
||||
if (xshm_data) {
|
||||
xshmAvail = true;
|
||||
xshmBaseEvent = xshm_data->first_event;
|
||||
xshmBaseError = xshm_data->first_error;
|
||||
} else {
|
||||
xshmAvail = false;
|
||||
qWarning() << "xcb framebuffer: WARNING: XSHM extension not available!";
|
||||
}
|
||||
} else {
|
||||
// if there is no xdamage available, this plugin can be considered useless anyway.
|
||||
// you can use just qt framebuffer plugin instead...
|
||||
qWarning() << "xcb framebuffer: ERROR: no XDamage extension available. I am useless.";
|
||||
qWarning() << "xcb framebuffer: use qt framebuffer plugin instead.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||
void *message, long *result) {
|
||||
Q_UNUSED(result); // "result" is only used on windows
|
||||
|
||||
if (xdamageBaseEvent == 0) return false; // no xdamage extension
|
||||
|
||||
if (eventType == "xcb_generic_event_t") {
|
||||
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
|
||||
if ((ev->response_type & 0x7F) == (xdamageBaseEvent + XCB_DAMAGE_NOTIFY)) {
|
||||
// this is xdamage notification
|
||||
this->fb_owner->handleXDamageNotify(ev);
|
||||
return true; // filter out this event, stop its processing
|
||||
}
|
||||
}
|
||||
|
||||
// continue event processing
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class XCBFrameBuffer::P {
|
||||
public:
|
||||
xcb_damage_damage_t damage;
|
||||
xcb_shm_segment_info_t shminfo;
|
||||
xcb_screen_t *rootScreen; // X screen info (all monitors)
|
||||
xcb_image_t *framebufferImage;
|
||||
xcb_image_t *updateTile;
|
||||
|
||||
KrfbXCBEventFilter *x11EvtFilter;
|
||||
|
||||
bool running;
|
||||
|
||||
QRect area; // capture area, primary monitor coordinates
|
||||
};
|
||||
|
||||
|
||||
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num) {
|
||||
xcb_screen_t *screen = NULL;
|
||||
xcb_screen_iterator_t screens_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
|
||||
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter))
|
||||
if (screen_num == 0)
|
||||
screen = screens_iter.data;
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
XCBFrameBuffer::XCBFrameBuffer(WId winid, QObject *parent):
|
||||
FrameBuffer(winid, parent), d(new XCBFrameBuffer::P)
|
||||
{
|
||||
d->running = false;
|
||||
d->damage = XCB_NONE;
|
||||
d->framebufferImage = Q_NULLPTR;
|
||||
d->shminfo.shmaddr = Q_NULLPTR;
|
||||
d->shminfo.shmid = XCB_NONE;
|
||||
d->shminfo.shmseg = XCB_NONE;
|
||||
d->updateTile = Q_NULLPTR;
|
||||
d->area.setRect(0, 0, 0, 0);
|
||||
d->x11EvtFilter = new KrfbXCBEventFilter(this);
|
||||
d->rootScreen = get_xcb_screen(QX11Info::connection(), QX11Info::appScreen());
|
||||
|
||||
this->fb = Q_NULLPTR;
|
||||
|
||||
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||
if (primaryScreen) {
|
||||
qDebug() << "xcb framebuffer: Primary screen: " << primaryScreen->name()
|
||||
<< ", geometry: " << primaryScreen->geometry()
|
||||
<< ", depth: " << primaryScreen->depth();
|
||||
//
|
||||
d->area = primaryScreen->geometry();
|
||||
} else {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get application's primary screen info!";
|
||||
return;
|
||||
}
|
||||
|
||||
d->framebufferImage = xcb_image_get(QX11Info::connection(),
|
||||
this->win,
|
||||
d->area.left(),
|
||||
d->area.top(),
|
||||
d->area.width(),
|
||||
d->area.height(),
|
||||
0xFFFFFFFF, // == Xlib: AllPlanes ((unsigned long)~0L)
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||
if (d->framebufferImage) {
|
||||
#ifdef _DEBUG
|
||||
qDebug() << "xcb framebuffer: Got primary screen image. bpp: " << d->framebufferImage->bpp
|
||||
<< ", size (" << d->framebufferImage->width << d->framebufferImage->height << ")"
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->stride;
|
||||
#endif
|
||||
this->fb = (char *)d->framebufferImage->data;
|
||||
} else {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get primary screen image!";
|
||||
return;
|
||||
}
|
||||
|
||||
// all XShm operations should take place only if Xshm extension was loaded
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
// Create xcb_image_t structure, but do not automatically allocate memory
|
||||
// for image data storage - it will be allocated as shared memory.
|
||||
// "If base == 0 and bytes == ~0 and data == 0, no storage will be auto-allocated."
|
||||
// Width and height of the image = size of the capture area.
|
||||
d->updateTile = xcb_image_create_native(
|
||||
QX11Info::connection(),
|
||||
d->area.width(), // width
|
||||
d->area.height(), // height
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
|
||||
d->rootScreen->root_depth, // depth
|
||||
NULL, // base address = 0
|
||||
(uint32_t)~0, // bytes = 0xffffffff
|
||||
NULL); // data = 0
|
||||
if (d->updateTile) {
|
||||
#ifdef _DEBUG
|
||||
qDebug() << "xcb framebuffer: Successfully created new empty image in native format";
|
||||
qDebug() << " size: " << d->updateTile->width << "x" << d->updateTile->height
|
||||
<< "(stride: " << d->updateTile->stride << ")";
|
||||
qDebug() << " bpp, depth: " << d->updateTile->bpp << d->updateTile->depth; // 32, 24
|
||||
qDebug() << " addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data;
|
||||
qDebug() << " size: " << d->updateTile->size;
|
||||
qDebug() << " image byte order = " << d->updateTile->byte_order; // == 0 .._LSB_FIRST
|
||||
qDebug() << " image bit order = " << d->updateTile->bit_order; // == 1 .._MSB_FIRST
|
||||
qDebug() << " image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
|
||||
#endif
|
||||
|
||||
// allocate shared memory block only once, make its size large enough
|
||||
// to fit whole capture area (d->area rect)
|
||||
// so, we get as many bytes as needed for image (updateTile->size)
|
||||
d->shminfo.shmid = shmget(IPC_PRIVATE, d->updateTile->size, IPC_CREAT | 0777);
|
||||
// attached shared memory address is stored both in shminfo structure and in xcb_image_t->data
|
||||
d->shminfo.shmaddr = (uint8_t *)shmat(d->shminfo.shmid, NULL, 0);
|
||||
d->updateTile->data = d->shminfo.shmaddr;
|
||||
// we keep updateTile->base == NULL here, so xcb_image_destroy() will not attempt
|
||||
// to free this block, just in case.
|
||||
|
||||
// attach this shm segment also to X server
|
||||
d->shminfo.shmseg = xcb_generate_id(QX11Info::connection());
|
||||
xcb_shm_attach(QX11Info::connection(), d->shminfo.shmseg, d->shminfo.shmid, 0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
qDebug() << " shm id: " << d->shminfo.shmseg << ", addr: " << (void *)d->shminfo.shmaddr;
|
||||
#endif
|
||||
|
||||
// will return 1 on success (yes!)
|
||||
int shmget_res = xcb_image_shm_get(
|
||||
QX11Info::connection(),
|
||||
this->win,
|
||||
d->updateTile,
|
||||
d->shminfo,
|
||||
d->area.left(), // x
|
||||
d->area.top(), // y (size taken from image structure itself)?
|
||||
0xFFFFFFFF);
|
||||
|
||||
if (shmget_res == 0) {
|
||||
// error! shared mem not working?
|
||||
// will not use shared mem! detach and cleanup
|
||||
xcb_shm_detach(QX11Info::connection(), d->shminfo.shmseg);
|
||||
shmdt(d->shminfo.shmaddr);
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, 0); // mark shm segment as removed
|
||||
d->x11EvtFilter->xshmAvail = false;
|
||||
d->shminfo.shmaddr = Q_NULLPTR;
|
||||
d->shminfo.shmid = XCB_NONE;
|
||||
d->shminfo.shmseg = XCB_NONE;
|
||||
qWarning() << "xcb framebuffer: ERROR: xcb_image_shm_get() result: " << shmget_res;
|
||||
}
|
||||
|
||||
// image is freed, and recreated again for every new damage rectangle
|
||||
// data was allocated manually and points to shared mem;
|
||||
// tell xcb_image_destroy() do not free image data
|
||||
d->updateTile->data = NULL;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
d->updateTile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
qDebug() << "xcb framebuffer: XCBFrameBuffer(), xshm base event = " << d->x11EvtFilter->xshmBaseEvent
|
||||
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError
|
||||
<< ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
|
||||
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
|
||||
#endif
|
||||
|
||||
QCoreApplication::instance()->installNativeEventFilter(d->x11EvtFilter);
|
||||
}
|
||||
|
||||
|
||||
XCBFrameBuffer::~XCBFrameBuffer() {
|
||||
// first - uninstall x11 event filter
|
||||
QCoreApplication::instance()->removeNativeEventFilter(d->x11EvtFilter);
|
||||
//
|
||||
if (d->framebufferImage) {
|
||||
xcb_image_destroy(d->framebufferImage);
|
||||
fb = Q_NULLPTR; // image data was already destroyed by above call
|
||||
}
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
// detach shared memory
|
||||
if (d->shminfo.shmseg != XCB_NONE)
|
||||
xcb_shm_detach(QX11Info::connection(), d->shminfo.shmseg); // detach from X server
|
||||
if (d->shminfo.shmaddr)
|
||||
shmdt(d->shminfo.shmaddr); // detach addr from our address space
|
||||
if (d->shminfo.shmid != XCB_NONE)
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, 0); // mark shm segment as removed
|
||||
}
|
||||
// and delete image used for shared mem
|
||||
if (d->updateTile) {
|
||||
d->updateTile->base = NULL;
|
||||
d->updateTile->data = NULL;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
}
|
||||
// we don't use d->x11EvtFilter anymore, can delete it now
|
||||
if (d->x11EvtFilter) {
|
||||
delete d->x11EvtFilter;
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
int XCBFrameBuffer::depth() {
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->depth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int XCBFrameBuffer::height() {
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->height;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int XCBFrameBuffer::width() {
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->width;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XCBFrameBuffer::paddedWidth() {
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->stride;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
|
||||
if (!d->framebufferImage) return;
|
||||
|
||||
// get information about XCB visual params
|
||||
xcb_visualtype_t *root_visualtype = NULL; // visual info
|
||||
if (d->rootScreen) {
|
||||
xcb_visualid_t root_visual = d->rootScreen->root_visual;
|
||||
xcb_depth_iterator_t depth_iter;
|
||||
// To get the xcb_visualtype_t structure, it's a bit less easy.
|
||||
// You have to get the xcb_screen_t structure that you want, get its
|
||||
// root_visual member, then iterate over the xcb_depth_t's and the
|
||||
// xcb_visualtype_t's, and compare the xcb_visualid_t of these
|
||||
// xcb_visualtype_ts: with root_visual
|
||||
depth_iter = xcb_screen_allowed_depths_iterator(d->rootScreen);
|
||||
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
|
||||
xcb_visualtype_iterator_t visual_iter;
|
||||
visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
|
||||
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
|
||||
if (root_visual == visual_iter.data->visual_id) {
|
||||
root_visualtype = visual_iter.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fill in format common info
|
||||
format.bitsPerPixel = d->framebufferImage->bpp;
|
||||
format.depth = d->framebufferImage->depth;
|
||||
format.trueColour = true; // not using color palettes
|
||||
format.bigEndian = false; // always false for ZPIXMAP format!
|
||||
|
||||
// information about pixels layout
|
||||
|
||||
if (root_visualtype) {
|
||||
uint16_t pixelmaxValue = (1 << root_visualtype->bits_per_rgb_value) - 1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
qDebug("xcb framebuffer: Got info about root visual:\n"
|
||||
" bits per rgb value: %d\n"
|
||||
" red mask: %08x\n"
|
||||
" green mask: %08x\n"
|
||||
" blue mask: %08x\n"
|
||||
" pixelMaxValue = %d\n",
|
||||
(int)root_visualtype->bits_per_rgb_value,
|
||||
root_visualtype->red_mask,
|
||||
root_visualtype->green_mask,
|
||||
root_visualtype->blue_mask,
|
||||
(int)pixelmaxValue);
|
||||
#endif
|
||||
|
||||
// calculate shifts
|
||||
format.redShift = 0;
|
||||
format.redMax = pixelmaxValue;
|
||||
if (root_visualtype->red_mask) {
|
||||
while (!(root_visualtype->red_mask & (1 << format.redShift))) {
|
||||
format.redShift++;
|
||||
}
|
||||
}
|
||||
format.greenShift = 0;
|
||||
format.greenMax = pixelmaxValue;
|
||||
if (root_visualtype->green_mask) {
|
||||
while (!(root_visualtype->green_mask & (1 << format.greenShift))) {
|
||||
format.greenShift++;
|
||||
}
|
||||
}
|
||||
format.blueShift = 0;
|
||||
format.blueMax = pixelmaxValue;
|
||||
if (root_visualtype->blue_mask) {
|
||||
while (!(root_visualtype->blue_mask & (1 << format.blueShift))) {
|
||||
format.blueShift++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
qDebug() << " Calculated redShift =" << (int)format.redShift;
|
||||
qDebug() << " Calculated greenShift =" << (int)format.greenShift;
|
||||
qDebug() << " Calculated blueShift =" << (int)format.blueShift;
|
||||
#endif
|
||||
} else {
|
||||
// some kind of fallback (unlikely code execution will go this way)
|
||||
// idea taken from qt framefuffer sources
|
||||
if (format.bitsPerPixel == 8) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 3;
|
||||
format.blueShift = 6;
|
||||
format.redMax = 7;
|
||||
format.greenMax = 7;
|
||||
format.blueMax = 3;
|
||||
} else if (format.bitsPerPixel == 16) {
|
||||
// TODO: 16 bits per pixel format ??
|
||||
// what format of pixels does X server use for 16-bpp?
|
||||
} else if (format.bitsPerPixel == 32) {
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
if (format.bigEndian) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 16;
|
||||
} else {
|
||||
format.redShift = 16;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function contents was taken from X11 framebuffer source code.
|
||||
* It simply several intersecting rectangles into one bigger rect.
|
||||
* Non-intersecting rects are treated as different rects and exist
|
||||
* separately in this->tiles QList.
|
||||
*/
|
||||
void XCBFrameBuffer::cleanupRects() {
|
||||
QList<QRect> cpy = tiles;
|
||||
bool inserted = false;
|
||||
tiles.clear();
|
||||
|
||||
QListIterator<QRect> iter(cpy);
|
||||
while (iter.hasNext()) {
|
||||
const QRect &r = iter.next();
|
||||
// skip rects not intersecting with primary monitor
|
||||
if (!r.intersects(d->area)) continue;
|
||||
// only take intersection of this rect with primary monitor rect
|
||||
QRect ri = r.intersected(d->area);
|
||||
|
||||
if (tiles.size() > 0) {
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
// if current rect has intersection with tiles[i], unite them
|
||||
if (ri.intersects(tiles[i])) {
|
||||
tiles[i] |= ri;
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
// else, append to list as different rect
|
||||
tiles.append(ri);
|
||||
}
|
||||
} else {
|
||||
// tiles list is empty, append first item
|
||||
tiles.append(ri);
|
||||
}
|
||||
}
|
||||
|
||||
// increase all rectangles size by 30 pixels each side.
|
||||
// limit coordinates to primary monitor boundaries.
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
tiles[i].adjust(-30, -30, 30, 30);
|
||||
if (tiles[i].top() < d->area.top()) {
|
||||
tiles[i].setTop(d->area.top());
|
||||
}
|
||||
if (tiles[i].bottom() > d->area.bottom()) {
|
||||
tiles[i].setBottom(d->area.bottom());
|
||||
}
|
||||
//
|
||||
if (tiles[i].left() < d->area.left()) {
|
||||
tiles[i].setLeft(d->area.left());
|
||||
}
|
||||
if (tiles[i].right() > d->area.right()) {
|
||||
tiles[i].setRight(d->area.right());
|
||||
}
|
||||
// move update rects so that they are positioned relative to
|
||||
// framebuffer image, not whole screen
|
||||
tiles[i].moveTo(tiles[i].left() - d->area.left(),
|
||||
tiles[i].top() - d->area.top());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is called by RfbServerManager::updateScreens()
|
||||
* approximately every 50ms (!!), driven by QTimer to get all
|
||||
* modified rectangles on the screen
|
||||
*/
|
||||
QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
||||
QList<QRect> ret;
|
||||
if (!d->running) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cleanupRects();
|
||||
|
||||
if (tiles.size() > 0) {
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
|
||||
// loop over all damage rectangles gathered up to this time
|
||||
QListIterator<QRect> iter(tiles);
|
||||
//foreach(const QRect &r, tiles) {
|
||||
while (iter.hasNext()) {
|
||||
const QRect &r = iter.next();
|
||||
|
||||
// get image data into shared memory segment
|
||||
// now rects are positioned relative to framebufferImage,
|
||||
// but we need to get image from the whole screen, so
|
||||
// translate whe coordinates
|
||||
xcb_shm_get_image_cookie_t sgi_cookie = xcb_shm_get_image(
|
||||
QX11Info::connection(),
|
||||
this->win,
|
||||
d->area.left() + r.left(),
|
||||
d->area.top() + r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
0xFFFFFFFF,
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
d->shminfo.shmseg,
|
||||
0);
|
||||
|
||||
xcb_shm_get_image_reply_t *sgi_reply = xcb_shm_get_image_reply(
|
||||
QX11Info::connection(), sgi_cookie, NULL);
|
||||
if (sgi_reply) {
|
||||
// create temporary image to get update rect contents into
|
||||
d->updateTile = xcb_image_create_native(
|
||||
QX11Info::connection(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
d->rootScreen->root_depth,
|
||||
NULL, // base == 0
|
||||
(uint32_t)~0, // bytes == ~0
|
||||
NULL);
|
||||
|
||||
if (d->updateTile) {
|
||||
d->updateTile->data = d->shminfo.shmaddr;
|
||||
|
||||
// copy pixels from this damage rectangle image
|
||||
// to our total framebuffer image
|
||||
int pxsize = d->framebufferImage->bpp / 8;
|
||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||
char *src = (char *)d->updateTile->data;
|
||||
for (int i = 0; i < d->updateTile->height; i++) {
|
||||
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
|
||||
dest += d->framebufferImage->stride;
|
||||
src += d->updateTile->stride;
|
||||
}
|
||||
|
||||
// delete temporary image
|
||||
d->updateTile->data = NULL;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
d->updateTile = NULL;
|
||||
}
|
||||
|
||||
free(sgi_reply);
|
||||
}
|
||||
} // foreach
|
||||
} else {
|
||||
// not using shared memory
|
||||
// will use just xcb_image_get() and copy pixels
|
||||
foreach(const QRect &r, tiles) {
|
||||
// I did not find XGetSubImage() analog in XCB!!
|
||||
// need function that copies pixels from one image to another
|
||||
xcb_image_t *damagedImage = xcb_image_get(
|
||||
QX11Info::connection(),
|
||||
this->win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
0xFFFFFFFF, // AllPlanes
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||
// manually copy pixels
|
||||
int pxsize = d->framebufferImage->bpp / 8;
|
||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||
char *src = (char *)damagedImage->data;
|
||||
// loop every row in damaged image
|
||||
for (int i = 0; i < damagedImage->height; i++) {
|
||||
// copy whole row of pixels from src image to dest
|
||||
memcpy(dest, src, damagedImage->stride);
|
||||
dest += d->framebufferImage->stride; // move 1 row down in dest
|
||||
src += damagedImage->stride; // move 1 row down in src
|
||||
}
|
||||
//
|
||||
xcb_image_destroy(damagedImage);
|
||||
}
|
||||
}
|
||||
} // if (tiles.size() > 0)
|
||||
|
||||
ret = tiles;
|
||||
tiles.clear();
|
||||
// ^^ If we clear here all our known "damage areas", then we can also clear
|
||||
// damaged area for xdamage? No, we don't need to in our case
|
||||
// (XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES report mode)
|
||||
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void XCBFrameBuffer::startMonitor() {
|
||||
if (d->running) return;
|
||||
|
||||
d->running = true;
|
||||
d->damage = xcb_generate_id(QX11Info::connection());
|
||||
xcb_damage_create(QX11Info::connection(), d->damage, this->win,
|
||||
XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
|
||||
|
||||
// (currently) we do not call xcb_damage_subtract() EVER, because
|
||||
// RAW rectangles are reported. every time some area of the screen
|
||||
// was changed, we get only that rectangle
|
||||
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||
}
|
||||
|
||||
|
||||
void XCBFrameBuffer::stopMonitor() {
|
||||
if (!d->running) return;
|
||||
d->running = false;
|
||||
xcb_damage_destroy(QX11Info::connection(), d->damage);
|
||||
}
|
||||
|
||||
|
||||
// void XCBFrameBuffer::acquireEvents() {} // this function was totally unused
|
||||
// in X11 framebuffer, but it was the only function where XDamageSubtract() was called?
|
||||
// Also it had a blocking event loop like:
|
||||
//
|
||||
// XEvent ev;
|
||||
// while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
|
||||
// handleXDamage(&ev);
|
||||
// }
|
||||
// XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
//
|
||||
// This loop takes all available Xdamage events from queue, and ends if there are no
|
||||
// more such events in input queue.
|
||||
|
||||
|
||||
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent) {
|
||||
xcb_damage_notify_event_t *xdevt = (xcb_damage_notify_event_t *)xevent;
|
||||
|
||||
QRect r((int)xdevt->area.x, (int)xdevt->area.y,
|
||||
(int)xdevt->area.width, (int)xdevt->area.height);
|
||||
this->tiles.append(r);
|
||||
}
|
||||
|
||||
48
framebuffers/xcb/xcb_framebuffer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2017 Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
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 KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include <QWidget>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@author Alexey Min <alexey.min@gmail.com>
|
||||
*/
|
||||
class XCBFrameBuffer: public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XCBFrameBuffer(WId winid, QObject *parent = 0);
|
||||
~XCBFrameBuffer();
|
||||
|
||||
public:
|
||||
QList<QRect> modifiedTiles() Q_DECL_OVERRIDE;
|
||||
int depth() Q_DECL_OVERRIDE;
|
||||
int height() Q_DECL_OVERRIDE;
|
||||
int width() Q_DECL_OVERRIDE;
|
||||
int paddedWidth() Q_DECL_OVERRIDE;
|
||||
void getServerFormat(rfbPixelFormat &format) Q_DECL_OVERRIDE;
|
||||
void startMonitor() Q_DECL_OVERRIDE;
|
||||
void stopMonitor() Q_DECL_OVERRIDE;
|
||||
|
||||
public:
|
||||
void handleXDamageNotify(xcb_generic_event_t *xevent);
|
||||
|
||||
private:
|
||||
void cleanupRects();
|
||||
|
||||
class P;
|
||||
P *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
46
framebuffers/xcb/xcb_framebufferplugin.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/* This file is part of the KDE project
|
||||
@author Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "xcb_framebufferplugin.h"
|
||||
#include "xcb_framebuffer.h"
|
||||
#include <KPluginFactory>
|
||||
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(XCBFrameBufferPluginFactory, "krfb_framebuffer_xcb.json",
|
||||
registerPlugin<XCBFrameBufferPlugin>();)
|
||||
|
||||
XCBFrameBufferPlugin::XCBFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
XCBFrameBufferPlugin::~XCBFrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FrameBuffer *XCBFrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
return new XCBFrameBuffer(id);
|
||||
}
|
||||
|
||||
#include "xcb_framebufferplugin.moc"
|
||||
|
||||
45
framebuffers/xcb/xcb_framebufferplugin.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* This file is part of the KDE project
|
||||
@author Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class XCBFrameBufferPlugin: public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~XCBFrameBufferPlugin();
|
||||
|
||||
FrameBuffer *frameBuffer(WId id) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(XCBFrameBufferPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
3
krfb.kdev4
Normal file
@@ -0,0 +1,3 @@
|
||||
[Project]
|
||||
Manager=KDevCMakeManager
|
||||
Name=krfb
|
||||
@@ -2,6 +2,8 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config-krfb.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config-krfb.h
|
||||
)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
|
||||
#####################################
|
||||
# First target: libkrfbprivate - a library
|
||||
# for linking plugins against.
|
||||
@@ -11,20 +13,23 @@ set (krfbprivate_SRCS
|
||||
framebufferplugin.cpp
|
||||
)
|
||||
|
||||
kde4_add_library (krfbprivate
|
||||
add_library (krfbprivate
|
||||
SHARED
|
||||
${krfbprivate_SRCS}
|
||||
)
|
||||
generate_export_header(krfbprivate BASE_NAME krfbprivate)
|
||||
|
||||
target_link_libraries (krfbprivate
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::X11Extras
|
||||
${X11_X11_LIB}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties (krfbprivate PROPERTIES
|
||||
VERSION ${GENERIC_LIB_VERSION}
|
||||
SOVERSION ${GENERIC_LIB_VERSION}
|
||||
VERSION 5
|
||||
SOVERSION 5.0
|
||||
)
|
||||
|
||||
install (TARGETS krfbprivate
|
||||
@@ -41,16 +46,6 @@ install (FILES
|
||||
# Second target: krfb - the app
|
||||
# itself.
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
add_definitions(-DKRFB_WITH_TELEPATHY_TUBES)
|
||||
include_directories(${TELEPATHY_QT4_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if(KTP_FOUND)
|
||||
add_definitions(-DKRFB_WITH_KDE_TELEPATHY)
|
||||
include_directories(${KTP_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
set (krfb_SRCS
|
||||
connectiondialog.cpp
|
||||
events.cpp
|
||||
@@ -66,59 +61,41 @@ set (krfb_SRCS
|
||||
invitationsrfbclient.cpp
|
||||
)
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
set (krfb_SRCS
|
||||
${krfb_SRCS}
|
||||
tubesrfbserver.cpp
|
||||
tubesrfbclient.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
kde4_add_kcfg_files (krfb_SRCS
|
||||
kconfig_add_kcfg_files (krfb_SRCS
|
||||
krfbconfig.kcfgc
|
||||
)
|
||||
|
||||
kde4_add_ui_files (krfb_SRCS
|
||||
ki18n_wrap_ui (krfb_SRCS
|
||||
ui/configtcp.ui
|
||||
ui/configsecurity.ui
|
||||
ui/configframebuffer.ui
|
||||
ui/connectionwidget.ui
|
||||
ui/mainwidget.ui
|
||||
)
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
kde4_add_ui_files(krfb_SRCS ui/tubesconnectionwidget.ui)
|
||||
endif()
|
||||
|
||||
kde4_add_executable (krfb
|
||||
add_executable (krfb
|
||||
${krfb_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb
|
||||
krfbprivate
|
||||
vncserver
|
||||
${JPEG_LIBRARIES}
|
||||
${X11_Xext_LIB}
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
${QT_QTNETWORK_LIBRARY}
|
||||
${KDE4_KDNSSD_LIBS}
|
||||
${KDE4_KDEUI_LIBS}
|
||||
Qt5::Network
|
||||
KF5::Completion
|
||||
KF5::CoreAddons
|
||||
KF5::DBusAddons
|
||||
KF5::DNSSD
|
||||
KF5::I18n
|
||||
KF5::Notifications
|
||||
KF5::Wallet
|
||||
KF5::WidgetsAddons
|
||||
KF5::XmlGui
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
)
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
target_link_libraries(krfb
|
||||
${TELEPATHY_QT4_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(KTP_FOUND)
|
||||
target_link_libraries(krfb
|
||||
${KTP_LIBRARIES}
|
||||
${KTP_MODELS_LIBRARIES}
|
||||
${KTP_WIDGETS_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (X11_XTest_FOUND)
|
||||
target_link_libraries (krfb
|
||||
${X11_XTest_LIB}
|
||||
@@ -129,21 +106,16 @@ install (TARGETS krfb
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
configure_file(org.freedesktop.Telepathy.Client.krfb_rfb_handler.service.in
|
||||
org.freedesktop.Telepathy.Client.krfb_rfb_handler.service)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.krfb_rfb_handler.service
|
||||
DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
|
||||
|
||||
install(FILES krfb_rfb_handler.client DESTINATION ${CMAKE_INSTALL_PREFIX}/share/telepathy/clients/)
|
||||
endif()
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install (PROGRAMS krfb.desktop
|
||||
install (PROGRAMS org.kde.krfb.desktop
|
||||
DESTINATION ${XDG_APPS_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install(FILES org.kde.krfb.appdata.xml
|
||||
DESTINATION ${KDE_INSTALL_METAINFODIR}
|
||||
)
|
||||
|
||||
install (FILES krfb.notifyrc
|
||||
DESTINATION ${DATA_INSTALL_DIR}/krfb
|
||||
)
|
||||
|
||||
@@ -21,20 +21,33 @@
|
||||
|
||||
#include "connectiondialog.h"
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KStandardGuiItem>
|
||||
#include <QCheckBox>
|
||||
#include <QIcon>
|
||||
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QLabel>
|
||||
#include <KLocalizedString>
|
||||
#include <KStandardGuiItem>
|
||||
#include <KConfigGroup>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <KGuiItem>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
template <typename UI>
|
||||
ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||
: KDialog(parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setCaption(i18n("New Connection"));
|
||||
setButtons(Ok | Cancel);
|
||||
setDefaultButton(Cancel);
|
||||
setWindowTitle(i18n("New Connection"));
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
|
||||
QWidget *mainWidget = new QWidget(this);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
setLayout(mainLayout);
|
||||
mainLayout->addWidget(mainWidget);
|
||||
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
|
||||
okButton->setDefault(true);
|
||||
okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &ConnectionDialog<UI>::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &ConnectionDialog<UI>::reject);
|
||||
buttonBox->button(QDialogButtonBox::Cancel)->setDefault(true);
|
||||
setModal(true);
|
||||
|
||||
setMinimumSize(500, 200);
|
||||
@@ -42,17 +55,18 @@ ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||
m_connectWidget = new QWidget(this);
|
||||
m_ui.setupUi(m_connectWidget);
|
||||
|
||||
m_ui.pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
m_ui.pixmapLabel->setPixmap(QIcon::fromTheme("krfb").pixmap(128));
|
||||
|
||||
KGuiItem accept = KStandardGuiItem::ok();
|
||||
accept.setText(i18n("Accept Connection"));
|
||||
setButtonGuiItem(Ok, accept);
|
||||
KGuiItem::assign(okButton, accept);
|
||||
|
||||
KGuiItem refuse = KStandardGuiItem::cancel();
|
||||
refuse.setText(i18n("Refuse Connection"));
|
||||
setButtonGuiItem(Cancel, refuse);
|
||||
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), refuse);
|
||||
|
||||
setMainWidget(m_connectWidget);
|
||||
mainLayout->addWidget(m_connectWidget);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
}
|
||||
|
||||
//**********
|
||||
@@ -69,20 +83,4 @@ void InvitationsConnectionDialog::setRemoteHost(const QString &host)
|
||||
|
||||
//**********
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
TubesConnectionDialog::TubesConnectionDialog(QWidget *parent)
|
||||
: ConnectionDialog<Ui::TubesConnectionWidget>(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TubesConnectionDialog::setContactName(const QString & name)
|
||||
{
|
||||
QString txt = i18n("You have requested to share your desktop with %1. If you proceed, "
|
||||
"you will allow the remote user to watch your desktop.", name);
|
||||
m_ui.mainTextLabel->setText(txt);
|
||||
}
|
||||
|
||||
#endif // KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
#include "connectiondialog.moc"
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
#define CONNECTIONDIALOG_H
|
||||
|
||||
#include "ui_connectionwidget.h"
|
||||
#include <KDialog>
|
||||
#include <QDialog>
|
||||
|
||||
template <typename UI>
|
||||
class ConnectionDialog : public KDialog
|
||||
class ConnectionDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
ConnectionDialog(QWidget *parent);
|
||||
@@ -65,18 +65,5 @@ public:
|
||||
|
||||
//*********
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
# include "ui_tubesconnectionwidget.h"
|
||||
|
||||
class TubesConnectionDialog : public ConnectionDialog<Ui::TubesConnectionWidget>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TubesConnectionDialog(QWidget *parent);
|
||||
void setContactName(const QString & name);
|
||||
};
|
||||
|
||||
#endif // KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
#endif // CONNECTIONDIALOG_H
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QX11Info>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <KGlobal>
|
||||
#include <QApplication>
|
||||
#include <QX11Info>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
@@ -60,7 +60,7 @@ private:
|
||||
void init();
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(EventData, data)
|
||||
Q_GLOBAL_STATIC(EventData, data)
|
||||
|
||||
EventData::EventData()
|
||||
{
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
|
||||
#include "rfb.h"
|
||||
|
||||
#include <kdemacros.h>
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QList>
|
||||
#include <QWidget>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class KDE_EXPORT FrameBuffer : public QObject
|
||||
class KRFBPRIVATE_EXPORT FrameBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#include "framebufferplugin.h"
|
||||
#include "krfbconfig.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KGlobal>
|
||||
#include <KServiceTypeTrader>
|
||||
#include <QDebug>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginMetaData>
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
@@ -35,71 +38,75 @@ public:
|
||||
FrameBufferManager instance;
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic)
|
||||
Q_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic)
|
||||
|
||||
FrameBufferManager::FrameBufferManager()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
loadPlugins();
|
||||
}
|
||||
|
||||
FrameBufferManager::~FrameBufferManager()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
}
|
||||
|
||||
FrameBufferManager *FrameBufferManager::instance()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
return &frameBufferManagerStatic->instance;
|
||||
}
|
||||
|
||||
void FrameBufferManager::loadPlugins()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
// Load the all the plugin factories here, for use later.
|
||||
KService::List offers = KServiceTypeTrader::self()->query("krfb/framebuffer");
|
||||
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("krfb"), [](const KPluginMetaData & md) {
|
||||
return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer"));
|
||||
});
|
||||
|
||||
KService::List::const_iterator iter;
|
||||
|
||||
for (iter = offers.constBegin(); iter < offers.constEnd(); ++iter) {
|
||||
QString error;
|
||||
KService::Ptr service = *iter;
|
||||
|
||||
KPluginFactory *factory = KPluginLoader(service->library()).factory();
|
||||
QVectorIterator<KPluginMetaData> i(plugins);
|
||||
i.toBack();
|
||||
QSet<QString> unique;
|
||||
while (i.hasPrevious()) {
|
||||
const KPluginMetaData &data = i.previous();
|
||||
// only load plugins once, even if found multiple times!
|
||||
if (unique.contains(data.name()))
|
||||
continue;
|
||||
KPluginFactory *factory = KPluginLoader(data.fileName()).factory();
|
||||
|
||||
if (!factory) {
|
||||
kWarning() << "KPluginFactory could not load the plugin:" << service->library();
|
||||
continue;
|
||||
qDebug() << "KPluginFactory could not load the plugin:" << data.fileName();
|
||||
} else {
|
||||
qDebug() << "found plugin at " << data.fileName();
|
||||
}
|
||||
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(this);
|
||||
|
||||
if (plugin) {
|
||||
kDebug() << "Loaded plugin:" << service->name();
|
||||
m_plugins.insert(service->library(), plugin);
|
||||
m_plugins.insert(data.pluginId(), plugin);
|
||||
qDebug() << "Loaded plugin with name " << data.pluginId();
|
||||
} else {
|
||||
kDebug() << error;
|
||||
qDebug() << "unable to load pluign for " << data.fileName();
|
||||
}
|
||||
unique.insert (data.name());
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
// See if there is still an existing framebuffer to this WId.
|
||||
if (m_frameBuffers.contains(id)) {
|
||||
QWeakPointer<FrameBuffer> weakFrameBuffer = m_frameBuffers.value(id);
|
||||
|
||||
if (weakFrameBuffer) {
|
||||
kDebug() << "Found cached frame buffer.";
|
||||
//qDebug() << "Found cached frame buffer.";
|
||||
return weakFrameBuffer.toStrongRef();
|
||||
} else {
|
||||
kDebug() << "Found deleted cached frame buffer. Don't use.";
|
||||
//qDebug() << "Found deleted cached frame buffer. Don't use.";
|
||||
m_frameBuffers.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -110,7 +117,7 @@ QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
|
||||
while (iter != m_plugins.constEnd()) {
|
||||
|
||||
if (iter.key() == KrfbConfig::preferredFrameBufferPlugin()) {
|
||||
kDebug() << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
|
||||
qDebug() << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
|
||||
|
||||
QSharedPointer<FrameBuffer> frameBuffer(iter.value()->frameBuffer(id));
|
||||
|
||||
@@ -125,7 +132,7 @@ QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
|
||||
}
|
||||
|
||||
// No valid framebuffer plugin found.
|
||||
kDebug() << "No valid framebuffer found. returning null.";
|
||||
qDebug() << "No valid framebuffer found. returning null.";
|
||||
return QSharedPointer<FrameBuffer>();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,19 +23,19 @@
|
||||
|
||||
#include "framebuffer.h"
|
||||
|
||||
#include <kdemacros.h>
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QWeakPointer>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBufferPlugin;
|
||||
class KPluginFactory;
|
||||
|
||||
class KDE_EXPORT FrameBufferManager : public QObject
|
||||
class KRFBPRIVATE_EXPORT FrameBufferManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class FrameBufferManagerStatic;
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
#ifndef LIB_KRFB_FRAMEBUFFERPLUGIN_H
|
||||
#define LIB_KRFB_FRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include <kdemacros.h>
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QVariantList>
|
||||
#include <QWidget>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class KDE_EXPORT FrameBufferPlugin : public QObject
|
||||
class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -40,6 +40,5 @@ public:
|
||||
virtual FrameBuffer *frameBuffer(WId id) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
|
||||
@@ -24,10 +24,14 @@
|
||||
#include "krfbconfig.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "connectiondialog.h"
|
||||
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <poll.h>
|
||||
#include <KConfigGroup>
|
||||
|
||||
struct PendingInvitationsRfbClient::Private
|
||||
{
|
||||
@@ -50,8 +54,8 @@ PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QO
|
||||
d->client->clientGoneHook = clientGoneHookNoop;
|
||||
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(true);
|
||||
connect(d->notifier, SIGNAL(activated(int)),
|
||||
this, SLOT(onSocketActivated()));
|
||||
connect(d->notifier, &QSocketNotifier::activated,
|
||||
this, &PendingInvitationsRfbClient::onSocketActivated);
|
||||
}
|
||||
|
||||
PendingInvitationsRfbClient::~PendingInvitationsRfbClient()
|
||||
@@ -79,8 +83,8 @@ void PendingInvitationsRfbClient::processNewClient()
|
||||
dialog->setRemoteHost(host);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
|
||||
connect(dialog, &InvitationsConnectionDialog::accepted, this, &PendingInvitationsRfbClient::dialogAccepted);
|
||||
connect(dialog, &InvitationsConnectionDialog::rejected, this, &PendingInvitationsRfbClient::reject);
|
||||
|
||||
dialog->show();
|
||||
}
|
||||
@@ -111,7 +115,7 @@ void PendingInvitationsRfbClient::onSocketActivated()
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
kDebug() << "disconnected from socket signal";
|
||||
qDebug() << "disconnected from socket signal";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
break;
|
||||
@@ -122,7 +126,7 @@ void PendingInvitationsRfbClient::onSocketActivated()
|
||||
bool PendingInvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
|
||||
{
|
||||
QByteArray password ;
|
||||
kDebug() << "about to start autentication";
|
||||
qDebug() << "about to start autentication";
|
||||
|
||||
if(InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword(
|
||||
InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(),
|
||||
|
||||
@@ -36,9 +36,9 @@ public:
|
||||
virtual ~PendingInvitationsRfbClient();
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient();
|
||||
void processNewClient() override;
|
||||
virtual void onSocketActivated();
|
||||
virtual bool checkPassword(const QByteArray & encryptedPassword);
|
||||
bool checkPassword(const QByteArray & encryptedPassword) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
|
||||
@@ -23,16 +23,17 @@
|
||||
#include "krfbconfig.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QApplication>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <KUser>
|
||||
#include <KRandom>
|
||||
#include <KStringHandler>
|
||||
#include <KWallet/Wallet>
|
||||
#include <DNSSD/PublicService>
|
||||
#include <KWallet/KWallet>
|
||||
|
||||
#include <dnssd/publicservice.h>
|
||||
using KWallet::Wallet;
|
||||
|
||||
//static
|
||||
@@ -42,7 +43,7 @@ InvitationsRfbServer *InvitationsRfbServer::instance;
|
||||
void InvitationsRfbServer::init()
|
||||
{
|
||||
instance = new InvitationsRfbServer;
|
||||
instance->m_publicService = new DNSSD::PublicService(
|
||||
instance->m_publicService = new KDNSSD::PublicService(
|
||||
i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()),
|
||||
@@ -52,10 +53,17 @@ void InvitationsRfbServer::init()
|
||||
instance->setListeningPort(KrfbConfig::port());
|
||||
instance->setPasswordRequired(true);
|
||||
|
||||
instance->m_wallet = Wallet::openWallet(
|
||||
Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
||||
connect(instance->m_wallet, SIGNAL(walletOpened(bool)),
|
||||
instance, SLOT(walletOpened(bool)));
|
||||
if (KrfbConfig::noWallet()) {
|
||||
instance->walletOpened(false);
|
||||
}
|
||||
else {
|
||||
instance->m_wallet = Wallet::openWallet(
|
||||
Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
||||
if(instance->m_wallet) {
|
||||
connect(instance->m_wallet, &KWallet::Wallet::walletOpened,
|
||||
instance, &InvitationsRfbServer::walletOpened);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString& InvitationsRfbServer::desktopPassword() const
|
||||
@@ -93,11 +101,11 @@ bool InvitationsRfbServer::start()
|
||||
return false;
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::stop(bool disconnectClients)
|
||||
void InvitationsRfbServer::stop()
|
||||
{
|
||||
if(m_publicService->isPublished())
|
||||
m_publicService->stop();
|
||||
RfbServer::stop(disconnectClients);
|
||||
RfbServer::stop();
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::toggleUnattendedAccess(bool allow)
|
||||
@@ -109,8 +117,7 @@ InvitationsRfbServer::InvitationsRfbServer()
|
||||
{
|
||||
m_desktopPassword = readableRandomString(4)+"-"+readableRandomString(3);
|
||||
m_unattendedPassword = readableRandomString(4)+"-"+readableRandomString(3);
|
||||
KSharedConfigPtr config = KGlobal::config();
|
||||
KConfigGroup krfbConfig(config,"Security");
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
m_allowUnattendedAccess = krfbConfig.readEntry(
|
||||
"allowUnattendedAccess", QVariant(false)).toBool();
|
||||
}
|
||||
@@ -118,11 +125,10 @@ InvitationsRfbServer::InvitationsRfbServer()
|
||||
InvitationsRfbServer::~InvitationsRfbServer()
|
||||
{
|
||||
stop();
|
||||
KSharedConfigPtr config = KGlobal::config();
|
||||
KConfigGroup krfbConfig(config,"Security");
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
krfbConfig.writeEntry("allowUnattendedAccess",m_allowUnattendedAccess);
|
||||
if(m_wallet->isOpen()) {
|
||||
|
||||
if(!KrfbConfig::noWallet()) {
|
||||
if (m_wallet && m_wallet->isOpen()) {
|
||||
if( (m_wallet->currentFolder()=="krfb") ||
|
||||
((m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb")) &&
|
||||
m_wallet->setFolder("krfb")) ) {
|
||||
@@ -130,6 +136,7 @@ InvitationsRfbServer::~InvitationsRfbServer()
|
||||
m_wallet->writePassword("desktopSharingPassword",m_desktopPassword);
|
||||
m_wallet->writePassword("unattendedAccessPassword",m_unattendedPassword);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
krfbConfig.writeEntry("desktopPassword",
|
||||
@@ -150,6 +157,7 @@ void InvitationsRfbServer::walletOpened(bool opened)
|
||||
{
|
||||
QString desktopPassword;
|
||||
QString unattendedPassword;
|
||||
Q_ASSERT(m_wallet);
|
||||
if( opened &&
|
||||
( m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb") ) &&
|
||||
m_wallet->setFolder("krfb") ) {
|
||||
@@ -167,9 +175,8 @@ void InvitationsRfbServer::walletOpened(bool opened)
|
||||
|
||||
} else {
|
||||
|
||||
kDebug() << "Could not open KWallet, Falling back to config file";
|
||||
KSharedConfigPtr config = KGlobal::config();
|
||||
KConfigGroup krfbConfig(config,"Security");
|
||||
qDebug() << "Could not open KWallet, Falling back to config file";
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
|
||||
desktopPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
||||
"desktopPassword", QString()));
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace KWallet {
|
||||
class Wallet;
|
||||
}
|
||||
|
||||
namespace DNSSD {
|
||||
namespace KDNSSD {
|
||||
class PublicService;
|
||||
}
|
||||
|
||||
@@ -47,20 +47,20 @@ Q_SIGNALS:
|
||||
void passwordChanged(const QString&);
|
||||
|
||||
public Q_SLOTS:
|
||||
bool start();
|
||||
void stop(bool disconnectClients=true);
|
||||
void toggleUnattendedAccess(bool allow=true);
|
||||
bool start() override;
|
||||
void stop() override;
|
||||
void toggleUnattendedAccess(bool allow);
|
||||
|
||||
protected:
|
||||
InvitationsRfbServer();
|
||||
virtual ~InvitationsRfbServer();
|
||||
virtual PendingRfbClient* newClient(rfbClientPtr client);
|
||||
PendingRfbClient* newClient(rfbClientPtr client) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void walletOpened(bool);
|
||||
|
||||
private:
|
||||
DNSSD::PublicService *m_publicService;
|
||||
KDNSSD::PublicService *m_publicService;
|
||||
bool m_allowUnattendedAccess;
|
||||
QString m_desktopPassword;
|
||||
QString m_unattendedPassword;
|
||||
|
||||
@@ -3,7 +3,7 @@ Type=ServiceType
|
||||
X-KDE-ServiceType=krfb/framebuffer
|
||||
|
||||
Comment=Frame Buffer plugins for KRfb
|
||||
Comment[ast]=Complementu de buffer pa KRfb
|
||||
Comment[ast]=Complementos del búfer de cuadros pa KRfb
|
||||
Comment[bg]=Приставки за фреймбуфер за KRfb
|
||||
Comment[bs]=Priključci framebafera za KRfb
|
||||
Comment[ca]=Connectors de «framebuffer» per al KRfb.
|
||||
@@ -19,7 +19,7 @@ Comment[eu]=Irteerako bideoaren pluginak KRfb-rentzako
|
||||
Comment[fi]=Kehyspuskuriliitännäinen kohteelle KRfb
|
||||
Comment[fr]=Modules externes de sortie vidéo pour Krfb
|
||||
Comment[ga]=Breiseáin Mhaoláin Fráma le haghaidh KRfb
|
||||
Comment[gl]=Engadido de frame buffer para KRfb
|
||||
Comment[gl]=Complementos de búfer de fotograma para KRfb
|
||||
Comment[hr]=Priključci za međuspremnike okvira za KRfb
|
||||
Comment[hu]=Framebuffer bővítmények a Krfb-hez
|
||||
Comment[ia]=Plug-ins de Frame Buffer per KRfb
|
||||
@@ -28,7 +28,7 @@ Comment[ja]=KRfb の フレームバッファプラグイン
|
||||
Comment[kk]=KRfb кадр буфер плагині
|
||||
Comment[km]=កម្មវិធីជំនួយ Frame Buffer សម្រាប់ KRfb
|
||||
Comment[ko]=KRfb 프레임버퍼 플러그인
|
||||
Comment[lt]=Frame Buffer priedai skirti KRfb
|
||||
Comment[lt]=Frame Buffer papildiniai skirti KRfb
|
||||
Comment[lv]=Kadru bufera sprudņi priekš KRfb
|
||||
Comment[nb]=Rammebuffer-programtillegg for KRfb
|
||||
Comment[nds]=Bildpuffer-Modulen för KRfb
|
||||
|
||||
39
krfb/krfb-framebuffer.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Description": "Frame Buffer plugins for KRfb",
|
||||
"Description[ast]": "Complementos del búfer de cuadros pa KRfb",
|
||||
"Description[ca@valencia]": "Connectors de «framebuffer» per al KRfb.",
|
||||
"Description[ca]": "Connectors de «framebuffer» per al KRfb.",
|
||||
"Description[cs]": "Moduly Frame bufferu pro KRfb",
|
||||
"Description[da]": "Framebuffer-plugins til KRfb",
|
||||
"Description[de]": "Framebuffer-Module für KRfb",
|
||||
"Description[el]": "Πρόσθετα μνήμης ανανέωσης βίντεο καρέ για το KRfb",
|
||||
"Description[es]": "Complementos de framebuffer para KRfb",
|
||||
"Description[et]": "KRfb kaadripuhvri pluginad",
|
||||
"Description[fi]": "Kehyspuskuriliitännäinen kohteelle KRfb",
|
||||
"Description[fr]": "Modules de tampons d'image pour KRfb",
|
||||
"Description[gl]": "Complemento de búfer de fotograma para KRfb",
|
||||
"Description[ia]": "Plug-ins de Frame Buffer per KRfb",
|
||||
"Description[it]": "Estensioni del framebuffer per KRfb",
|
||||
"Description[ko]": "KRfb 프레임버퍼 플러그인",
|
||||
"Description[nl]": "Framebuffer-plugins voor KRfb",
|
||||
"Description[nn]": "Biletbuffer-tillegg KRfb",
|
||||
"Description[pl]": "Wtyczki buforów ramek dla KRfb",
|
||||
"Description[pt]": "'Plugins' do 'Framebuffer' para o KRfb",
|
||||
"Description[pt_BR]": "Plugins de framebuffers para o KRfb",
|
||||
"Description[ru]": "Модули буфера кадров для KRfb",
|
||||
"Description[sk]": "Frame Buffer modul pre KRfb",
|
||||
"Description[sl]": "Vstavki slikovnih medpomnilnikov za KRfb",
|
||||
"Description[sr@ijekavian]": "Прикључци кадробафера за КРФБ",
|
||||
"Description[sr@ijekavianlatin]": "Priključci kadrobafera za KRFB",
|
||||
"Description[sr@latin]": "Priključci kadrobafera za KRFB",
|
||||
"Description[sr]": "Прикључци кадробафера за КРФБ",
|
||||
"Description[sv]": "Insticksprogram med rambuffert för Krfb",
|
||||
"Description[tr]": "KRfb için Çerçeve Tamponu eklentileri",
|
||||
"Description[uk]": "Додатки буфера кадрів для KRfb",
|
||||
"Description[x-test]": "xxFrame Buffer plugins for KRfbxx",
|
||||
"Description[zh_CN]": "KRfb 的帧缓冲插件",
|
||||
"Description[zh_TW]": "KRfb 的 Frame Buffer 外掛程式"
|
||||
},
|
||||
"X-KDE-ServiceType": "krfb/framebuffer"
|
||||
}
|
||||
@@ -3,6 +3,12 @@
|
||||
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfg>
|
||||
<kcfgfile />
|
||||
<group name="MainWindow">
|
||||
<entry name="startMinimized" type="Bool">
|
||||
<label>Start minimized</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="TCP">
|
||||
<entry name="useDefaultPort" type="Bool">
|
||||
<label>Use the default port for VNC (5900)</label>
|
||||
@@ -18,6 +24,10 @@
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Security">
|
||||
<entry name="noWallet" type="Bool">
|
||||
<label>Do not store passwords in KWallet</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="allowDesktopControl" type="Bool">
|
||||
<label>Allow remote connections to manage the desktop.</label>
|
||||
<default>true</default>
|
||||
@@ -36,7 +46,7 @@
|
||||
<group name="FrameBuffer">
|
||||
<entry name="preferredFrameBufferPlugin" type="String">
|
||||
<label>Preferred Frame Buffer Plugin</label>
|
||||
<default>krfb_framebuffer_x11</default>
|
||||
<default>xcb</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
||||
@@ -3,13 +3,13 @@ IconName=krfb
|
||||
Comment=Desktop Sharing
|
||||
Comment[af]=Werkskerm Deeling
|
||||
Comment[ar]=مشاركة سطح المكتب
|
||||
Comment[ast]=Escritoriu compartíu
|
||||
Comment[ast]=Compartición d'escritoriu
|
||||
Comment[bg]=Споделяне на работния плот
|
||||
Comment[bn]=ডেস্কটপ ভাগাভাগি
|
||||
Comment[br]=Rannañ ar vurev
|
||||
Comment[bs]=Dijeljenje radne površine
|
||||
Comment[ca]=Compartició de l'escriptori
|
||||
Comment[ca@valencia]=Compartició de l'escriptori
|
||||
Comment[ca]=Compartir l'escriptori
|
||||
Comment[ca@valencia]=Compartir l'escriptori
|
||||
Comment[cs]=Sdílení pracovní plochy
|
||||
Comment[cy]=Rhannu Penbwrdd
|
||||
Comment[da]=Skrivebordsdeling
|
||||
@@ -36,7 +36,7 @@ Comment[ja]=デスクトップ共有
|
||||
Comment[kk]=Үстелді ортақтастыру
|
||||
Comment[km]=ការចែករំលែកផ្ទែតុ
|
||||
Comment[ko]=데스크톱 공유
|
||||
Comment[lt]=Dalinimasis darbastaliu
|
||||
Comment[lt]=Dalinimasis darbalaukiu
|
||||
Comment[lv]=Darbvirsmas koplietošana
|
||||
Comment[mk]=Делење на работната површина
|
||||
Comment[ml]=പണിയിടം പങ്കുവെക്കല്
|
||||
@@ -358,7 +358,7 @@ Name[eu]=Konexioa itxi da
|
||||
Name[fi]=Yhteys suljettu
|
||||
Name[fr]=Connexion fermée
|
||||
Name[ga]=Ceangal Dúnta
|
||||
Name[gl]=Conexión fechada
|
||||
Name[gl]=Conexión pechada
|
||||
Name[hi]=कनेक्शन बन्द
|
||||
Name[hne]=कनेक्सन बन्द
|
||||
Name[hr]=Veza prekinuta
|
||||
@@ -404,7 +404,7 @@ Name[zh_TW]=連線已關閉
|
||||
Comment=Connection closed
|
||||
Comment[af]=Verbinding gesluit
|
||||
Comment[ar]=تمّ غلق الاتصال
|
||||
Comment[ast]=Conexón zarrada
|
||||
Comment[ast]=Zarróse la conexón
|
||||
Comment[bg]=Връзката е прекъсната
|
||||
Comment[bn]=সংযোগ বন্ধ করা হল
|
||||
Comment[br]=Serret eo ar gevreadenn
|
||||
@@ -424,7 +424,7 @@ Comment[eu]=Konexioa itxi da
|
||||
Comment[fi]=Yhteys suljettu
|
||||
Comment[fr]=Connexion fermée
|
||||
Comment[ga]=Ceangal dúnta
|
||||
Comment[gl]=A conexión está fechada
|
||||
Comment[gl]=A conexión está pechada
|
||||
Comment[he]=החיבור נסגר
|
||||
Comment[hi]=कनेक्शन बन्द
|
||||
Comment[hne]=कनेक्सन बन्द
|
||||
@@ -480,7 +480,7 @@ Action=Popup
|
||||
[Event/InvalidPassword]
|
||||
Name=Invalid Password
|
||||
Name[ar]=كلمة المرور غير صحيحة
|
||||
Name[ast]=Contraseña incorreuta
|
||||
Name[ast]=Contraseña non válida
|
||||
Name[bg]=Неправилна парола
|
||||
Name[bs]=Neispravna šifra
|
||||
Name[ca]=Contrasenya no vàlida
|
||||
@@ -543,7 +543,7 @@ Name[zh_TW]=不正確的密碼
|
||||
Comment=Invalid password
|
||||
Comment[af]=Ongeldige wagwoord
|
||||
Comment[ar]=كلمة المرور غير صحيحة
|
||||
Comment[ast]=Contraseña incorreuta
|
||||
Comment[ast]=La contraseña nun ye válida
|
||||
Comment[bg]=Неправилна парола
|
||||
Comment[bn]=অবৈধ পাসওয়ার্ড
|
||||
Comment[br]=Tremenger siek
|
||||
@@ -622,7 +622,6 @@ Action=Popup
|
||||
[Event/InvalidPasswordInvitations]
|
||||
Name=Invalid Password Invitations
|
||||
Name[ar]=كلمة المرور الدعوات غير صحيحة
|
||||
Name[ast]=Contraseñas d'invitaciones incorreutes
|
||||
Name[bg]=Неправилна парола за покана
|
||||
Name[bs]=Neispravna šifra pozivnice
|
||||
Name[ca]=Contrasenya de les invitacions no vàlides
|
||||
@@ -683,7 +682,7 @@ Name[zh_TW]=不合法的密碼邀請
|
||||
Comment=The invited party sent an invalid password. Connection refused.
|
||||
Comment[af]=Die uitgenooi party gestuur 'n ongeldige wagwoord. Verbinding geweier.
|
||||
Comment[ar]=المدعو أرسل كلمة مرور غير صحيحة. رفض الإتصال.
|
||||
Comment[ast]=L'invitáu unvió una contraseña incorreuta. Conexón refugada.
|
||||
Comment[ast]=La parte invitada unvió una contraseña non válida. Refugóse la conexón.
|
||||
Comment[bg]=Поканената страна изпрати неправилна парола. Връзката е отказана.
|
||||
Comment[bn]=আমন্ত্রিত দল একটি অবৈধ পাসওয়ার্ড পাঠাল। সংযোগ অস্বীকার করা হল।
|
||||
Comment[bs]=Pozvana strana je poslala pogrešnu šifru. Veza je odbijena.
|
||||
@@ -753,11 +752,11 @@ Action=Popup
|
||||
[Event/NewConnectionOnHold]
|
||||
Name=New Connection on Hold
|
||||
Name[ar]=اتصال جديد على التوقف
|
||||
Name[ast]=Conexón nueva a la espera
|
||||
Name[ast]=Conexón nueva n'espera
|
||||
Name[bg]=Изчакване на новата връзка
|
||||
Name[bs]=Nova veza je na čekanju
|
||||
Name[ca]=Nova connexió en espera
|
||||
Name[ca@valencia]=Nova connexió en espera
|
||||
Name[ca]=Connexió nova en espera
|
||||
Name[ca@valencia]=Connexió nova en espera
|
||||
Name[cs]=Nové spojení pozdrženo
|
||||
Name[da]=Ny forbindelse sat til at vente
|
||||
Name[de]=Neue Verbindung wartet
|
||||
@@ -813,12 +812,12 @@ Name[zh_TW]=新連線等待處理
|
||||
Comment=Connection requested, user must accept
|
||||
Comment[af]=Verbinding versoekte, gebruiker moet aanvaar
|
||||
Comment[ar]=الاتصال طلب، يجب موافقة المستخدم
|
||||
Comment[ast]=Conexón solicitada, l'usuario tien d'aceutala
|
||||
Comment[ast]=Solicitóse la conexón, l'usuariu ha aceutar
|
||||
Comment[bg]=Поискана е връзка, следва потребителят да приеме
|
||||
Comment[bn]=সংযোগ অনুরোধ করা হল, ব্যবহারকারীকে অবশ্যই স্বীকার করতে হবে
|
||||
Comment[bs]=Veza je zahtijevana, korinik mora da je prihvati
|
||||
Comment[ca]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[ca@valencia]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[ca]=Connexió sol·licitada, l'usuari l'ha d'acceptar
|
||||
Comment[ca@valencia]=Connexió sol·licitada, l'usuari l'ha d'acceptar
|
||||
Comment[cs]=Vyžadováno spojení, uživatel musí přijmout
|
||||
Comment[cy]=Cais wedi'i wneud am gysylltiad,rhaid i'r ddefnyddiwr ei dderbyn
|
||||
Comment[da]=Forbindelse forespurgt, bruger skal acceptere
|
||||
@@ -884,11 +883,11 @@ Action=Popup
|
||||
[Event/NewConnectionAutoAccepted]
|
||||
Name=New Connection Auto Accepted
|
||||
Name[ar]=اتصال جديد مقبول تلقائيا
|
||||
Name[ast]=Conexón nueva aceutada automáticamente
|
||||
Name[ast]=Conexón nueva auto-aceutada
|
||||
Name[bg]=Автоматично приемане на новата връзка
|
||||
Name[bs]=Nova veza je automatski prihvaćena
|
||||
Name[ca]=Nova connexió acceptada automàticament
|
||||
Name[ca@valencia]=Nova connexió acceptada automàticament
|
||||
Name[ca]=Connexió nova acceptada automàticament
|
||||
Name[ca@valencia]=Connexió nova acceptada automàticament
|
||||
Name[cs]=Nové spojení automaticky přijato
|
||||
Name[da]=Ny forbindelse automatisk accepteret
|
||||
Name[de]=Neue Verbindung automatisch angenommen
|
||||
@@ -944,12 +943,12 @@ Name[zh_TW]=新連線自動接受
|
||||
Comment=New connection automatically established
|
||||
Comment[af]=Nuwe verbinding automaties vasgestel
|
||||
Comment[ar]=اتصال جديد مفعل تلقائيا
|
||||
Comment[ast]=Conexón nueva afitada automáticamente
|
||||
Comment[ast]=Afitóse automáticamente la conexón nueva
|
||||
Comment[bg]=Новата връзка е автоматично приета
|
||||
Comment[bn]=নতুন সংযোগ স্বয়ংক্রীয়ভাবে স্থাপন করা হল
|
||||
Comment[bs]=Nova veza je automatski uspostavljena
|
||||
Comment[ca]=Nova connexió establerta automàticament
|
||||
Comment[ca@valencia]=Nova connexió establerta automàticament
|
||||
Comment[ca]=Connexió nova establerta automàticament
|
||||
Comment[ca@valencia]=Connexió nova establida automàticament
|
||||
Comment[cs]=Automaticky navázáno nové spojení
|
||||
Comment[cy]=Sefydlwyd cysylltiad newydd yn awtomatig
|
||||
Comment[da]=Ny forbindelse automatisk etableret
|
||||
@@ -1015,7 +1014,7 @@ Action=Popup
|
||||
[Event/TooManyConnections]
|
||||
Name=Too Many Connections
|
||||
Name[ar]=اتصالات عديدة
|
||||
Name[ast]=Abondes conexones
|
||||
Name[ast]=Milenta conexones
|
||||
Name[bg]=Твърде много връзки
|
||||
Name[bs]=Previše veza
|
||||
Name[ca]=Massa connexions
|
||||
@@ -1075,7 +1074,7 @@ Name[zh_TW]=太多連線
|
||||
Comment=Busy, connection refused
|
||||
Comment[af]=Besig, verbinding geweier
|
||||
Comment[ar]=مشغول، الإتصال رفض
|
||||
Comment[ast]=Ocupáu, conexón refugada
|
||||
Comment[ast]=Ocupáu, refugóse la conexón
|
||||
Comment[bg]=Заето. Връзката е отказана.
|
||||
Comment[bn]=ব্যস্ত, সংযোগ অস্বীকার করল
|
||||
Comment[br]=Dalc'het, kevreadenn disteuleret
|
||||
@@ -1210,12 +1209,12 @@ Name[zh_TW]=未知的連線
|
||||
Comment=Received unexpected connection, abort
|
||||
Comment[af]=Ontvang onverwagte verbinding, staak
|
||||
Comment[ar]=استقبال اتصال غير متوقع، إنهاء
|
||||
Comment[ast]=Recibióse conexón inesperada, albortando
|
||||
Comment[ast]=Recibióse una conexón inesperada, albortando
|
||||
Comment[bg]=Получена е неочаквана връзка. Прекъсване.
|
||||
Comment[bn]=অপ্রত্যাশিত সংযোগ গ্রহণ করল, বাতিল করুন
|
||||
Comment[bs]=Primljena je neočekivana veza, prekini
|
||||
Comment[ca]=Rebuda una connexió inesperada, avortant
|
||||
Comment[ca@valencia]=Rebuda una connexió inesperada, avortant
|
||||
Comment[ca]=S'ha rebut una connexió inesperada, avortant
|
||||
Comment[ca@valencia]=S'ha rebut una connexió inesperada, avortant
|
||||
Comment[cs]=Obdrženo neočekávané spojení, přerušeno
|
||||
Comment[cy]=Derbynwyd cysylltiad annisgwyl,terfynu
|
||||
Comment[da]=Modtog uventet forbindelse, afbrød
|
||||
|
||||
110
krfb/main.cpp
@@ -18,29 +18,26 @@
|
||||
#include "mainwindow.h"
|
||||
#include "trayicon.h"
|
||||
#include "invitationsrfbserver.h"
|
||||
#include "krfbconfig.h"
|
||||
|
||||
#include <KAboutApplicationDialog>
|
||||
#include <KAboutData>
|
||||
#include <KAction>
|
||||
#include <KUniqueApplication>
|
||||
#include <KCmdLineArgs>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KDBusService>
|
||||
#include <KLocalizedString>
|
||||
#include <KMessageBox>
|
||||
#include <KNotification>
|
||||
|
||||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/qwindowdefs.h>
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
# include "tubesrfbserver.h"
|
||||
#endif
|
||||
#include <QDebug>
|
||||
#include <QPixmap>
|
||||
#include <qwindowdefs.h>
|
||||
#include <QX11Info>
|
||||
|
||||
#include <signal.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#include <QCommandLineParser>
|
||||
#include <QCommandLineOption>
|
||||
|
||||
static const char KRFB_VERSION[] = "5.0";
|
||||
static const char description[] = I18N_NOOP("VNC-compatible server to share "
|
||||
"KDE desktops");
|
||||
"desktops");
|
||||
|
||||
static bool checkX11Capabilities()
|
||||
{
|
||||
@@ -59,61 +56,89 @@ static bool checkX11Capabilities()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void checkOldX11PluginConfig() {
|
||||
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("x11")) {
|
||||
qDebug() << "Detected deprecated configuration: preferredFrameBufferPlugin = x11";
|
||||
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(
|
||||
QStringLiteral("preferredFrameBufferPlugin"));
|
||||
if (config_item) {
|
||||
config_item->setProperty(QStringLiteral("xcb"));
|
||||
KrfbConfig::self()->save();
|
||||
qDebug() << " Fixed preferredFrameBufferPlugin from x11 to xcb.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
KAboutData aboutData("krfb", 0, ki18n("Desktop Sharing"), KDE_VERSION_STRING,
|
||||
ki18n(description), KAboutData::License_GPL,
|
||||
ki18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||
QApplication app(argc, argv);
|
||||
|
||||
KLocalizedString::setApplicationDomain("krfb");
|
||||
|
||||
KAboutData aboutData("krfb",
|
||||
i18n("Desktop Sharing"),
|
||||
KRFB_VERSION,
|
||||
i18n(description),
|
||||
KAboutLicense::GPL,
|
||||
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||
"(c) 2007, Alessandro Praduroux\n"
|
||||
"(c) 2001-2003, Tim Jansen\n"
|
||||
"(c) 2001, Johannes E. Schindelin\n"
|
||||
"(c) 2000-2001, Const Kaplinsky\n"
|
||||
"(c) 2000, Tridia Corporation\n"
|
||||
"(c) 1999, AT&T Laboratories Boston\n"));
|
||||
aboutData.addAuthor(ki18n("George Goldberg"),
|
||||
ki18n("Telepathy tubes support"),
|
||||
aboutData.addAuthor(i18n("George Goldberg"),
|
||||
i18n("Telepathy tubes support"),
|
||||
"george.goldberg@collabora.co.uk");
|
||||
aboutData.addAuthor(ki18n("George Kiagiadakis"),
|
||||
KLocalizedString(),
|
||||
aboutData.addAuthor(i18n("George Kiagiadakis"),
|
||||
QString(),
|
||||
"george.kiagiadakis@collabora.co.uk");
|
||||
aboutData.addAuthor(ki18n("Alessandro Praduroux"), ki18n("KDE4 porting"), "pradu@pradu.it");
|
||||
aboutData.addAuthor(ki18n("Tim Jansen"), ki18n("Original author"), "tim@tjansen.de");
|
||||
aboutData.addCredit(ki18n("Johannes E. Schindelin"),
|
||||
ki18n("libvncserver"));
|
||||
aboutData.addCredit(ki18n("Const Kaplinsky"),
|
||||
ki18n("TightVNC encoder"));
|
||||
aboutData.addCredit(ki18n("Tridia Corporation"),
|
||||
ki18n("ZLib encoder"));
|
||||
aboutData.addCredit(ki18n("AT&T Laboratories Boston"),
|
||||
ki18n("original VNC encoders and "
|
||||
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), "pradu@pradu.it");
|
||||
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), "tim@tjansen.de");
|
||||
aboutData.addCredit(i18n("Johannes E. Schindelin"),
|
||||
i18n("libvncserver"));
|
||||
aboutData.addCredit(i18n("Const Kaplinsky"),
|
||||
i18n("TightVNC encoder"));
|
||||
aboutData.addCredit(i18n("Tridia Corporation"),
|
||||
i18n("ZLib encoder"));
|
||||
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
||||
i18n("original VNC encoders and "
|
||||
"protocol design"));
|
||||
KCmdLineArgs::init(argc, argv, &aboutData);
|
||||
QCommandLineParser parser;
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
parser.addVersionOption();
|
||||
parser.addHelpOption();
|
||||
aboutData.setupCommandLine(&parser);
|
||||
parser.process(app);
|
||||
aboutData.processCommandLine(&parser);
|
||||
|
||||
KCmdLineOptions options;
|
||||
options.add("nodialog", ki18n("Do not show the invitations management dialog at startup"));
|
||||
KCmdLineArgs::addCmdLineOptions(options);
|
||||
KDBusService service(KDBusService::Unique, &app);
|
||||
|
||||
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nodialog"), i18n("Do not show the invitations management dialog at startup")));
|
||||
|
||||
KUniqueApplication app;
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!checkX11Capabilities()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// upgrade the configuration
|
||||
checkOldX11PluginConfig();
|
||||
|
||||
//init the core
|
||||
InvitationsRfbServer::init();
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
TubesRfbServer::init();
|
||||
#endif
|
||||
|
||||
//init the GUI
|
||||
MainWindow mainWindow;
|
||||
TrayIcon trayicon(&mainWindow);
|
||||
|
||||
if (app.isSessionRestored() && KMainWindow::canBeRestored(1)) {
|
||||
if (KrfbConfig::startMinimized()) {
|
||||
mainWindow.hide();
|
||||
} else if (app.isSessionRestored() && KMainWindow::canBeRestored(1)) {
|
||||
mainWindow.restore(1, false);
|
||||
} else if (KCmdLineArgs::parsedArgs()->isSet("dialog")) {
|
||||
} else if (!parser.isSet("nodialog")) {
|
||||
mainWindow.show();
|
||||
}
|
||||
|
||||
@@ -124,4 +149,3 @@ int main(int argc, char *argv[])
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,32 +13,27 @@
|
||||
#include "krfbconfig.h"
|
||||
#include "ui_configtcp.h"
|
||||
#include "ui_configsecurity.h"
|
||||
#include "ui_configframebuffer.h"
|
||||
|
||||
#include <KConfigDialog>
|
||||
#include <KIcon>
|
||||
#include <KLocale>
|
||||
#include <KLocalizedString>
|
||||
#include <KMessageBox>
|
||||
#include <KStandardGuiItem>
|
||||
#include <KSystemTimeZone>
|
||||
#include <KToolInvocation>
|
||||
#include <KStandardAction>
|
||||
#include <KActionCollection>
|
||||
#include <KLineEdit>
|
||||
#include <KNewPasswordDialog>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginMetaData>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QSizePolicy>
|
||||
#include <QIcon>
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QSizePolicy>
|
||||
#include <QVector>
|
||||
#include <QSet>
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
#include "tubesrfbserver.h"
|
||||
#include <TelepathyQt/PendingReady>
|
||||
#include <TelepathyQt/PendingChannelRequest>
|
||||
#include <KTp/actions.h>
|
||||
#include <KTp/Widgets/contact-view-widget.h>
|
||||
#include <KTp/Models/contacts-list-model.h>
|
||||
#include <KTp/Models/contacts-filter-model.h>
|
||||
#endif
|
||||
|
||||
class TCP: public QWidget, public Ui::TCP
|
||||
{
|
||||
@@ -56,6 +51,40 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ConfigFramebuffer: public QWidget, public Ui::Framebuffer
|
||||
{
|
||||
public:
|
||||
ConfigFramebuffer(QWidget *parent = 0) : QWidget(parent) {
|
||||
setupUi(this);
|
||||
// hide the line edit with framebuffer string
|
||||
kcfg_preferredFrameBufferPlugin->hide();
|
||||
// fill drop-down combo with a list of real existing plugins
|
||||
this->fillFrameBuffersCombo();
|
||||
// initialize combo with currently configured framebuffer plugin
|
||||
cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin());
|
||||
// connect signals between combo<->lineedit
|
||||
// if we change selection in combo, lineedit is updated
|
||||
QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged,
|
||||
kcfg_preferredFrameBufferPlugin, &QLineEdit::setText);
|
||||
}
|
||||
|
||||
void fillFrameBuffersCombo() {
|
||||
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(
|
||||
QStringLiteral("krfb"), [](const KPluginMetaData & md) {
|
||||
return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer"));
|
||||
});
|
||||
QSet<QString> unique;
|
||||
QVectorIterator<KPluginMetaData> i(plugins);
|
||||
i.toBack();
|
||||
while (i.hasPrevious()) {
|
||||
const KPluginMetaData &metadata = i.previous();
|
||||
if (unique.contains(metadata.pluginId())) continue;
|
||||
cb_preferredFrameBufferPlugin->addItem(metadata.pluginId());
|
||||
unique.insert(metadata.pluginId());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: KXmlGuiWindow(parent)
|
||||
@@ -69,26 +98,26 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
QWidget *mainWidget = new QWidget;
|
||||
m_ui.setupUi(mainWidget);
|
||||
m_ui.krfbIconLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme("krfb").pixmap(128));
|
||||
m_ui.enableUnattendedCheckBox->setChecked(
|
||||
InvitationsRfbServer::instance->allowUnattendedAccess());
|
||||
|
||||
setCentralWidget(mainWidget);
|
||||
|
||||
connect(m_ui.passwordEditButton,SIGNAL(clicked()),
|
||||
this,SLOT(editPassword()));
|
||||
connect(m_ui.enableSharingCheckBox,SIGNAL(toggled(bool)),
|
||||
this, SLOT(toggleDesktopSharing(bool)));
|
||||
connect(m_ui.enableUnattendedCheckBox, SIGNAL(toggled(bool)),
|
||||
InvitationsRfbServer::instance, SLOT(toggleUnattendedAccess(bool)));
|
||||
connect(m_ui.unattendedPasswordButton, SIGNAL(clicked()),
|
||||
this, SLOT(editUnattendedPassword()));
|
||||
connect(m_ui.addressAboutButton, SIGNAL(clicked()),
|
||||
this, SLOT(aboutConnectionAddress()));
|
||||
connect(m_ui.unattendedAboutButton, SIGNAL(clicked()),
|
||||
this, SLOT(aboutUnattendedMode()));
|
||||
connect(InvitationsRfbServer::instance, SIGNAL(passwordChanged(const QString&)),
|
||||
this, SLOT(passwordChanged(const QString&)));
|
||||
connect(m_ui.passwordEditButton, &QToolButton::clicked,
|
||||
this, &MainWindow::editPassword);
|
||||
connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled,
|
||||
this, &MainWindow::toggleDesktopSharing);
|
||||
connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled,
|
||||
InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess);
|
||||
connect(m_ui.unattendedPasswordButton, &QPushButton::clicked,
|
||||
this, &MainWindow::editUnattendedPassword);
|
||||
connect(m_ui.addressAboutButton, &QToolButton::clicked,
|
||||
this, &MainWindow::aboutConnectionAddress);
|
||||
connect(m_ui.unattendedAboutButton, &QToolButton::clicked,
|
||||
this, &MainWindow::aboutUnattendedMode);
|
||||
connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged,
|
||||
this, &MainWindow::passwordChanged);
|
||||
|
||||
// Figure out the address
|
||||
int port = KrfbConfig::port();
|
||||
@@ -108,36 +137,15 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
m_ui.passwordDisplayLabel->setText(
|
||||
InvitationsRfbServer::instance->desktopPassword());
|
||||
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
|
||||
m_contactViewWidget = new KTp::ContactViewWidget(
|
||||
TubesRfbServer::instance->contactsListModel(), this);
|
||||
|
||||
m_contactViewWidget->setEnabled(false);
|
||||
connect(m_ui.enableSharingCheckBox, SIGNAL(toggled(bool)),
|
||||
m_contactViewWidget, SLOT(setEnabled(bool)));
|
||||
m_contactViewWidget->setIconSize(QSize(32,32));
|
||||
m_contactViewWidget->setMinimumWidth(120);
|
||||
m_contactViewWidget->setMaximumWidth(360);
|
||||
m_contactViewWidget->setMinimumHeight(300);
|
||||
m_contactViewWidget->contactFilterLineEdit()->setClickMessage(i18n("Search in Contacts..."));
|
||||
m_contactViewWidget->filter()->setPresenceTypeFilterFlags(KTp::ContactsFilterModel::ShowOnlyConnected);
|
||||
m_contactViewWidget->filter()->setTubesFilterStrings(QStringList("rfb"));
|
||||
m_contactViewWidget->filter()->setCapabilityFilterFlags(KTp::ContactsFilterModel::FilterByTubes);
|
||||
|
||||
m_contactViewWidget->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
|
||||
m_ui.tpContactsLayout->addWidget(m_contactViewWidget);
|
||||
connect(m_contactViewWidget, SIGNAL(contactDoubleClicked(const Tp::AccountPtr &, const KTp::ContactPtr &)),
|
||||
this, SLOT(onContactDoubleClicked(const Tp::AccountPtr &, const KTp::ContactPtr &)));
|
||||
#endif
|
||||
|
||||
|
||||
KStandardAction::quit(QCoreApplication::instance(), SLOT(quit()), actionCollection());
|
||||
KStandardAction::preferences(this, SLOT(showConfiguration()), actionCollection());
|
||||
|
||||
setupGUI();
|
||||
|
||||
if (KrfbConfig::allowDesktopControl()) {
|
||||
m_ui.enableSharingCheckBox->setChecked(true);
|
||||
}
|
||||
|
||||
setAutoSaveSettings();
|
||||
}
|
||||
|
||||
@@ -149,7 +157,7 @@ void MainWindow::editPassword()
|
||||
{
|
||||
if(m_passwordEditable) {
|
||||
m_passwordEditable = false;
|
||||
m_ui.passwordEditButton->setIcon(KIcon("document-properties"));
|
||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-properties"));
|
||||
m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit);
|
||||
InvitationsRfbServer::instance->setDesktopPassword(
|
||||
m_passwordLineEdit->text());
|
||||
@@ -158,7 +166,7 @@ void MainWindow::editPassword()
|
||||
m_passwordLineEdit->setVisible(false);
|
||||
} else {
|
||||
m_passwordEditable = true;
|
||||
m_ui.passwordEditButton->setIcon(KIcon("document-save"));
|
||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-save"));
|
||||
m_ui.passwordGridLayout->addWidget(m_passwordLineEdit,0,0);
|
||||
m_passwordLineEdit->setText(
|
||||
InvitationsRfbServer::instance->desktopPassword());
|
||||
@@ -190,7 +198,7 @@ void MainWindow::toggleDesktopSharing(bool enable)
|
||||
if(m_passwordEditable) {
|
||||
m_passwordEditable = false;
|
||||
m_passwordLineEdit->setVisible(false);
|
||||
m_ui.passwordEditButton->setIcon(KIcon("document-properties"));
|
||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-properties"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,36 +223,30 @@ void MainWindow::aboutUnattendedMode()
|
||||
i18n("KDE Desktop Sharing"));
|
||||
}
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
|
||||
void MainWindow::onContactDoubleClicked(const Tp::AccountPtr &account, const KTp::ContactPtr &contact)
|
||||
{
|
||||
Tp::PendingOperation *op = KTp::Actions::startDesktopSharing(account, contact);
|
||||
connect(op, SIGNAL(finished(Tp::PendingOperation*)),
|
||||
this, SLOT(pendingDesktopShareFinished(Tp::PendingOperation*)));
|
||||
}
|
||||
|
||||
void MainWindow::pendingDesktopShareFinished(Tp::PendingOperation *operation)
|
||||
{
|
||||
if(operation->isError()) {
|
||||
KMessageBox::error(this,
|
||||
operation->errorName() + ": " + operation->errorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MainWindow::showConfiguration()
|
||||
{
|
||||
static QString s_prevFramebufferPlugin;
|
||||
// ^^ needs to be static, because lambda will be called long time
|
||||
// after showConfiguration() ends, so auto variable would go out of scope
|
||||
// save previously selected framebuffer plugin config
|
||||
s_prevFramebufferPlugin = KrfbConfig::preferredFrameBufferPlugin();
|
||||
|
||||
if (KConfigDialog::showDialog("settings")) {
|
||||
return;
|
||||
}
|
||||
|
||||
KConfigDialog *dialog = new KConfigDialog(this, "settings", KrfbConfig::self());
|
||||
dialog->addPage(new TCP, i18n("Network"), "network-workgroup");
|
||||
dialog->addPage(new TCP, i18n("Network"), "network-wired");
|
||||
dialog->addPage(new Security, i18n("Security"), "security-high");
|
||||
dialog->setHelp(QString(), "krfb");
|
||||
dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), "video-display");
|
||||
dialog->show();
|
||||
connect(dialog, &KConfigDialog::settingsChanged, [this] () {
|
||||
// check if framebuffer plugin config has changed
|
||||
if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) {
|
||||
KMessageBox::information(this, i18n("To apply framebuffer plugin setting, "
|
||||
"you need to restart the program."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::readProperties(const KConfigGroup& group)
|
||||
|
||||
@@ -15,17 +15,6 @@
|
||||
|
||||
#include <KXmlGuiWindow>
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
#include <KTp/contact.h>
|
||||
#include <TelepathyQt/PendingReady>
|
||||
namespace KTp {
|
||||
class ContactViewWidget;
|
||||
}
|
||||
namespace Tp {
|
||||
class PendingOperation;
|
||||
}
|
||||
#endif
|
||||
|
||||
class KLineEdit;
|
||||
|
||||
class MainWindow : public KXmlGuiWindow
|
||||
@@ -40,8 +29,8 @@ class MainWindow : public KXmlGuiWindow
|
||||
void showConfiguration();
|
||||
|
||||
protected:
|
||||
virtual void readProperties(const KConfigGroup & group);
|
||||
virtual void saveProperties(KConfigGroup & group);
|
||||
void readProperties(const KConfigGroup & group) override;
|
||||
void saveProperties(KConfigGroup & group) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void editPassword();
|
||||
@@ -50,19 +39,11 @@ class MainWindow : public KXmlGuiWindow
|
||||
void passwordChanged(const QString&);
|
||||
void aboutConnectionAddress();
|
||||
void aboutUnattendedMode();
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
void onContactDoubleClicked(const Tp::AccountPtr &, const KTp::ContactPtr &);
|
||||
void pendingDesktopShareFinished(Tp::PendingOperation*);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Ui::MainWidget m_ui;
|
||||
bool m_passwordEditable;
|
||||
KLineEdit *m_passwordLineEdit;
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
KTp::ContactViewWidget *m_contactViewWidget;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.Telepathy.Client.krfb_rfb_handler
|
||||
Exec=@CMAKE_INSTALL_PREFIX@/bin/krfb --nodialog
|
||||
100
krfb/org.kde.krfb.appdata.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.kde.krfb.desktop</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<name>Krfb</name>
|
||||
<name xml:lang="ast">Krfb</name>
|
||||
<name xml:lang="ca">Krfb</name>
|
||||
<name xml:lang="ca-valencia">Krfb</name>
|
||||
<name xml:lang="cs">Krfb</name>
|
||||
<name xml:lang="de">Krfb</name>
|
||||
<name xml:lang="el">Krfb</name>
|
||||
<name xml:lang="en-GB">Krfb</name>
|
||||
<name xml:lang="es">Krfb</name>
|
||||
<name xml:lang="fr">Krfb</name>
|
||||
<name xml:lang="gl">Krfb</name>
|
||||
<name xml:lang="it">Krfb</name>
|
||||
<name xml:lang="nl">Krfb</name>
|
||||
<name xml:lang="pl">Krfb</name>
|
||||
<name xml:lang="pt">Krfb</name>
|
||||
<name xml:lang="pt-BR">Krfb</name>
|
||||
<name xml:lang="sk">Krfb</name>
|
||||
<name xml:lang="sl">Krfb</name>
|
||||
<name xml:lang="sr">КРФБ</name>
|
||||
<name xml:lang="sr-Latn">KRFB</name>
|
||||
<name xml:lang="sr-ijekavian">КРФБ</name>
|
||||
<name xml:lang="sr-ijekavianlatin">KRFB</name>
|
||||
<name xml:lang="sv">Krfb</name>
|
||||
<name xml:lang="tr">Krfb</name>
|
||||
<name xml:lang="uk">Krfb</name>
|
||||
<name xml:lang="x-test">xxKrfbxx</name>
|
||||
<name xml:lang="zh-CN">Krfb</name>
|
||||
<summary>Desktop sharing</summary>
|
||||
<summary xml:lang="ast">Compartición d'escritoriu</summary>
|
||||
<summary xml:lang="ca">Compartició de l'escriptori</summary>
|
||||
<summary xml:lang="ca-valencia">Compartició de l'escriptori</summary>
|
||||
<summary xml:lang="cs">Sdílení pracovní plochy</summary>
|
||||
<summary xml:lang="de">Freigabe der Arbeitsfläche</summary>
|
||||
<summary xml:lang="el">Κοινή χρήση επιφάνειας εργασίας</summary>
|
||||
<summary xml:lang="en-GB">Desktop sharing</summary>
|
||||
<summary xml:lang="es">Compartir el escritorio</summary>
|
||||
<summary xml:lang="fr">Partage de bureau</summary>
|
||||
<summary xml:lang="gl">Compartición do escritorio</summary>
|
||||
<summary xml:lang="it">Condivisione del desktop</summary>
|
||||
<summary xml:lang="nl">Bureaublad delen</summary>
|
||||
<summary xml:lang="pl">Współdzielenie pulpitu</summary>
|
||||
<summary xml:lang="pt">Partilha do ecrã</summary>
|
||||
<summary xml:lang="pt-BR">Compartilhamento de tela</summary>
|
||||
<summary xml:lang="sk">Zdieľanie pracovnej plochy</summary>
|
||||
<summary xml:lang="sl">Souporaba namizja</summary>
|
||||
<summary xml:lang="sr">Дељење површи</summary>
|
||||
<summary xml:lang="sr-Latn">Deljenje površi</summary>
|
||||
<summary xml:lang="sr-ijekavian">Дељење површи</summary>
|
||||
<summary xml:lang="sr-ijekavianlatin">Deljenje površi</summary>
|
||||
<summary xml:lang="sv">Skrivbordsdelning</summary>
|
||||
<summary xml:lang="tr">Masaüstü paylaşımı</summary>
|
||||
<summary xml:lang="uk">Спільне користування стільницею</summary>
|
||||
<summary xml:lang="x-test">xxDesktop sharingxx</summary>
|
||||
<summary xml:lang="zh-CN">桌面共享</summary>
|
||||
<description>
|
||||
<p>Krfb Desktop Sharing is a server application that allows you to share your current session with a user on another machine, who can use a VNC client to view or even control the desktop.</p>
|
||||
<p xml:lang="ca">El Krfb és una aplicació de servidor que permet compartir la vostra sessió actual amb un usuari en una altra màquina, la qual pot emprar un client VNC per veure o controlar l'escriptori.</p>
|
||||
<p xml:lang="ca-valencia">El Krfb és una aplicació de servidor que permet compartir la vostra sessió actual amb un usuari en una altra màquina, la qual pot emprar un client VNC per veure o controlar l'escriptori.</p>
|
||||
<p xml:lang="de">Krfb ist eine Serveranwendung, welche die gemeinsame Benutzung der aktuellen Sitzung mit einem Benutzer auf einem anderen Rechner ermöglicht, der mit Hilfe eines VNC-Programms den Bildschirminhalt sehen oder sogar die Arbeitsfläche bedienen kann.</p>
|
||||
<p xml:lang="el">Η κοινή χρήση επιφάνειας εργασίας Krfb είναι μια εφαρμογή εξυπηρετητή που σας επιτρέπει να μοιράζεστε την τρέχουσα συνεδρία σας με έναν χρήστη σε άλλο μηχάνημα, ο οποίος μπορεί να χρησιμοποιεί έναν πελάτη VNC για να παρακολουθεί ή και να ελέγχει την επιφάνεια εργασίας σας.</p>
|
||||
<p xml:lang="en-GB">Krfb Desktop Sharing is a server application that allows you to share your current session with a user on another machine, who can use a VNC client to view or even control the desktop.</p>
|
||||
<p xml:lang="es">Krfb para compartir el escritorio es una aplicación de servidor que le permite compartir su sesión actual con un usuario de otra máquina, que puede usar un cliente VNC para ver e incluso controlar su escritorio.</p>
|
||||
<p xml:lang="fr">Le partage de bureau Krfb est une application de serveur qui vous permet de partager votre session courante avec un utilisateur sur une autre machine, qui peut utiliser un client VNC pour afficher et même contrôler le bureau.</p>
|
||||
<p xml:lang="gl">Krfb é un aplicativo de servidor que permite compartir a sesión actual cun usuario que está noutro equipo, que pode usar un cliente VNC para ver ou mesmo controlar o escritorio.</p>
|
||||
<p xml:lang="it">Condivisione del desktop Krfb è un'applicazione server che permette di condividere la sessione attuale con un utente su un'altra macchina, che potrà usare un client VNC per visualizzare ed anche controllare il desktop.</p>
|
||||
<p xml:lang="nl">Bureaublad delen is een server-applicatie die u in staat stelt uw huidige sessie te delen met een gebruiker op een andere machine, die een VNC-client kan gebruiken om uw bureaublad te bekijken of zelfs te besturen.</p>
|
||||
<p xml:lang="pl">Współdzielenie pulpitu Krfb jest aplikacją serwerową, która umożliwia współdzielenie twojej bieżącej sesji z użytkownikiem na innym komputerze, który może użyć klienta VNC do oglądania,a a nawet sterowania twoim pulpitem.</p>
|
||||
<p xml:lang="pt">A Partilha de Ecrã Krfb é uma aplicação de servidor que lhe permite partilhar a sua sessão actual com um utilizador noutra máquina, o qual poderá usar um cliente de VNC para ver ou mesmo controlar o ambiente de trabalho.</p>
|
||||
<p xml:lang="sk">Krfb je serverová aplikácia, ktorá vám umožní zdieľať vaše aktuálne sedenie s používateľom na inom stroji, ktorý môže používať VNC klienta na pripojenie alebo ovládanie stanice.</p>
|
||||
<p xml:lang="sl">Souporaba namizja Krfb je strežniški program, ki vam dovoli, da delite vašo trenutno sejo z uporabnikom na drugem računalniku, ki ima odjemalec VNC. Uporabnik lahko gleda ali celo nadzira namizje.</p>
|
||||
<p xml:lang="sr">КРФБ је серверски програм за дељење површи, којим можете да поделите своју текућу сесију са корисником на другој машини. Удаљени корисник може да употреби неки ВНЦ клијент за гледање површи, па чак и управљање њоме.</p>
|
||||
<p xml:lang="sr-Latn">KRFB je serverski program za deljenje površi, kojim možete da podelite svoju tekuću sesiju sa korisnikom na drugoj mašini. Udaljeni korisnik može da upotrebi neki VNC klijent za gledanje površi, pa čak i upravljanje njome.</p>
|
||||
<p xml:lang="sr-ijekavian">КРФБ је серверски програм за дељење површи, којим можете да поделите своју текућу сесију са корисником на другој машини. Удаљени корисник може да употреби неки ВНЦ клијент за гледање површи, па чак и управљање њоме.</p>
|
||||
<p xml:lang="sr-ijekavianlatin">KRFB je serverski program za deljenje površi, kojim možete da podelite svoju tekuću sesiju sa korisnikom na drugoj mašini. Udaljeni korisnik može da upotrebi neki VNC klijent za gledanje površi, pa čak i upravljanje njome.</p>
|
||||
<p xml:lang="sv">Krfb-skrivbordsdelning är ett serverprogram som gör det möjligt att dela aktuell session med en användare på en annan dator, som kan använda en VNC-klient för att betrakta eller till och med kontrollera skrivbordet.</p>
|
||||
<p xml:lang="tr">Krfb Masaüstü Paylaşımı, mevcut oturumu masaüstünü görüntülemek veya kontrol etmek için, VNC istemcisi kullanan başka bir makinedeki, kullanıcıyla paylaşmanızı sağlayan bir sunucu uygulamasıdır.</p>
|
||||
<p xml:lang="uk">Програма для спільного використання стільниці Krfb — це серверна програма, яка надає вам змогу розділити ваш поточний сеанс роботи з користувачем, який працює на іншому комп’ютері, так, щоб цей користувач зміг скористатися клієнтом VNC для перегляду або навіть керування вашою стільницею.</p>
|
||||
<p xml:lang="x-test">xxKrfb Desktop Sharing is a server application that allows you to share your current session with a user on another machine, who can use a VNC client to view or even control the desktop.xx</p>
|
||||
<p xml:lang="zh-CN">Krfb 桌面共享是一个可以让您与另一个在其他机器上的用户共享当前会话的服务器程序,他可以使用 VNC 客户端来查看甚至控制桌面。</p>
|
||||
</description>
|
||||
<url type="homepage">https://www.kde.org</url>
|
||||
<url type="bugtracker">https://bugs.kde.org</url>
|
||||
<url type="donation">https://www.kde.org/community/donations</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>
|
||||
https://cdn.kde.org/screenshots/krfb/krfb.png
|
||||
</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<provides>
|
||||
<binary>krfb</binary>
|
||||
</provides>
|
||||
<project_group>KDE</project_group>
|
||||
</component>
|
||||
@@ -1,7 +1,7 @@
|
||||
# KDE Config File
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Exec=krfb -caption %c %i
|
||||
Exec=krfb -qwindowtitle %c %i
|
||||
Icon=krfb
|
||||
X-DBUS-StartupType=Unique
|
||||
X-DocPath=krfb/index.html
|
||||
@@ -76,13 +76,13 @@ Name[zh_HK]=Krfb
|
||||
Name[zh_TW]=桌面分享_Krfb
|
||||
GenericName=Desktop Sharing
|
||||
GenericName[ar]=مشاركة سطح المكتب
|
||||
GenericName[ast]=Escritoriu compartíu
|
||||
GenericName[ast]=Compartición d'escritoriu
|
||||
GenericName[bg]=Споделяне на работния плот
|
||||
GenericName[bn]=ডেস্কটপ ভাগাভাগি
|
||||
GenericName[br]=Rannañ ar vurev
|
||||
GenericName[bs]=Dijeljenje radne površine
|
||||
GenericName[ca]=Compartició de l'escriptori
|
||||
GenericName[ca@valencia]=Compartició de l'escriptori
|
||||
GenericName[ca]=Compartir l'escriptori
|
||||
GenericName[ca@valencia]=Compartir l'escriptori
|
||||
GenericName[cs]=Sdílení pracovní plochy
|
||||
GenericName[cy]=Rhannu Penbwrdd
|
||||
GenericName[da]=Skrivebordsdeling
|
||||
@@ -110,7 +110,7 @@ GenericName[ja]=デスクトップ共有
|
||||
GenericName[kk]=Үстелді ортақтастыру
|
||||
GenericName[km]=ការចែករំលែកផ្ទៃតុ
|
||||
GenericName[ko]=데스크톱 공유
|
||||
GenericName[lt]=Dalinimasis darbastaliu
|
||||
GenericName[lt]=Dalinimasis darbalaukiu
|
||||
GenericName[lv]=Darbvirsmas koplietošana
|
||||
GenericName[ml]=പണിയിടം പങ്കുവെക്കല്
|
||||
GenericName[mr]=डेस्कटॉप शेअरींग
|
||||
@@ -144,4 +144,76 @@ GenericName[x-test]=xxDesktop Sharingxx
|
||||
GenericName[zh_CN]=桌面共享
|
||||
GenericName[zh_HK]=桌面分享
|
||||
GenericName[zh_TW]=桌面分享
|
||||
Comment=Desktop Sharing
|
||||
Comment[af]=Werkskerm Deeling
|
||||
Comment[ar]=مشاركة سطح المكتب
|
||||
Comment[ast]=Compartición d'escritoriu
|
||||
Comment[bg]=Споделяне на работния плот
|
||||
Comment[bn]=ডেস্কটপ ভাগাভাগি
|
||||
Comment[br]=Rannañ ar vurev
|
||||
Comment[bs]=Dijeljenje radne površine
|
||||
Comment[ca]=Compartir l'escriptori
|
||||
Comment[ca@valencia]=Compartir l'escriptori
|
||||
Comment[cs]=Sdílení pracovní plochy
|
||||
Comment[cy]=Rhannu Penbwrdd
|
||||
Comment[da]=Skrivebordsdeling
|
||||
Comment[de]=Arbeitsflächen-Freigabe
|
||||
Comment[el]=Κοινή χρήση επιφάνειας εργασίας
|
||||
Comment[en_GB]=Desktop Sharing
|
||||
Comment[eo]=Tabula komunigado
|
||||
Comment[es]=Escritorio compartido
|
||||
Comment[et]=Töölaua jagamine
|
||||
Comment[eu]=Mahaigaina partekatzea
|
||||
Comment[fi]=Työpöydän jakaminen
|
||||
Comment[fr]=Partage de bureaux
|
||||
Comment[ga]=Roinnt Deisce
|
||||
Comment[gl]=Compartición do escritorio
|
||||
Comment[he]=שיתוף שולחנות עבודה
|
||||
Comment[hi]=डेस्कटॉप साझेदारी
|
||||
Comment[hne]=डेस्कटाप साझेदारी
|
||||
Comment[hr]=Dijeljenje radne površine
|
||||
Comment[hu]=Munkaasztal-megosztás
|
||||
Comment[ia]=Compartir de scriptorio
|
||||
Comment[is]=Skjáborðamiðlun
|
||||
Comment[it]=Condivisione del desktop
|
||||
Comment[ja]=デスクトップ共有
|
||||
Comment[kk]=Үстелді ортақтастыру
|
||||
Comment[km]=ការចែករំលែកផ្ទែតុ
|
||||
Comment[ko]=데스크톱 공유
|
||||
Comment[lt]=Dalinimasis darbalaukiu
|
||||
Comment[lv]=Darbvirsmas koplietošana
|
||||
Comment[mk]=Делење на работната површина
|
||||
Comment[ml]=പണിയിടം പങ്കുവെക്കല്
|
||||
Comment[mr]=डेस्कटॉप शेअरींग
|
||||
Comment[ms]=Perkongsian Ruang Kerja
|
||||
Comment[nb]=Delte skrivebord
|
||||
Comment[nds]=Schriefdisch-Freegaav
|
||||
Comment[nl]=Bureaublad delen
|
||||
Comment[nn]=Skrivebordsdeling
|
||||
Comment[pa]=ਡੈਸਕਟਾਪ ਸ਼ੇਅਰਿੰਗ
|
||||
Comment[pl]=Współdzielenie pulpitu
|
||||
Comment[pt]=Partilha do Ecrã
|
||||
Comment[pt_BR]=Compartilhamento do ambiente de trabalho
|
||||
Comment[ro]=Partajare birou
|
||||
Comment[ru]=Параметры общего рабочего стола
|
||||
Comment[si]=වැඩතල හවුල්
|
||||
Comment[sk]=Zdieľanie pracovnej plochy
|
||||
Comment[sl]=Souporaba namizja
|
||||
Comment[sr]=Дељење површи
|
||||
Comment[sr@ijekavian]=Дијељење површи
|
||||
Comment[sr@ijekavianlatin]=Dijeljenje površi
|
||||
Comment[sr@latin]=Deljenje površi
|
||||
Comment[sv]=Dela ut skrivbordet
|
||||
Comment[ta]=பணிமேடை பகிர்வு
|
||||
Comment[tg]=Истифодаи Муштараки Мизи Корӣ
|
||||
Comment[th]=ใช้งานพื้นที่ทำงานร่วมกัน
|
||||
Comment[tr]=Masaüstü Paylaşımı
|
||||
Comment[ug]=ئۈستەلئۈستىنى ھەمبەھىرلەش
|
||||
Comment[uk]=Спільні стільниці
|
||||
Comment[xh]=Ulwahlulelano lwe Desktop
|
||||
Comment[x-test]=xxDesktop Sharingxx
|
||||
Comment[zh_CN]=桌面共享
|
||||
Comment[zh_HK]=桌面分享
|
||||
Comment[zh_TW]=桌面分享
|
||||
Categories=Qt;KDE;System;Network;RemoteAccess;
|
||||
X-DBUS-ServiceName=org.kde.krfb
|
||||
@@ -6,7 +6,11 @@
|
||||
#ifndef KRFB_RFB_H
|
||||
#define KRFB_RFB_H
|
||||
|
||||
#include "../libvncserver/rfb/rfb.h"
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
#include "sockethelpers.h"
|
||||
#include "events.h"
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <KDebug>
|
||||
#include <KNotification>
|
||||
#include <QDebug>
|
||||
#include <poll.h>
|
||||
#include <strings.h> //for bzero()
|
||||
|
||||
@@ -49,12 +48,12 @@ RfbClient::RfbClient(rfbClientPtr client, QObject* parent)
|
||||
|
||||
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(false);
|
||||
connect(d->notifier, SIGNAL(activated(int)), this, SLOT(onSocketActivated()));
|
||||
connect(d->notifier, &QSocketNotifier::activated, this, &RfbClient::onSocketActivated);
|
||||
}
|
||||
|
||||
RfbClient::~RfbClient()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
delete d;
|
||||
}
|
||||
|
||||
@@ -140,7 +139,7 @@ void RfbClient::onSocketActivated()
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
kDebug() << "disconnected from socket signal";
|
||||
//qDebug() << "disconnected from socket signal";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
break;
|
||||
@@ -159,7 +158,7 @@ void RfbClient::update()
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
kDebug() << "disconnected during update";
|
||||
//qDebug() << "disconnected during update";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
}
|
||||
@@ -178,7 +177,7 @@ PendingRfbClient::~PendingRfbClient()
|
||||
|
||||
void PendingRfbClient::accept(RfbClient *newClient)
|
||||
{
|
||||
kDebug() << "accepted connection";
|
||||
//qDebug() << "accepted connection";
|
||||
|
||||
m_rfbClient->clientData = newClient;
|
||||
newClient->setOnHold(false);
|
||||
@@ -191,7 +190,7 @@ static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
|
||||
|
||||
void PendingRfbClient::reject()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
//qDebug() << "refused connection";
|
||||
|
||||
//override the clientGoneHook that was previously set by RfbServer
|
||||
m_rfbClient->clientGoneHook = clientGoneHookNoop;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <KDebug>
|
||||
#include <QDebug>
|
||||
|
||||
struct RfbServer::Private
|
||||
{
|
||||
@@ -90,6 +90,7 @@ bool RfbServer::start()
|
||||
if (!d->screen) {
|
||||
d->screen = RfbServerManager::instance()->newScreen();
|
||||
if (!d->screen) {
|
||||
qDebug() << "Unable to get rbfserver screen";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,31 +123,31 @@ bool RfbServer::start()
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
}
|
||||
|
||||
kDebug() << "Starting server. Listen port:" << listeningPort()
|
||||
qDebug() << "Starting server. Listen port:" << listeningPort()
|
||||
<< "Listen Address:" << listeningAddress()
|
||||
<< "Password enabled:" << passwordRequired();
|
||||
|
||||
rfbInitServer(d->screen);
|
||||
|
||||
if (!rfbIsActive(d->screen)) {
|
||||
kDebug() << "Failed to start server";
|
||||
qDebug() << "Failed to start server";
|
||||
rfbShutdownServer(d->screen, false);
|
||||
return false;
|
||||
};
|
||||
|
||||
d->notifier = new QSocketNotifier(d->screen->listenSock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(true);
|
||||
connect(d->notifier, SIGNAL(activated(int)), this, SLOT(onListenSocketActivated()));
|
||||
connect(QApplication::clipboard(), SIGNAL(dataChanged()),
|
||||
this, SLOT(krfbSendServerCutText()));
|
||||
connect(d->notifier, &QSocketNotifier::activated, this, &RfbServer::onListenSocketActivated);
|
||||
connect(QApplication::clipboard(), &QClipboard::dataChanged,
|
||||
this, &RfbServer::krfbSendServerCutText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RfbServer::stop(bool disconnectClients)
|
||||
void RfbServer::stop()
|
||||
{
|
||||
if (d->screen) {
|
||||
rfbShutdownServer(d->screen, disconnectClients);
|
||||
rfbShutdownServer(d->screen, true);
|
||||
if (d->notifier) {
|
||||
d->notifier->setEnabled(false);
|
||||
d->notifier->deleteLater();
|
||||
@@ -187,13 +188,13 @@ void krfb_rfbSetCursorPosition(rfbScreenInfoPtr screen, rfbClientPtr client, int
|
||||
/* Inform all clients about this cursor movement. */
|
||||
iterator = rfbGetClientIterator(screen);
|
||||
while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
|
||||
cl->cursorWasMoved = TRUE;
|
||||
cl->cursorWasMoved = true;
|
||||
}
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
/* The cursor was moved by this client, so don't send CursorPos. */
|
||||
if (client) {
|
||||
client->cursorWasMoved = FALSE;
|
||||
client->cursorWasMoved = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +221,7 @@ void RfbServer::onListenSocketActivated()
|
||||
|
||||
void RfbServer::pendingClientFinished(RfbClient *client)
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
if (client) {
|
||||
RfbServerManager::instance()->addClient(client);
|
||||
client->getRfbClientPtr()->clientGoneHook = clientGoneHook;
|
||||
@@ -230,12 +231,12 @@ void RfbServer::pendingClientFinished(RfbClient *client)
|
||||
//static
|
||||
rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
|
||||
{
|
||||
kDebug() << "New client";
|
||||
//qDebug() << "New client";
|
||||
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
|
||||
|
||||
PendingRfbClient *pendingClient = server->newClient(cl);
|
||||
connect(pendingClient, SIGNAL(finished(RfbClient*)),
|
||||
server, SLOT(pendingClientFinished(RfbClient*)));
|
||||
connect(pendingClient, &PendingRfbClient::finished,
|
||||
server, &RfbServer::pendingClientFinished);
|
||||
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
@@ -243,7 +244,7 @@ rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
|
||||
//static
|
||||
void RfbServer::clientGoneHook(rfbClientPtr cl)
|
||||
{
|
||||
kDebug() << "client gone";
|
||||
//qDebug() << "client gone";
|
||||
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
|
||||
|
||||
RfbServerManager::instance()->removeClient(client);
|
||||
@@ -273,7 +274,7 @@ void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
}
|
||||
|
||||
//static
|
||||
void RfbServer::clipboardHook(char *str, int len, rfbClientPtr cl)
|
||||
void RfbServer::clipboardHook(char *str, int len, rfbClientPtr /*cl*/)
|
||||
{
|
||||
QApplication::clipboard()->setText(QString::fromLocal8Bit(str,len));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual bool start();
|
||||
virtual void stop(bool disconnectClients = true);
|
||||
virtual void stop();
|
||||
|
||||
void updateScreen(const QList<QRect> & modifiedTiles);
|
||||
void updateCursorPosition(const QPoint & position);
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
#include "sockethelpers.h"
|
||||
#include "krfbconfig.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGlobalStatic>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <KGlobal>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <QDebug>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <KUser>
|
||||
#include <KNotification>
|
||||
|
||||
@@ -82,7 +83,7 @@ struct RfbServerManagerStatic
|
||||
RfbServerManager server;
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(RfbServerManagerStatic, s_instance)
|
||||
Q_GLOBAL_STATIC(RfbServerManagerStatic, s_instance)
|
||||
|
||||
RfbServerManager* RfbServerManager::instance()
|
||||
{
|
||||
@@ -114,7 +115,7 @@ RfbServerManager::~RfbServerManager()
|
||||
|
||||
void RfbServerManager::init()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
d->fb = FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId());
|
||||
d->myCursor = rfbMakeXCursor(19, 19, (char *) cur, (char *) mask);
|
||||
@@ -122,8 +123,8 @@ void RfbServerManager::init()
|
||||
d->desktopName = QString("%1@%2 (shared desktop)") //FIXME check if we can use utf8
|
||||
.arg(KUser().loginName(),QHostInfo::localHostName()).toLatin1();
|
||||
|
||||
connect(&d->rfbUpdateTimer, SIGNAL(timeout()), SLOT(updateScreens()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(cleanup()));
|
||||
connect(&d->rfbUpdateTimer, &QTimer::timeout, this, &RfbServerManager::updateScreens);
|
||||
connect(qApp, &QApplication::aboutToQuit, this, &RfbServerManager::cleanup);
|
||||
}
|
||||
|
||||
void RfbServerManager::updateScreens()
|
||||
@@ -147,7 +148,7 @@ void RfbServerManager::updateScreens()
|
||||
|
||||
void RfbServerManager::cleanup()
|
||||
{
|
||||
kDebug();
|
||||
//qDebug();
|
||||
|
||||
//copy because d->servers is going to be modified while we delete the servers
|
||||
QSet<RfbServer*> servers = d->servers;
|
||||
@@ -187,7 +188,7 @@ rfbScreenInfoPtr RfbServerManager::newScreen()
|
||||
bpp = 4;
|
||||
}
|
||||
|
||||
kDebug() << "bpp: " << bpp;
|
||||
//qDebug() << "bpp: " << bpp;
|
||||
|
||||
rfbLogEnable(0);
|
||||
|
||||
@@ -206,7 +207,7 @@ rfbScreenInfoPtr RfbServerManager::newScreen()
|
||||
void RfbServerManager::addClient(RfbClient* cc)
|
||||
{
|
||||
if (d->clients.size() == 0) {
|
||||
kDebug() << "Starting framebuffer monitor";
|
||||
//qDebug() << "Starting framebuffer monitor";
|
||||
d->fb->startMonitor();
|
||||
d->rfbUpdateTimer.start(50);
|
||||
}
|
||||
@@ -222,7 +223,7 @@ void RfbServerManager::removeClient(RfbClient* cc)
|
||||
{
|
||||
d->clients.remove(cc);
|
||||
if (d->clients.size() == 0) {
|
||||
kDebug() << "Stopping framebuffer monitor";
|
||||
//qDebug() << "Stopping framebuffer monitor";
|
||||
d->fb->stopMonitor();
|
||||
d->rfbUpdateTimer.stop();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class RfbClient;
|
||||
class RfbServerManagerStatic;
|
||||
struct RfbServerManagerStatic;
|
||||
class RfbServer;
|
||||
|
||||
class RfbServerManager : public QObject
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
Q_DISABLE_COPY(RfbServerManager)
|
||||
|
||||
friend class RfbServer;
|
||||
friend class RfbServerManagerStatic;
|
||||
friend struct RfbServerManagerStatic;
|
||||
|
||||
struct Private;
|
||||
Private *const d;
|
||||
|
||||
@@ -22,49 +22,51 @@
|
||||
#include "rfbservermanager.h"
|
||||
#include "rfbclient.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QMenu>
|
||||
|
||||
#include <KAboutApplicationDialog>
|
||||
#include <KActionCollection>
|
||||
#include <KDialog>
|
||||
#include <KGlobal>
|
||||
#include <KLocale>
|
||||
#include <KMenu>
|
||||
#include <QDialog>
|
||||
#include <KHelpMenu>
|
||||
#include <KLocalizedString>
|
||||
#include <KStandardAction>
|
||||
#include <KDebug>
|
||||
|
||||
#include <KToggleAction>
|
||||
#include <KConfigGroup>
|
||||
|
||||
class ClientActions
|
||||
{
|
||||
public:
|
||||
ClientActions(RfbClient *client, KMenu *menu, QAction *before);
|
||||
ClientActions(RfbClient *client, QMenu *menu, QAction *before);
|
||||
virtual ~ClientActions();
|
||||
|
||||
private:
|
||||
KMenu *m_menu;
|
||||
QMenu *m_menu;
|
||||
QAction *m_title;
|
||||
QAction *m_disconnectAction;
|
||||
QAction *m_enableControlAction;
|
||||
QAction *m_separator;
|
||||
};
|
||||
|
||||
ClientActions::ClientActions(RfbClient* client, KMenu* menu, QAction* before)
|
||||
ClientActions::ClientActions(RfbClient* client, QMenu* menu, QAction* before)
|
||||
: m_menu(menu)
|
||||
{
|
||||
m_title = m_menu->addTitle(client->name(), before);
|
||||
m_title = m_menu->insertSection(before, client->name());
|
||||
|
||||
m_disconnectAction = new KAction(i18n("Disconnect"), m_menu);
|
||||
m_disconnectAction = new QAction(i18n("Disconnect"), m_menu);
|
||||
m_menu->insertAction(before, m_disconnectAction);
|
||||
|
||||
QObject::connect(m_disconnectAction, SIGNAL(triggered()), client, SLOT(closeConnection()));
|
||||
QObject::connect(m_disconnectAction, &QAction::triggered, client, &RfbClient::closeConnection);
|
||||
|
||||
if (client->controlCanBeEnabled()) {
|
||||
m_enableControlAction = new KToggleAction(i18n("Enable Remote Control"), m_menu);
|
||||
m_enableControlAction->setChecked(client->controlEnabled());
|
||||
m_menu->insertAction(before, m_enableControlAction);
|
||||
|
||||
QObject::connect(m_enableControlAction, SIGNAL(triggered(bool)),
|
||||
client, SLOT(setControlEnabled(bool)));
|
||||
QObject::connect(client, SIGNAL(controlEnabledChanged(bool)),
|
||||
m_enableControlAction, SLOT(setChecked(bool)));
|
||||
QObject::connect(m_enableControlAction, &KToggleAction::triggered,
|
||||
client, &RfbClient::setControlEnabled);
|
||||
QObject::connect(client, &RfbClient::controlEnabledChanged,
|
||||
m_enableControlAction, &KToggleAction::setChecked);
|
||||
} else {
|
||||
m_enableControlAction = NULL;
|
||||
}
|
||||
@@ -74,8 +76,6 @@ ClientActions::ClientActions(RfbClient* client, KMenu* menu, QAction* before)
|
||||
|
||||
ClientActions::~ClientActions()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
m_menu->removeAction(m_title);
|
||||
delete m_title;
|
||||
|
||||
@@ -96,24 +96,22 @@ ClientActions::~ClientActions()
|
||||
TrayIcon::TrayIcon(QWidget *mainWindow)
|
||||
: KStatusNotifierItem(mainWindow)
|
||||
{
|
||||
setIconByPixmap(KIcon("krfb").pixmap(22, 22, KIcon::Disabled));
|
||||
setIconByPixmap(QIcon::fromTheme("krfb").pixmap(22, 22, QIcon::Disabled));
|
||||
|
||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||
setCategory(KStatusNotifierItem::ApplicationStatus);
|
||||
|
||||
connect(RfbServerManager::instance(), SIGNAL(clientConnected(RfbClient*)),
|
||||
this, SLOT(onClientConnected(RfbClient*)));
|
||||
connect(RfbServerManager::instance(), SIGNAL(clientDisconnected(RfbClient*)),
|
||||
this, SLOT(onClientDisconnected(RfbClient*)));
|
||||
connect(RfbServerManager::instance(), &RfbServerManager::clientConnected,
|
||||
this, &TrayIcon::onClientConnected);
|
||||
connect(RfbServerManager::instance(), &RfbServerManager::clientDisconnected,
|
||||
this, &TrayIcon::onClientDisconnected);
|
||||
|
||||
m_aboutAction = KStandardAction::aboutApp(this, SLOT(showAbout()), actionCollection());
|
||||
m_aboutAction = KStandardAction::aboutApp(this, SLOT(showAbout()), this);
|
||||
contextMenu()->addAction(m_aboutAction);
|
||||
}
|
||||
|
||||
void TrayIcon::onClientConnected(RfbClient* client)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (m_clientActions.isEmpty()) { //first client connected
|
||||
setIconByName("krfb");
|
||||
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
||||
@@ -127,13 +125,11 @@ void TrayIcon::onClientConnected(RfbClient* client)
|
||||
|
||||
void TrayIcon::onClientDisconnected(RfbClient* client)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
ClientActions *actions = m_clientActions.take(client);
|
||||
delete actions;
|
||||
|
||||
if (m_clientActions.isEmpty()) {
|
||||
setIconByPixmap(KIcon("krfb").pixmap(22, 22, KIcon::Disabled));
|
||||
setIconByPixmap(QIcon::fromTheme("krfb").pixmap(22, 22, QIcon::Disabled));
|
||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||
setStatus(KStatusNotifierItem::Passive);
|
||||
} else if (m_clientActions.size() == 1) { //clients number dropped back to 1
|
||||
@@ -144,9 +140,8 @@ void TrayIcon::onClientDisconnected(RfbClient* client)
|
||||
|
||||
void TrayIcon::showAbout()
|
||||
{
|
||||
KDialog *dlg = new KAboutApplicationDialog(KGlobal::mainComponent().aboutData());
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
dlg->show();
|
||||
KHelpMenu menu;
|
||||
menu.aboutApplication();
|
||||
}
|
||||
|
||||
#include "trayicon.moc"
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
#define TRAYICON_H
|
||||
|
||||
#include <KStatusNotifierItem>
|
||||
#include <KToggleAction>
|
||||
|
||||
class KDialog;
|
||||
class RfbClient;
|
||||
class ClientActions;
|
||||
|
||||
@@ -42,7 +40,7 @@ public Q_SLOTS:
|
||||
void showAbout();
|
||||
|
||||
private:
|
||||
KAction *m_aboutAction;
|
||||
QAction *m_aboutAction;
|
||||
QHash<RfbClient*, ClientActions*> m_clientActions;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tubesrfbclient.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "connectiondialog.h"
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
|
||||
QString TubesRfbClient::name() const
|
||||
{
|
||||
return m_contact->alias();
|
||||
}
|
||||
|
||||
//********
|
||||
|
||||
PendingTubesRfbClient::PendingTubesRfbClient(rfbClientPtr client, QObject* parent) :
|
||||
PendingRfbClient(client, parent),
|
||||
m_processNewClientCalled(false)
|
||||
{
|
||||
processNewClient();
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::setContact(const Tp::ContactPtr & contact)
|
||||
{
|
||||
m_contact = contact;
|
||||
if (m_processNewClientCalled) {
|
||||
//processNewClient has already been called, so we need to act here
|
||||
showConfirmationDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::processNewClient()
|
||||
{
|
||||
if (!m_contact) {
|
||||
//no associated contact yet, hold.
|
||||
m_processNewClientCalled = true; //act when a contact is set
|
||||
} else {
|
||||
//we have a contact, begin handling
|
||||
showConfirmationDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::showConfirmationDialog()
|
||||
{
|
||||
QString name = m_contact->alias();
|
||||
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
name));
|
||||
|
||||
TubesConnectionDialog *dialog = new TubesConnectionDialog(0);
|
||||
dialog->setContactName(name);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
|
||||
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::dialogAccepted()
|
||||
{
|
||||
TubesConnectionDialog *dialog = qobject_cast<TubesConnectionDialog *>(sender());
|
||||
Q_ASSERT(dialog);
|
||||
|
||||
TubesRfbClient *client = new TubesRfbClient(m_rfbClient, m_contact, parent());
|
||||
client->setControlEnabled(dialog->allowRemoteControl());
|
||||
accept(client);
|
||||
}
|
||||
|
||||
#include "tubesrfbclient.moc"
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TUBESRFBCLIENT_H
|
||||
#define TUBESRFBCLIENT_H
|
||||
|
||||
#include "rfbclient.h"
|
||||
#include <TelepathyQt/Contact>
|
||||
|
||||
class TubesRfbClient : public RfbClient
|
||||
{
|
||||
public:
|
||||
TubesRfbClient(rfbClientPtr client,
|
||||
const Tp::ContactPtr &contact, QObject *parent=0)
|
||||
: RfbClient(client, parent), m_contact(contact)
|
||||
{}
|
||||
|
||||
virtual QString name() const;
|
||||
|
||||
private:
|
||||
Tp::ContactPtr m_contact;
|
||||
};
|
||||
|
||||
//*********
|
||||
|
||||
class PendingTubesRfbClient : public PendingRfbClient
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PendingTubesRfbClient(rfbClientPtr client, QObject* parent = 0);
|
||||
|
||||
void setContact(const Tp::ContactPtr & contact);
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient();
|
||||
|
||||
private Q_SLOTS:
|
||||
void showConfirmationDialog();
|
||||
void dialogAccepted();
|
||||
|
||||
private:
|
||||
Tp::ContactPtr m_contact;
|
||||
bool m_processNewClientCalled;
|
||||
};
|
||||
|
||||
#endif // TUBESRFBCLIENT_H
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009-2011 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tubesrfbserver.h"
|
||||
#include "tubesrfbclient.h"
|
||||
#include "sockethelpers.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KRandom>
|
||||
|
||||
#include <TelepathyQt/Debug>
|
||||
#include <TelepathyQt/Contact>
|
||||
#include <TelepathyQt/AccountFactory>
|
||||
#include <TelepathyQt/ConnectionFactory>
|
||||
#include <TelepathyQt/ContactFactory>
|
||||
#include <TelepathyQt/ChannelFactory>
|
||||
#include <TelepathyQt/OutgoingStreamTubeChannel>
|
||||
#include <TelepathyQt/StreamTubeServer>
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
#include <TelepathyQt/AccountSet>
|
||||
#include <TelepathyQt/AccountManager>
|
||||
#include <TelepathyQt/PendingReady>
|
||||
#include <KTp/Models/contacts-list-model.h>
|
||||
#include <KTp/contact-factory.h>
|
||||
#endif
|
||||
|
||||
struct TubesRfbServer::Private
|
||||
{
|
||||
Tp::StreamTubeServerPtr stubeServer;
|
||||
QHash<quint16, Tp::ContactPtr> contactsPerPort;
|
||||
QHash<quint16, PendingTubesRfbClient*> clientsPerPort;
|
||||
};
|
||||
|
||||
//static
|
||||
TubesRfbServer *TubesRfbServer::instance;
|
||||
|
||||
//static
|
||||
void TubesRfbServer::init()
|
||||
{
|
||||
instance = new TubesRfbServer;
|
||||
//RfbServerManager takes care of deletion
|
||||
|
||||
instance->startAndCheck();
|
||||
}
|
||||
|
||||
TubesRfbServer::TubesRfbServer(QObject *parent)
|
||||
: RfbServer(parent), d(new Private)
|
||||
{
|
||||
kDebug() << "starting";
|
||||
|
||||
Tp::enableDebug(true);
|
||||
Tp::enableWarnings(true);
|
||||
Tp::registerTypes();
|
||||
|
||||
Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(
|
||||
QDBusConnection::sessionBus(),
|
||||
Tp::Features() << Tp::Account::FeatureCore
|
||||
<< Tp::Account::FeatureAvatar
|
||||
<< Tp::Account::FeatureCapabilities
|
||||
<< Tp::Account::FeatureProtocolInfo
|
||||
<< Tp::Account::FeatureProfile);
|
||||
|
||||
Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(
|
||||
QDBusConnection::sessionBus(),
|
||||
Tp::Features() << Tp::Connection::FeatureCore
|
||||
<< Tp::Connection::FeatureSelfContact);
|
||||
|
||||
Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(
|
||||
QDBusConnection::sessionBus());
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
Tp::ContactFactoryPtr contactFactory = KTp::ContactFactory::create(
|
||||
Tp::Features() << Tp::Contact::FeatureAlias
|
||||
<<Tp::Contact::FeatureAvatarToken
|
||||
<<Tp::Contact::FeatureAvatarData
|
||||
<<Tp::Contact::FeatureSimplePresence
|
||||
<<Tp::Contact::FeatureCapabilities
|
||||
<<Tp::Contact::FeatureClientTypes);
|
||||
|
||||
m_accountManager = Tp::AccountManager::create(
|
||||
QDBusConnection::sessionBus(),
|
||||
accountFactory,
|
||||
connectionFactory,
|
||||
channelFactory,
|
||||
contactFactory);
|
||||
|
||||
d->stubeServer = Tp::StreamTubeServer::create(
|
||||
m_accountManager,
|
||||
QStringList() << QLatin1String("rfb"),
|
||||
QStringList(),
|
||||
QLatin1String("krfb_rfb_handler"),
|
||||
true);
|
||||
|
||||
connect(m_accountManager->becomeReady(),
|
||||
SIGNAL(finished(Tp::PendingOperation*)),
|
||||
this,
|
||||
SLOT(onAccountManagerReady()));
|
||||
|
||||
m_contactsListModel = new KTp::ContactsListModel(this);
|
||||
#else
|
||||
Tp::ContactFactoryPtr contactFactory = Tp::ContactFactory::create(
|
||||
Tp::Contact::FeatureAlias);
|
||||
|
||||
d->stubeServer = Tp::StreamTubeServer::create(
|
||||
QStringList() << QLatin1String("rfb"),
|
||||
QStringList(),
|
||||
QLatin1String("krfb_rfb_handler"),
|
||||
true,
|
||||
accountFactory,
|
||||
connectionFactory,
|
||||
channelFactory,
|
||||
contactFactory);
|
||||
#endif //KRFB_WITH_KDE_TELEPATHY
|
||||
|
||||
connect(d->stubeServer.data(),
|
||||
SIGNAL(tubeRequested(Tp::AccountPtr,Tp::OutgoingStreamTubeChannelPtr,
|
||||
QDateTime,Tp::ChannelRequestHints)),
|
||||
SLOT(onTubeRequested()));
|
||||
connect(d->stubeServer.data(),
|
||||
SIGNAL(tubeClosed(Tp::AccountPtr,Tp::OutgoingStreamTubeChannelPtr,QString,QString)),
|
||||
SLOT(onTubeClosed()));
|
||||
|
||||
connect(d->stubeServer.data(),
|
||||
SIGNAL(newTcpConnection(QHostAddress,quint16,Tp::AccountPtr,
|
||||
Tp::ContactPtr,Tp::OutgoingStreamTubeChannelPtr)),
|
||||
SLOT(onNewTcpConnection(QHostAddress,quint16,Tp::AccountPtr,
|
||||
Tp::ContactPtr,Tp::OutgoingStreamTubeChannelPtr)));
|
||||
connect(d->stubeServer.data(),
|
||||
SIGNAL(tcpConnectionClosed(QHostAddress,quint16,Tp::AccountPtr,Tp::ContactPtr,
|
||||
QString,QString,Tp::OutgoingStreamTubeChannelPtr)),
|
||||
SLOT(onTcpConnectionClosed(QHostAddress,quint16,Tp::AccountPtr,Tp::ContactPtr,
|
||||
QString,QString,Tp::OutgoingStreamTubeChannelPtr)));
|
||||
|
||||
// Pick a random port in the private range (49152–65535)
|
||||
setListeningPort((KRandom::random() % 16383) + 49152);
|
||||
// Listen only on the loopback network interface
|
||||
setListeningAddress("127.0.0.1");
|
||||
setPasswordRequired(false);
|
||||
}
|
||||
|
||||
TubesRfbServer::~TubesRfbServer()
|
||||
{
|
||||
kDebug();
|
||||
stop();
|
||||
delete d;
|
||||
}
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
KTp::ContactsListModel *TubesRfbServer::contactsListModel()
|
||||
{
|
||||
return m_contactsListModel;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TubesRfbServer::startAndCheck()
|
||||
{
|
||||
if (!start()) {
|
||||
//try a few times with different ports
|
||||
bool ok = false;
|
||||
for (int i=0; !ok && i<5; i++) {
|
||||
setListeningPort((KRandom::random() % 16383) + 49152);
|
||||
ok = start();
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
kError() << "Failed to start tubes rfb server";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO listeningAddress() should be a QHostAddress
|
||||
d->stubeServer->exportTcpSocket(QHostAddress(QString::fromAscii(listeningAddress())),
|
||||
listeningPort());
|
||||
}
|
||||
|
||||
void TubesRfbServer::onTubeRequested()
|
||||
{
|
||||
kDebug() << "Got a tube";
|
||||
}
|
||||
|
||||
void TubesRfbServer::onTubeClosed()
|
||||
{
|
||||
kDebug() << "tube closed";
|
||||
}
|
||||
|
||||
void TubesRfbServer::onNewTcpConnection(const QHostAddress & sourceAddress,
|
||||
quint16 sourcePort,
|
||||
const Tp::AccountPtr & account,
|
||||
const Tp::ContactPtr & contact,
|
||||
const Tp::OutgoingStreamTubeChannelPtr & tube)
|
||||
{
|
||||
Q_UNUSED(account);
|
||||
Q_UNUSED(tube);
|
||||
|
||||
kDebug() << "CM signaled tube connection from" << sourceAddress << ":" << sourcePort;
|
||||
|
||||
d->contactsPerPort[sourcePort] = contact;
|
||||
if (d->clientsPerPort.contains(sourcePort)) {
|
||||
kDebug() << "client already exists";
|
||||
d->clientsPerPort[sourcePort]->setContact(contact);
|
||||
}
|
||||
}
|
||||
|
||||
void TubesRfbServer::onTcpConnectionClosed(const QHostAddress& sourceAddress,
|
||||
quint16 sourcePort,
|
||||
const Tp::AccountPtr& account,
|
||||
const Tp::ContactPtr& contact,
|
||||
const QString& error,
|
||||
const QString& message,
|
||||
const Tp::OutgoingStreamTubeChannelPtr& tube)
|
||||
{
|
||||
Q_UNUSED(account);
|
||||
Q_UNUSED(contact);
|
||||
Q_UNUSED(tube);
|
||||
|
||||
kDebug() << "Connection from" << sourceAddress << ":" << sourcePort << "closed."
|
||||
<< error << message;
|
||||
|
||||
d->clientsPerPort.remove(sourcePort);
|
||||
d->contactsPerPort.remove(sourcePort);
|
||||
}
|
||||
|
||||
PendingRfbClient* TubesRfbServer::newClient(rfbClientPtr client)
|
||||
{
|
||||
PendingTubesRfbClient *c = new PendingTubesRfbClient(client, this);
|
||||
quint16 port = peerPort(client->sock);
|
||||
|
||||
kDebug() << "new tube client on port" << port;
|
||||
|
||||
d->clientsPerPort[port] = c;
|
||||
if (d->contactsPerPort.contains(port)) {
|
||||
kDebug() << "already have a contact";
|
||||
c->setContact(d->contactsPerPort[port]);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
void TubesRfbServer::onAccountManagerReady()
|
||||
{
|
||||
m_contactsListModel->setAccountManager(m_accountManager);
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "tubesrfbserver.moc"
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009-2011 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TUBESRFBSERVER_H
|
||||
#define TUBESRFBSERVER_H
|
||||
|
||||
#include "rfbserver.h"
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include <TelepathyQt/Types>
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
namespace KTp {
|
||||
class ContactsListModel;
|
||||
}
|
||||
#endif
|
||||
|
||||
class TubesRfbServer : public RfbServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static TubesRfbServer *instance;
|
||||
static void init();
|
||||
|
||||
virtual ~TubesRfbServer();
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
KTp::ContactsListModel *contactsListModel();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
TubesRfbServer(QObject *parent = 0);
|
||||
|
||||
virtual PendingRfbClient* newClient(rfbClientPtr client);
|
||||
|
||||
private Q_SLOTS:
|
||||
void startAndCheck();
|
||||
|
||||
void onTubeRequested();
|
||||
void onTubeClosed();
|
||||
|
||||
void onNewTcpConnection(
|
||||
const QHostAddress &sourceAddress,
|
||||
quint16 sourcePort,
|
||||
const Tp::AccountPtr &account,
|
||||
const Tp::ContactPtr &contact,
|
||||
const Tp::OutgoingStreamTubeChannelPtr &tube);
|
||||
|
||||
void onTcpConnectionClosed(
|
||||
const QHostAddress &sourceAddress,
|
||||
quint16 sourcePort,
|
||||
const Tp::AccountPtr &account,
|
||||
const Tp::ContactPtr &contact,
|
||||
const QString &error,
|
||||
const QString &message,
|
||||
const Tp::OutgoingStreamTubeChannelPtr &tube);
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
void onAccountManagerReady();
|
||||
#endif
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private *const d;
|
||||
|
||||
#ifdef KRFB_WITH_KDE_TELEPATHY
|
||||
KTp::ContactsListModel *m_contactsListModel;
|
||||
Tp::AccountManagerPtr m_accountManager;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // TUBESRFBSERVER_H
|
||||
90
krfb/ui/configframebuffer.ui
Normal file
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Framebuffer</class>
|
||||
<widget class="QWidget" name="Framebuffer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>418</width>
|
||||
<height>186</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Framebuffer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Preferred frameb&uffer plugin:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cb_preferredFrameBufferPlugin</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cb_preferredFrameBufferPlugin">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="kcfg_preferredFrameBufferPlugin"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="helpText">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>When using x11, <span style=" font-weight:600;">xcb</span> plugin should be preferred, because it is more performant.<br/><span style=" font-weight:600;">qt</span> plugin is a safe fallback, if for some reason others don't work. But also it is very slow.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>63</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>cb_preferredFrameBufferPlugin</tabstop>
|
||||
<tabstop>kcfg_preferredFrameBufferPlugin</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,171 +0,0 @@
|
||||
<ui version="4.0" >
|
||||
<class>InviteWidget</class>
|
||||
<widget class="QWidget" name="InviteWidget" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>603</width>
|
||||
<height>364</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="pixmapLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="TextLabel2" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Welcome to KDE Desktop Sharing</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="helpLabel" >
|
||||
<property name="text" >
|
||||
<string>KDE Desktop Sharing allows you to invite somebody at a remote location to watch and possibly control your desktop. <a href="whatsthis">More about invitations...</a></string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>215</width>
|
||||
<height>101</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>90</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCreateInvite" >
|
||||
<property name="toolTip" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string>Create a new invitation and display the connection data. Use this option if you want to invite somebody personally, for example, to give the connection data over the phone.</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Create &Personal Invitation...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnEmailInvite" >
|
||||
<property name="whatsThis" >
|
||||
<string>This button will start your email application with a pre-configured text that explains to the recipient how to connect to your computer. </string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Invite via &Email...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnManageInvite" >
|
||||
<property name="text" >
|
||||
<string>&Manage Invitations (%1)...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>90</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -442,7 +442,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KPushButton" name="unattendedPasswordButton">
|
||||
<widget class="QPushButton" name="unattendedPasswordButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -486,11 +486,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KPushButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>kpushbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>enableSharingCheckBox</tabstop>
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TubesConnectionWidget</class>
|
||||
<widget class="QWidget" name="TubesConnectionWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="pixmapLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="TextLabel5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>13</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Confirmation</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mainTextLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="midLineWidth">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbAllowRemoteControl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>If you turn this option on, the remote user can enter keystrokes and use your mouse pointer. This gives them full control over your computer, so be careful. When the option is disabled the remote user can only watch your screen.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow remote user to &control keyboard and mouse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,132 +0,0 @@
|
||||
# Striped down version of libvncserver's original CMakeLists.txt
|
||||
|
||||
project(LibVNCServer)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckTypeSize)
|
||||
include(TestBigEndian)
|
||||
include(MacroBoolTo01)
|
||||
|
||||
set(FULL_PACKAGE_NAME "Krfb LibVNCServer")
|
||||
set(PACKAGE_VERSION "0.9.8-10-g17ce0c5")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
macro_optional_find_package(ZLIB)
|
||||
macro_log_feature(ZLIB_FOUND "ZLib" "The Zlib compression library" "http://www.zlib.net" FALSE "" "Used by the vncserver library.")
|
||||
|
||||
macro_optional_find_package(JPEG)
|
||||
macro_log_feature(JPEG_FOUND "LibJPEG" "The JPEG library" "" FALSE "" "Used by the vncserver library")
|
||||
|
||||
macro_bool_to_01(ZLIB_FOUND LIBVNCSERVER_HAVE_LIBZ)
|
||||
macro_bool_to_01(JPEG_FOUND LIBVNCSERVER_HAVE_LIBJPEG)
|
||||
option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON)
|
||||
# if(GNUTLS_FOUND)
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_TLS 1)
|
||||
# endif(GNUTLS_FOUND)
|
||||
# if(LIBGCRYPT_LIBRARIES)
|
||||
# message(STATUS "Found libgcrypt: ${LIBGCRYPT_LIBRARIES}")
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_GCRYPT 1)
|
||||
# endif(LIBGCRYPT_LIBRARIES)
|
||||
|
||||
|
||||
check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H)
|
||||
check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H)
|
||||
check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H)
|
||||
check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H)
|
||||
check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H)
|
||||
check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H)
|
||||
check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H)
|
||||
|
||||
# headers needed for check_type_size()
|
||||
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
|
||||
check_include_file("stdint.h" HAVE_STDINT_H)
|
||||
check_include_file("stddef.h" HAVE_STDDEF_H)
|
||||
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
|
||||
|
||||
check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY)
|
||||
|
||||
macro_bool_to_01(CMAKE_USE_PTHREADS_INIT LIBVNCSERVER_HAVE_LIBPTHREAD)
|
||||
if(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
# socklen_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
endif(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
if(HAVE_ARPA_INET_H)
|
||||
# in_addr_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h")
|
||||
endif(HAVE_ARPA_INET_H)
|
||||
|
||||
check_type_size(pid_t LIBVNCSERVER_PID_T)
|
||||
check_type_size(size_t LIBVNCSERVER_SIZE_T)
|
||||
check_type_size(socklen_t LIBVNCSERVER_SOCKLEN_T)
|
||||
check_type_size(in_addr_t LIBVNCSERVER_IN_ADDR_T)
|
||||
if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
set(LIBVNCSERVER_NEED_INADDR_T 1)
|
||||
endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
|
||||
test_big_endian(LIBVNCSERVER_WORDS_BIGENDIAN)
|
||||
|
||||
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libvncserver-config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libvncserver-config.h
|
||||
)
|
||||
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
main.c
|
||||
rfbserver.c
|
||||
rfbregion.c
|
||||
auth.c
|
||||
sockets.c
|
||||
stats.c
|
||||
corre.c
|
||||
hextile.c
|
||||
rre.c
|
||||
translate.c
|
||||
cutpaste.c
|
||||
httpd.c
|
||||
cursor.c
|
||||
font.c
|
||||
draw.c
|
||||
selbox.c
|
||||
d3des.c
|
||||
vncauth.c
|
||||
cargs.c
|
||||
minilzo.c
|
||||
ultra.c
|
||||
scale.c
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBZ)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
zlib.c
|
||||
zrle.c
|
||||
zrleoutstream.c
|
||||
zrlepalettehelper.c
|
||||
)
|
||||
endif(ZLIB_FOUND)
|
||||
|
||||
if(JPEG_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
tight.c
|
||||
)
|
||||
endif(JPEG_FOUND)
|
||||
|
||||
|
||||
add_library(vncserver STATIC ${LIBVNCSERVER_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
set(ADDITIONAL_LIBS ws2_32)
|
||||
endif(WIN32)
|
||||
|
||||
target_link_libraries(vncserver
|
||||
${ADDITIONAL_LIBS}
|
||||
${ZLIB_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
)
|
||||
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
* auth.c - deal with authentication.
|
||||
*
|
||||
* This file implements the VNC authentication protocol when setting up an RFB
|
||||
* connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/* RFB 3.8 clients are well informed */
|
||||
void rfbClientSendString(rfbClientPtr cl, const char *reason);
|
||||
|
||||
|
||||
/*
|
||||
* Handle security types
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler* securityHandlers = NULL;
|
||||
|
||||
/*
|
||||
* This method registers a list of new security types.
|
||||
* It avoids same security type getting registered multiple times.
|
||||
* The order is not preserved if multiple security types are
|
||||
* registered at one-go.
|
||||
*/
|
||||
void
|
||||
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *head = securityHandlers, *next = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
next = handler->next;
|
||||
|
||||
while(head != NULL) {
|
||||
if(head == handler) {
|
||||
rfbRegisterSecurityHandler(next);
|
||||
return;
|
||||
}
|
||||
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
handler->next = securityHandlers;
|
||||
securityHandlers = handler;
|
||||
|
||||
rfbRegisterSecurityHandler(next);
|
||||
}
|
||||
|
||||
/*
|
||||
* This method unregisters a list of security types.
|
||||
* These security types won't be available for any new
|
||||
* client connection.
|
||||
*/
|
||||
void
|
||||
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *cur = NULL, *pre = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
if(securityHandlers == handler) {
|
||||
securityHandlers = securityHandlers->next;
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
return;
|
||||
}
|
||||
|
||||
cur = pre = securityHandlers;
|
||||
|
||||
while(cur) {
|
||||
if(cur == handler) {
|
||||
pre->next = cur->next;
|
||||
break;
|
||||
}
|
||||
pre = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the authentication challenge.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthSendChallenge(rfbClientPtr cl)
|
||||
{
|
||||
|
||||
/* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
|
||||
(same as rfbVncAuth). Just send the challenge. */
|
||||
rfbRandomBytes(cl->authChallenge);
|
||||
if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
|
||||
rfbLogPerror("rfbAuthNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbVncAuthProcessResponse. */
|
||||
cl->state = RFB_AUTHENTICATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the NO AUTHENTICATION. SCARR
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthNone(rfbClientPtr cl)
|
||||
{
|
||||
uint32_t authResult;
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) {
|
||||
rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cl->state = RFB_INITIALISATION;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Advertise the supported security types (protocol 3.7). Here before sending
|
||||
* the list of security types to the client one more security type is added
|
||||
* to the list if primaryType is not set to rfbSecTypeInvalid. This security
|
||||
* type is the standard vnc security type which does the vnc authentication
|
||||
* or it will be security type for no authentication.
|
||||
* Different security types will be added by applications using this library.
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerVncAuth = {
|
||||
rfbSecTypeVncAuth,
|
||||
rfbVncAuthSendChallenge,
|
||||
NULL
|
||||
};
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerNone = {
|
||||
rfbSecTypeNone,
|
||||
rfbVncAuthNone,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
|
||||
{
|
||||
/* The size of the message is the count of security types +1,
|
||||
* since the first byte is the number of types. */
|
||||
int size = 1;
|
||||
rfbSecurityHandler* handler;
|
||||
#define MAX_SECURITY_TYPES 255
|
||||
uint8_t buffer[MAX_SECURITY_TYPES+1];
|
||||
|
||||
|
||||
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
|
||||
switch (primaryType) {
|
||||
case rfbSecTypeNone:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
|
||||
break;
|
||||
}
|
||||
|
||||
for (handler = securityHandlers;
|
||||
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
|
||||
buffer[size] = handler->type;
|
||||
size++;
|
||||
}
|
||||
buffer[0] = (unsigned char)size-1;
|
||||
|
||||
/* Send the list. */
|
||||
if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityTypeList: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if count is 0, we need to send the reason and close the connection.
|
||||
*/
|
||||
if(size <= 1) {
|
||||
/* This means total count is Zero and so reason msg should be sent */
|
||||
/* The execution should never reach here */
|
||||
char* reason = "No authentication mode is registered!";
|
||||
|
||||
rfbClientSendString(cl, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbProcessClientSecurityType. */
|
||||
cl->state = RFB_SECURITY_TYPE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tell the client what security type will be used (protocol 3.3).
|
||||
*/
|
||||
static void
|
||||
rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
|
||||
{
|
||||
uint32_t value32;
|
||||
|
||||
/* Send the value. */
|
||||
value32 = Swap32IfLE(securityType);
|
||||
if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityType: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decide what to do next. */
|
||||
switch (securityType) {
|
||||
case rfbSecTypeNone:
|
||||
/* Dispatch client input to rfbProcessClientInitMessage. */
|
||||
cl->state = RFB_INITIALISATION;
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
/* Begin the standard VNC authentication procedure. */
|
||||
rfbVncAuthSendChallenge(cl);
|
||||
break;
|
||||
default:
|
||||
/* Impossible case (hopefully). */
|
||||
rfbLogPerror("rfbSendSecurityType: assertion failed");
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthNewClient is called right after negotiating the protocol
|
||||
* version. Depending on the protocol version, we send either a code
|
||||
* for authentication scheme to be used (protocol 3.3), or a list of
|
||||
* possible "security types" (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthNewClient(rfbClientPtr cl)
|
||||
{
|
||||
int32_t securityType = rfbSecTypeInvalid;
|
||||
|
||||
if (!cl->screen->authPasswdData || cl->reverseConnection) {
|
||||
/* chk if this condition is valid or not. */
|
||||
securityType = rfbSecTypeNone;
|
||||
} else if (cl->screen->authPasswdData) {
|
||||
securityType = rfbSecTypeVncAuth;
|
||||
}
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
|
||||
{
|
||||
/* Make sure we use only RFB 3.3 compatible security types. */
|
||||
if (securityType == rfbSecTypeInvalid) {
|
||||
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
|
||||
rfbClientConnFailed(cl, "Your viewer cannot handle required "
|
||||
"authentication methods");
|
||||
return;
|
||||
}
|
||||
rfbSendSecurityType(cl, securityType);
|
||||
} else {
|
||||
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
|
||||
rfbSendSecurityTypeList(cl, securityType);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the security type chosen by the client (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbProcessClientSecurityType(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t chosenType;
|
||||
rfbSecurityHandler* handler;
|
||||
|
||||
/* Read the security type. */
|
||||
n = rfbReadExact(cl, (char *)&chosenType, 1);
|
||||
if (n <= 0) {
|
||||
if (n == 0)
|
||||
rfbLog("rfbProcessClientSecurityType: client gone\n");
|
||||
else
|
||||
rfbLogPerror("rfbProcessClientSecurityType: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure it was present in the list sent by the server. */
|
||||
for (handler = securityHandlers; handler; handler = handler->next) {
|
||||
if (chosenType == handler->type) {
|
||||
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
|
||||
handler->handler(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthProcessClientMessage is called when the client sends its
|
||||
* authentication response.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthProcessClientMessage(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t response[CHALLENGESIZE];
|
||||
uint32_t authResult;
|
||||
|
||||
if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
|
||||
if (n != 0)
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
|
||||
rfbErr("rfbAuthProcessClientMessage: password check failed\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthFailed);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
}
|
||||
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
|
||||
if (cl->protocolMinorVersion > 7) {
|
||||
rfbClientSendString(cl, "password check failed!");
|
||||
}
|
||||
else
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
cl->state = RFB_INITIALISATION;
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* This parses the command line arguments. It was seperated from main.c by
|
||||
* Justin Dearing <jdeari01@longisland.poly.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* see GPL (latest version) for full details
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
extern int rfbStringToAddr(char *str, in_addr_t *iface);
|
||||
|
||||
void
|
||||
rfbUsage(void)
|
||||
{
|
||||
rfbProtocolExtension* extension;
|
||||
|
||||
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
|
||||
fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
|
||||
fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
|
||||
" (use 'storepasswd' to create a password file)\n");
|
||||
fprintf(stderr, "-rfbversion 3.x Set the version of the RFB we choose to advertise\n");
|
||||
fprintf(stderr, "-permitfiletransfer permit file transfer support\n");
|
||||
fprintf(stderr, "-passwd plain-password use authentication \n"
|
||||
" (use plain-password as password, USE AT YOUR RISK)\n");
|
||||
fprintf(stderr, "-deferupdate time time in ms to defer updates "
|
||||
"(default 40)\n");
|
||||
fprintf(stderr, "-deferptrupdate time time in ms to defer pointer updates"
|
||||
" (default none)\n");
|
||||
fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n");
|
||||
fprintf(stderr, "-alwaysshared always treat new clients as shared\n");
|
||||
fprintf(stderr, "-nevershared never treat new clients as shared\n");
|
||||
fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a "
|
||||
"new non-shared\n"
|
||||
" connection comes in (refuse new connection "
|
||||
"instead)\n");
|
||||
fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n");
|
||||
fprintf(stderr, "-httpport portnum use portnum for http connection\n");
|
||||
fprintf(stderr, "-enablehttpproxy enable http proxy support\n");
|
||||
fprintf(stderr, "-progressive height enable progressive updating for slow links\n");
|
||||
fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n");
|
||||
fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n");
|
||||
|
||||
for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
|
||||
if(extension->usage)
|
||||
extension->usage();
|
||||
rfbReleaseExtensionIterator();
|
||||
}
|
||||
|
||||
/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
|
||||
POSITION points to the first non purged argument afterwards. */
|
||||
void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
|
||||
{
|
||||
int amount=(*argc)-(*position)-count;
|
||||
if(amount)
|
||||
memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
|
||||
(*argc)-=count;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
|
||||
for (i = i1 = 1; i < *argc;) {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
} else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->port = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->maxClientWait = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->authPasswdData = argv[++i];
|
||||
|
||||
} else if (strcmp(argv[i], "-permitfiletransfer") == 0) { /* -permitfiletransfer */
|
||||
rfbScreen->permitFileTransfer = TRUE;
|
||||
} else if (strcmp(argv[i], "-rfbversion") == 0) { /* -rfbversion 3.6 */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
sscanf(argv[++i],"%d.%d", &rfbScreen->protocolMajorVersion, &rfbScreen->protocolMinorVersion);
|
||||
} else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */
|
||||
char **passwds = malloc(sizeof(char**)*2);
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
passwds[0] = argv[++i];
|
||||
passwds[1] = NULL;
|
||||
rfbScreen->authPasswdData = (void*)passwds;
|
||||
rfbScreen->passwordCheck = rfbCheckPasswordByList;
|
||||
} else if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-deferptrupdate") == 0) { /* -deferptrupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferPtrUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->desktopName = argv[++i];
|
||||
} else if (strcmp(argv[i], "-alwaysshared") == 0) {
|
||||
rfbScreen->alwaysShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-nevershared") == 0) {
|
||||
rfbScreen->neverShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-dontdisconnect") == 0) {
|
||||
rfbScreen->dontDisconnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-httpdir") == 0) { /* -httpdir directory-path */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpDir = argv[++i];
|
||||
} else if (strcmp(argv[i], "-httpport") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpPort = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
|
||||
rfbScreen->httpEnableProxyConnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->progressiveSliceHeight = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-listen") == 0) { /* -listen ipaddr */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
rfbProtocolExtension* extension;
|
||||
int handled=0;
|
||||
|
||||
for(extension=rfbGetExtensionIterator();handled==0 && extension;
|
||||
extension=extension->next)
|
||||
if(extension->processArgument)
|
||||
handled = extension->processArgument(*argc - i, argv + i);
|
||||
rfbReleaseExtensionIterator();
|
||||
|
||||
if(handled==0) {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
i+=handled-1;
|
||||
}
|
||||
/* we just remove the processed arguments from the list */
|
||||
rfbPurgeArguments(argc,&i1,i-i1+1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
for (i = i1 = 1; i < *argc-1;) {
|
||||
if (strcmp(argv[i], "-bpp") == 0) {
|
||||
*bpp = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-width") == 0) {
|
||||
*width = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-height") == 0) {
|
||||
*height = atoi(argv[++i]);
|
||||
} else {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
rfbPurgeArguments(argc,&i1,i-i1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/*
|
||||
* corre.c
|
||||
*
|
||||
* Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
|
||||
* code is based on krw's original javatel rfbserver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the RRE encoded version. If the RRE encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
|
||||
static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
|
||||
static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
|
||||
static uint32_t getBgColour(char *data, int size, int bpp);
|
||||
static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
|
||||
int w, int h);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
if (h > cl->correMaxHeight) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
|
||||
h - cl->correMaxHeight));
|
||||
}
|
||||
|
||||
if (w > cl->correMaxWidth) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
|
||||
w - cl->correMaxWidth, h));
|
||||
}
|
||||
|
||||
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
|
||||
* rectangle using CoRRE encoding.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbRREHeader hdr;
|
||||
int nSubrects;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
if (cl->afterEncBufSize < maxRawSize) {
|
||||
cl->afterEncBufSize = maxRawSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
(*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat),
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 16:
|
||||
nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 32:
|
||||
nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
default:
|
||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nSubrects < 0) {
|
||||
|
||||
/* RRE encoding was too large, use raw */
|
||||
|
||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE,
|
||||
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
||||
cl->ublen += sz_rfbRREHeader;
|
||||
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
||||
* colour overwritten by single-coloured rectangles. It returns the number
|
||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
||||
* fit in the buffer. It puts the encoded rectangles in cl->afterEncBuf. The
|
||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
||||
* coordinate position.
|
||||
*
|
||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
||||
* <subrect> is [<colour><x><y><w><h>].
|
||||
*/
|
||||
|
||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
||||
static int \
|
||||
subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
|
||||
uint##bpp##_t cl; \
|
||||
rfbCoRRERectangle subrect; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
|
||||
\
|
||||
*((uint##bpp##_t*)client->afterEncBuf) = bg; \
|
||||
\
|
||||
client->afterEncBufLen = (bpp/8); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
||||
* We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
subrect.x = thex; \
|
||||
subrect.y = they; \
|
||||
subrect.w = thew; \
|
||||
subrect.h = theh; \
|
||||
\
|
||||
newLen = client->afterEncBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
|
||||
if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
|
||||
return -1; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
*((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
|
||||
client->afterEncBufLen += (bpp/8); \
|
||||
memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbCoRRERectangle); \
|
||||
client->afterEncBufLen += sz_rfbCoRRERectangle; \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return numsubs; \
|
||||
}
|
||||
|
||||
DEFINE_SUBRECT_ENCODE(8)
|
||||
DEFINE_SUBRECT_ENCODE(16)
|
||||
DEFINE_SUBRECT_ENCODE(32)
|
||||
|
||||
|
||||
/*
|
||||
* getBgColour() gets the most prevalent colour in a byte array.
|
||||
*/
|
||||
static uint32_t
|
||||
getBgColour(char *data, int size, int bpp)
|
||||
{
|
||||
|
||||
#define NUMCLRS 256
|
||||
|
||||
static int counts[NUMCLRS];
|
||||
int i,j,k;
|
||||
|
||||
int maxcount = 0;
|
||||
uint8_t maxclr = 0;
|
||||
|
||||
if (bpp != 8) {
|
||||
if (bpp == 16) {
|
||||
return ((uint16_t *)data)[0];
|
||||
} else if (bpp == 32) {
|
||||
return ((uint32_t *)data)[0];
|
||||
} else {
|
||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUMCLRS; i++) {
|
||||
counts[i] = 0;
|
||||
}
|
||||
|
||||
for (j=0; j<size; j++) {
|
||||
k = (int)(((uint8_t *)data)[j]);
|
||||
if (k >= NUMCLRS) {
|
||||
rfbLog("getBgColour: unusual colour = %d\n", k);
|
||||
return 0;
|
||||
}
|
||||
counts[k] += 1;
|
||||
if (counts[k] > maxcount) {
|
||||
maxcount = counts[k];
|
||||
maxclr = ((uint8_t *)data)[j];
|
||||
}
|
||||
}
|
||||
|
||||
return maxclr;
|
||||
}
|
||||
@@ -1,756 +0,0 @@
|
||||
/*
|
||||
* cursor.c - support for cursor shape updates.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
#include "private.h"
|
||||
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
|
||||
|
||||
/*
|
||||
* Send cursor shape either in X-style format or in client pixel format.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorShape(rfbClientPtr cl)
|
||||
{
|
||||
rfbCursorPtr pCursor;
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbXCursorColors colors;
|
||||
int saved_ublen;
|
||||
int bitmapRowBytes, maskBytes, dataBytes;
|
||||
int i, j;
|
||||
uint8_t *bitmapData;
|
||||
uint8_t bitmapByte;
|
||||
|
||||
/* TODO: scale the cursor data to the correct size */
|
||||
|
||||
pCursor = cl->screen->getCursorPtr(cl);
|
||||
/*if(!pCursor) return TRUE;*/
|
||||
|
||||
if (cl->useRichCursorEncoding) {
|
||||
if(pCursor && !pCursor->richSource)
|
||||
rfbMakeRichCursorFromXCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
|
||||
} else {
|
||||
if(pCursor && !pCursor->source)
|
||||
rfbMakeXCursorFromRichCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingXCursor);
|
||||
}
|
||||
|
||||
/* If there is no cursor, send update with empty cursor data. */
|
||||
|
||||
if ( pCursor && pCursor->width == 1 &&
|
||||
pCursor->height == 1 &&
|
||||
pCursor->mask[0] == 0 ) {
|
||||
pCursor = NULL;
|
||||
}
|
||||
|
||||
if (pCursor == NULL) {
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
rect.r.x = rect.r.y = 0;
|
||||
rect.r.w = rect.r.h = 0;
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Calculate data sizes. */
|
||||
|
||||
bitmapRowBytes = (pCursor->width + 7) / 8;
|
||||
maskBytes = bitmapRowBytes * pCursor->height;
|
||||
dataBytes = (cl->useRichCursorEncoding) ?
|
||||
(pCursor->width * pCursor->height *
|
||||
(cl->format.bitsPerPixel / 8)) : maskBytes;
|
||||
|
||||
/* Send buffer contents if needed. */
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
return FALSE; /* FIXME. */
|
||||
}
|
||||
|
||||
saved_ublen = cl->ublen;
|
||||
|
||||
/* Prepare rectangle header. */
|
||||
|
||||
rect.r.x = Swap16IfLE(pCursor->xhot);
|
||||
rect.r.y = Swap16IfLE(pCursor->yhot);
|
||||
rect.r.w = Swap16IfLE(pCursor->width);
|
||||
rect.r.h = Swap16IfLE(pCursor->height);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
/* Prepare actual cursor data (depends on encoding used). */
|
||||
|
||||
if (!cl->useRichCursorEncoding) {
|
||||
/* XCursor encoding. */
|
||||
colors.foreRed = (char)(pCursor->foreRed >> 8);
|
||||
colors.foreGreen = (char)(pCursor->foreGreen >> 8);
|
||||
colors.foreBlue = (char)(pCursor->foreBlue >> 8);
|
||||
colors.backRed = (char)(pCursor->backRed >> 8);
|
||||
colors.backGreen = (char)(pCursor->backGreen >> 8);
|
||||
colors.backBlue = (char)(pCursor->backBlue >> 8);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
|
||||
cl->ublen += sz_rfbXCursorColors;
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->source;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* RichCursor encoding. */
|
||||
int bpp1=cl->screen->serverFormat.bitsPerPixel/8,
|
||||
bpp2=cl->format.bitsPerPixel/8;
|
||||
(*cl->translateFn)(cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat),
|
||||
&cl->format, (char*)pCursor->richSource,
|
||||
&cl->updateBuf[cl->ublen],
|
||||
pCursor->width*bpp1, pCursor->width, pCursor->height);
|
||||
|
||||
cl->ublen += pCursor->width*bpp2*pCursor->height;
|
||||
}
|
||||
|
||||
/* Prepare transparency mask. */
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->mask;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send everything we have prepared in the cl->updateBuf[]. */
|
||||
rfbStatRecordEncodingSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor),
|
||||
sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen));
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send cursor position (PointerPos pseudo-encoding).
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorPos(rfbClientPtr cl)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
|
||||
rect.r.x = Swap16IfLE(cl->screen->cursorX);
|
||||
rect.r.y = Swap16IfLE(cl->screen->cursorY);
|
||||
rect.r.w = 0;
|
||||
rect.r.h = 0;
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* conversion routine for predefined cursors in LSB order */
|
||||
unsigned char rfbReverseByte[0x100] = {
|
||||
/* copied from Xvnc/lib/font/util/utilbitmap.c */
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||
};
|
||||
|
||||
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
|
||||
{
|
||||
int i,t=(width+7)/8*height;
|
||||
for(i=0;i<t;i++)
|
||||
bitmap[i]=rfbReverseByte[(int)bitmap[i]];
|
||||
}
|
||||
|
||||
/* Cursor creation. You "paint" a cursor and let these routines do the work */
|
||||
|
||||
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
|
||||
char* cp;
|
||||
unsigned char bit;
|
||||
|
||||
cursor->cleanup=TRUE;
|
||||
cursor->width=width;
|
||||
cursor->height=height;
|
||||
/*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
|
||||
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
|
||||
|
||||
cursor->source = (unsigned char*)calloc(w,height);
|
||||
cursor->cleanupSource = TRUE;
|
||||
for(j=0,cp=cursorString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
|
||||
|
||||
if(maskString) {
|
||||
cursor->mask = (unsigned char*)calloc(w,height);
|
||||
for(j=0,cp=maskString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
|
||||
} else
|
||||
cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
|
||||
cursor->cleanupMask = TRUE;
|
||||
|
||||
return(cursor);
|
||||
}
|
||||
|
||||
char* rfbMakeMaskForXCursor(int width,int height,char* source)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
char* mask=(char*)calloc(w,height);
|
||||
unsigned char c;
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=w-1;i>=0;i--) {
|
||||
c=source[j*w+i];
|
||||
if(j>0) c|=source[(j-1)*w+i];
|
||||
if(j<height-1) c|=source[(j+1)*w+i];
|
||||
|
||||
if(i>0 && (c&0x80))
|
||||
mask[j*w+i-1]|=0x01;
|
||||
if(i<w-1 && (c&0x01))
|
||||
mask[j*w+i+1]|=0x80;
|
||||
|
||||
mask[j*w+i]|=(c<<1)|c|(c>>1);
|
||||
}
|
||||
|
||||
return(mask);
|
||||
}
|
||||
|
||||
/* this function dithers the alpha using Floyd-Steinberg */
|
||||
|
||||
char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource)
|
||||
{
|
||||
int* error=(int*)calloc(sizeof(int),width);
|
||||
int i,j,currentError=0,maskStride=(width+7)/8;
|
||||
unsigned char* result=(unsigned char*)calloc(maskStride,height);
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=0;i<width;i++) {
|
||||
int right,middle,left;
|
||||
currentError+=alphaSource[i+width*j]+error[i];
|
||||
|
||||
if(currentError<0x80) {
|
||||
/* set to transparent */
|
||||
/* alpha was treated as 0 */
|
||||
} else {
|
||||
/* set to solid */
|
||||
result[i/8+j*maskStride]|=(0x100>>(i&7));
|
||||
/* alpha was treated as 0xff */
|
||||
currentError-=0xff;
|
||||
}
|
||||
/* propagate to next row */
|
||||
right=currentError/16;
|
||||
middle=currentError*5/16;
|
||||
left=currentError*3/16;
|
||||
currentError-=right+middle+left;
|
||||
error[i]=right;
|
||||
if(i>0) {
|
||||
error[i-1]=middle;
|
||||
if(i>1)
|
||||
error[i-2]=left;
|
||||
}
|
||||
}
|
||||
free(error);
|
||||
return (char *) result;
|
||||
}
|
||||
|
||||
void rfbFreeCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
if(cursor) {
|
||||
if(cursor->cleanupRichSource && cursor->richSource)
|
||||
free(cursor->richSource);
|
||||
if(cursor->cleanupRichSource && cursor->alphaSource)
|
||||
free(cursor->alphaSource);
|
||||
if(cursor->cleanupSource && cursor->source)
|
||||
free(cursor->source);
|
||||
if(cursor->cleanupMask && cursor->mask)
|
||||
free(cursor->mask);
|
||||
if(cursor->cleanup)
|
||||
free(cursor);
|
||||
else {
|
||||
cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
|
||||
=cursor->cleanupRichSource=FALSE;
|
||||
cursor->source=cursor->mask=cursor->richSource=NULL;
|
||||
cursor->alphaSource=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* background and foregroud colour have to be set beforehand */
|
||||
void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
|
||||
width=cursor->width*bpp;
|
||||
uint32_t background;
|
||||
char *back=(char*)&background;
|
||||
unsigned char bit;
|
||||
int interp = 0, db = 0;
|
||||
|
||||
if(cursor->source && cursor->cleanupSource)
|
||||
free(cursor->source);
|
||||
cursor->source=(unsigned char*)calloc(w,cursor->height);
|
||||
cursor->cleanupSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
}
|
||||
|
||||
/* all zeros means we should interpolate to black+white ourselves */
|
||||
if (!cursor->backRed && !cursor->backGreen && !cursor->backBlue &&
|
||||
!cursor->foreRed && !cursor->foreGreen && !cursor->foreBlue) {
|
||||
if (format->trueColour && (bpp == 1 || bpp == 2 || bpp == 4)) {
|
||||
interp = 1;
|
||||
cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
background = ((format->redMax * cursor->backRed) / 0xffff) << format->redShift |
|
||||
((format->greenMax * cursor->backGreen) / 0xffff) << format->greenShift |
|
||||
((format->blueMax * cursor->backBlue) / 0xffff) << format->blueShift;
|
||||
|
||||
#define SETRGB(u) \
|
||||
r = (255 * (((format->redMax << format->redShift) & (*u)) >> format->redShift)) / format->redMax; \
|
||||
g = (255 * (((format->greenMax << format->greenShift) & (*u)) >> format->greenShift)) / format->greenMax; \
|
||||
b = (255 * (((format->blueMax << format->blueShift) & (*u)) >> format->blueShift)) / format->blueMax;
|
||||
|
||||
if (db) fprintf(stderr, "interp: %d\n", interp);
|
||||
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1) {
|
||||
if (interp) {
|
||||
int r = 0, g = 0, b = 0, grey;
|
||||
unsigned char *p = cursor->richSource+j*width+i*bpp;
|
||||
if (bpp == 1) {
|
||||
unsigned char* uc = (unsigned char*) p;
|
||||
SETRGB(uc);
|
||||
} else if (bpp == 2) {
|
||||
unsigned short* us = (unsigned short*) p;
|
||||
SETRGB(us);
|
||||
} else if (bpp == 4) {
|
||||
unsigned int* ui = (unsigned int*) p;
|
||||
SETRGB(ui);
|
||||
}
|
||||
grey = (r + g + b) / 3;
|
||||
if (grey >= 128) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
if (db) fprintf(stderr, "1");
|
||||
} else {
|
||||
if (db) fprintf(stderr, "0");
|
||||
}
|
||||
|
||||
} else if(memcmp(cursor->richSource+j*width+i*bpp, back, bpp)) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
}
|
||||
}
|
||||
if (db) fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
|
||||
uint32_t background,foreground;
|
||||
char *back=(char*)&background,*fore=(char*)&foreground;
|
||||
unsigned char *cp;
|
||||
unsigned char bit;
|
||||
|
||||
if(cursor->richSource && cursor->cleanupRichSource)
|
||||
free(cursor->richSource);
|
||||
cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
|
||||
cursor->cleanupRichSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
fore+=4-bpp;
|
||||
}
|
||||
|
||||
background=cursor->backRed<<format->redShift|
|
||||
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
|
||||
foreground=cursor->foreRed<<format->redShift|
|
||||
cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
|
||||
|
||||
for(j=0;j<cursor->height;j++)
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
|
||||
if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
|
||||
else memcpy(cp,back,bpp);
|
||||
}
|
||||
|
||||
/* functions to draw/hide cursor directly in the frame buffer */
|
||||
|
||||
void rfbHideCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes;
|
||||
LOCK(s->cursorMutex);
|
||||
if(!c) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* restore what is under the cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) x1=0;
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) y1=0;
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get saved data */
|
||||
for(j=0;j<y2;j++)
|
||||
memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
|
||||
s->underCursorBuffer+j*x2*bpp,
|
||||
x2*bpp);
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
void rfbShowCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes,
|
||||
bufSize,w;
|
||||
rfbBool wasChanged=FALSE;
|
||||
|
||||
if(!c) return;
|
||||
LOCK(s->cursorMutex);
|
||||
|
||||
bufSize=c->width*c->height*bpp;
|
||||
w=(c->width+7)/8;
|
||||
if(s->underCursorBufferLen<bufSize) {
|
||||
if(s->underCursorBuffer!=NULL)
|
||||
free(s->underCursorBuffer);
|
||||
s->underCursorBuffer=malloc(bufSize);
|
||||
s->underCursorBufferLen=bufSize;
|
||||
}
|
||||
|
||||
/* save what is under the cursor */
|
||||
i1=j1=0; /* offset in cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) { i1=-x1; x1=0; }
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) { j1=-y1; y1=0; }
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
/* save data */
|
||||
for(j=0;j<y2;j++) {
|
||||
char* dest=s->underCursorBuffer+j*x2*bpp;
|
||||
const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp;
|
||||
unsigned int count=x2*bpp;
|
||||
if(wasChanged || memcmp(dest,src,count)) {
|
||||
wasChanged=TRUE;
|
||||
memcpy(dest,src,count);
|
||||
}
|
||||
}
|
||||
|
||||
if(!c->richSource)
|
||||
rfbMakeRichCursorFromXCursor(s,c);
|
||||
|
||||
if (c->alphaSource) {
|
||||
int rmax, rshift;
|
||||
int gmax, gshift;
|
||||
int bmax, bshift;
|
||||
int amax = 255; /* alphaSource is always 8bits of info per pixel */
|
||||
unsigned int rmask, gmask, bmask;
|
||||
|
||||
rmax = s->serverFormat.redMax;
|
||||
gmax = s->serverFormat.greenMax;
|
||||
bmax = s->serverFormat.blueMax;
|
||||
rshift = s->serverFormat.redShift;
|
||||
gshift = s->serverFormat.greenShift;
|
||||
bshift = s->serverFormat.blueShift;
|
||||
|
||||
rmask = (rmax << rshift);
|
||||
gmask = (gmax << gshift);
|
||||
bmask = (bmax << bshift);
|
||||
|
||||
for(j=0;j<y2;j++) {
|
||||
for(i=0;i<x2;i++) {
|
||||
/*
|
||||
* we loop over the whole cursor ignoring c->mask[],
|
||||
* using the extracted alpha value instead.
|
||||
*/
|
||||
char *dest;
|
||||
unsigned char *src, *aptr;
|
||||
unsigned int val, dval, sval;
|
||||
int rdst, gdst, bdst; /* fb RGB */
|
||||
int asrc, rsrc, gsrc, bsrc; /* rich source ARGB */
|
||||
|
||||
dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp;
|
||||
src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp;
|
||||
aptr = c->alphaSource + (j+j1)*c->width + (i+i1);
|
||||
|
||||
asrc = *aptr;
|
||||
if (!asrc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bpp == 1) {
|
||||
dval = *((unsigned char*) dest);
|
||||
sval = *((unsigned char*) src);
|
||||
} else if (bpp == 2) {
|
||||
dval = *((unsigned short*) dest);
|
||||
sval = *((unsigned short*) src);
|
||||
} else if (bpp == 3) {
|
||||
unsigned char *dst = (unsigned char *) dest;
|
||||
dval = 0;
|
||||
dval |= ((*(dst+0)) << 0);
|
||||
dval |= ((*(dst+1)) << 8);
|
||||
dval |= ((*(dst+2)) << 16);
|
||||
sval = 0;
|
||||
sval |= ((*(src+0)) << 0);
|
||||
sval |= ((*(src+1)) << 8);
|
||||
sval |= ((*(src+2)) << 16);
|
||||
} else if (bpp == 4) {
|
||||
dval = *((unsigned int*) dest);
|
||||
sval = *((unsigned int*) src);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* extract dest and src RGB */
|
||||
rdst = (dval & rmask) >> rshift; /* fb */
|
||||
gdst = (dval & gmask) >> gshift;
|
||||
bdst = (dval & bmask) >> bshift;
|
||||
|
||||
rsrc = (sval & rmask) >> rshift; /* richcursor */
|
||||
gsrc = (sval & gmask) >> gshift;
|
||||
bsrc = (sval & bmask) >> bshift;
|
||||
|
||||
/* blend in fb data. */
|
||||
if (! c->alphaPreMultiplied) {
|
||||
rsrc = (asrc * rsrc)/amax;
|
||||
gsrc = (asrc * gsrc)/amax;
|
||||
bsrc = (asrc * bsrc)/amax;
|
||||
}
|
||||
rdst = rsrc + ((amax - asrc) * rdst)/amax;
|
||||
gdst = gsrc + ((amax - asrc) * gdst)/amax;
|
||||
bdst = bsrc + ((amax - asrc) * bdst)/amax;
|
||||
|
||||
val = 0;
|
||||
val |= (rdst << rshift);
|
||||
val |= (gdst << gshift);
|
||||
val |= (bdst << bshift);
|
||||
|
||||
/* insert the cooked pixel into the fb */
|
||||
memcpy(dest, &val, bpp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* now the cursor has to be drawn */
|
||||
for(j=0;j<y2;j++)
|
||||
for(i=0;i<x2;i++)
|
||||
if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
|
||||
memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
|
||||
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
|
||||
}
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* If enableCursorShapeUpdates is FALSE, and the cursor is hidden, make sure
|
||||
* that if the frameBuffer was transmitted with a cursor drawn, then that
|
||||
* region gets redrawn.
|
||||
*/
|
||||
|
||||
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion)
|
||||
{
|
||||
rfbScreenInfoPtr s = cl->screen;
|
||||
rfbCursorPtr c = s->cursor;
|
||||
|
||||
if(c) {
|
||||
int x,y,x2,y2;
|
||||
|
||||
x = cl->cursorX-c->xhot;
|
||||
y = cl->cursorY-c->yhot;
|
||||
x2 = x+c->width;
|
||||
y2 = y+c->height;
|
||||
|
||||
if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) {
|
||||
sraRegionPtr rect;
|
||||
rect = sraRgnCreateRect(x,y,x2,y2);
|
||||
if(updateRegion) {
|
||||
sraRgnOr(updateRegion,rect);
|
||||
} else {
|
||||
LOCK(cl->updateMutex);
|
||||
sraRgnOr(cl->modifiedRegion,rect);
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
sraRgnDestroy(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void rfbPrintXCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
int i,i1,j,w=(cursor->width+7)/8;
|
||||
unsigned char bit;
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar(':');
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
|
||||
{
|
||||
rfbClientIteratorPtr iterator;
|
||||
rfbClientPtr cl;
|
||||
|
||||
LOCK(rfbScreen->cursorMutex);
|
||||
|
||||
if(rfbScreen->cursor) {
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator)))
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
if(rfbScreen->cursor->cleanup)
|
||||
rfbFreeCursor(rfbScreen->cursor);
|
||||
}
|
||||
|
||||
rfbScreen->cursor = c;
|
||||
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator))) {
|
||||
cl->cursorWasChanged = TRUE;
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
}
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
UNLOCK(rfbScreen->cursorMutex);
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* cutpaste.c - routines to deal with cut & paste buffers / selection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetXCutText sets the cut buffer to be the given string. We also clear
|
||||
* the primary selection. Ideally we'd like to set it to the same thing, but I
|
||||
* can't work out how to do that without some kind of helper X client.
|
||||
*/
|
||||
|
||||
void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len)
|
||||
{
|
||||
rfbSendServerCutText(rfbScreen, str, len);
|
||||
}
|
||||
@@ -1,436 +0,0 @@
|
||||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC. Also the bytebit[] array
|
||||
* has been reversed so that the most significant bit in each byte of the
|
||||
* key is ignored, not the least significant.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* D3DES (V5.09) -
|
||||
*
|
||||
* A portable, public domain, version of the Data Encryption Standard.
|
||||
*
|
||||
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
|
||||
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
|
||||
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
|
||||
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
|
||||
* for humouring me on.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||
*/
|
||||
|
||||
#include "d3des.h"
|
||||
|
||||
static void scrunch(unsigned char *, unsigned long *);
|
||||
static void unscrun(unsigned long *, unsigned char *);
|
||||
static void desfunc(unsigned long *, unsigned long *);
|
||||
static void cookey(unsigned long *);
|
||||
|
||||
static unsigned long KnL[32] = { 0L };
|
||||
/*
|
||||
static unsigned long KnR[32] = { 0L };
|
||||
static unsigned long Kn3[32] = { 0L };
|
||||
static unsigned char Df_Key[24] = {
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
|
||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
|
||||
*/
|
||||
|
||||
static unsigned short bytebit[8] = {
|
||||
01, 02, 04, 010, 020, 040, 0100, 0200 };
|
||||
|
||||
static unsigned long bigbyte[24] = {
|
||||
0x800000L, 0x400000L, 0x200000L, 0x100000L,
|
||||
0x80000L, 0x40000L, 0x20000L, 0x10000L,
|
||||
0x8000L, 0x4000L, 0x2000L, 0x1000L,
|
||||
0x800L, 0x400L, 0x200L, 0x100L,
|
||||
0x80L, 0x40L, 0x20L, 0x10L,
|
||||
0x8L, 0x4L, 0x2L, 0x1L };
|
||||
|
||||
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
|
||||
|
||||
static unsigned char pc1[56] = {
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
|
||||
|
||||
static unsigned char totrot[16] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
|
||||
|
||||
static unsigned char pc2[48] = {
|
||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
|
||||
|
||||
void rfbDesKey(unsigned char *key,
|
||||
int edf)
|
||||
{
|
||||
register int i, j, l, m, n;
|
||||
unsigned char pc1m[56], pcr[56];
|
||||
unsigned long kn[32];
|
||||
|
||||
for ( j = 0; j < 56; j++ ) {
|
||||
l = pc1[j];
|
||||
m = l & 07;
|
||||
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) {
|
||||
if( edf == DE1 ) m = (15 - i) << 1;
|
||||
else m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0L;
|
||||
for( j = 0; j < 28; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 28 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 28; j < 56; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 56 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 0; j < 24; j++ ) {
|
||||
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
|
||||
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
|
||||
}
|
||||
}
|
||||
cookey(kn);
|
||||
return;
|
||||
}
|
||||
|
||||
static void cookey(register unsigned long *raw1)
|
||||
{
|
||||
register unsigned long *cook, *raw0;
|
||||
unsigned long dough[32];
|
||||
register int i;
|
||||
|
||||
cook = dough;
|
||||
for( i = 0; i < 16; i++, raw1++ ) {
|
||||
raw0 = raw1++;
|
||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
||||
*cook++ |= (*raw1 & 0x0000003fL);
|
||||
}
|
||||
rfbUseKey(dough);
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbCPKey(register unsigned long *into)
|
||||
{
|
||||
register unsigned long *from, *endp;
|
||||
|
||||
from = KnL, endp = &KnL[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbUseKey(register unsigned long *from)
|
||||
{
|
||||
register unsigned long *to, *endp;
|
||||
|
||||
to = KnL, endp = &KnL[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbDes(unsigned char *inblock,
|
||||
unsigned char *outblock)
|
||||
{
|
||||
unsigned long work[2];
|
||||
|
||||
scrunch(inblock, work);
|
||||
desfunc(work, KnL);
|
||||
unscrun(work, outblock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void scrunch(register unsigned char *outof,
|
||||
register unsigned long *into)
|
||||
{
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into++ |= (*outof++ & 0xffL);
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into |= (*outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void unscrun(register unsigned long *outof,
|
||||
register unsigned char *into)
|
||||
{
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into++ = (unsigned char)( *outof++ & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into = (unsigned char)( *outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long SP1[64] = {
|
||||
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
|
||||
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
|
||||
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
|
||||
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
|
||||
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
|
||||
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
|
||||
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
|
||||
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
|
||||
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
|
||||
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
|
||||
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
|
||||
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
|
||||
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
|
||||
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
|
||||
|
||||
static unsigned long SP2[64] = {
|
||||
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
|
||||
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
|
||||
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
|
||||
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
|
||||
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
|
||||
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
|
||||
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
|
||||
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
|
||||
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
|
||||
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
|
||||
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
|
||||
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
|
||||
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
|
||||
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
|
||||
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
|
||||
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
|
||||
|
||||
static unsigned long SP3[64] = {
|
||||
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
|
||||
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
|
||||
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
|
||||
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
|
||||
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
|
||||
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
|
||||
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
|
||||
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
|
||||
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
|
||||
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
|
||||
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
|
||||
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
|
||||
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
|
||||
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
|
||||
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
|
||||
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
|
||||
|
||||
static unsigned long SP4[64] = {
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
|
||||
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
|
||||
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
|
||||
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
|
||||
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
|
||||
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
|
||||
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
|
||||
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
|
||||
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
|
||||
|
||||
static unsigned long SP5[64] = {
|
||||
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
|
||||
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
|
||||
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
|
||||
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
|
||||
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
|
||||
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
|
||||
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
|
||||
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
|
||||
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
|
||||
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
|
||||
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
|
||||
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
|
||||
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
|
||||
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
|
||||
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
|
||||
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
|
||||
|
||||
static unsigned long SP6[64] = {
|
||||
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
|
||||
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
|
||||
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
|
||||
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
|
||||
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
|
||||
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
|
||||
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
|
||||
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
|
||||
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
|
||||
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
|
||||
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
|
||||
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
|
||||
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
|
||||
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
|
||||
|
||||
static unsigned long SP7[64] = {
|
||||
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
|
||||
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
|
||||
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
|
||||
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
|
||||
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
|
||||
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
|
||||
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
|
||||
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
|
||||
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
|
||||
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
|
||||
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
|
||||
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
|
||||
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
|
||||
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
|
||||
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
|
||||
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
|
||||
|
||||
static unsigned long SP8[64] = {
|
||||
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
|
||||
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
|
||||
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
|
||||
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
|
||||
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
|
||||
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
|
||||
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
|
||||
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
|
||||
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
|
||||
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
|
||||
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
|
||||
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
|
||||
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
|
||||
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
|
||||
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
|
||||
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
|
||||
|
||||
static void desfunc(register unsigned long *block,
|
||||
register unsigned long *keys)
|
||||
{
|
||||
register unsigned long fval, work, right, leftt;
|
||||
register int round;
|
||||
|
||||
leftt = block[0];
|
||||
right = block[1];
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 4);
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 16);
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
||||
leftt ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 8);
|
||||
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
|
||||
|
||||
for( round = 0; round < 8; round++ ) {
|
||||
work = (right << 28) | (right >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = right ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
leftt ^= fval;
|
||||
work = (leftt << 28) | (leftt >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = leftt ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
right ^= fval;
|
||||
}
|
||||
|
||||
right = (right << 31) | (right >> 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = (leftt << 31) | (leftt >> 1);
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 8);
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
||||
right ^= work;
|
||||
leftt ^= (work << 2);
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 16);
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 4);
|
||||
*block++ = right;
|
||||
*block = leftt;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validation sets:
|
||||
*
|
||||
* Single-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : c957 4425 6a5e d31d
|
||||
*
|
||||
* Double-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : 7f1d 0a77 826b 8aff
|
||||
*
|
||||
* Double-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
|
||||
*
|
||||
* Triple-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : de0b 7c06 ae5e 0ed5
|
||||
*
|
||||
* Triple-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
|
||||
*
|
||||
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
|
||||
**********************************************************************/
|
||||
@@ -1,56 +0,0 @@
|
||||
#ifndef D3DES_H
|
||||
#define D3DES_H
|
||||
|
||||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* d3des.h -
|
||||
*
|
||||
* Headers and defines for d3des.c
|
||||
* Graven Imagery, 1992.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
|
||||
* (GEnie : OUTER; CIS : [71755,204])
|
||||
*/
|
||||
|
||||
#define EN0 0 /* MODE == encrypt */
|
||||
#define DE1 1 /* MODE == decrypt */
|
||||
|
||||
extern void rfbDesKey(unsigned char *, int);
|
||||
/* hexkey[8] MODE
|
||||
* Sets the internal key register according to the hexadecimal
|
||||
* key contained in the 8 bytes of hexkey, according to the DES,
|
||||
* for encryption or decryption according to MODE.
|
||||
*/
|
||||
|
||||
extern void rfbUseKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Loads the internal key register with the data in cookedkey.
|
||||
*/
|
||||
|
||||
extern void rfbCPKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Copies the contents of the internal key register into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
extern void rfbDes(unsigned char *, unsigned char *);
|
||||
/* from[8] to[8]
|
||||
* Encrypts/Decrypts (according to the key currently loaded in the
|
||||
* internal key register) one block of eight bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
|
||||
********************************************************************/
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i,j;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
for(j=y1;j<y2;j++)
|
||||
for(i=x1;i<x2;i++)
|
||||
memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp);
|
||||
rfbMarkRectAsModified(s,x1,y1,x2,y2);
|
||||
}
|
||||
|
||||
#define SETPIXEL(x,y) \
|
||||
memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp)
|
||||
|
||||
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
SETPIXEL(x,y);
|
||||
rfbMarkRectAsModified(s,x,y,x+1,y+1);
|
||||
}
|
||||
|
||||
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
|
||||
#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; }
|
||||
if(abs(x1-x2)<abs(y1-y2)) {
|
||||
if(y1>y2)
|
||||
SWAPPOINTS
|
||||
for(i=y1;i<=y2;i++)
|
||||
SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i);
|
||||
/* TODO: Maybe make this more intelligently? */
|
||||
if(x2<x1) { i=x1; x1=x2; x2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
} else {
|
||||
if(x1>x2)
|
||||
SWAPPOINTS
|
||||
else if(x1==x2) {
|
||||
rfbDrawPixel(s,x1,y1,col);
|
||||
return;
|
||||
}
|
||||
for(i=x1;i<=x2;i++)
|
||||
SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1));
|
||||
if(y2<y1) { i=y1; y1=y2; y2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,unsigned char c,rfbPixel col)
|
||||
{
|
||||
int i,j,width,height;
|
||||
unsigned char* data=font->data+font->metaData[c*5];
|
||||
unsigned char d=*data;
|
||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
||||
int bpp=rfbScreen->serverFormat.bitsPerPixel/8;
|
||||
char *colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
|
||||
width=font->metaData[c*5+1];
|
||||
height=font->metaData[c*5+2];
|
||||
x+=font->metaData[c*5+3];
|
||||
y+=-font->metaData[c*5+4]-height+1;
|
||||
|
||||
for(j=0;j<height;j++) {
|
||||
for(i=0;i<width;i++) {
|
||||
if((i&7)==0) {
|
||||
d=*data;
|
||||
data++;
|
||||
}
|
||||
if(d&0x80 && y+j >= 0 && y+j < rfbScreen->height &&
|
||||
x+i >= 0 && x+i < rfbScreen->width)
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp);
|
||||
d<<=1;
|
||||
}
|
||||
/* if((i&7)!=0) data++; */
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,const char* string,rfbPixel colour)
|
||||
{
|
||||
while(*string) {
|
||||
x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: these two functions need to be more efficient */
|
||||
/* if col==bcol, assume transparent background */
|
||||
int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,unsigned char c,
|
||||
int x1,int y1,int x2,int y2,
|
||||
rfbPixel col,rfbPixel bcol)
|
||||
{
|
||||
int i,j,width,height;
|
||||
unsigned char* data=font->data+font->metaData[c*5];
|
||||
unsigned char d;
|
||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
||||
int bpp=rfbScreen->serverFormat.bitsPerPixel/8,extra_bytes=0;
|
||||
char* colour=(char*)&col;
|
||||
char* bcolour=(char*)&bcol;
|
||||
|
||||
if(!rfbEndianTest) {
|
||||
colour+=4-bpp;
|
||||
bcolour+=4-bpp;
|
||||
}
|
||||
|
||||
width=font->metaData[c*5+1];
|
||||
height=font->metaData[c*5+2];
|
||||
x+=font->metaData[c*5+3];
|
||||
y+=-font->metaData[c*5+4]-height+1;
|
||||
|
||||
/* after clipping, x2 will be count of bytes between rows,
|
||||
* x1 start of i, y1 start of j, width and height will be adjusted. */
|
||||
if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0;
|
||||
if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0;
|
||||
if(y2<y+height) height-=y+height-y2;
|
||||
if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; }
|
||||
|
||||
d=*data;
|
||||
for(j=y1;j<height;j++) {
|
||||
if((x1&7)!=0)
|
||||
d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */
|
||||
for(i=x1;i<width;i++) {
|
||||
if((i&7)==0) {
|
||||
d=*data;
|
||||
data++;
|
||||
}
|
||||
/* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ {
|
||||
if(d&0x80) {
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
||||
colour,bpp);
|
||||
} else if(bcol!=col) {
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
||||
bcolour,bpp);
|
||||
}
|
||||
}
|
||||
d<<=1;
|
||||
}
|
||||
/* if((i&7)==0) data++; */
|
||||
data += extra_bytes;
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,const char* string,
|
||||
int x1,int y1,int x2,int y2,
|
||||
rfbPixel colour,rfbPixel backColour)
|
||||
{
|
||||
while(*string) {
|
||||
x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2,
|
||||
colour,backColour);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
int rfbWidthOfString(rfbFontDataPtr font,const char* string)
|
||||
{
|
||||
int i=0;
|
||||
while(*string) {
|
||||
i+=font->metaData[*string*5+1];
|
||||
string++;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
|
||||
{
|
||||
return(font->metaData[c*5+1]+font->metaData[c*5+3]);
|
||||
}
|
||||
|
||||
void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2)
|
||||
{
|
||||
*x1+=font->metaData[c*5+3];
|
||||
*y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1;
|
||||
*x2=*x1+font->metaData[c*5+1]+1;
|
||||
*y2=*y1+font->metaData[c*5+2]+1;
|
||||
}
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
void rfbWholeFontBBox(rfbFontDataPtr font,
|
||||
int *x1, int *y1, int *x2, int *y2)
|
||||
{
|
||||
int i;
|
||||
int* m=font->metaData;
|
||||
|
||||
(*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=1-(INT_MAX);
|
||||
for(i=0;i<256;i++) {
|
||||
if(m[i*5+1]-m[i*5+3]>(*x2))
|
||||
(*x2)=m[i*5+1]-m[i*5+3];
|
||||
if(-m[i*5+2]+m[i*5+4]<(*y1))
|
||||
(*y1)=-m[i*5+2]+m[i*5+4];
|
||||
if(m[i*5+3]<(*x1))
|
||||
(*x1)=m[i*5+3];
|
||||
if(-m[i*5+4]>(*y2))
|
||||
(*y2)=-m[i*5+4];
|
||||
}
|
||||
(*x2)++;
|
||||
(*y2)++;
|
||||
}
|
||||
|
||||
rfbFontDataPtr rfbLoadConsoleFont(char *filename)
|
||||
{
|
||||
FILE *f=fopen(filename,"rb");
|
||||
rfbFontDataPtr p;
|
||||
int i;
|
||||
|
||||
if(!f) return NULL;
|
||||
|
||||
p=(rfbFontDataPtr)malloc(sizeof(rfbFontData));
|
||||
p->data=(unsigned char*)malloc(4096);
|
||||
if(1!=fread(p->data,4096,1,f)) {
|
||||
free(p->data);
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
fclose(f);
|
||||
p->metaData=(int*)malloc(256*5*sizeof(int));
|
||||
for(i=0;i<256;i++) {
|
||||
p->metaData[i*5+0]=i*16; /* offset */
|
||||
p->metaData[i*5+1]=8; /* width */
|
||||
p->metaData[i*5+2]=16; /* height */
|
||||
p->metaData[i*5+3]=0; /* xhot */
|
||||
p->metaData[i*5+4]=0; /* yhot */
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
void rfbFreeFont(rfbFontDataPtr f)
|
||||
{
|
||||
free(f->data);
|
||||
free(f->metaData);
|
||||
free(f);
|
||||
}
|
||||
@@ -1,342 +0,0 @@
|
||||
/*
|
||||
* hextile.c
|
||||
*
|
||||
* Routines to implement Hextile Encoding
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingHextile(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingHextile);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
|
||||
sz_rfbFramebufferUpdateRectHeader,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
return sendHextiles8(cl, x, y, w, h);
|
||||
case 16:
|
||||
return sendHextiles16(cl, x, y, w, h);
|
||||
case 32:
|
||||
return sendHextiles32(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
|
||||
|
||||
#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
|
||||
|
||||
#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
|
||||
|
||||
|
||||
#define DEFINE_SEND_HEXTILES(bpp) \
|
||||
\
|
||||
\
|
||||
static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \
|
||||
int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\
|
||||
static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \
|
||||
rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \
|
||||
\
|
||||
\
|
||||
/* \
|
||||
* rfbSendHextiles \
|
||||
*/ \
|
||||
\
|
||||
static rfbBool \
|
||||
sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \
|
||||
int x, y, w, h; \
|
||||
int startUblen; \
|
||||
char *fbptr; \
|
||||
uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \
|
||||
rfbBool mono, solid; \
|
||||
rfbBool validBg = FALSE; \
|
||||
rfbBool validFg = FALSE; \
|
||||
uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \
|
||||
\
|
||||
for (y = ry; y < ry+rh; y += 16) { \
|
||||
for (x = rx; x < rx+rw; x += 16) { \
|
||||
w = h = 16; \
|
||||
if (rx+rw - x < 16) \
|
||||
w = rx+rw - x; \
|
||||
if (ry+rh - y < 16) \
|
||||
h = ry+rh - y; \
|
||||
\
|
||||
if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
|
||||
UPDATE_BUF_SIZE) { \
|
||||
if (!rfbSendUpdateBuf(cl)) \
|
||||
return FALSE; \
|
||||
} \
|
||||
\
|
||||
fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8))); \
|
||||
\
|
||||
(*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \
|
||||
&cl->format, fbptr, (char *)clientPixelData, \
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h); \
|
||||
\
|
||||
startUblen = cl->ublen; \
|
||||
cl->updateBuf[startUblen] = 0; \
|
||||
cl->ublen++; \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
testColours##bpp(clientPixelData, w * h, \
|
||||
&mono, &solid, &newBg, &newFg); \
|
||||
\
|
||||
if (!validBg || (newBg != bg)) { \
|
||||
validBg = TRUE; \
|
||||
bg = newBg; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
|
||||
PUT_PIXEL##bpp(bg); \
|
||||
} \
|
||||
\
|
||||
if (solid) { \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
|
||||
\
|
||||
if (mono) { \
|
||||
if (!validFg || (newFg != fg)) { \
|
||||
validFg = TRUE; \
|
||||
fg = newFg; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
|
||||
PUT_PIXEL##bpp(fg); \
|
||||
} \
|
||||
} else { \
|
||||
validFg = FALSE; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
|
||||
} \
|
||||
\
|
||||
if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
|
||||
/* encoding was too large, use raw */ \
|
||||
validBg = FALSE; \
|
||||
validFg = FALSE; \
|
||||
cl->ublen = startUblen; \
|
||||
cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
|
||||
(*cl->translateFn)(cl->translateLookupTable, \
|
||||
&(cl->screen->serverFormat), &cl->format, fbptr, \
|
||||
(char *)clientPixelData, \
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h); \
|
||||
\
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
|
||||
w * h * (bpp/8)); \
|
||||
\
|
||||
cl->ublen += w * h * (bpp/8); \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
|
||||
w * h * (bpp/8)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
static rfbBool \
|
||||
subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \
|
||||
uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \
|
||||
{ \
|
||||
uint##bpp##_t cl2; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
int nSubrectsUblen; \
|
||||
\
|
||||
nSubrectsUblen = cl->ublen; \
|
||||
cl->ublen++; \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl2 = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl2) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl2) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) { \
|
||||
hy += 1; \
|
||||
} else { \
|
||||
hyflag = 0; \
|
||||
} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and \
|
||||
* (x,y,vx,vy). We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
if (mono) { \
|
||||
newLen = cl->ublen - nSubrectsUblen + 2; \
|
||||
} else { \
|
||||
newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
|
||||
} \
|
||||
\
|
||||
if (newLen > (w * h * (bpp/8))) \
|
||||
return FALSE; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
\
|
||||
if (!mono) PUT_PIXEL##bpp(cl2); \
|
||||
\
|
||||
cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
|
||||
cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
cl->updateBuf[nSubrectsUblen] = numsubs; \
|
||||
\
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
/* \
|
||||
* testColours() tests if there are one (solid), two (mono) or more \
|
||||
* colours in a tile and gets a reasonable guess at the best background \
|
||||
* pixel, and the foreground pixel for mono. \
|
||||
*/ \
|
||||
\
|
||||
static void \
|
||||
testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \
|
||||
uint##bpp##_t *bg, uint##bpp##_t *fg) { \
|
||||
uint##bpp##_t colour1 = 0, colour2 = 0; \
|
||||
int n1 = 0, n2 = 0; \
|
||||
*mono = TRUE; \
|
||||
*solid = TRUE; \
|
||||
\
|
||||
for (; size > 0; size--, data++) { \
|
||||
\
|
||||
if (n1 == 0) \
|
||||
colour1 = *data; \
|
||||
\
|
||||
if (*data == colour1) { \
|
||||
n1++; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
if (n2 == 0) { \
|
||||
*solid = FALSE; \
|
||||
colour2 = *data; \
|
||||
} \
|
||||
\
|
||||
if (*data == colour2) { \
|
||||
n2++; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
*mono = FALSE; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (n1 > n2) { \
|
||||
*bg = colour1; \
|
||||
*fg = colour2; \
|
||||
} else { \
|
||||
*bg = colour2; \
|
||||
*fg = colour1; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFINE_SEND_HEXTILES(8)
|
||||
DEFINE_SEND_HEXTILES(16)
|
||||
DEFINE_SEND_HEXTILES(32)
|
||||
@@ -1,600 +0,0 @@
|
||||
/*
|
||||
* httpd.c - a simple HTTP server
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#define close closesocket
|
||||
#else
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBWRAP
|
||||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#define connection_close
|
||||
#ifndef connection_close
|
||||
|
||||
#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \
|
||||
"<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>File Not Found</H1></BODY>\n"
|
||||
|
||||
#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\n\r\n" \
|
||||
"<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>Invalid request</H1></BODY>\n"
|
||||
|
||||
#define OK_STR "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
|
||||
|
||||
#else
|
||||
|
||||
#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \
|
||||
"<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>File Not Found</H1></BODY>\n"
|
||||
|
||||
#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\nConnection: close\r\n\r\n" \
|
||||
"<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>Invalid request</H1></BODY>\n"
|
||||
|
||||
#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n"
|
||||
|
||||
#endif
|
||||
|
||||
static void httpProcessInput(rfbScreenInfoPtr screen);
|
||||
static rfbBool compareAndSkip(char **ptr, const char *str);
|
||||
static rfbBool parseParams(const char *request, char *result, int max_bytes);
|
||||
static rfbBool validateString(char *str);
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
|
||||
static char buf[BUF_SIZE];
|
||||
static size_t buf_filled=0;
|
||||
|
||||
/*
|
||||
* httpInitSockets sets up the TCP socket to listen for HTTP connections.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
if (rfbScreen->httpInitDone)
|
||||
return;
|
||||
|
||||
rfbScreen->httpInitDone = TRUE;
|
||||
|
||||
if (!rfbScreen->httpDir)
|
||||
return;
|
||||
|
||||
if (rfbScreen->httpPort == 0) {
|
||||
rfbScreen->httpPort = rfbScreen->port-100;
|
||||
}
|
||||
|
||||
rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
|
||||
|
||||
rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort);
|
||||
|
||||
if ((rfbScreen->httpListenSock =
|
||||
rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) {
|
||||
rfbLogPerror("ListenOnTCPPort");
|
||||
return;
|
||||
}
|
||||
|
||||
/*AddEnabledDevice(httpListenSock);*/
|
||||
}
|
||||
|
||||
void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {
|
||||
if(rfbScreen->httpSock>-1) {
|
||||
close(rfbScreen->httpSock);
|
||||
FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds);
|
||||
rfbScreen->httpSock=-1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* httpCheckFds is called from ProcessInputEvents to check for input on the
|
||||
* HTTP socket(s). If there is input to process, httpProcessInput is called.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
int nfds;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
if (!rfbScreen->httpDir)
|
||||
return;
|
||||
|
||||
if (rfbScreen->httpListenSock < 0)
|
||||
return;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(rfbScreen->httpListenSock, &fds);
|
||||
if (rfbScreen->httpSock >= 0) {
|
||||
FD_SET(rfbScreen->httpSock, &fds);
|
||||
}
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv);
|
||||
if (nfds == 0) {
|
||||
return;
|
||||
}
|
||||
if (nfds < 0) {
|
||||
#ifdef WIN32
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno != EINTR)
|
||||
rfbLogPerror("httpCheckFds: select");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
|
||||
httpProcessInput(rfbScreen);
|
||||
}
|
||||
|
||||
if (FD_ISSET(rfbScreen->httpListenSock, &fds)) {
|
||||
if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);
|
||||
|
||||
if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock,
|
||||
(struct sockaddr *)&addr, &addrlen)) < 0) {
|
||||
rfbLogPerror("httpCheckFds: accept");
|
||||
return;
|
||||
}
|
||||
#ifdef USE_LIBWRAP
|
||||
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
|
||||
STRING_UNKNOWN)) {
|
||||
rfbLog("Rejected HTTP connection from client %s\n",
|
||||
inet_ntoa(addr.sin_addr));
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock=-1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(!rfbSetNonBlocking(rfbScreen->httpSock)) {
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock=-1;
|
||||
return;
|
||||
}
|
||||
/*AddEnabledDevice(httpSock);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
httpCloseSock(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
buf_filled = 0;
|
||||
}
|
||||
|
||||
static rfbClientRec cl;
|
||||
|
||||
/*
|
||||
* httpProcessInput is called when input is received on the HTTP socket.
|
||||
*/
|
||||
|
||||
static void
|
||||
httpProcessInput(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
char fullFname[512];
|
||||
char params[1024];
|
||||
char *ptr;
|
||||
char *fname;
|
||||
unsigned int maxFnameLen;
|
||||
FILE* fd;
|
||||
rfbBool performSubstitutions = FALSE;
|
||||
char str[256+32];
|
||||
#ifndef WIN32
|
||||
char* user=getenv("USER");
|
||||
#endif
|
||||
|
||||
cl.sock=rfbScreen->httpSock;
|
||||
|
||||
if (strlen(rfbScreen->httpDir) > 255) {
|
||||
rfbErr("-httpd directory too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
strcpy(fullFname, rfbScreen->httpDir);
|
||||
fname = &fullFname[strlen(fullFname)];
|
||||
maxFnameLen = 511 - strlen(fullFname);
|
||||
|
||||
buf_filled=0;
|
||||
|
||||
/* Read data from the HTTP client until we get a complete request. */
|
||||
while (1) {
|
||||
ssize_t got;
|
||||
|
||||
if (buf_filled > sizeof (buf)) {
|
||||
rfbErr("httpProcessInput: HTTP request is too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
got = read (rfbScreen->httpSock, buf + buf_filled,
|
||||
sizeof (buf) - buf_filled - 1);
|
||||
|
||||
if (got <= 0) {
|
||||
if (got == 0) {
|
||||
rfbErr("httpd: premature connection close\n");
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
errno=WSAGetLastError();
|
||||
#endif
|
||||
if (errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
rfbLogPerror("httpProcessInput: read");
|
||||
}
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_filled += got;
|
||||
buf[buf_filled] = '\0';
|
||||
|
||||
/* Is it complete yet (is there a blank line)? */
|
||||
if (strstr (buf, "\r\r") || strstr (buf, "\n\n") ||
|
||||
strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r"))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Process the request. */
|
||||
if(rfbScreen->httpEnableProxyConnect) {
|
||||
const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n";
|
||||
if(!strncmp(buf, "CONNECT ", 8)) {
|
||||
if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) {
|
||||
rfbErr("httpd: CONNECT format invalid.\n");
|
||||
rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
/* proxy connection */
|
||||
rfbLog("httpd: client asked for CONNECT\n");
|
||||
rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
|
||||
rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
return;
|
||||
}
|
||||
if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) {
|
||||
/* proxy connection */
|
||||
rfbLog("httpd: client asked for /proxied.connection\n");
|
||||
rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
|
||||
rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(buf, "GET ", 4)) {
|
||||
rfbErr("httpd: no GET line\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
} else {
|
||||
/* Only use the first line. */
|
||||
buf[strcspn(buf, "\n\r")] = '\0';
|
||||
}
|
||||
|
||||
if (strlen(buf) > maxFnameLen) {
|
||||
rfbErr("httpd: GET line too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) {
|
||||
rfbErr("httpd: couldn't parse GET line\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fname[0] != '/') {
|
||||
rfbErr("httpd: filename didn't begin with '/'\n");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strchr(fname+1, '/') != NULL) {
|
||||
rfbErr("httpd: asking for file in other directory\n");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
|
||||
rfbLog("httpd: get '%s' for %s\n", fname+1,
|
||||
inet_ntoa(addr.sin_addr));
|
||||
|
||||
/* Extract parameters from the URL string if necessary */
|
||||
|
||||
params[0] = '\0';
|
||||
ptr = strchr(fname, '?');
|
||||
if (ptr != NULL) {
|
||||
*ptr = '\0';
|
||||
if (!parseParams(&ptr[1], params, 1024)) {
|
||||
params[0] = '\0';
|
||||
rfbErr("httpd: bad parameters in the URL\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If we were asked for '/', actually read the file index.vnc */
|
||||
|
||||
if (strcmp(fname, "/") == 0) {
|
||||
strcpy(fname, "/index.vnc");
|
||||
rfbLog("httpd: defaulting to '%s'\n", fname+1);
|
||||
}
|
||||
|
||||
/* Substitutions are performed on files ending .vnc */
|
||||
|
||||
if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
|
||||
performSubstitutions = TRUE;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
|
||||
if ((fd = fopen(fullFname, "r")) == 0) {
|
||||
rfbLogPerror("httpProcessInput: open");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
rfbWriteExact(&cl, OK_STR, strlen(OK_STR));
|
||||
|
||||
while (1) {
|
||||
int n = fread(buf, 1, BUF_SIZE-1, fd);
|
||||
if (n < 0) {
|
||||
rfbLogPerror("httpProcessInput: read");
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
if (performSubstitutions) {
|
||||
|
||||
/* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
|
||||
This won't quite work properly if the .vnc file is longer than
|
||||
BUF_SIZE, but it's reasonable to assume that .vnc files will
|
||||
always be short. */
|
||||
|
||||
char *ptr = buf;
|
||||
char *dollar;
|
||||
buf[n] = 0; /* make sure it's null-terminated */
|
||||
|
||||
while ((dollar = strchr(ptr, '$'))!=NULL) {
|
||||
rfbWriteExact(&cl, ptr, (dollar - ptr));
|
||||
|
||||
ptr = dollar;
|
||||
|
||||
if (compareAndSkip(&ptr, "$WIDTH")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->width);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$HEIGHT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->height);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->width);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->height + 32);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$PORT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->port);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$DESKTOP")) {
|
||||
|
||||
rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$DISPLAY")) {
|
||||
|
||||
sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$USER")) {
|
||||
#ifndef WIN32
|
||||
if (user) {
|
||||
rfbWriteExact(&cl, user,
|
||||
strlen(user));
|
||||
} else
|
||||
#endif
|
||||
rfbWriteExact(&cl, "?", 1);
|
||||
} else if (compareAndSkip(&ptr, "$PARAMS")) {
|
||||
if (params[0] != '\0')
|
||||
rfbWriteExact(&cl, params, strlen(params));
|
||||
} else {
|
||||
if (!compareAndSkip(&ptr, "$$"))
|
||||
ptr++;
|
||||
|
||||
if (rfbWriteExact(&cl, "$", 1) < 0) {
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0)
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
/* For files not ending .vnc, just write out the buffer */
|
||||
|
||||
if (rfbWriteExact(&cl, buf, n) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
}
|
||||
|
||||
|
||||
static rfbBool
|
||||
compareAndSkip(char **ptr, const char *str)
|
||||
{
|
||||
if (strncmp(*ptr, str, strlen(str)) == 0) {
|
||||
*ptr += strlen(str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the request tail after the '?' character, and format a sequence
|
||||
* of <param> tags for inclusion into an HTML page with embedded applet.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
parseParams(const char *request, char *result, int max_bytes)
|
||||
{
|
||||
char param_request[128];
|
||||
char param_formatted[196];
|
||||
const char *tail;
|
||||
char *delim_ptr;
|
||||
char *value_str;
|
||||
int cur_bytes, len;
|
||||
|
||||
result[0] = '\0';
|
||||
cur_bytes = 0;
|
||||
|
||||
tail = request;
|
||||
for (;;) {
|
||||
/* Copy individual "name=value" string into a buffer */
|
||||
delim_ptr = strchr((char *)tail, '&');
|
||||
if (delim_ptr == NULL) {
|
||||
if (strlen(tail) >= sizeof(param_request)) {
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(param_request, tail);
|
||||
} else {
|
||||
len = delim_ptr - tail;
|
||||
if (len >= sizeof(param_request)) {
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(param_request, tail, len);
|
||||
param_request[len] = '\0';
|
||||
}
|
||||
|
||||
/* Split the request into parameter name and value */
|
||||
value_str = strchr(¶m_request[1], '=');
|
||||
if (value_str == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
*value_str++ = '\0';
|
||||
if (strlen(value_str) == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Validate both parameter name and value */
|
||||
if (!validateString(param_request) || !validateString(value_str)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Prepare HTML-formatted representation of the name=value pair */
|
||||
len = sprintf(param_formatted,
|
||||
"<PARAM NAME=\"%s\" VALUE=\"%s\">\n",
|
||||
param_request, value_str);
|
||||
if (cur_bytes + len + 1 > max_bytes) {
|
||||
return FALSE;
|
||||
}
|
||||
strcat(result, param_formatted);
|
||||
cur_bytes += len;
|
||||
|
||||
/* Go to the next parameter */
|
||||
if (delim_ptr == NULL) {
|
||||
break;
|
||||
}
|
||||
tail = delim_ptr + 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the string consists only of alphanumeric characters, '+'
|
||||
* signs, underscores, and dots. Replace all '+' signs with spaces.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
validateString(char *str)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (ptr = str; *ptr != '\0'; ptr++) {
|
||||
if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') {
|
||||
if (*ptr == '+') {
|
||||
*ptr = ' ';
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#ifndef _RFB_RFBCONFIG_H
|
||||
#define _RFB_RFBCONFIG_H
|
||||
|
||||
/* rfb/rfbconfig.h. Generated automatically by cmake. */
|
||||
|
||||
/* Enable 24 bit per pixel in native framebuffer */
|
||||
#cmakedefine LIBVNCSERVER_ALLOW24BPP 1
|
||||
|
||||
/* work around when write() returns ENOENT but does not mean it */
|
||||
#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `jpeg' library (-ljpeg). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1
|
||||
|
||||
/* Need a typedef for in_addr_t */
|
||||
#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* Define to 1 if libgcrypt is present */
|
||||
#cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1
|
||||
|
||||
/* Define to 1 if GnuTLS is present */
|
||||
#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#cmakedefine const @CMAKE_CONST@
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
#cmakedefine inline @CMAKE_INLINE@
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_PID_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_PID_T
|
||||
typedef int pid_t;
|
||||
#endif
|
||||
|
||||
/* The type for size_t */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_SIZE_T
|
||||
typedef int size_t;
|
||||
#endif
|
||||
|
||||
/* The type for socklen */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
/* once: _RFB_RFBCONFIG_H */
|
||||
#endif
|
||||
@@ -1,419 +0,0 @@
|
||||
/* lzoconf.h -- configuration for the LZO real-time data compression library
|
||||
|
||||
This file is part of the LZO real-time data compression library.
|
||||
|
||||
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
The LZO library 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.
|
||||
|
||||
The LZO library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the LZO library; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LZOCONF_H_INCLUDED
|
||||
#define __LZOCONF_H_INCLUDED 1
|
||||
|
||||
#define LZO_VERSION 0x2040
|
||||
#define LZO_VERSION_STRING "2.04"
|
||||
#define LZO_VERSION_DATE "Oct 31 2010"
|
||||
|
||||
/* internal Autoconf configuration file - only used when building LZO */
|
||||
#if defined(LZO_HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// LZO requires a conforming <limits.h>
|
||||
************************************************************************/
|
||||
|
||||
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
|
||||
# error "invalid CHAR_BIT"
|
||||
#endif
|
||||
#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
|
||||
# error "check your compiler installation"
|
||||
#endif
|
||||
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
|
||||
# error "your limits.h macros are broken"
|
||||
#endif
|
||||
|
||||
/* get OS and architecture defines */
|
||||
#ifndef __LZODEFS_H_INCLUDED
|
||||
#include "lzodefs.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// some core defines
|
||||
************************************************************************/
|
||||
|
||||
#if !defined(LZO_UINT32_C)
|
||||
# if (UINT_MAX < LZO_0xffffffffL)
|
||||
# define LZO_UINT32_C(c) c ## UL
|
||||
# else
|
||||
# define LZO_UINT32_C(c) ((c) + 0U)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* memory checkers */
|
||||
#if !defined(__LZO_CHECKER)
|
||||
# if defined(__BOUNDS_CHECKING_ON)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__CHECKER__)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__INSURE__)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__PURIFY__)
|
||||
# define __LZO_CHECKER 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// integral and pointer types
|
||||
************************************************************************/
|
||||
|
||||
/* lzo_uint should match size_t */
|
||||
#if !defined(LZO_UINT_MAX)
|
||||
# if defined(LZO_ABI_LLP64) /* WIN64 */
|
||||
# if defined(LZO_OS_WIN64)
|
||||
typedef unsigned __int64 lzo_uint;
|
||||
typedef __int64 lzo_int;
|
||||
# else
|
||||
typedef unsigned long long lzo_uint;
|
||||
typedef long long lzo_int;
|
||||
# endif
|
||||
# define LZO_UINT_MAX 0xffffffffffffffffull
|
||||
# define LZO_INT_MAX 9223372036854775807LL
|
||||
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
|
||||
# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
|
||||
typedef unsigned int lzo_uint;
|
||||
typedef int lzo_int;
|
||||
# define LZO_UINT_MAX UINT_MAX
|
||||
# define LZO_INT_MAX INT_MAX
|
||||
# define LZO_INT_MIN INT_MIN
|
||||
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned long lzo_uint;
|
||||
typedef long lzo_int;
|
||||
# define LZO_UINT_MAX ULONG_MAX
|
||||
# define LZO_INT_MAX LONG_MAX
|
||||
# define LZO_INT_MIN LONG_MIN
|
||||
# else
|
||||
# error "lzo_uint"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Integral types with 32 bits or more. */
|
||||
#if !defined(LZO_UINT32_MAX)
|
||||
# if (UINT_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned int lzo_uint32;
|
||||
typedef int lzo_int32;
|
||||
# define LZO_UINT32_MAX UINT_MAX
|
||||
# define LZO_INT32_MAX INT_MAX
|
||||
# define LZO_INT32_MIN INT_MIN
|
||||
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned long lzo_uint32;
|
||||
typedef long lzo_int32;
|
||||
# define LZO_UINT32_MAX ULONG_MAX
|
||||
# define LZO_INT32_MAX LONG_MAX
|
||||
# define LZO_INT32_MIN LONG_MIN
|
||||
# else
|
||||
# error "lzo_uint32"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The larger type of lzo_uint and lzo_uint32. */
|
||||
#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
|
||||
# define lzo_xint lzo_uint
|
||||
#else
|
||||
# define lzo_xint lzo_uint32
|
||||
#endif
|
||||
|
||||
/* Memory model that allows to access memory at offsets of lzo_uint. */
|
||||
#if !defined(__LZO_MMODEL)
|
||||
# if (LZO_UINT_MAX <= UINT_MAX)
|
||||
# define __LZO_MMODEL /*empty*/
|
||||
# elif defined(LZO_HAVE_MM_HUGE_PTR)
|
||||
# define __LZO_MMODEL_HUGE 1
|
||||
# define __LZO_MMODEL __huge
|
||||
# else
|
||||
# define __LZO_MMODEL /*empty*/
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* no typedef here because of const-pointer issues */
|
||||
#define lzo_bytep unsigned char __LZO_MMODEL *
|
||||
#define lzo_charp char __LZO_MMODEL *
|
||||
#define lzo_voidp void __LZO_MMODEL *
|
||||
#define lzo_shortp short __LZO_MMODEL *
|
||||
#define lzo_ushortp unsigned short __LZO_MMODEL *
|
||||
#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
|
||||
#define lzo_int32p lzo_int32 __LZO_MMODEL *
|
||||
#define lzo_uintp lzo_uint __LZO_MMODEL *
|
||||
#define lzo_intp lzo_int __LZO_MMODEL *
|
||||
#define lzo_xintp lzo_xint __LZO_MMODEL *
|
||||
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
|
||||
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
|
||||
/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
|
||||
#define lzo_byte unsigned char __LZO_MMODEL
|
||||
|
||||
typedef int lzo_bool;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// function types
|
||||
************************************************************************/
|
||||
|
||||
/* name mangling */
|
||||
#if !defined(__LZO_EXTERN_C)
|
||||
# ifdef __cplusplus
|
||||
# define __LZO_EXTERN_C extern "C"
|
||||
# else
|
||||
# define __LZO_EXTERN_C extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* calling convention */
|
||||
#if !defined(__LZO_CDECL)
|
||||
# define __LZO_CDECL __lzo_cdecl
|
||||
#endif
|
||||
|
||||
/* DLL export information */
|
||||
#if !defined(__LZO_EXPORT1)
|
||||
# define __LZO_EXPORT1 /*empty*/
|
||||
#endif
|
||||
#if !defined(__LZO_EXPORT2)
|
||||
# define __LZO_EXPORT2 /*empty*/
|
||||
#endif
|
||||
|
||||
/* __cdecl calling convention for public C and assembly functions */
|
||||
#if !defined(LZO_PUBLIC)
|
||||
# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
|
||||
#endif
|
||||
#if !defined(LZO_EXTERN)
|
||||
# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
|
||||
#endif
|
||||
#if !defined(LZO_PRIVATE)
|
||||
# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
|
||||
#endif
|
||||
|
||||
/* function types */
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem,
|
||||
const lzo_bytep dict, lzo_uint dict_len );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem,
|
||||
const lzo_bytep dict, lzo_uint dict_len );
|
||||
|
||||
|
||||
/* Callback interface. Currently only the progress indicator ("nprogress")
|
||||
* is used, but this may change in a future release. */
|
||||
|
||||
struct lzo_callback_t;
|
||||
typedef struct lzo_callback_t lzo_callback_t;
|
||||
#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
|
||||
|
||||
/* malloc & free function types */
|
||||
typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
|
||||
(lzo_callback_p self, lzo_uint items, lzo_uint size);
|
||||
typedef void (__LZO_CDECL *lzo_free_func_t)
|
||||
(lzo_callback_p self, lzo_voidp ptr);
|
||||
|
||||
/* a progress indicator callback function */
|
||||
typedef void (__LZO_CDECL *lzo_progress_func_t)
|
||||
(lzo_callback_p, lzo_uint, lzo_uint, int);
|
||||
|
||||
struct lzo_callback_t
|
||||
{
|
||||
/* custom allocators (set to 0 to disable) */
|
||||
lzo_alloc_func_t nalloc; /* [not used right now] */
|
||||
lzo_free_func_t nfree; /* [not used right now] */
|
||||
|
||||
/* a progress indicator callback function (set to 0 to disable) */
|
||||
lzo_progress_func_t nprogress;
|
||||
|
||||
/* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
|
||||
* callbacks points back to this struct, so you are free to store
|
||||
* some extra info in the following variables. */
|
||||
lzo_voidp user1;
|
||||
lzo_xint user2;
|
||||
lzo_xint user3;
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// error codes and prototypes
|
||||
************************************************************************/
|
||||
|
||||
/* Error codes for the compression/decompression functions. Negative
|
||||
* values are errors, positive values will be used for special but
|
||||
* normal events.
|
||||
*/
|
||||
#define LZO_E_OK 0
|
||||
#define LZO_E_ERROR (-1)
|
||||
#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
|
||||
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
|
||||
#define LZO_E_INPUT_OVERRUN (-4)
|
||||
#define LZO_E_OUTPUT_OVERRUN (-5)
|
||||
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
|
||||
#define LZO_E_EOF_NOT_FOUND (-7)
|
||||
#define LZO_E_INPUT_NOT_CONSUMED (-8)
|
||||
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
|
||||
|
||||
|
||||
#ifndef lzo_sizeof_dict_t
|
||||
# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
|
||||
#endif
|
||||
|
||||
/* lzo_init() should be the first function you call.
|
||||
* Check the return code !
|
||||
*
|
||||
* lzo_init() is a macro to allow checking that the library and the
|
||||
* compiler's view of various types are consistent.
|
||||
*/
|
||||
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
|
||||
(int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
|
||||
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
|
||||
(int)sizeof(lzo_callback_t))
|
||||
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
|
||||
|
||||
/* version functions (useful for shared libraries) */
|
||||
LZO_EXTERN(unsigned) lzo_version(void);
|
||||
LZO_EXTERN(const char *) lzo_version_string(void);
|
||||
LZO_EXTERN(const char *) lzo_version_date(void);
|
||||
LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
|
||||
LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
|
||||
|
||||
/* string functions */
|
||||
LZO_EXTERN(int)
|
||||
lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
|
||||
|
||||
/* checksum functions */
|
||||
LZO_EXTERN(lzo_uint32)
|
||||
lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||
LZO_EXTERN(lzo_uint32)
|
||||
lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||
LZO_EXTERN(const lzo_uint32p)
|
||||
lzo_get_crc32_table(void);
|
||||
|
||||
/* misc. */
|
||||
LZO_EXTERN(int) _lzo_config_check(void);
|
||||
typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
|
||||
typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
|
||||
typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
|
||||
|
||||
/* align a char pointer on a boundary that is a multiple of 'size' */
|
||||
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
|
||||
#define LZO_PTR_ALIGN_UP(p,size) \
|
||||
((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// deprecated macros - only for backward compatibility with LZO v1.xx
|
||||
************************************************************************/
|
||||
|
||||
#if defined(LZO_CFG_COMPAT)
|
||||
|
||||
#define __LZOCONF_H 1
|
||||
|
||||
#if defined(LZO_ARCH_I086)
|
||||
# define __LZO_i386 1
|
||||
#elif defined(LZO_ARCH_I386)
|
||||
# define __LZO_i386 1
|
||||
#endif
|
||||
|
||||
#if defined(LZO_OS_DOS16)
|
||||
# define __LZO_DOS 1
|
||||
# define __LZO_DOS16 1
|
||||
#elif defined(LZO_OS_DOS32)
|
||||
# define __LZO_DOS 1
|
||||
#elif defined(LZO_OS_WIN16)
|
||||
# define __LZO_WIN 1
|
||||
# define __LZO_WIN16 1
|
||||
#elif defined(LZO_OS_WIN32)
|
||||
# define __LZO_WIN 1
|
||||
#endif
|
||||
|
||||
#define __LZO_CMODEL /*empty*/
|
||||
#define __LZO_DMODEL /*empty*/
|
||||
#define __LZO_ENTRY __LZO_CDECL
|
||||
#define LZO_EXTERN_CDECL LZO_EXTERN
|
||||
#define LZO_ALIGN LZO_PTR_ALIGN_UP
|
||||
|
||||
#define lzo_compress_asm_t lzo_compress_t
|
||||
#define lzo_decompress_asm_t lzo_decompress_t
|
||||
|
||||
#endif /* LZO_CFG_COMPAT */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/* vim:set ts=4 et: */
|
||||
1181
libvncserver/main.c
@@ -1,108 +0,0 @@
|
||||
/* minilzo.h -- mini subset of the LZO real-time data compression library
|
||||
|
||||
This file is part of the LZO real-time data compression library.
|
||||
|
||||
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
The LZO library 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.
|
||||
|
||||
The LZO library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the LZO library; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* the full LZO package can be found at
|
||||
* http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MINILZO_H
|
||||
#define __MINILZO_H 1
|
||||
|
||||
#define MINILZO_VERSION 0x2040
|
||||
|
||||
#ifdef __LZOCONF_H
|
||||
# error "you cannot use both LZO and miniLZO"
|
||||
#endif
|
||||
|
||||
#undef LZO_HAVE_CONFIG_H
|
||||
#include "lzoconf.h"
|
||||
|
||||
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
|
||||
# error "version mismatch in header files"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
//
|
||||
************************************************************************/
|
||||
|
||||
/* Memory required for the wrkmem parameter.
|
||||
* When the required size is 0, you can also pass a NULL pointer.
|
||||
*/
|
||||
|
||||
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
|
||||
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
|
||||
#define LZO1X_MEM_DECOMPRESS (0)
|
||||
|
||||
|
||||
/* compression */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
/* decompression */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem /* NOT USED */ );
|
||||
|
||||
/* safe decompression with overrun testing */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem /* NOT USED */ );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef RFB_PRIVATE_H
|
||||
#define RFB_PRIVATE_H
|
||||
|
||||
/* from cursor.c */
|
||||
|
||||
void rfbShowCursor(rfbClientPtr cl);
|
||||
void rfbHideCursor(rfbClientPtr cl);
|
||||
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion);
|
||||
|
||||
/* from main.c */
|
||||
|
||||
rfbClientPtr rfbClientIteratorHead(rfbClientIteratorPtr i);
|
||||
|
||||
/* from tight.c */
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
|
||||
extern void rfbTightCleanup(rfbScreenInfoPtr screen);
|
||||
#endif
|
||||
|
||||
/* from zlib.c */
|
||||
extern void rfbZlibCleanup(rfbScreenInfoPtr screen);
|
||||
|
||||
/* from zrle.c */
|
||||
void rfbFreeZrleData(rfbClientPtr cl);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* from ultra.c */
|
||||
|
||||
extern void rfbFreeUltraData(rfbClientPtr cl);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
static unsigned char default8x16FontData[4096+1]={
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00,
|
||||
0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,
|
||||
0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,
|
||||
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00,
|
||||
0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00,
|
||||
0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00,
|
||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
|
||||
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||
0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
|
||||
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
static int default8x16FontMetaData[256*5+1]={
|
||||
0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,};
|
||||
static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData };
|
||||
@@ -1,430 +0,0 @@
|
||||
#ifndef RFBCLIENT_H
|
||||
#define RFBCLIENT_H
|
||||
|
||||
/**
|
||||
* @defgroup libvncclient_api LibVNCClient API Reference
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rfbclient.h
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "rfbproto.h"
|
||||
#include "keysym.h"
|
||||
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
#define rfbClientSwap16IfLE(s) \
|
||||
(*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
|
||||
|
||||
#define rfbClientSwap32IfLE(l) \
|
||||
(*(char *)&client->endianTest ? ((((l) & 0xff000000) >> 24) | \
|
||||
(((l) & 0x00ff0000) >> 8) | \
|
||||
(((l) & 0x0000ff00) << 8) | \
|
||||
(((l) & 0x000000ff) << 24)) : (l))
|
||||
|
||||
#define rfbClientSwap64IfLE(l) \
|
||||
(*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \
|
||||
(((l) & 0x00ff000000000000ULL) >> 40) | \
|
||||
(((l) & 0x0000ff0000000000ULL) >> 24) | \
|
||||
(((l) & 0x000000ff00000000ULL) >> 8) | \
|
||||
(((l) & 0x00000000ff000000ULL) << 8) | \
|
||||
(((l) & 0x0000000000ff0000ULL) << 24) | \
|
||||
(((l) & 0x000000000000ff00ULL) << 40) | \
|
||||
(((l) & 0x00000000000000ffULL) << 56)) : (l))
|
||||
|
||||
#define FLASH_PORT_OFFSET 5400
|
||||
#define LISTEN_PORT_OFFSET 5500
|
||||
#define TUNNEL_PORT_OFFSET 5500
|
||||
#define SERVER_PORT_OFFSET 5900
|
||||
|
||||
#define DEFAULT_SSH_CMD "/usr/bin/ssh"
|
||||
#define DEFAULT_TUNNEL_CMD \
|
||||
(DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20")
|
||||
#define DEFAULT_VIA_CMD \
|
||||
(DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20")
|
||||
|
||||
#if(defined __cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** vncrec */
|
||||
|
||||
typedef struct {
|
||||
FILE* file;
|
||||
struct timeval tv;
|
||||
rfbBool readTimestamp;
|
||||
rfbBool doNotSleep;
|
||||
} rfbVNCRec;
|
||||
|
||||
/** client data */
|
||||
|
||||
typedef struct rfbClientData {
|
||||
void* tag;
|
||||
void* data;
|
||||
struct rfbClientData* next;
|
||||
} rfbClientData;
|
||||
|
||||
/** app data (belongs into rfbClient?) */
|
||||
|
||||
typedef struct {
|
||||
rfbBool shareDesktop;
|
||||
rfbBool viewOnly;
|
||||
|
||||
const char* encodingsString;
|
||||
|
||||
rfbBool useBGR233;
|
||||
int nColours;
|
||||
rfbBool forceOwnCmap;
|
||||
rfbBool forceTrueColour;
|
||||
int requestedDepth;
|
||||
|
||||
int compressLevel;
|
||||
int qualityLevel;
|
||||
rfbBool enableJPEG;
|
||||
rfbBool useRemoteCursor;
|
||||
rfbBool palmVNC; /**< use palmvnc specific SetScale (vs ultravnc) */
|
||||
int scaleSetting; /**< 0 means no scale set, else 1/scaleSetting */
|
||||
} AppData;
|
||||
|
||||
/** For GetCredentialProc callback function to return */
|
||||
typedef union _rfbCredential
|
||||
{
|
||||
/** X509 (VeNCrypt) */
|
||||
struct
|
||||
{
|
||||
char *x509CACertFile;
|
||||
char *x509CACrlFile;
|
||||
char *x509ClientCertFile;
|
||||
char *x509ClientKeyFile;
|
||||
} x509Credential;
|
||||
/** Plain (VeNCrypt), MSLogon (UltraVNC) */
|
||||
struct
|
||||
{
|
||||
char *username;
|
||||
char *password;
|
||||
} userCredential;
|
||||
} rfbCredential;
|
||||
|
||||
#define rfbCredentialTypeX509 1
|
||||
#define rfbCredentialTypeUser 2
|
||||
|
||||
struct _rfbClient;
|
||||
|
||||
typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text);
|
||||
typedef void (*HandleXvpMsgProc)(struct _rfbClient* client, uint8_t version, uint8_t opcode);
|
||||
typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad);
|
||||
typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y);
|
||||
typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h);
|
||||
typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client);
|
||||
typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h);
|
||||
typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client);
|
||||
typedef char* (*GetPasswordProc)(struct _rfbClient* client);
|
||||
typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType);
|
||||
typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client);
|
||||
typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen);
|
||||
typedef void (*BellProc)(struct _rfbClient* client);
|
||||
|
||||
typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel);
|
||||
typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y);
|
||||
|
||||
typedef struct _rfbClient {
|
||||
uint8_t* frameBuffer;
|
||||
int width, height;
|
||||
|
||||
int endianTest;
|
||||
|
||||
AppData appData;
|
||||
|
||||
const char* programName;
|
||||
char* serverHost;
|
||||
int serverPort; /**< if -1, then use file recorded by vncrec */
|
||||
rfbBool listenSpecified;
|
||||
int listenPort, flashPort;
|
||||
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
} updateRect;
|
||||
|
||||
/** Note that the CoRRE encoding uses this buffer and assumes it is big enough
|
||||
to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes.
|
||||
Hextile also assumes it is big enough to hold 16 * 16 * 32 bits.
|
||||
Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */
|
||||
|
||||
#define RFB_BUFFER_SIZE (640*480)
|
||||
char buffer[RFB_BUFFER_SIZE];
|
||||
|
||||
/* rfbproto.c */
|
||||
|
||||
int sock;
|
||||
rfbBool canUseCoRRE;
|
||||
rfbBool canUseHextile;
|
||||
char *desktopName;
|
||||
rfbPixelFormat format;
|
||||
rfbServerInitMsg si;
|
||||
|
||||
/* listen.c */
|
||||
int listenSock;
|
||||
|
||||
/* sockets.c */
|
||||
#define RFB_BUF_SIZE 8192
|
||||
char buf[RFB_BUF_SIZE];
|
||||
char *bufoutptr;
|
||||
int buffered;
|
||||
|
||||
/* The zlib encoding requires expansion/decompression/deflation of the
|
||||
compressed data in the "buffer" above into another, result buffer.
|
||||
However, the size of the result buffer can be determined precisely
|
||||
based on the bitsPerPixel, height and width of the rectangle. We
|
||||
allocate this buffer one time to be the full size of the buffer. */
|
||||
|
||||
/* Ultra Encoding uses this buffer too */
|
||||
|
||||
int ultra_buffer_size;
|
||||
char *ultra_buffer;
|
||||
|
||||
int raw_buffer_size;
|
||||
char *raw_buffer;
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
z_stream decompStream;
|
||||
rfbBool decompStreamInited;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
/*
|
||||
* Variables for the ``tight'' encoding implementation.
|
||||
*/
|
||||
|
||||
/** Separate buffer for compressed data. */
|
||||
#define ZLIB_BUFFER_SIZE 30000
|
||||
char zlib_buffer[ZLIB_BUFFER_SIZE];
|
||||
|
||||
/* Four independent compression streams for zlib library. */
|
||||
z_stream zlibStream[4];
|
||||
rfbBool zlibStreamActive[4];
|
||||
|
||||
/* Filter stuff. Should be initialized by filter initialization code. */
|
||||
rfbBool cutZeros;
|
||||
int rectWidth, rectColors;
|
||||
char tightPalette[256*4];
|
||||
uint8_t tightPrevRow[2048*3*sizeof(uint16_t)];
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
|
||||
/** JPEG decoder state. */
|
||||
rfbBool jpegError;
|
||||
|
||||
struct jpeg_source_mgr* jpegSrcManager;
|
||||
void* jpegBufferPtr;
|
||||
size_t jpegBufferLen;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* cursor.c */
|
||||
uint8_t *rcSource, *rcMask;
|
||||
|
||||
/** private data pointer */
|
||||
rfbClientData* clientData;
|
||||
|
||||
rfbVNCRec* vncRec;
|
||||
|
||||
/* Keyboard State support (is 'Caps Lock' set on the remote display???) */
|
||||
int KeyboardLedStateEnabled;
|
||||
int CurrentKeyboardLedState;
|
||||
|
||||
int canHandleNewFBSize;
|
||||
|
||||
/* hooks */
|
||||
HandleTextChatProc HandleTextChat;
|
||||
HandleKeyboardLedStateProc HandleKeyboardLedState;
|
||||
HandleCursorPosProc HandleCursorPos;
|
||||
SoftCursorLockAreaProc SoftCursorLockArea;
|
||||
SoftCursorUnlockScreenProc SoftCursorUnlockScreen;
|
||||
GotFrameBufferUpdateProc GotFrameBufferUpdate;
|
||||
FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate;
|
||||
/** the pointer returned by GetPassword will be freed after use! */
|
||||
GetPasswordProc GetPassword;
|
||||
MallocFrameBufferProc MallocFrameBuffer;
|
||||
GotXCutTextProc GotXCutText;
|
||||
BellProc Bell;
|
||||
|
||||
GotCursorShapeProc GotCursorShape;
|
||||
GotCopyRectProc GotCopyRect;
|
||||
|
||||
/** Which messages are supported by the server
|
||||
* This is a *guess* for most servers.
|
||||
* (If we can even detect the type of server)
|
||||
*
|
||||
* If the server supports the "rfbEncodingSupportedMessages"
|
||||
* then this will be updated when the encoding is received to
|
||||
* accurately reflect the servers capabilities.
|
||||
*/
|
||||
rfbSupportedMessages supportedMessages;
|
||||
|
||||
/** negotiated protocol version */
|
||||
int major, minor;
|
||||
|
||||
/** The selected security types */
|
||||
uint32_t authScheme, subAuthScheme;
|
||||
|
||||
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
|
||||
/** The TLS session for Anonymous TLS and VeNCrypt */
|
||||
gnutls_session_t tlsSession;
|
||||
#endif
|
||||
|
||||
/** To support security types that requires user input (except VNC password
|
||||
* authentication), for example VeNCrypt and MSLogon, this callback function
|
||||
* must be set before the authentication. Otherwise, it implicates that the
|
||||
* caller application does not support it and related security types should
|
||||
* be bypassed.
|
||||
*/
|
||||
GetCredentialProc GetCredential;
|
||||
|
||||
/** The 0-terminated security types supported by the client.
|
||||
* Set by function SetClientAuthSchemes() */
|
||||
uint32_t *clientAuthSchemes;
|
||||
|
||||
/** When the server is a repeater, this specifies the final destination */
|
||||
char *destHost;
|
||||
int destPort;
|
||||
|
||||
/** the QoS IP DSCP for this client */
|
||||
int QoS_DSCP;
|
||||
|
||||
/** hook to handle xvp server messages */
|
||||
HandleXvpMsgProc HandleXvpMsg;
|
||||
} rfbClient;
|
||||
|
||||
/* cursor.c */
|
||||
|
||||
extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc);
|
||||
|
||||
/* listen.c */
|
||||
|
||||
extern void listenForIncomingConnections(rfbClient* viewer);
|
||||
extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout);
|
||||
|
||||
/* rfbproto.c */
|
||||
|
||||
extern rfbBool rfbEnableClientLogging;
|
||||
typedef void (*rfbClientLogProc)(const char *format, ...);
|
||||
extern rfbClientLogProc rfbClientLog,rfbClientErr;
|
||||
extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port);
|
||||
extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort);
|
||||
extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size);
|
||||
extern rfbBool InitialiseRFBConnection(rfbClient* client);
|
||||
extern rfbBool SetFormatAndEncodings(rfbClient* client);
|
||||
extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client);
|
||||
extern rfbBool SendFramebufferUpdateRequest(rfbClient* client,
|
||||
int x, int y, int w, int h,
|
||||
rfbBool incremental);
|
||||
extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting);
|
||||
extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask);
|
||||
extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down);
|
||||
extern rfbBool SendClientCutText(rfbClient* client,char *str, int len);
|
||||
extern rfbBool HandleRFBServerMessage(rfbClient* client);
|
||||
|
||||
extern rfbBool TextChatSend(rfbClient* client, char *text);
|
||||
extern rfbBool TextChatOpen(rfbClient* client);
|
||||
extern rfbBool TextChatClose(rfbClient* client);
|
||||
extern rfbBool TextChatFinish(rfbClient* client);
|
||||
extern rfbBool PermitServerInput(rfbClient* client, int enabled);
|
||||
extern rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code);
|
||||
|
||||
extern void PrintPixelFormat(rfbPixelFormat *format);
|
||||
|
||||
extern rfbBool SupportsClient2Server(rfbClient* client, int messageType);
|
||||
extern rfbBool SupportsServer2Client(rfbClient* client, int messageType);
|
||||
|
||||
/* client data */
|
||||
|
||||
void rfbClientSetClientData(rfbClient* client, void* tag, void* data);
|
||||
void* rfbClientGetClientData(rfbClient* client, void* tag);
|
||||
|
||||
/* protocol extensions */
|
||||
|
||||
typedef struct _rfbClientProtocolExtension {
|
||||
int* encodings;
|
||||
/** returns TRUE if the encoding was handled */
|
||||
rfbBool (*handleEncoding)(rfbClient* cl,
|
||||
rfbFramebufferUpdateRectHeader* rect);
|
||||
/** returns TRUE if it handled the message */
|
||||
rfbBool (*handleMessage)(rfbClient* cl,
|
||||
rfbServerToClientMsg* message);
|
||||
struct _rfbClientProtocolExtension* next;
|
||||
} rfbClientProtocolExtension;
|
||||
|
||||
void rfbClientRegisterExtension(rfbClientProtocolExtension* e);
|
||||
|
||||
/* sockets.c */
|
||||
|
||||
extern rfbBool errorMessageOnReadFailure;
|
||||
|
||||
extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n);
|
||||
extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n);
|
||||
extern int FindFreeTcpPort(void);
|
||||
extern int ListenAtTcpPort(int port);
|
||||
extern int ConnectClientToTcpAddr(unsigned int host, int port);
|
||||
extern int ConnectClientToTcpAddr6(const char *hostname, int port);
|
||||
extern int ConnectClientToUnixSock(const char *sockFile);
|
||||
extern int AcceptTcpConnection(int listenSock);
|
||||
extern rfbBool SetNonBlocking(int sock);
|
||||
extern rfbBool SetDSCP(int sock, int dscp);
|
||||
|
||||
extern rfbBool StringToIPAddr(const char *str, unsigned int *addr);
|
||||
extern rfbBool SameMachine(int sock);
|
||||
extern int WaitForMessage(rfbClient* client,unsigned int usecs);
|
||||
|
||||
/* vncviewer.c */
|
||||
rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel);
|
||||
rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv);
|
||||
/** rfbClientCleanup() does not touch client->frameBuffer */
|
||||
void rfbClientCleanup(rfbClient* client);
|
||||
|
||||
#if(defined __cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
@page libvncclient_doc LibVNCClient Documentation
|
||||
@section example_code Example Code
|
||||
See SDLvncviewer.c for a rather complete client example.
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef SRAREGION_H
|
||||
#define SRAREGION_H
|
||||
|
||||
/* -=- SRA - Simple Region Algorithm
|
||||
* A simple rectangular region implementation.
|
||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
||||
*/
|
||||
|
||||
/* -=- sraRect */
|
||||
|
||||
typedef struct _rect {
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
} sraRect;
|
||||
|
||||
typedef struct sraRegion sraRegion;
|
||||
|
||||
/* -=- Region manipulation functions */
|
||||
|
||||
extern sraRegion *sraRgnCreate();
|
||||
extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2);
|
||||
extern sraRegion *sraRgnCreateRgn(const sraRegion *src);
|
||||
|
||||
extern void sraRgnDestroy(sraRegion *rgn);
|
||||
extern void sraRgnMakeEmpty(sraRegion *rgn);
|
||||
extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src);
|
||||
extern void sraRgnOr(sraRegion *dst, const sraRegion *src);
|
||||
extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src);
|
||||
|
||||
extern void sraRgnOffset(sraRegion *dst, int dx, int dy);
|
||||
|
||||
extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect,
|
||||
unsigned long flags);
|
||||
|
||||
extern unsigned long sraRgnCountRects(const sraRegion *rgn);
|
||||
extern rfbBool sraRgnEmpty(const sraRegion *rgn);
|
||||
|
||||
extern sraRegion *sraRgnBBox(const sraRegion *src);
|
||||
|
||||
/* -=- rectangle iterator */
|
||||
|
||||
typedef struct sraRectangleIterator {
|
||||
rfbBool reverseX,reverseY;
|
||||
int ptrSize,ptrPos;
|
||||
struct sraSpan** sPtrs;
|
||||
} sraRectangleIterator;
|
||||
|
||||
extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s);
|
||||
extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY);
|
||||
extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r);
|
||||
extern void sraRgnReleaseIterator(sraRectangleIterator *i);
|
||||
|
||||
void sraRgnPrint(const sraRegion *s);
|
||||
|
||||
/* -=- Rectangle clipper (for speed) */
|
||||
|
||||
extern rfbBool sraClipRect(int *x, int *y, int *w, int *h,
|
||||
int cx, int cy, int cw, int ch);
|
||||
|
||||
extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2,
|
||||
int cx, int cy, int cx2, int cy2);
|
||||
|
||||
#endif
|
||||
@@ -1,886 +0,0 @@
|
||||
/* -=- sraRegion.c
|
||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
||||
*
|
||||
* A general purpose region clipping library
|
||||
* Only deals with rectangular regions, though.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
|
||||
/* -=- Internal Span structure */
|
||||
|
||||
struct sraRegion;
|
||||
|
||||
typedef struct sraSpan {
|
||||
struct sraSpan *_next;
|
||||
struct sraSpan *_prev;
|
||||
int start;
|
||||
int end;
|
||||
struct sraRegion *subspan;
|
||||
} sraSpan;
|
||||
|
||||
typedef struct sraRegion {
|
||||
sraSpan front;
|
||||
sraSpan back;
|
||||
} sraSpanList;
|
||||
|
||||
/* -=- Span routines */
|
||||
|
||||
sraSpanList *sraSpanListDup(const sraSpanList *src);
|
||||
void sraSpanListDestroy(sraSpanList *list);
|
||||
|
||||
static sraSpan *
|
||||
sraSpanCreate(int start, int end, const sraSpanList *subspan) {
|
||||
sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
|
||||
item->_next = item->_prev = NULL;
|
||||
item->start = start;
|
||||
item->end = end;
|
||||
item->subspan = sraSpanListDup(subspan);
|
||||
return item;
|
||||
}
|
||||
|
||||
static sraSpan *
|
||||
sraSpanDup(const sraSpan *src) {
|
||||
sraSpan *span;
|
||||
if (!src) return NULL;
|
||||
span = sraSpanCreate(src->start, src->end, src->subspan);
|
||||
return span;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
|
||||
newspan->_next = after->_next;
|
||||
newspan->_prev = after;
|
||||
after->_next->_prev = newspan;
|
||||
after->_next = newspan;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
|
||||
newspan->_next = before;
|
||||
newspan->_prev = before->_prev;
|
||||
before->_prev->_next = newspan;
|
||||
before->_prev = newspan;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanRemove(sraSpan *span) {
|
||||
span->_prev->_next = span->_next;
|
||||
span->_next->_prev = span->_prev;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanDestroy(sraSpan *span) {
|
||||
if (span->subspan) sraSpanListDestroy(span->subspan);
|
||||
free(span);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
sraSpanCheck(const sraSpan *span, const char *text) {
|
||||
/* Check the span is valid! */
|
||||
if (span->start == span->end) {
|
||||
printf(text);
|
||||
printf(":%d-%d\n", span->start, span->end);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -=- SpanList routines */
|
||||
|
||||
static void sraSpanPrint(const sraSpan *s);
|
||||
|
||||
static void
|
||||
sraSpanListPrint(const sraSpanList *l) {
|
||||
sraSpan *curr;
|
||||
if (!l) {
|
||||
printf("NULL");
|
||||
return;
|
||||
}
|
||||
curr = l->front._next;
|
||||
printf("[");
|
||||
while (curr != &(l->back)) {
|
||||
sraSpanPrint(curr);
|
||||
curr = curr->_next;
|
||||
}
|
||||
printf("]");
|
||||
}
|
||||
|
||||
void
|
||||
sraSpanPrint(const sraSpan *s) {
|
||||
printf("(%d-%d)", (s->start), (s->end));
|
||||
if (s->subspan)
|
||||
sraSpanListPrint(s->subspan);
|
||||
}
|
||||
|
||||
static sraSpanList *
|
||||
sraSpanListCreate(void) {
|
||||
sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
|
||||
item->front._next = &(item->back);
|
||||
item->front._prev = NULL;
|
||||
item->back._prev = &(item->front);
|
||||
item->back._next = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
sraSpanList *
|
||||
sraSpanListDup(const sraSpanList *src) {
|
||||
sraSpanList *newlist;
|
||||
sraSpan *newspan, *curr;
|
||||
|
||||
if (!src) return NULL;
|
||||
newlist = sraSpanListCreate();
|
||||
curr = src->front._next;
|
||||
while (curr != &(src->back)) {
|
||||
newspan = sraSpanDup(curr);
|
||||
sraSpanInsertBefore(newspan, &(newlist->back));
|
||||
curr = curr->_next;
|
||||
}
|
||||
|
||||
return newlist;
|
||||
}
|
||||
|
||||
void
|
||||
sraSpanListDestroy(sraSpanList *list) {
|
||||
sraSpan *curr, *next;
|
||||
while (list->front._next != &(list->back)) {
|
||||
curr = list->front._next;
|
||||
next = curr->_next;
|
||||
sraSpanRemove(curr);
|
||||
sraSpanDestroy(curr);
|
||||
curr = next;
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanListMakeEmpty(sraSpanList *list) {
|
||||
sraSpan *curr, *next;
|
||||
while (list->front._next != &(list->back)) {
|
||||
curr = list->front._next;
|
||||
next = curr->_next;
|
||||
sraSpanRemove(curr);
|
||||
sraSpanDestroy(curr);
|
||||
curr = next;
|
||||
}
|
||||
list->front._next = &(list->back);
|
||||
list->front._prev = NULL;
|
||||
list->back._prev = &(list->front);
|
||||
list->back._next = NULL;
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
|
||||
sraSpan *sp1, *sp2;
|
||||
|
||||
if (!s1) {
|
||||
if (!s2) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
sp1 = s1->front._next;
|
||||
sp2 = s2->front._next;
|
||||
while ((sp1 != &(s1->back)) &&
|
||||
(sp2 != &(s2->back))) {
|
||||
if ((sp1->start != sp2->start) ||
|
||||
(sp1->end != sp2->end) ||
|
||||
(!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
|
||||
return 0;
|
||||
}
|
||||
sp1 = sp1->_next;
|
||||
sp2 = sp2->_next;
|
||||
}
|
||||
|
||||
if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListEmpty(const sraSpanList *list) {
|
||||
return (list->front._next == &(list->back));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sraSpanListCount(const sraSpanList *list) {
|
||||
sraSpan *curr = list->front._next;
|
||||
unsigned long count = 0;
|
||||
while (curr != &(list->back)) {
|
||||
if (curr->subspan) {
|
||||
count += sraSpanListCount(curr->subspan);
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
curr = curr->_next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanMergePrevious(sraSpan *dest) {
|
||||
sraSpan *prev = dest->_prev;
|
||||
|
||||
while ((prev->_prev) &&
|
||||
(prev->end == dest->start) &&
|
||||
(sraSpanListEqual(prev->subspan, dest->subspan))) {
|
||||
/*
|
||||
printf("merge_prev:");
|
||||
sraSpanPrint(prev);
|
||||
printf(" & ");
|
||||
sraSpanPrint(dest);
|
||||
printf("\n");
|
||||
*/
|
||||
dest->start = prev->start;
|
||||
sraSpanRemove(prev);
|
||||
sraSpanDestroy(prev);
|
||||
prev = dest->_prev;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanMergeNext(sraSpan *dest) {
|
||||
sraSpan *next = dest->_next;
|
||||
while ((next->_next) &&
|
||||
(next->start == dest->end) &&
|
||||
(sraSpanListEqual(next->subspan, dest->subspan))) {
|
||||
/*
|
||||
printf("merge_next:");
|
||||
sraSpanPrint(dest);
|
||||
printf(" & ");
|
||||
sraSpanPrint(next);
|
||||
printf("\n");
|
||||
*/
|
||||
dest->end = next->end;
|
||||
sraSpanRemove(next);
|
||||
sraSpanDestroy(next);
|
||||
next = dest->_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr;
|
||||
int s_start, s_end;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return;
|
||||
} else {
|
||||
rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
while (s_curr != &(src->back)) {
|
||||
|
||||
/* - If we are at end of destination list OR
|
||||
If the new span comes before the next destination one */
|
||||
if ((d_curr == &(dest->back)) ||
|
||||
(d_curr->start >= s_end)) {
|
||||
/* - Add the span */
|
||||
sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
|
||||
s_curr->subspan),
|
||||
d_curr);
|
||||
if (d_curr != &(dest->back))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
s_curr = s_curr->_next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
} else {
|
||||
|
||||
/* - If the new span overlaps the existing one */
|
||||
if ((s_start < d_curr->end) &&
|
||||
(s_end > d_curr->start)) {
|
||||
|
||||
/* - Insert new span before the existing destination one? */
|
||||
if (s_start < d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(s_start,
|
||||
d_curr->start,
|
||||
s_curr->subspan),
|
||||
d_curr);
|
||||
sraSpanMergePrevious(d_curr);
|
||||
}
|
||||
|
||||
/* Split the existing span if necessary */
|
||||
if (s_end < d_curr->end) {
|
||||
sraSpanInsertAfter(sraSpanCreate(s_end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_end;
|
||||
}
|
||||
if (s_start > d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
||||
s_start,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->start = s_start;
|
||||
}
|
||||
|
||||
/* Recursively OR subspans */
|
||||
sraSpanListOr(d_curr->subspan, s_curr->subspan);
|
||||
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
if (d_curr->_next != &(dest->back))
|
||||
sraSpanMergeNext(d_curr);
|
||||
|
||||
/* Move onto the next pair to compare */
|
||||
if (s_end > d_curr->end) {
|
||||
s_start = d_curr->end;
|
||||
d_curr = d_curr->_next;
|
||||
} else {
|
||||
s_curr = s_curr->_next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
}
|
||||
} else {
|
||||
/* - No overlap. Move to the next destination span */
|
||||
d_curr = d_curr->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr, *d_next;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
||||
|
||||
/* - If we haven't reached a destination span yet then move on */
|
||||
if (d_curr->start >= s_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we are beyond the current destination span then remove it */
|
||||
if (d_curr->end <= s_curr->start) {
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we partially overlap a span then split it up or remove bits */
|
||||
if (s_curr->start > d_curr->start) {
|
||||
/* - The top bit of the span does not match */
|
||||
d_curr->start = s_curr->start;
|
||||
}
|
||||
if (s_curr->end < d_curr->end) {
|
||||
/* - The end of the span does not match */
|
||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_curr->end;
|
||||
}
|
||||
|
||||
/* - Now recursively process the affected span */
|
||||
if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
|
||||
/* - The destination subspan is now empty, so we should remove it */
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
} else {
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
|
||||
/* - Move on to the next span */
|
||||
d_next = d_curr;
|
||||
if (s_curr->end >= d_curr->end) {
|
||||
d_next = d_curr->_next;
|
||||
}
|
||||
if (s_curr->end <= d_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
}
|
||||
d_curr = d_next;
|
||||
}
|
||||
}
|
||||
|
||||
while (d_curr != &(dest->back)) {
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr=next;
|
||||
}
|
||||
|
||||
return !sraSpanListEmpty(dest);
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
||||
|
||||
/* - If we haven't reached a destination span yet then move on */
|
||||
if (d_curr->start >= s_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we are beyond the current destination span then skip it */
|
||||
if (d_curr->end <= s_curr->start) {
|
||||
d_curr = d_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we partially overlap the current span then split it up */
|
||||
if (s_curr->start > d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
||||
s_curr->start,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->start = s_curr->start;
|
||||
}
|
||||
if (s_curr->end < d_curr->end) {
|
||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_curr->end;
|
||||
}
|
||||
|
||||
/* - Now recursively process the affected span */
|
||||
if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
|
||||
/* - The destination subspan is now empty, so we should remove it */
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
} else {
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
if (d_curr->_next != &(dest->back))
|
||||
sraSpanMergeNext(d_curr);
|
||||
|
||||
/* - Move on to the next span */
|
||||
if (s_curr->end > d_curr->end) {
|
||||
d_curr = d_curr->_next;
|
||||
} else {
|
||||
s_curr = s_curr->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !sraSpanListEmpty(dest);
|
||||
}
|
||||
|
||||
/* -=- Region routines */
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreate(void) {
|
||||
return (sraRegion*)sraSpanListCreate();
|
||||
}
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreateRect(int x1, int y1, int x2, int y2) {
|
||||
sraSpanList *vlist, *hlist;
|
||||
sraSpan *vspan, *hspan;
|
||||
|
||||
/* - Build the horizontal portion of the span */
|
||||
hlist = sraSpanListCreate();
|
||||
hspan = sraSpanCreate(x1, x2, NULL);
|
||||
sraSpanInsertAfter(hspan, &(hlist->front));
|
||||
|
||||
/* - Build the vertical portion of the span */
|
||||
vlist = sraSpanListCreate();
|
||||
vspan = sraSpanCreate(y1, y2, hlist);
|
||||
sraSpanInsertAfter(vspan, &(vlist->front));
|
||||
|
||||
sraSpanListDestroy(hlist);
|
||||
|
||||
return (sraRegion*)vlist;
|
||||
}
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreateRgn(const sraRegion *src) {
|
||||
return (sraRegion*)sraSpanListDup((sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnDestroy(sraRegion *rgn) {
|
||||
sraSpanListDestroy((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnMakeEmpty(sraRegion *rgn) {
|
||||
sraSpanListMakeEmpty((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
/* -=- Boolean Region ops */
|
||||
|
||||
rfbBool
|
||||
sraRgnAnd(sraRegion *dst, const sraRegion *src) {
|
||||
return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnOr(sraRegion *dst, const sraRegion *src) {
|
||||
sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
|
||||
return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnOffset(sraRegion *dst, int dx, int dy) {
|
||||
sraSpan *vcurr, *hcurr;
|
||||
|
||||
vcurr = ((sraSpanList*)dst)->front._next;
|
||||
while (vcurr != &(((sraSpanList*)dst)->back)) {
|
||||
vcurr->start += dy;
|
||||
vcurr->end += dy;
|
||||
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
while (hcurr != &(vcurr->subspan->back)) {
|
||||
hcurr->start += dx;
|
||||
hcurr->end += dx;
|
||||
hcurr = hcurr->_next;
|
||||
}
|
||||
|
||||
vcurr = vcurr->_next;
|
||||
}
|
||||
}
|
||||
|
||||
sraRegion *sraRgnBBox(const sraRegion *src) {
|
||||
int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
|
||||
sraSpan *vcurr, *hcurr;
|
||||
|
||||
if(!src)
|
||||
return sraRgnCreate();
|
||||
|
||||
vcurr = ((sraSpanList*)src)->front._next;
|
||||
while (vcurr != &(((sraSpanList*)src)->back)) {
|
||||
if(vcurr->start<ymin)
|
||||
ymin=vcurr->start;
|
||||
if(vcurr->end>ymax)
|
||||
ymax=vcurr->end;
|
||||
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
while (hcurr != &(vcurr->subspan->back)) {
|
||||
if(hcurr->start<xmin)
|
||||
xmin=hcurr->start;
|
||||
if(hcurr->end>xmax)
|
||||
xmax=hcurr->end;
|
||||
hcurr = hcurr->_next;
|
||||
}
|
||||
|
||||
vcurr = vcurr->_next;
|
||||
}
|
||||
|
||||
if(xmax<xmin || ymax<ymin)
|
||||
return sraRgnCreate();
|
||||
|
||||
return sraRgnCreateRect(xmin,ymin,xmax,ymax);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
|
||||
sraSpan *vcurr, *hcurr;
|
||||
sraSpan *vend, *hend;
|
||||
rfbBool right2left = (flags & 2) == 2;
|
||||
rfbBool bottom2top = (flags & 1) == 1;
|
||||
|
||||
/* - Pick correct order */
|
||||
if (bottom2top) {
|
||||
vcurr = ((sraSpanList*)rgn)->back._prev;
|
||||
vend = &(((sraSpanList*)rgn)->front);
|
||||
} else {
|
||||
vcurr = ((sraSpanList*)rgn)->front._next;
|
||||
vend = &(((sraSpanList*)rgn)->back);
|
||||
}
|
||||
|
||||
if (vcurr != vend) {
|
||||
rect->y1 = vcurr->start;
|
||||
rect->y2 = vcurr->end;
|
||||
|
||||
/* - Pick correct order */
|
||||
if (right2left) {
|
||||
hcurr = vcurr->subspan->back._prev;
|
||||
hend = &(vcurr->subspan->front);
|
||||
} else {
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
hend = &(vcurr->subspan->back);
|
||||
}
|
||||
|
||||
if (hcurr != hend) {
|
||||
rect->x1 = hcurr->start;
|
||||
rect->x2 = hcurr->end;
|
||||
|
||||
sraSpanRemove(hcurr);
|
||||
sraSpanDestroy(hcurr);
|
||||
|
||||
if (sraSpanListEmpty(vcurr->subspan)) {
|
||||
sraSpanRemove(vcurr);
|
||||
sraSpanDestroy(vcurr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("poprect:(%dx%d)-(%dx%d)\n",
|
||||
rect->x1, rect->y1, rect->x2, rect->y2);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
sraRgnCountRects(const sraRegion *rgn) {
|
||||
unsigned long count = sraSpanListCount((sraSpanList*)rgn);
|
||||
return count;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnEmpty(const sraRegion *rgn) {
|
||||
return sraSpanListEmpty((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
/* iterator stuff */
|
||||
sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
|
||||
{
|
||||
/* these values have to be multiples of 4 */
|
||||
#define DEFSIZE 4
|
||||
#define DEFSTEP 8
|
||||
sraRectangleIterator *i =
|
||||
(sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
|
||||
if(!i)
|
||||
return NULL;
|
||||
|
||||
/* we have to recurse eventually. So, the first sPtr is the pointer to
|
||||
the sraSpan in the first level. the second sPtr is the pointer to
|
||||
the sraRegion.back. The third and fourth sPtr are for the second
|
||||
recursion level and so on. */
|
||||
i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
|
||||
if(!i->sPtrs) {
|
||||
free(i);
|
||||
return NULL;
|
||||
}
|
||||
i->ptrSize = DEFSIZE;
|
||||
i->sPtrs[0] = &(s->front);
|
||||
i->sPtrs[1] = &(s->back);
|
||||
i->ptrPos = 0;
|
||||
i->reverseX = 0;
|
||||
i->reverseY = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY)
|
||||
{
|
||||
sraRectangleIterator *i = sraRgnGetIterator(s);
|
||||
if(reverseY) {
|
||||
i->sPtrs[1] = &(s->front);
|
||||
i->sPtrs[0] = &(s->back);
|
||||
}
|
||||
i->reverseX = reverseX;
|
||||
i->reverseY = reverseY;
|
||||
return(i);
|
||||
}
|
||||
|
||||
static rfbBool sraReverse(sraRectangleIterator *i)
|
||||
{
|
||||
return( ((i->ptrPos&2) && i->reverseX) ||
|
||||
(!(i->ptrPos&2) && i->reverseY));
|
||||
}
|
||||
|
||||
static sraSpan* sraNextSpan(sraRectangleIterator *i)
|
||||
{
|
||||
if(sraReverse(i))
|
||||
return(i->sPtrs[i->ptrPos]->_prev);
|
||||
else
|
||||
return(i->sPtrs[i->ptrPos]->_next);
|
||||
}
|
||||
|
||||
rfbBool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
|
||||
{
|
||||
/* is the subspan finished? */
|
||||
while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
|
||||
i->ptrPos -= 2;
|
||||
if(i->ptrPos < 0) /* the end */
|
||||
return(0);
|
||||
}
|
||||
|
||||
i->sPtrs[i->ptrPos] = sraNextSpan(i);
|
||||
|
||||
/* is this a new subspan? */
|
||||
while(i->sPtrs[i->ptrPos]->subspan) {
|
||||
if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
|
||||
i->ptrSize += DEFSTEP;
|
||||
i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
|
||||
}
|
||||
i->ptrPos =+ 2;
|
||||
if(sraReverse(i)) {
|
||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
|
||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
|
||||
} else {
|
||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
|
||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
|
||||
}
|
||||
}
|
||||
|
||||
if((i->ptrPos%4)!=2) {
|
||||
rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r->y1 = i->sPtrs[i->ptrPos-2]->start;
|
||||
r->y2 = i->sPtrs[i->ptrPos-2]->end;
|
||||
r->x1 = i->sPtrs[i->ptrPos]->start;
|
||||
r->x2 = i->sPtrs[i->ptrPos]->end;
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void sraRgnReleaseIterator(sraRectangleIterator* i)
|
||||
{
|
||||
free(i->sPtrs);
|
||||
free(i);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnPrint(const sraRegion *rgn) {
|
||||
sraSpanListPrint((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraClipRect(int *x, int *y, int *w, int *h,
|
||||
int cx, int cy, int cw, int ch) {
|
||||
if (*x < cx) {
|
||||
*w -= (cx-*x);
|
||||
*x = cx;
|
||||
}
|
||||
if (*y < cy) {
|
||||
*h -= (cy-*y);
|
||||
*y = cy;
|
||||
}
|
||||
if (*x+*w > cx+cw) {
|
||||
*w = (cx+cw)-*x;
|
||||
}
|
||||
if (*y+*h > cy+ch) {
|
||||
*h = (cy+ch)-*y;
|
||||
}
|
||||
return (*w>0) && (*h>0);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraClipRect2(int *x, int *y, int *x2, int *y2,
|
||||
int cx, int cy, int cx2, int cy2) {
|
||||
if (*x < cx)
|
||||
*x = cx;
|
||||
if (*y < cy)
|
||||
*y = cy;
|
||||
if (*x >= cx2)
|
||||
*x = cx2-1;
|
||||
if (*y >= cy2)
|
||||
*y = cy2-1;
|
||||
if (*x2 <= cx)
|
||||
*x2 = cx+1;
|
||||
if (*y2 <= cy)
|
||||
*y2 = cy+1;
|
||||
if (*x2 > cx2)
|
||||
*x2 = cx2;
|
||||
if (*y2 > cy2)
|
||||
*y2 = cy2;
|
||||
return (*x2>*x) && (*y2>*y);
|
||||
}
|
||||
|
||||
/* test */
|
||||
|
||||
#ifdef SRA_TEST
|
||||
/* pipe the output to sort|uniq -u and you'll get the errors. */
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
sraRegionPtr region, region1, region2;
|
||||
sraRectangleIterator* i;
|
||||
sraRect rect;
|
||||
rfbBool b;
|
||||
|
||||
region = sraRgnCreateRect(10, 10, 600, 300);
|
||||
region1 = sraRgnCreateRect(40, 50, 350, 200);
|
||||
region2 = sraRgnCreateRect(0, 0, 20, 40);
|
||||
|
||||
sraRgnPrint(region);
|
||||
printf("\n[(10-300)[(10-600)]]\n\n");
|
||||
|
||||
b = sraRgnSubtract(region, region1);
|
||||
printf("%s ",b?"true":"false");
|
||||
sraRgnPrint(region);
|
||||
printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
|
||||
|
||||
sraRgnOr(region, region2);
|
||||
printf("%ld\n6\n\n", sraRgnCountRects(region));
|
||||
|
||||
i = sraRgnGetIterator(region);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
|
||||
|
||||
i = sraRgnGetReverseIterator(region,1,0);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
|
||||
|
||||
i = sraRgnGetReverseIterator(region,1,1);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
|
||||
|
||||
sraRgnDestroy(region);
|
||||
sraRgnDestroy(region1);
|
||||
sraRgnDestroy(region2);
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* rre.c
|
||||
*
|
||||
* Routines to implement Rise-and-Run-length Encoding (RRE). This
|
||||
* code is based on krw's original javatel rfbserver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the RRE encoded version. If the RRE encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
|
||||
static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
|
||||
static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
|
||||
static uint32_t getBgColour(char *data, int size, int bpp);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbRREHeader hdr;
|
||||
int nSubrects;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
if (cl->afterEncBufSize < maxRawSize) {
|
||||
cl->afterEncBufSize = maxRawSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
(*cl->translateFn)(cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat),
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 16:
|
||||
nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 32:
|
||||
nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
default:
|
||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nSubrects < 0) {
|
||||
|
||||
/* RRE encoding was too large, use raw */
|
||||
|
||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingRRE,
|
||||
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingRRE);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
||||
cl->ublen += sz_rfbRREHeader;
|
||||
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
||||
* colour overwritten by single-coloured rectangles. It returns the number
|
||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
||||
* fit in the buffer. It puts the encoded rectangles in cl->afterEncBuf. The
|
||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
||||
* coordinate position.
|
||||
*
|
||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
||||
* <subrect> is [<colour><x><y><w><h>].
|
||||
*/
|
||||
|
||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
||||
static int \
|
||||
subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
|
||||
uint##bpp##_t cl; \
|
||||
rfbRectangle subrect; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
|
||||
\
|
||||
*((uint##bpp##_t*)client->afterEncBuf) = bg; \
|
||||
\
|
||||
client->afterEncBufLen = (bpp/8); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
||||
* We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
subrect.x = Swap16IfLE(thex); \
|
||||
subrect.y = Swap16IfLE(they); \
|
||||
subrect.w = Swap16IfLE(thew); \
|
||||
subrect.h = Swap16IfLE(theh); \
|
||||
\
|
||||
newLen = client->afterEncBufLen + (bpp/8) + sz_rfbRectangle; \
|
||||
if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
|
||||
return -1; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
*((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
|
||||
client->afterEncBufLen += (bpp/8); \
|
||||
memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbRectangle); \
|
||||
client->afterEncBufLen += sz_rfbRectangle; \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return numsubs; \
|
||||
}
|
||||
|
||||
DEFINE_SUBRECT_ENCODE(8)
|
||||
DEFINE_SUBRECT_ENCODE(16)
|
||||
DEFINE_SUBRECT_ENCODE(32)
|
||||
|
||||
|
||||
/*
|
||||
* getBgColour() gets the most prevalent colour in a byte array.
|
||||
*/
|
||||
static uint32_t
|
||||
getBgColour(char *data, int size, int bpp)
|
||||
{
|
||||
|
||||
#define NUMCLRS 256
|
||||
|
||||
static int counts[NUMCLRS];
|
||||
int i,j,k;
|
||||
|
||||
int maxcount = 0;
|
||||
uint8_t maxclr = 0;
|
||||
|
||||
if (bpp != 8) {
|
||||
if (bpp == 16) {
|
||||
return ((uint16_t *)data)[0];
|
||||
} else if (bpp == 32) {
|
||||
return ((uint32_t *)data)[0];
|
||||
} else {
|
||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUMCLRS; i++) {
|
||||
counts[i] = 0;
|
||||
}
|
||||
|
||||
for (j=0; j<size; j++) {
|
||||
k = (int)(((uint8_t *)data)[j]);
|
||||
if (k >= NUMCLRS) {
|
||||
rfbErr("getBgColour: unusual colour = %d\n", k);
|
||||
return 0;
|
||||
}
|
||||
counts[k] += 1;
|
||||
if (counts[k] > maxcount) {
|
||||
maxcount = counts[k];
|
||||
maxclr = ((uint8_t *)data)[j];
|
||||
}
|
||||
}
|
||||
|
||||
return maxclr;
|
||||
}
|
||||
@@ -1,416 +0,0 @@
|
||||
/*
|
||||
* scale.c - deal with server-side scaling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
#include "private.h"
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define write(sock,buf,len) send(sock,buf,len,0)
|
||||
#else
|
||||
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGPROTO
|
||||
#undef DEBUGPROTO
|
||||
#define DEBUGPROTO(x) x
|
||||
#else
|
||||
#define DEBUGPROTO(x)
|
||||
#endif
|
||||
|
||||
/****************************/
|
||||
#define CEIL(x) ( (double) ((int) (x)) == (x) ? \
|
||||
(double) ((int) (x)) : (double) ((int) (x) + 1) )
|
||||
#define FLOOR(x) ( (double) ((int) (x)) )
|
||||
|
||||
|
||||
int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x)
|
||||
{
|
||||
if ((from==to) || (from==NULL) || (to==NULL)) return x;
|
||||
return ((int)(((double) x / (double)from->width) * (double)to->width ));
|
||||
}
|
||||
|
||||
int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y)
|
||||
{
|
||||
if ((from==to) || (from==NULL) || (to==NULL)) return y;
|
||||
return ((int)(((double) y / (double)from->height) * (double)to->height ));
|
||||
}
|
||||
|
||||
/* So, all of the encodings point to the ->screen->frameBuffer,
|
||||
* We need to change this!
|
||||
*/
|
||||
void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, const char *function)
|
||||
{
|
||||
double x1,y1,w1,h1, x2, y2, w2, h2;
|
||||
double scaleW = ((double) to->width) / ((double) from->width);
|
||||
double scaleH = ((double) to->height) / ((double) from->height);
|
||||
|
||||
|
||||
/*
|
||||
* rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n",
|
||||
* from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h);
|
||||
*/
|
||||
|
||||
/* If it's the original framebuffer... */
|
||||
if (from==to) return;
|
||||
|
||||
x1 = ((double) *x) * scaleW;
|
||||
y1 = ((double) *y) * scaleH;
|
||||
w1 = ((double) *w) * scaleW;
|
||||
h1 = ((double) *h) * scaleH;
|
||||
|
||||
|
||||
/*cast from double to int is same as "*x = floor(x1);" */
|
||||
x2 = FLOOR(x1);
|
||||
y2 = FLOOR(y1);
|
||||
|
||||
/* include into W and H the jitter of scaling X and Y */
|
||||
w2 = CEIL(w1 + ( x1 - x2 ));
|
||||
h2 = CEIL(h1 + ( y1 - y2 ));
|
||||
|
||||
/*
|
||||
* rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n",
|
||||
* function, *x, *y, *w, *h, x2, y2, w2, h2,
|
||||
* from->width, from->height, to->width, to->height);
|
||||
*/
|
||||
|
||||
/* simulate ceil() without math library */
|
||||
*x = (int)x2;
|
||||
*y = (int)y2;
|
||||
*w = (int)w2;
|
||||
*h = (int)h2;
|
||||
|
||||
/* Small changes for a thumbnail may be scaled to zero */
|
||||
if (*w==0) (*w)++;
|
||||
if (*h==0) (*h)++;
|
||||
/* scaling from small to big may overstep the size a bit */
|
||||
if (*x+*w > to->width) *w=to->width - *x;
|
||||
if (*y+*h > to->height) *h=to->height - *y;
|
||||
}
|
||||
|
||||
void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0)
|
||||
{
|
||||
int x,y,w,v,z;
|
||||
int x1, y1, w1, h1;
|
||||
int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2;
|
||||
unsigned char *srcptr, *dstptr;
|
||||
|
||||
/* Nothing to do!!! */
|
||||
if (screen==ptr) return;
|
||||
|
||||
x1 = x0;
|
||||
y1 = y0;
|
||||
w1 = w0;
|
||||
h1 = h0;
|
||||
|
||||
rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect");
|
||||
x0 = ScaleX(ptr, screen, x1);
|
||||
y0 = ScaleY(ptr, screen, y1);
|
||||
w0 = ScaleX(ptr, screen, w1);
|
||||
h0 = ScaleY(ptr, screen, h1);
|
||||
|
||||
bitsPerPixel = screen->bitsPerPixel;
|
||||
bytesPerPixel = bitsPerPixel / 8;
|
||||
bytesPerLine = w1 * bytesPerPixel;
|
||||
srcptr = (unsigned char *)(screen->frameBuffer +
|
||||
(y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel));
|
||||
dstptr = (unsigned char *)(ptr->frameBuffer +
|
||||
( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel));
|
||||
/* The area of the source framebuffer for each destination pixel */
|
||||
areaX = ScaleX(ptr,screen,1);
|
||||
areaY = ScaleY(ptr,screen,1);
|
||||
area2 = areaX*areaY;
|
||||
|
||||
|
||||
/* Ensure that we do not go out of bounds */
|
||||
if ((x1+w1) > (ptr->width))
|
||||
{
|
||||
if (x1==0) w1=ptr->width; else x1 = ptr->width - w1;
|
||||
}
|
||||
if ((y1+h1) > (ptr->height))
|
||||
{
|
||||
if (y1==0) h1=ptr->height; else y1 = ptr->height - h1;
|
||||
}
|
||||
/*
|
||||
* rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n",
|
||||
* x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY,
|
||||
* screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer);
|
||||
*/
|
||||
|
||||
if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */
|
||||
unsigned char *srcptr2;
|
||||
unsigned long pixel_value, red, green, blue;
|
||||
unsigned int redShift = screen->serverFormat.redShift;
|
||||
unsigned int greenShift = screen->serverFormat.greenShift;
|
||||
unsigned int blueShift = screen->serverFormat.blueShift;
|
||||
unsigned long redMax = screen->serverFormat.redMax;
|
||||
unsigned long greenMax = screen->serverFormat.greenMax;
|
||||
unsigned long blueMax = screen->serverFormat.blueMax;
|
||||
|
||||
/* for each *destination* pixel... */
|
||||
for (y = 0; y < h1; y++) {
|
||||
for (x = 0; x < w1; x++) {
|
||||
red = green = blue = 0;
|
||||
/* Get the totals for rgb from the source grid... */
|
||||
for (w = 0; w < areaX; w++) {
|
||||
for (v = 0; v < areaY; v++) {
|
||||
srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) +
|
||||
(v * screen->paddedWidthInBytes)];
|
||||
pixel_value = 0;
|
||||
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 4: pixel_value = *((unsigned int *)srcptr2); break;
|
||||
case 2: pixel_value = *((unsigned short *)srcptr2); break;
|
||||
case 1: pixel_value = *((unsigned char *)srcptr2); break;
|
||||
default:
|
||||
/* fixme: endianess problem? */
|
||||
for (z = 0; z < bytesPerPixel; z++)
|
||||
pixel_value += (srcptr2[z] << (8 * z));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
srcptr2 += bytesPerPixel;
|
||||
*/
|
||||
|
||||
red += ((pixel_value >> redShift) & redMax);
|
||||
green += ((pixel_value >> greenShift) & greenMax);
|
||||
blue += ((pixel_value >> blueShift) & blueMax);
|
||||
|
||||
}
|
||||
}
|
||||
/* We now have a total for all of the colors, find the average! */
|
||||
red /= area2;
|
||||
green /= area2;
|
||||
blue /= area2;
|
||||
/* Stuff the new value back into memory */
|
||||
pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift);
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break;
|
||||
case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break;
|
||||
case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break;
|
||||
default:
|
||||
/* fixme: endianess problem? */
|
||||
for (z = 0; z < bytesPerPixel; z++)
|
||||
dstptr[z]=(pixel_value >> (8 * z)) & 0xff;
|
||||
break;
|
||||
}
|
||||
dstptr += bytesPerPixel;
|
||||
}
|
||||
srcptr += (screen->paddedWidthInBytes * areaY);
|
||||
dstptr += (ptr->paddedWidthInBytes - bytesPerLine);
|
||||
}
|
||||
} else
|
||||
{ /* Not truecolour, so we can't blend. Just use the top-left pixel instead */
|
||||
for (y = y1; y < (y1+h1); y++) {
|
||||
for (x = x1; x < (x1+w1); x++)
|
||||
memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)],
|
||||
&screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
/* ok, now the task is to update each and every scaled version of the framebuffer
|
||||
* and we only have to do this for this specific changed rectangle!
|
||||
*/
|
||||
rfbScreenInfoPtr ptr;
|
||||
int count=0;
|
||||
|
||||
/* We don't point to cl->screen as it is the original */
|
||||
for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext)
|
||||
{
|
||||
/* Only update if it has active clients... */
|
||||
if (ptr->scaledScreenRefCount>0)
|
||||
{
|
||||
rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new scaled version of the framebuffer */
|
||||
rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
ptr = malloc(sizeof(rfbScreenInfo));
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
/* copy *everything* (we don't use most of it, but just in case) */
|
||||
memcpy(ptr, cl->screen, sizeof(rfbScreenInfo));
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width;
|
||||
|
||||
/* Need to by multiples of 4 for Sparc systems */
|
||||
ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4);
|
||||
|
||||
/* Reset the reference count to 0! */
|
||||
ptr->scaledScreenRefCount = 0;
|
||||
|
||||
ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height;
|
||||
ptr->serverFormat = cl->screen->serverFormat;
|
||||
|
||||
ptr->frameBuffer = malloc(ptr->sizeInBytes);
|
||||
if (ptr->frameBuffer!=NULL)
|
||||
{
|
||||
/* Reset to a known condition: scale the entire framebuffer */
|
||||
rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height);
|
||||
/* Now, insert into the chain */
|
||||
LOCK(cl->updateMutex);
|
||||
ptr->scaledScreenNext = cl->screen->scaledScreenNext;
|
||||
cl->screen->scaledScreenNext = ptr;
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to malloc the new frameBuffer, cleanup */
|
||||
free(ptr);
|
||||
ptr=NULL;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Find an active scaled version of the framebuffer
|
||||
* TODO: implement a refcount per scaled screen to prevent
|
||||
* unreferenced scaled screens from hanging around
|
||||
*/
|
||||
rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
/* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */
|
||||
for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext)
|
||||
{
|
||||
if ((ptr->width==width) && (ptr->height==height))
|
||||
return ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Future needs "scale to 320x240, as that's the client's screen size */
|
||||
void rfbScalingSetup(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
|
||||
ptr = rfbScalingFind(cl,width,height);
|
||||
if (ptr==NULL)
|
||||
ptr = rfbScaledScreenAllocate(cl,width,height);
|
||||
/* Now, there is a new screen available (if ptr is not NULL) */
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
/* Update it! */
|
||||
if (ptr->scaledScreenRefCount<1)
|
||||
rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height);
|
||||
/*
|
||||
* rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n",
|
||||
* cl->scaledScreen->width, cl->scaledScreen->height,
|
||||
* cl->scaledScreen->scaledScreenRefCount,
|
||||
* ptr->width, ptr->height, ptr->scaledScreenRefCount);
|
||||
*/
|
||||
|
||||
LOCK(cl->updateMutex);
|
||||
cl->scaledScreen->scaledScreenRefCount--;
|
||||
ptr->scaledScreenRefCount++;
|
||||
cl->scaledScreen=ptr;
|
||||
cl->newFBSizePending = TRUE;
|
||||
UNLOCK(cl->updateMutex);
|
||||
|
||||
rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount);
|
||||
}
|
||||
else
|
||||
rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height);
|
||||
}
|
||||
|
||||
int rfbSendNewScaleSize(rfbClientPtr cl)
|
||||
{
|
||||
/* if the client supports newFBsize Encoding, use it */
|
||||
if (cl->useNewFBSize && cl->newFBSizePending)
|
||||
return FALSE;
|
||||
|
||||
LOCK(cl->updateMutex);
|
||||
cl->newFBSizePending = FALSE;
|
||||
UNLOCK(cl->updateMutex);
|
||||
|
||||
if (cl->PalmVNC==TRUE)
|
||||
{
|
||||
rfbPalmVNCReSizeFrameBufferMsg pmsg;
|
||||
pmsg.type = rfbPalmVNCReSizeFrameBuffer;
|
||||
pmsg.pad1 = 0;
|
||||
pmsg.desktop_w = Swap16IfLE(cl->screen->width);
|
||||
pmsg.desktop_h = Swap16IfLE(cl->screen->height);
|
||||
pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width);
|
||||
pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height);
|
||||
pmsg.pad2 = 0;
|
||||
|
||||
rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height);
|
||||
if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) {
|
||||
rfbLogPerror("rfbNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
rfbClientConnectionGone(cl);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rfbResizeFrameBufferMsg rmsg;
|
||||
rmsg.type = rfbResizeFrameBuffer;
|
||||
rmsg.pad1=0;
|
||||
rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width);
|
||||
rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height);
|
||||
rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height);
|
||||
if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) {
|
||||
rfbLogPerror("rfbNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
rfbClientConnectionGone(cl);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/****************************/
|
||||