From 5c30d3e80ff682f94fdc6ba5a7e63372c2e7a471 Mon Sep 17 00:00:00 2001 From: Michal Srb 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 \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 \nint main(int c, char** v) { return FL_Volume_Down; }" HAVE_FLTK_MEDIAKEYS) + + # FLTK STR #2641 + check_cxx_source_compiles("#include \nint main(int c, char** v) { return FL_FULLSCREEN; }" HAVE_FLTK_FULLSCREEN) + + # FLTK STR #2660 + check_cxx_source_compiles("#include \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 \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 \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 \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 \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 \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.