Skip to content

Commit

Permalink
examples,build: add Qt client example
Browse files Browse the repository at this point in the history
* CMake: Adds C++ as project language

* CMake: Adds WITH_QT option to build Qt client example

* Examples: Adds qt5client.cpp

* CMake: adds specific way of building Qt client example

* CMake: try to find Qt if needed

* CMake: makes Qt not required, quiet if not found

* CMake: removes CXX as language

* CMake: checks if we have C++ compiler before setting standard

* CMake: checks C++ compiler before setting project languages

I could not find a better solution. It seems like the languages must be set before almost everything.

* CMake: check if C++ compiler defined instead of string comparison

* CMake: appends CXX to languages, in a better syntax

As suggested by dantti

* Examples: changes to static_cast in Qt5 client example

As suggested by @dantti

* Examples: adds description to Qt example

* Examples: Qt example can't handle new fb size

* Examples: adds additional condition to build Qt example

This is need to remove the following message: 'CMake Error: Cannot determine link language for target'

* CMake: adds comment about C++ example (Qt client)

* Examples: adds CMake remarks to Qt client example

* CMake: changes Qt5::Widgets to Qt5Widgets_LIBRARIES

Just for standardization
  • Loading branch information
nicmorais authored Apr 3, 2024
1 parent 6e777e6 commit b44665c
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 2 deletions.
27 changes: 25 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
cmake_minimum_required(VERSION 3.4)

project(LibVNCServer VERSION 0.9.14 LANGUAGES C)
set(PROJECT_LANGUAGES C)

if(DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_STANDARD 17)
list(APPEND PROJECT_LANGUAGES CXX)
endif(DEFINED CMAKE_CXX_COMPILER)

project(LibVNCServer VERSION 0.9.14 LANGUAGES ${PROJECT_LANGUAGES})
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckIncludeFile)
Expand All @@ -25,6 +32,7 @@ set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(CMAKE_GENERATOR MATCHES "Unix Makefiles|Ninja")
# some LSP servers expect compile_commands.json in the project root
add_custom_target(
Expand Down Expand Up @@ -67,7 +75,7 @@ option(WITH_SASL "Build with SASL support" ON)
option(WITH_XCB "Build with XCB support" ON)
option(WITH_EXAMPLES "Build examples" ON)
option(WITH_TESTS "Build tests" ON)

option(WITH_QT "Build the Qt client example" ON)


if(WITH_ZLIB)
Expand Down Expand Up @@ -147,6 +155,10 @@ if(WITH_GTK)
find_package(GTK2)
endif(WITH_GTK)

if(WITH_QT)
find_package(Qt5 COMPONENTS Core Widgets QUIET)
endif(WITH_QT)

if(WITH_LIBSSHTUNNEL)
find_path(LIBSSHTUNNEL_INCLUDE_DIR libsshtunnel.h)
find_library(LIBSSHTUNNEL_LIBRARY sshtunnel)
Expand Down Expand Up @@ -656,6 +668,17 @@ if(WITH_EXAMPLES)
set_target_properties(client_examples_${e} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL2_LIBRARY} ${GTK2_LIBRARIES} ${FFMPEG_LIBRARIES} ${LIBSSHTUNNEL_LIBRARY})
endforeach(e ${LIBVNCCLIENT_EXAMPLES})

