f3919e3250
- Updated to tigervnc 1.5.0. - Dropped no longer needed patches: * tigervnc-sf3495623.patch * u_syslog.patch * u_tigervnc-build-with-xserver-1.17.patch - Use encryption everywhere. (fate#318936) - Work with fltk 1.3.2. * N_tigervnc_revert_fltk_1_3_3_requirements.patch OBS-URL: https://build.opensuse.org/request/show/316948 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/tigervnc?expand=0&rev=58
1006 lines
30 KiB
Diff
1006 lines
30 KiB
Diff
From 5c30d3e80ff682f94fdc6ba5a7e63372c2e7a471 Mon Sep 17 00:00:00 2001
|
|
From: Michal Srb <michalsrb@gmail.com>
|
|
Date: Wed, 15 Jul 2015 16:41:33 +0300
|
|
Subject: [PATCH] Revert "Raise FLTK requirement to 1.3.3"
|
|
|
|
This reverts commit 56610fb847eaf1fe27a5b7331ede93296ff835ff.
|
|
|
|
Conflicts:
|
|
BUILDING.txt
|
|
config.h.in
|
|
vncviewer/DesktopWindow.cxx
|
|
vncviewer/Viewport.cxx
|
|
|
|
diff --git a/BUILDING.txt b/BUILDING.txt
|
|
index 9987bd7..9703b1c 100644
|
|
--- a/BUILDING.txt
|
|
+++ b/BUILDING.txt
|
|
@@ -12,6 +12,9 @@ Build Requirements (All Systems)
|
|
-- zlib
|
|
|
|
-- FLTK 1.3.3 or later
|
|
+-- FLTK 1.3.2
|
|
+ * Must be a patched snapshot to get full functionality
|
|
+ * See "Building FLTK" below.
|
|
|
|
-- If building TLS support:
|
|
* GnuTLS 3.x
|
|
@@ -62,6 +65,38 @@ Build Requirements (Java)
|
|
-- See "Building Java Support" below.
|
|
|
|
|
|
+=============
|
|
+Building FLTK
|
|
+=============
|
|
+
|
|
+TigerVNC requires FLTK 1.3.2 (or later). Although it will build and work
|
|
+with plain 1.3.2, to get full functionality and the best behaviour you
|
|
+need to build a patched version:
|
|
+
|
|
+1. Check out FLTK 1.3.2 using Subversion:
|
|
+$ svn co http://svn.easysw.com/public/fltk/fltk/tags/release-1.3.2 fltk-1.3.2
|
|
+
|
|
+2. For full functionality, apply patches. All patches can be found in
|
|
+ the contrib/fltk/ directory. There are also some general fixes to
|
|
+ FLTK that can be found in the contrib/fltk/fixes/ directory that
|
|
+ might be useful.
|
|
+
|
|
+3. Use CMake to build FLTK using the same procedures described below for
|
|
+ building TigerVNC. The recipes in the "Build Recipes" section also apply.
|
|
+ If you want optimized code, make sure to build with
|
|
+ -DCMAKE_BUILD_TYPE=Release.
|
|
+
|
|
+4. (optional) Use 'make install' to install FLTK into a directory of your
|
|
+ choosing.
|
|
+
|
|
+5. When building TigerVNC, set the FLTK_FLUID_EXECUTABLE CMake variable to the
|
|
+ location of the fluid executable that was built in Step 3 or installed in
|
|
+ Step 4. This gives CMake a hint as to where to find the FLTK library.
|
|
+
|
|
+6. If you did not install FLTK, then set the FLTK_INCLUDE_DIR CMake variable to
|
|
+ the location of the FLTK source directory.
|
|
+
|
|
+
|
|
==================
|
|
Out-of-Tree Builds
|
|
==================
|
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
index a46679b..cd91965 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -226,6 +226,41 @@ if(UNIX AND NOT APPLE)
|
|
endif()
|
|
endif()
|
|
|
|
+if(FLTK_FOUND)
|
|
+ set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR})
|
|
+ set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES})
|
|
+
|
|
+ # FLTK STR #2636
|
|
+ check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_clipboard_notify(NULL, NULL); return 0; }" HAVE_FLTK_CLIPBOARD)
|
|
+
|
|
+ # FLTK STR #2638
|
|
+ check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_Volume_Down; }" HAVE_FLTK_MEDIAKEYS)
|
|
+
|
|
+ # FLTK STR #2641
|
|
+ check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_FULLSCREEN; }" HAVE_FLTK_FULLSCREEN)
|
|
+
|
|
+ # FLTK STR #2660
|
|
+ check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { void (Fl_Window::*foo)(const Fl_RGB_Image*,int,int) = &Fl_Window::cursor; return 0; }" HAVE_FLTK_CURSOR)
|
|
+
|
|
+ # FLTK STR #2697
|
|
+ check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { int X, Y, W, H; Fl::screen_work_area(X, Y, W, H); return 0; }" HAVE_FLTK_WORK_AREA)
|
|
+
|
|
+ # FLTK STR #2816
|
|
+ check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { Fl_Window::default_icons(0, 0); return 0; }" HAVE_FLTK_ICONS)
|
|
+
|
|
+ # FLTK STR #2860
|
|
+ check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { void (Fl_Window::*foo)(int,int,int,int) = &Fl_Window::fullscreen_screens; return 0; }" HAVE_FLTK_FULLSCREEN_SCREENS)
|
|
+
|
|
+ # FLTK STR #xxxx
|
|
+ check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_system_handler(NULL, NULL); return 0; }" HAVE_FLTK_XHANDLERS)
|
|
+
|
|
+ # FLTK STR #xxxx
|
|
+ check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::disable_im(); return 0; }" HAVE_FLTK_IM)
|
|
+
|
|
+ set(CMAKE_REQUIRED_INCLUDES)
|
|
+ set(CMAKE_REQUIRED_LIBRARIES)
|
|
+endif()
|
|
+
|
|
# Check for GNUTLS library
|
|
option(ENABLE_GNUTLS "Enable protocol encryption and advanced authentication" ON)
|
|
if(ENABLE_GNUTLS)
|
|
diff --git a/config.h.in b/config.h.in
|
|
index 345af7d..490d7f6 100644
|
|
--- a/config.h.in
|
|
+++ b/config.h.in
|
|
@@ -1,6 +1,25 @@
|
|
#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
|
|
#define PACKAGE_VERSION "@VERSION@"
|
|
|
|
+#cmakedefine HAVE_INET_ATON
|
|
+#cmakedefine HAVE_INET_PTON
|
|
+#cmakedefine HAVE_GETADDRINFO
|
|
+#cmakedefine HAVE_GNUTLS_SET_GLOBAL_ERRNO
|
|
+#cmakedefine HAVE_GNUTLS_SET_ERRNO
|
|
+#cmakedefine HAVE_GNUTLS_X509_CRT_PRINT
|
|
+#cmakedefine HAVE_GNUTLS_X509_CRT_T
|
|
+#cmakedefine HAVE_GNUTLS_DATUM_T
|
|
+#cmakedefine HAVE_GNUTLS_PK_ALGORITHM_T
|
|
+#cmakedefine HAVE_GNUTLS_SIGN_ALGORITHM_T
|
|
+#cmakedefine HAVE_FLTK_CLIPBOARD
|
|
+#cmakedefine HAVE_FLTK_MEDIAKEYS
|
|
+#cmakedefine HAVE_FLTK_FULLSCREEN
|
|
+#cmakedefine HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#cmakedefine HAVE_FLTK_CURSOR
|
|
+#cmakedefine HAVE_FLTK_WORK_AREA
|
|
+#cmakedefine HAVE_FLTK_ICONS
|
|
+#cmakedefine HAVE_FLTK_XHANDLERS
|
|
+#cmakedefine HAVE_FLTK_IM
|
|
#cmakedefine HAVE_ACTIVE_DESKTOP_H
|
|
#cmakedefine HAVE_ACTIVE_DESKTOP_L
|
|
#cmakedefine ENABLE_NLS 1
|
|
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
|
|
index bba502b..1a6e02b 100644
|
|
--- a/vncviewer/DesktopWindow.cxx
|
|
+++ b/vncviewer/DesktopWindow.cxx
|
|
@@ -112,8 +112,13 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
// On OS X we can do the maximize thing properly before the
|
|
// window is showned. Other platforms handled further down...
|
|
if (maximize) {
|
|
+#ifdef HAVE_FLTK_WORK_AREA
|
|
int dummy;
|
|
Fl::screen_work_area(dummy, dummy, w, h, geom_x, geom_y);
|
|
+#else
|
|
+ w = Fl::w();
|
|
+ h = Fl::h();
|
|
+#endif
|
|
}
|
|
#endif
|
|
|
|
@@ -123,6 +128,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
size(w, h);
|
|
}
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (fullScreen) {
|
|
// Hack: Window managers seem to be rather crappy at respecting
|
|
// fullscreen hints on initial windows. So on X11 we'll have to
|
|
@@ -133,13 +139,16 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
delayedFullscreen = true;
|
|
#endif
|
|
}
|
|
+#endif
|
|
|
|
show();
|
|
|
|
// Full screen events are not sent out for a hidden window,
|
|
// so send a fake one here to set up things properly.
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (fullscreen_active())
|
|
handle(FL_FULLSCREEN);
|
|
+#endif
|
|
|
|
// Unfortunately, current FLTK does not allow us to set the
|
|
// maximized property on Windows and X11 before showing the window.
|
|
@@ -156,6 +165,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
if ((w != this->w()) || (h != this->h()))
|
|
scroll->size(this->w(), this->h());
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (delayedFullscreen) {
|
|
// Hack: Fullscreen requests may be ignored, so we need a timeout for
|
|
// when we should stop waiting. We also really need to wait for the
|
|
@@ -163,6 +173,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
Fl::add_timeout(0.5, handleFullscreenTimeout, this);
|
|
fullscreen_on();
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -234,7 +245,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h)
|
|
// If we're letting the viewport match the window perfectly, then
|
|
// keep things that way for the new size, otherwise just keep things
|
|
// like they are.
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (!fullscreen_active()) {
|
|
+#endif
|
|
if ((w() == viewport->w()) && (h() == viewport->h()))
|
|
size(new_w, new_h);
|
|
else {
|
|
@@ -244,7 +257,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h)
|
|
if ((w() > new_w) || (h() > new_h))
|
|
size(__rfbmin(w(), new_w), __rfbmin(h(), new_h));
|
|
}
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
}
|
|
+#endif
|
|
|
|
viewport->size(new_w, new_h);
|
|
|
|
@@ -273,7 +288,10 @@ void DesktopWindow::resize(int x, int y, int w, int h)
|
|
#if ! (defined(WIN32) || defined(__APPLE__))
|
|
// X11 window managers will treat a resize to cover the entire
|
|
// monitor as a request to go full screen. Make sure we avoid this.
|
|
- if (!fullscreen_active()) {
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
+ if (!fullscreen_active())
|
|
+#endif
|
|
+ {
|
|
bool resize_req;
|
|
|
|
// If there is no X11 window, then this must be a resize request,
|
|
@@ -349,6 +367,7 @@ void DesktopWindow::resize(int x, int y, int w, int h)
|
|
int DesktopWindow::handle(int event)
|
|
{
|
|
switch (event) {
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
case FL_FULLSCREEN:
|
|
fullScreen.setParam(fullscreen_active());
|
|
|
|
@@ -387,6 +406,16 @@ int DesktopWindow::handle(int event)
|
|
}
|
|
// Continue processing so that the viewport also gets mouse events
|
|
break;
|
|
+#endif
|
|
+
|
|
+ case FL_SHORTCUT:
|
|
+ // Sometimes the focus gets out of whack and we fall through to the
|
|
+ // shortcut dispatching. Try to make things sane again...
|
|
+ if (Fl::focus() == NULL) {
|
|
+ take_focus();
|
|
+ Fl::handle(FL_KEYDOWN, this);
|
|
+ }
|
|
+ return 1;
|
|
}
|
|
|
|
return Fl_Window::handle(event);
|
|
@@ -399,6 +428,7 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
|
|
|
|
ret = Fl::handle_(event, win);
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
// This is hackish and the result of the dodgy focus handling in FLTK.
|
|
// The basic problem is that FLTK's view of focus and the system's tend
|
|
// to differ, and as a result we do not see all the FL_FOCUS events we
|
|
@@ -426,6 +456,7 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
|
|
break;
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
return ret;
|
|
}
|
|
@@ -433,6 +464,8 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
|
|
|
|
void DesktopWindow::fullscreen_on()
|
|
{
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
if (not fullScreenAllMonitors)
|
|
fullscreen_screens(-1, -1, -1, -1);
|
|
else {
|
|
@@ -471,8 +504,10 @@ void DesktopWindow::fullscreen_on()
|
|
|
|
fullscreen_screens(top, bottom, left, right);
|
|
}
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
|
|
fullscreen();
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
}
|
|
|
|
void DesktopWindow::grabKeyboard()
|
|
@@ -492,7 +527,13 @@ void DesktopWindow::grabKeyboard()
|
|
#elif defined(__APPLE__)
|
|
int ret;
|
|
|
|
- ret = cocoa_capture_display(this, fullScreenAllMonitors);
|
|
+ ret = cocoa_capture_display(this,
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+ fullScreenAllMonitors
|
|
+#else
|
|
+ false
|
|
+#endif
|
|
+ );
|
|
if (ret != 0)
|
|
vlog.error(_("Failure grabbing keyboard"));
|
|
#else
|
|
@@ -549,12 +590,14 @@ void DesktopWindow::handleGrab(void *data)
|
|
|
|
assert(self);
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (!fullscreenSystemKeys)
|
|
return;
|
|
if (!self->fullscreen_active())
|
|
return;
|
|
|
|
self->grabKeyboard();
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -565,22 +608,31 @@ void DesktopWindow::maximizeWindow()
|
|
// We cannot use ShowWindow() in full screen mode as it will
|
|
// resize things implicitly. Fortunately modifying the style
|
|
// directly results in a maximized state once we leave full screen.
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (fullscreen_active()) {
|
|
WINDOWINFO wi;
|
|
wi.cbSize = sizeof(WINDOWINFO);
|
|
GetWindowInfo(fl_xid(this), &wi);
|
|
SetWindowLongPtr(fl_xid(this), GWL_STYLE, wi.dwStyle | WS_MAXIMIZE);
|
|
} else
|
|
+#endif
|
|
ShowWindow(fl_xid(this), SW_MAXIMIZE);
|
|
#elif defined(__APPLE__)
|
|
// OS X is somewhat strange and does not really have a concept of a
|
|
// maximized window, so we can simply resize the window to the workarea.
|
|
// Note that we shouldn't do this whilst in full screen as that will
|
|
// incorrectly adjust things.
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (fullscreen_active())
|
|
return;
|
|
+#endif
|
|
int X, Y, W, H;
|
|
+#ifdef HAVE_FLTK_WORK_AREA
|
|
Fl::screen_work_area(X, Y, W, H, this->x(), this->y());
|
|
+#else
|
|
+ W = Fl::w();
|
|
+ H = Fl::h();
|
|
+#endif
|
|
size(W, H);
|
|
#else
|
|
// X11
|
|
@@ -638,7 +690,9 @@ void DesktopWindow::remoteResize(int width, int height)
|
|
ScreenSet layout;
|
|
ScreenSet::iterator iter;
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (!fullscreen_active() || (width > w()) || (height > h())) {
|
|
+#endif
|
|
// In windowed mode (or the framebuffer is so large that we need
|
|
// to scroll) we just report a single virtual screen that covers
|
|
// the entire framebuffer.
|
|
@@ -669,6 +723,7 @@ void DesktopWindow::remoteResize(int width, int height)
|
|
layout.begin()->dimensions.tl.y = 0;
|
|
layout.begin()->dimensions.br.x = width;
|
|
layout.begin()->dimensions.br.y = height;
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
} else {
|
|
int i;
|
|
rdr::U32 id;
|
|
@@ -735,6 +790,7 @@ void DesktopWindow::remoteResize(int width, int height)
|
|
if (layout.num_screens() == 0)
|
|
layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0));
|
|
}
|
|
+#endif
|
|
|
|
// Do we actually change anything?
|
|
if ((width == cc->cp.width) &&
|
|
@@ -810,6 +866,7 @@ void DesktopWindow::handleOptions(void *data)
|
|
{
|
|
DesktopWindow *self = (DesktopWindow*)data;
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (self->fullscreen_active() && fullscreenSystemKeys)
|
|
self->grabKeyboard();
|
|
else
|
|
@@ -819,6 +876,7 @@ void DesktopWindow::handleOptions(void *data)
|
|
self->fullscreen_on();
|
|
else if (!fullScreen && self->fullscreen_active())
|
|
self->fullscreen_off();
|
|
+#endif
|
|
}
|
|
|
|
void DesktopWindow::handleFullscreenTimeout(void *data)
|
|
@@ -837,6 +895,7 @@ void DesktopWindow::handleFullscreenTimeout(void *data)
|
|
|
|
void DesktopWindow::handleEdgeScroll(void *data)
|
|
{
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
DesktopWindow *self = (DesktopWindow *)data;
|
|
|
|
int mx, my;
|
|
@@ -893,4 +952,5 @@ void DesktopWindow::handleEdgeScroll(void *data)
|
|
self->scroll->scroll_to(self->scroll->xposition() - dx, self->scroll->yposition() - dy);
|
|
|
|
Fl::repeat_timeout(0.1, handleEdgeScroll, data);
|
|
+#endif
|
|
}
|
|
diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx
|
|
index 3c8fcb4..d1495ef 100644
|
|
--- a/vncviewer/OptionsDialog.cxx
|
|
+++ b/vncviewer/OptionsDialog.cxx
|
|
@@ -290,8 +290,12 @@ void OptionsDialog::loadOptions(void)
|
|
desktopHeightInput->value(buf);
|
|
}
|
|
remoteResizeCheckbox->value(remoteResize);
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
fullScreenCheckbox->value(fullScreen);
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
|
|
handleDesktopSize(desktopSizeCheckbox, this);
|
|
|
|
@@ -394,8 +398,12 @@ void OptionsDialog::storeOptions(void)
|
|
desktopSize.setParam("");
|
|
}
|
|
remoteResize.setParam(remoteResizeCheckbox->value());
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
fullScreen.setParam(fullScreenCheckbox->value());
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
|
|
/* Misc. */
|
|
shared.setParam(sharedCheckbox->value());
|
|
@@ -750,18 +758,26 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
|
|
_("Resize remote session to the local window")));
|
|
ty += CHECK_HEIGHT + TIGHT_MARGIN;
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
+
|
|
fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
|
|
CHECK_MIN_WIDTH,
|
|
CHECK_HEIGHT,
|
|
_("Full-screen mode")));
|
|
ty += CHECK_HEIGHT + TIGHT_MARGIN;
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+
|
|
fullScreenAllMonitorsCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
|
|
CHECK_MIN_WIDTH,
|
|
CHECK_HEIGHT,
|
|
_("Enable full-screen mode over all monitors")));
|
|
ty += CHECK_HEIGHT + TIGHT_MARGIN;
|
|
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
+
|
|
group->end();
|
|
}
|
|
|
|
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
|
|
index ca65acd..4c989f3 100644
|
|
--- a/vncviewer/Viewport.cxx
|
|
+++ b/vncviewer/Viewport.cxx
|
|
@@ -106,10 +106,15 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
|
|
lastPointerPos(0, 0), lastButtonMask(0),
|
|
menuCtrlKey(false), menuAltKey(false), cursor(NULL)
|
|
{
|
|
+// FLTK STR #2636 gives us the ability to monitor clipboard changes
|
|
+#ifdef HAVE_FLTK_CLIPBOARD
|
|
Fl::add_clipboard_notify(handleClipboardChange, this);
|
|
+#endif
|
|
|
|
+#ifdef HAVE_FLTK_XHANDLERS
|
|
// We need to intercept keyboard events early
|
|
Fl::add_system_handler(handleSystemEvent, this);
|
|
+#endif
|
|
|
|
frameBuffer = createFramebuffer(w, h);
|
|
assert(frameBuffer);
|
|
@@ -143,9 +148,13 @@ Viewport::~Viewport()
|
|
// again later when this object is already gone.
|
|
Fl::remove_timeout(handlePointerTimeout, this);
|
|
|
|
+#ifdef HAVE_FLTK_XHANDLERS
|
|
Fl::remove_system_handler(handleSystemEvent);
|
|
+#endif
|
|
|
|
+#ifdef HAVE_FLTK_CLIPBOARD
|
|
Fl::remove_clipboard_notify(handleClipboardChange);
|
|
+#endif
|
|
|
|
OptionsDialog::removeCallback(handleOptions);
|
|
|
|
@@ -185,6 +194,7 @@ rfb::ModifiablePixelBuffer* Viewport::getFramebuffer(void)
|
|
return frameBuffer;
|
|
}
|
|
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
static const char * dotcursor_xpm[] = {
|
|
"5 5 2 1",
|
|
". c #000000",
|
|
@@ -194,10 +204,12 @@ static const char * dotcursor_xpm[] = {
|
|
" ... ",
|
|
" ... ",
|
|
" "};
|
|
+#endif
|
|
|
|
void Viewport::setCursor(int width, int height, const Point& hotspot,
|
|
void* data, void* mask)
|
|
{
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
if (cursor) {
|
|
if (!cursor->alloc_array)
|
|
delete [] cursor->array;
|
|
@@ -257,6 +269,7 @@ void Viewport::setCursor(int width, int height, const Point& hotspot,
|
|
|
|
if (Fl::belowmouse() == this)
|
|
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -354,13 +367,17 @@ int Viewport::handle(int event)
|
|
return 1;
|
|
|
|
case FL_ENTER:
|
|
+ // Yes, we would like some pointer events please!
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
if (cursor)
|
|
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
|
|
- // Yes, we would like some pointer events please!
|
|
+#endif
|
|
return 1;
|
|
|
|
case FL_LEAVE:
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
window()->cursor(FL_CURSOR_DEFAULT);
|
|
+#endif
|
|
// Fall through as we want a last move event to help trigger edge stuff
|
|
case FL_PUSH:
|
|
case FL_RELEASE:
|
|
@@ -396,7 +413,9 @@ int Viewport::handle(int event)
|
|
return 1;
|
|
|
|
case FL_FOCUS:
|
|
+#ifdef HAVE_FLTK_IM
|
|
Fl::disable_im();
|
|
+#endif
|
|
// Yes, we would like some focus please!
|
|
return 1;
|
|
|
|
@@ -405,12 +424,17 @@ int Viewport::handle(int event)
|
|
// sense (e.g. Alt+Tab where we only see the Alt press)
|
|
while (!downKeySym.empty())
|
|
handleKeyRelease(downKeySym.begin()->first);
|
|
+#ifdef HAVE_FLTK_IM
|
|
Fl::enable_im();
|
|
+#endif
|
|
return 1;
|
|
|
|
case FL_KEYDOWN:
|
|
+ handleFLTKKeyPress();
|
|
+ return 1;
|
|
+
|
|
case FL_KEYUP:
|
|
- // Just ignore these as keys were handled in the event handler
|
|
+ handleKeyRelease(Fl::event_original_key());
|
|
return 1;
|
|
}
|
|
|
|
@@ -784,6 +808,258 @@ int Viewport::handleSystemEvent(void *event, void *data)
|
|
return 0;
|
|
}
|
|
|
|
+
|
|
+rdr::U32 Viewport::translateKeyEvent(void)
|
|
+{
|
|
+ unsigned ucs;
|
|
+ int keyCode, origKeyCode;
|
|
+ const char *keyText;
|
|
+ int keyTextLen;
|
|
+
|
|
+ keyCode = Fl::event_key();
|
|
+ origKeyCode = Fl::event_original_key();
|
|
+ keyText = Fl::event_text();
|
|
+ keyTextLen = Fl::event_length();
|
|
+
|
|
+ vlog.debug("FLTK key %d (%d) '%s'[%d]", origKeyCode, keyCode, keyText, keyTextLen);
|
|
+
|
|
+ // First check for function keys
|
|
+ if ((keyCode > FL_F) && (keyCode <= FL_F_Last))
|
|
+ return XK_F1 + (keyCode - FL_F - 1);
|
|
+
|
|
+ // Numpad numbers
|
|
+ if ((keyCode >= (FL_KP + '0')) && (keyCode <= (FL_KP + '9')))
|
|
+ return XK_KP_0 + (keyCode - (FL_KP + '0'));
|
|
+
|
|
+ // FLTK does some special remapping of numpad keys when numlock is off
|
|
+ if ((origKeyCode >= FL_KP) && (origKeyCode <= FL_KP_Last)) {
|
|
+ switch (keyCode) {
|
|
+ case FL_F+1:
|
|
+ return XK_KP_F1;
|
|
+ case FL_F+2:
|
|
+ return XK_KP_F2;
|
|
+ case FL_F+3:
|
|
+ return XK_KP_F3;
|
|
+ case FL_F+4:
|
|
+ return XK_KP_F4;
|
|
+ case FL_Home:
|
|
+ return XK_KP_Home;
|
|
+ case FL_Left:
|
|
+ return XK_KP_Left;
|
|
+ case FL_Up:
|
|
+ return XK_KP_Up;
|
|
+ case FL_Right:
|
|
+ return XK_KP_Right;
|
|
+ case FL_Down:
|
|
+ return XK_KP_Down;
|
|
+ case FL_Page_Up:
|
|
+ return XK_KP_Page_Up;
|
|
+ case FL_Page_Down:
|
|
+ return XK_KP_Page_Down;
|
|
+ case FL_End:
|
|
+ return XK_KP_End;
|
|
+ case FL_Insert:
|
|
+ return XK_KP_Insert;
|
|
+ case FL_Delete:
|
|
+ return XK_KP_Delete;
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if defined(WIN32) || defined(__APPLE__)
|
|
+ // X11 fairly consistently uses XK_KP_Separator for comma and
|
|
+ // XK_KP_Decimal for period. Windows and OS X are a different matter
|
|
+ // though.
|
|
+ //
|
|
+ // OS X will consistently generate the same key code no matter what
|
|
+ // layout is being used.
|
|
+ //
|
|
+ // Windows is terribly inconcistent, and is not something that's
|
|
+ // likely to change:
|
|
+ // http://blogs.msdn.com/michkap/archive/2006/09/13/752377.aspx
|
|
+ //
|
|
+ // To get X11 behaviour, we instead look at the text generated by
|
|
+ // they key.
|
|
+ if ((keyCode == (FL_KP + ',')) || (keyCode == (FL_KP + '.'))) {
|
|
+ switch (keyText[0]) {
|
|
+ case ',':
|
|
+ return XK_KP_Separator;
|
|
+ case '.':
|
|
+ return XK_KP_Decimal;
|
|
+ default:
|
|
+ vlog.error(_("Unknown decimal separator: '%s'"), keyText);
|
|
+ return XK_KP_Decimal;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ // Then other special keys
|
|
+ switch (keyCode) {
|
|
+ case FL_BackSpace:
|
|
+ return XK_BackSpace;
|
|
+ case FL_Tab:
|
|
+ return XK_Tab;
|
|
+ case FL_Enter:
|
|
+ return XK_Return;
|
|
+ case FL_Pause:
|
|
+ return XK_Pause;
|
|
+ case FL_Scroll_Lock:
|
|
+ return XK_Scroll_Lock;
|
|
+ case FL_Escape:
|
|
+ return XK_Escape;
|
|
+ case FL_Home:
|
|
+ return XK_Home;
|
|
+ case FL_Left:
|
|
+ return XK_Left;
|
|
+ case FL_Up:
|
|
+ return XK_Up;
|
|
+ case FL_Right:
|
|
+ return XK_Right;
|
|
+ case FL_Down:
|
|
+ return XK_Down;
|
|
+ case FL_Page_Up:
|
|
+ return XK_Page_Up;
|
|
+ case FL_Page_Down:
|
|
+ return XK_Page_Down;
|
|
+ case FL_End:
|
|
+ return XK_End;
|
|
+ case FL_Print:
|
|
+ return XK_Print;
|
|
+ case FL_Insert:
|
|
+ return XK_Insert;
|
|
+ case FL_Menu:
|
|
+ return XK_Menu;
|
|
+ case FL_Help:
|
|
+ return XK_Help;
|
|
+ case FL_Num_Lock:
|
|
+ return XK_Num_Lock;
|
|
+ case FL_Shift_L:
|
|
+ return XK_Shift_L;
|
|
+ case FL_Shift_R:
|
|
+ return XK_Shift_R;
|
|
+ case FL_Control_L:
|
|
+ return XK_Control_L;
|
|
+ case FL_Control_R:
|
|
+ return XK_Control_R;
|
|
+ case FL_Caps_Lock:
|
|
+ return XK_Caps_Lock;
|
|
+ case FL_Meta_L:
|
|
+ return XK_Super_L;
|
|
+ case FL_Meta_R:
|
|
+ return XK_Super_R;
|
|
+ case FL_Alt_L:
|
|
+ return XK_Alt_L;
|
|
+ case FL_Alt_R:
|
|
+ return XK_Alt_R;
|
|
+ case FL_Delete:
|
|
+ return XK_Delete;
|
|
+ case FL_KP_Enter:
|
|
+ return XK_KP_Enter;
|
|
+ case FL_KP + '=':
|
|
+ return XK_KP_Equal;
|
|
+ case FL_KP + '*':
|
|
+ return XK_KP_Multiply;
|
|
+ case FL_KP + '+':
|
|
+ return XK_KP_Add;
|
|
+ case FL_KP + ',':
|
|
+ return XK_KP_Separator;
|
|
+ case FL_KP + '-':
|
|
+ return XK_KP_Subtract;
|
|
+ case FL_KP + '.':
|
|
+ return XK_KP_Decimal;
|
|
+ case FL_KP + '/':
|
|
+ return XK_KP_Divide;
|
|
+#ifdef HAVE_FLTK_MEDIAKEYS
|
|
+ case FL_Volume_Down:
|
|
+ return XF86XK_AudioLowerVolume;
|
|
+ case FL_Volume_Mute:
|
|
+ return XF86XK_AudioMute;
|
|
+ case FL_Volume_Up:
|
|
+ return XF86XK_AudioRaiseVolume;
|
|
+ case FL_Media_Play:
|
|
+ return XF86XK_AudioPlay;
|
|
+ case FL_Media_Stop:
|
|
+ return XF86XK_AudioStop;
|
|
+ case FL_Media_Prev:
|
|
+ return XF86XK_AudioPrev;
|
|
+ case FL_Media_Next:
|
|
+ return XF86XK_AudioNext;
|
|
+ case FL_Home_Page:
|
|
+ return XF86XK_HomePage;
|
|
+ case FL_Mail:
|
|
+ return XF86XK_Mail;
|
|
+ case FL_Search:
|
|
+ return XF86XK_Search;
|
|
+ case FL_Back:
|
|
+ return XF86XK_Back;
|
|
+ case FL_Forward:
|
|
+ return XF86XK_Forward;
|
|
+ case FL_Stop:
|
|
+ return XF86XK_Stop;
|
|
+ case FL_Refresh:
|
|
+ return XF86XK_Refresh;
|
|
+ case FL_Sleep:
|
|
+ return XF86XK_Sleep;
|
|
+ case FL_Favorites:
|
|
+ return XF86XK_Favorites;
|
|
+#endif
|
|
+ case XK_ISO_Level3_Shift:
|
|
+ // FLTK tends to let this one leak through on X11...
|
|
+ return XK_ISO_Level3_Shift;
|
|
+ case XK_Multi_key:
|
|
+ // Same for this...
|
|
+ return XK_Multi_key;
|
|
+ }
|
|
+
|
|
+ // Unknown special key?
|
|
+ if (keyTextLen == 0) {
|
|
+ vlog.error(_("Unknown FLTK key code %d (0x%04x)"), keyCode, keyCode);
|
|
+ return NoSymbol;
|
|
+ }
|
|
+
|
|
+ // Control character?
|
|
+ if ((keyTextLen == 1) && ((keyText[0] < 0x20) | (keyText[0] == 0x7f))) {
|
|
+ if (keyText[0] == 0x00)
|
|
+ return XK_2;
|
|
+ else if (keyText[0] < 0x1b) {
|
|
+ if (!!Fl::event_state(FL_SHIFT) != !!Fl::event_state(FL_CAPS_LOCK))
|
|
+ return keyText[0] + XK_A - 0x01;
|
|
+ else
|
|
+ return keyText[0] + XK_a - 0x01;
|
|
+ } else if (keyText[0] < 0x20)
|
|
+ return keyText[0] + XK_3 - 0x1b;
|
|
+ else
|
|
+ return XK_8;
|
|
+ }
|
|
+
|
|
+ // Look up the symbol the key produces and translate that from Unicode
|
|
+ // to a X11 keysym.
|
|
+ if (fl_utf_nb_char((const unsigned char*)keyText, strlen(keyText)) != 1) {
|
|
+ vlog.error(_("Multiple characters given for key code %d (0x%04x): '%s'"),
|
|
+ keyCode, keyCode, keyText);
|
|
+ return NoSymbol;
|
|
+ }
|
|
+
|
|
+ ucs = fl_utf8decode(keyText, NULL, NULL);
|
|
+ return ucs2keysym(ucs);
|
|
+}
|
|
+
|
|
+
|
|
+void Viewport::handleFLTKKeyPress(void)
|
|
+{
|
|
+ rdr::U32 keySym;
|
|
+
|
|
+#ifdef HAVE_FLTK_XHANDLERS
|
|
+ return;
|
|
+#endif
|
|
+
|
|
+ keySym = translateKeyEvent();
|
|
+ if (keySym == NoSymbol)
|
|
+ return;
|
|
+
|
|
+ handleKeyPress(Fl::event_original_key(), keySym);
|
|
+}
|
|
+
|
|
+
|
|
void Viewport::initContextMenu()
|
|
{
|
|
contextMenu->clear();
|
|
@@ -791,11 +1067,15 @@ void Viewport::initContextMenu()
|
|
fltk_menu_add(contextMenu, _("E&xit viewer"), 0, NULL,
|
|
(void*)ID_EXIT, FL_MENU_DIVIDER);
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
fltk_menu_add(contextMenu, _("&Full screen"), 0, NULL, (void*)ID_FULLSCREEN,
|
|
FL_MENU_TOGGLE | (window()->fullscreen_active()?FL_MENU_VALUE:0));
|
|
+#endif
|
|
fltk_menu_add(contextMenu, _("Resize &window to session"), 0, NULL,
|
|
(void*)ID_RESIZE,
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
(window()->fullscreen_active()?FL_MENU_INACTIVE:0) |
|
|
+#endif
|
|
FL_MENU_DIVIDER);
|
|
|
|
fltk_menu_add(contextMenu, _("&Ctrl"), 0, NULL, (void*)ID_CTRL,
|
|
@@ -843,14 +1123,18 @@ void Viewport::popupContextMenu()
|
|
|
|
// Unfortunately FLTK doesn't reliably restore the mouse pointer for
|
|
// menus, so we have to help it out.
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
if (Fl::belowmouse() == this)
|
|
window()->cursor(FL_CURSOR_DEFAULT);
|
|
+#endif
|
|
|
|
m = contextMenu->popup();
|
|
|
|
// Back to our proper mouse pointer.
|
|
+#ifdef HAVE_FLTK_CURSOR
|
|
if ((Fl::belowmouse() == this) && cursor)
|
|
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
|
|
+#endif
|
|
|
|
if (m == NULL)
|
|
return;
|
|
@@ -859,15 +1143,19 @@ void Viewport::popupContextMenu()
|
|
case ID_EXIT:
|
|
exit_vncviewer();
|
|
break;
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
case ID_FULLSCREEN:
|
|
if (window()->fullscreen_active())
|
|
window()->fullscreen_off();
|
|
else
|
|
((DesktopWindow*)window())->fullscreen_on();
|
|
break;
|
|
+#endif
|
|
case ID_RESIZE:
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (window()->fullscreen_active())
|
|
break;
|
|
+#endif
|
|
window()->size(w(), h());
|
|
break;
|
|
case ID_CTRL:
|
|
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
|
|
index 387ff03..8e60da6 100644
|
|
--- a/vncviewer/Viewport.h
|
|
+++ b/vncviewer/Viewport.h
|
|
@@ -75,6 +75,9 @@ private:
|
|
|
|
static int handleSystemEvent(void *event, void *data);
|
|
|
|
+ rdr::U32 translateKeyEvent(void);
|
|
+ void handleFLTKKeyPress(void);
|
|
+
|
|
void initContextMenu();
|
|
void popupContextMenu();
|
|
|
|
diff --git a/vncviewer/cocoa.mm b/vncviewer/cocoa.mm
|
|
index 3919cb8..e51cba9 100644
|
|
--- a/vncviewer/cocoa.mm
|
|
+++ b/vncviewer/cocoa.mm
|
|
@@ -60,7 +60,11 @@ int cocoa_capture_display(Fl_Window *win, bool all_displays)
|
|
if (count != (unsigned)Fl::screen_count())
|
|
return 1;
|
|
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
index = Fl::screen_num(win->x(), win->y(), win->w(), win->h());
|
|
+#else
|
|
+ index = 0;
|
|
+#endif
|
|
|
|
if (CGDisplayCapture(displays[index]) != kCGErrorSuccess)
|
|
return 1;
|
|
@@ -95,9 +99,11 @@ void cocoa_release_display(Fl_Window *win)
|
|
|
|
// FIXME: Store the previous level somewhere so we don't have to hard
|
|
// code a level here.
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
if (win->fullscreen_active() && win->contains(Fl::focus()))
|
|
newlevel = NSStatusWindowLevel;
|
|
else
|
|
+#endif
|
|
newlevel = NSNormalWindowLevel;
|
|
|
|
// Only change if different as the level change also moves the window
|
|
diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx
|
|
index 7cce1cd..3dca578 100644
|
|
--- a/vncviewer/parameters.cxx
|
|
+++ b/vncviewer/parameters.cxx
|
|
@@ -92,10 +92,14 @@ IntParameter qualityLevel("QualityLevel",
|
|
8);
|
|
|
|
BoolParameter maximize("Maximize", "Maximize viewer window", false);
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
BoolParameter fullScreen("FullScreen", "Full screen mode", false);
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
BoolParameter fullScreenAllMonitors("FullScreenAllMonitors",
|
|
"Enable full screen over all monitors",
|
|
true);
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
StringParameter desktopSize("DesktopSize",
|
|
"Reconfigure desktop size on the server on "
|
|
"connect (if possible)", "");
|
|
@@ -156,8 +160,12 @@ static VoidParameter* parameterArray[] = {
|
|
&compressLevel,
|
|
&noJpeg,
|
|
&qualityLevel,
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
&fullScreen,
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
&fullScreenAllMonitors,
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
&desktopSize,
|
|
&geometry,
|
|
&remoteResize,
|
|
diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h
|
|
index 0de61d2..9827b14 100644
|
|
--- a/vncviewer/parameters.h
|
|
+++ b/vncviewer/parameters.h
|
|
@@ -39,8 +39,12 @@ extern rfb::BoolParameter noJpeg;
|
|
extern rfb::IntParameter qualityLevel;
|
|
|
|
extern rfb::BoolParameter maximize;
|
|
+#ifdef HAVE_FLTK_FULLSCREEN
|
|
extern rfb::BoolParameter fullScreen;
|
|
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
|
|
extern rfb::BoolParameter fullScreenAllMonitors;
|
|
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
|
|
+#endif // HAVE_FLTK_FULLSCREEN
|
|
extern rfb::StringParameter desktopSize;
|
|
extern rfb::StringParameter geometry;
|
|
extern rfb::BoolParameter remoteResize;
|
|
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
|
|
index 4b989bb..598acde 100644
|
|
--- a/vncviewer/vncviewer.cxx
|
|
+++ b/vncviewer/vncviewer.cxx
|
|
@@ -181,6 +181,7 @@ static void init_fltk()
|
|
Fl_Window::default_xclass("vncviewer");
|
|
|
|
// Set the default icon for all windows.
|
|
+#ifdef HAVE_FLTK_ICONS
|
|
#ifdef WIN32
|
|
HICON lg, sm;
|
|
|
|
@@ -240,6 +241,7 @@ static void init_fltk()
|
|
for (int i = 0;i < count;i++)
|
|
delete icons[i];
|
|
#endif
|
|
+#endif // FLTK_HAVE_ICONS
|
|
|
|
// This makes the "icon" in dialogs rounded, which fits better
|
|
// with the above schemes.
|