#This example must have its own building instructions,
#apart from the other examples because it is written in
#C++, so it has a distinct file extension and depends on
#a C++ compiler
if(Qt5Widgets_FOUND AND WITH_QT AND DEFINED CMAKE_CXX_COMPILER)
add_executable(client_examples_qt5client ${LIBVNCCLIEXAMPLE_DIR}/qt5client.cpp ${LIBVNCCLIEXAMPLE_DIR}/${qt5client_EXTRA_SOURCES})
set_target_properties(client_examples_qt5client PROPERTIES OUTPUT_NAME qt5client)
set_target_properties(client_examples_qt5client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
target_link_libraries(client_examples_qt5client vncclient ${CMAKE_THREAD_LIBS_INIT} ${Qt5Widgets_LIBRARIES})
endif(Qt5Widgets_FOUND AND WITH_QT AND DEFINED CMAKE_CXX_COMPILER)
endif(WITH_EXAMPLES)

#
Expand Down
149 changes: 149 additions & 0 deletions examples/client/qt5client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
*
* 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/

/*
* This is an example on how to make a simple VNC client with
* Qt5 Widgets. It suitable for desktop apps, but may not be
* good for mobile.
* It does not implement any form of cryptography,
* authentication support, client-side cursors or framebuffer
* resizing. If you want to make this a part of your
* application, please notice that you may need to change
* the while(true) loop to disconnect the client.
*
* To build this example with all the other components of
* libvncserver, you may need to explicitly define a C++
* compiler and the path to Qt libs when calling CMake.
* e.g. cmake -DCMAKE_PREFIX_PATH=~/Qt/5.15.2/gcc_64
* -DCMAKE_CXX_COMPILER=g++
*/

#include <QApplication>
#include <iostream>
#include <thread>
#include <QPaintEvent>
#include <QPainter>
#include "rfb/rfbclient.h"
#include <QWidget>

class VncViewer : public QWidget
{
//if you want to make use of signals/slots, uncomment the line bellow:
//Q_OBJECT
public:
VncViewer(QWidget *parent = nullptr) {};
virtual ~VncViewer() {};
void start();
std::string serverIp;
int serverPort;
std::thread *vncThread() const;
void paintEvent(QPaintEvent *event) override;

private:
QImage m_image;
rfbClient *cl;
std::thread *m_vncThread;
static void finishedFramebufferUpdateStatic(rfbClient *cl);
void finishedFramebufferUpdate(rfbClient *cl);
};

void VncViewer::finishedFramebufferUpdateStatic(rfbClient *cl)
{
VncViewer *ptr = static_cast<VncViewer*>(rfbClientGetClientData(cl, nullptr));
ptr->finishedFramebufferUpdate(cl);
}

void VncViewer::finishedFramebufferUpdate(rfbClient *cl)
{
m_image = QImage(cl->frameBuffer, cl->width, cl->height, QImage::Format_RGB16);

update();
}
void VncViewer::paintEvent(QPaintEvent *event)
{
event->accept();

QPainter painter(this);
painter.drawImage(this->rect(), m_image);
}

void VncViewer::start()
{
cl = rfbGetClient(8, 3, 4);
cl->format.depth = 24;
cl->format.depth = 16;
cl->format.bitsPerPixel = 16;
cl->format.redShift = 11;
cl->format.greenShift = 5;
cl->format.blueShift = 0;
cl->format.redMax = 0x1f;
cl->format.greenMax = 0x3f;
cl->format.blueMax = 0x1f;
cl->appData.compressLevel = 9;
cl->appData.qualityLevel = 1;
cl->appData.encodingsString = "tight ultra";
cl->FinishedFrameBufferUpdate = finishedFramebufferUpdateStatic;
cl->serverHost = strdup(serverIp.c_str());
cl->serverPort = serverPort;
cl->appData.useRemoteCursor = TRUE;

rfbClientSetClientData(cl, nullptr, this);

if (rfbInitClient(cl, 0, nullptr)) {
} else {
std::cout << "[INFO] disconnected" << std::endl;
return;
}

m_vncThread = new std::thread([this]() {
while (true) {
int i = WaitForMessage(cl, 500);
if (i < 0) {
std::cout << "[INFO] disconnected" << std::endl;
rfbClientCleanup(cl);
break;
}

if (i && !HandleRFBServerMessage(cl)) {
std::cout << "[INFO] disconnected" << std::endl;
rfbClientCleanup(cl);
break;
}
};
});
}

int main(int argc, char *argv[])
{
if(argc < 3) {
std::cout << "Usage: "
<< argv[0]
<< " <server ip>"
<< " <port>"
<< "\n";
return 1;
}

QApplication a(argc, argv);
VncViewer vncViewer;
vncViewer.serverIp = std::string{argv[1]};
vncViewer.serverPort = std::atoi(argv[2]);
vncViewer.show();
vncViewer.start();
return a.exec();
}

0 comments on commit b44665c

Please sign in to comment.