diff options
author | Pierre Ossman <ossman@cendio.se> | 2011-04-15 07:46:56 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2011-04-15 07:46:56 +0000 |
commit | d50b3d137b14c9111c9c789a9acb4d1d67802400 (patch) | |
tree | 94675ead37f01e2f613e1dc901db5f5309a01fb7 /vncviewer/DesktopWindow.cxx | |
parent | a64515286b115ba425297012bfb268d22cd5763c (diff) | |
download | tigervnc-d50b3d137b14c9111c9c789a9acb4d1d67802400.tar.gz tigervnc-d50b3d137b14c9111c9c789a9acb4d1d67802400.zip |
Split out the graphics and input handling to a separate widget in preparation
for things like scroll bars.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4371 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'vncviewer/DesktopWindow.cxx')
-rw-r--r-- | vncviewer/DesktopWindow.cxx | 430 |
1 files changed, 10 insertions, 420 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 189b5210..deae16ec 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -21,35 +21,13 @@ #include <stdio.h> #include <string.h> -#include <FL/fl_draw.H> - -#include <rfb/CMsgWriter.h> #include <rfb/LogWriter.h> -// FLTK can pull in the X11 headers on some systems -#ifndef XK_VoidSymbol -#define XK_MISCELLANY -#define XK_XKB_KEYS -#include <rfb/keysymdef.h> -#endif - #include "DesktopWindow.h" -#include "CConn.h" #include "i18n.h" -#include "parameters.h" -#include "keysym2ucs.h" - -// FLTK STR #2599 must be fixed for proper dead keys support -#ifndef HAVE_FLTK_DEAD_KEYS -#define event_compose_symbol event_text -#endif using namespace rfb; -#ifdef __APPLE__ -extern "C" const char *osx_event_string(void); -#endif - extern void exit_vncviewer(); static rfb::LogWriter vlog("DesktopWindow"); @@ -57,56 +35,34 @@ static rfb::LogWriter vlog("DesktopWindow"); DesktopWindow::DesktopWindow(int w, int h, const char *name, const rfb::PixelFormat& serverPF, CConn* cc_) - : Fl_Window(w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL), - lastPointerPos(0, 0), lastButtonMask(0) + : Fl_Window(w, h) { + viewport = new Viewport(w, h, serverPF, cc_); + callback(handleClose, this); setName(name); - frameBuffer = new ManagedPixelBuffer(getPreferredPF(), w, h); - assert(frameBuffer); - - setServerPF(serverPF); - show(); } DesktopWindow::~DesktopWindow() { - // Unregister all timeouts in case they get a change tro trigger - // again later when this object is already gone. - Fl::remove_timeout(handleUpdateTimeout, this); - Fl::remove_timeout(handleColourMap, this); - Fl::remove_timeout(handlePointerTimeout, this); - - delete frameBuffer; - - if (pixelTrans) - delete pixelTrans; + // FLTK automatically deletes all child widgets, so we shouldn't touch + // them ourselves here } void DesktopWindow::setServerPF(const rfb::PixelFormat& pf) { - if (pixelTrans) - delete pixelTrans; - pixelTrans = NULL; - - if (pf.equal(getPreferredPF())) - return; - - pixelTrans = new PixelTransformer(); - pixelTrans->init(pf, &colourMap, getPreferredPF()); + viewport->setServerPF(pf); } const rfb::PixelFormat &DesktopWindow::getPreferredPF() { - static PixelFormat prefPF(32, 24, false, true, 255, 255, 255, 0, 8, 16); - - return prefPF; + return viewport->getPreferredPF(); } @@ -128,18 +84,11 @@ void DesktopWindow::setName(const char *name) copy_label(windowNameStr.buf); } -// setColourMapEntries() changes some of the entries in the colourmap. -// Unfortunately these messages are often sent one at a time, so we delay the -// settings taking effect by 100ms. This is because recalculating the internal -// translation table can be expensive. + void DesktopWindow::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs) { - for (int i = 0; i < nColours; i++) - colourMap.set(firstColour+i, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]); - - if (!Fl::has_timeout(handleColourMap, this)) - Fl::add_timeout(0.100, handleColourMap, this); + viewport->setColourMapEntries(firstColour, nColours, rgbs); } @@ -148,370 +97,11 @@ void DesktopWindow::setColourMapEntries(int firstColour, int nColours, void DesktopWindow::updateWindow() { - Rect r; - - Fl::remove_timeout(handleUpdateTimeout, this); - - r = damage.get_bounding_rect(); - Fl_Window::damage(FL_DAMAGE_USER1, r.tl.x, r.tl.y, r.width(), r.height()); - - damage.clear(); + viewport->updateWindow(); } -void DesktopWindow::draw() -{ - int X, Y, W, H; - - int pixel_bytes, stride_bytes; - const uchar *buf_start; - - // Check what actually needs updating - fl_clip_box(0, 0, w(), h(), X, Y, W, H); - if ((W == 0) || (H == 0)) - return; - - pixel_bytes = frameBuffer->getPF().bpp/8; - stride_bytes = pixel_bytes * frameBuffer->getStride(); - buf_start = frameBuffer->data + - pixel_bytes * X + - stride_bytes * Y; - - // FIXME: Check how efficient this thing really is - fl_draw_image(buf_start, X, Y, W, H, pixel_bytes, stride_bytes); -} - - -int DesktopWindow::handle(int event) -{ - int buttonMask, wheelMask; - DownMap::const_iterator iter; - - switch (event) { - case FL_PUSH: - case FL_RELEASE: - case FL_DRAG: - case FL_MOVE: - case FL_MOUSEWHEEL: - buttonMask = 0; - if (Fl::event_button1()) - buttonMask |= 1; - if (Fl::event_button2()) - buttonMask |= 2; - if (Fl::event_button3()) - buttonMask |= 4; - - if (event == FL_MOUSEWHEEL) { - if (Fl::event_dy() < 0) - wheelMask = 8; - else - wheelMask = 16; - - // A quick press of the wheel "button", followed by a immediate - // release below - handlePointerEvent(Point(Fl::event_x(), Fl::event_y()), - buttonMask | wheelMask); - } - - handlePointerEvent(Point(Fl::event_x(), Fl::event_y()), buttonMask); - return 1; - - case FL_FOCUS: - // Yes, we would like some focus please! - return 1; - - case FL_UNFOCUS: - // Release all keys that were pressed as that generally makes most - // sense (e.g. Alt+Tab where we only see the Alt press) - for (iter = downKeySym.begin();iter != downKeySym.end();++iter) - cc->writer()->keyEvent(iter->second, false); - downKeySym.clear(); - return 1; - - case FL_KEYDOWN: - handleKeyEvent(Fl::event_key(), Fl::event_compose_symbol(), true); - return 1; - - case FL_KEYUP: - handleKeyEvent(Fl::event_key(), Fl::event_compose_symbol(), false); - return 1; - } - - return Fl_Window::handle(event); -} - - -void DesktopWindow::handleUpdateTimeout(void *data) -{ - DesktopWindow *self = (DesktopWindow *)data; - - assert(self); - - self->updateWindow(); -} - - -void DesktopWindow::handleColourMap(void *data) -{ - DesktopWindow *self = (DesktopWindow *)data; - - assert(self); - - if (self->pixelTrans != NULL) - self->pixelTrans->setColourMapEntries(0, 0); - - self->Fl_Window::damage(FL_DAMAGE_ALL); -} - void DesktopWindow::handleClose(Fl_Widget *wnd, void *data) { exit_vncviewer(); } - - -void DesktopWindow::handlePointerEvent(const rfb::Point& pos, int buttonMask) -{ - if (!viewOnly) { - if (pointerEventInterval == 0 || buttonMask != lastButtonMask) { - cc->writer()->pointerEvent(pos, buttonMask); - } else { - if (!Fl::has_timeout(handlePointerTimeout, this)) - Fl::add_timeout((double)pointerEventInterval/1000.0, - handlePointerTimeout, this); - } - lastPointerPos = pos; - lastButtonMask = buttonMask; - } -} - - -void DesktopWindow::handlePointerTimeout(void *data) -{ - DesktopWindow *self = (DesktopWindow *)data; - - assert(self); - - self->cc->writer()->pointerEvent(self->lastPointerPos, self->lastButtonMask); -} - - -rdr::U32 DesktopWindow::translateKeyEvent(int keyCode, const char *keyText) -{ - unsigned ucs; - - // 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')); - - // 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; - case XK_ISO_Level3_Shift: - // FLTK tends to let this one leak through on X11... - return XK_ISO_Level3_Shift; - } - - // Ctrl and Cmd tend to fudge input handling, so we need to cheat here - if (Fl::event_state() & (FL_COMMAND | FL_CTRL)) { -#ifdef WIN32 - BYTE keystate[256]; - WCHAR wbuf[8]; - int ret; - - static char buf[32]; - - switch (fl_msg.message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - // Most buttons end up here when Ctrl is pressed. Here we can pretend - // that Ctrl isn't pressed, and do a character lookup. - GetKeyboardState(keystate); - keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0; - - ret = ToUnicode(fl_msg.wParam, 0, keystate, wbuf, sizeof(wbuf)/sizeof(wbuf[0]), 0); - if (ret != 0) { - // -1 means one dead character - ret = abs(ret); - wbuf[ret] = 0x0000; - - if (fl_utf8fromwc(buf, sizeof(buf), wbuf, ret) >= sizeof(buf)) { - vlog.error(_("Out of buffer space whilst converting key event")); - return XK_VoidSymbol; - } - - keyText = buf; - } - break; - case WM_CHAR: - case WM_SYSCHAR: - // Windows doesn't seem to have any sanity when it comes to control - // characters. We assume that Ctrl-A through Ctrl-Z range maps to - // the VK_A through VK_Z keys, and just let the rest fall through. - if ((fl_msg.wParam < 0x01) || (fl_msg.wParam > 0x1a)) - break; - - // Pretend that Ctrl isn't pressed, and do a character lookup. - GetKeyboardState(keystate); - keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0; - - // Ctrl-A is 0x01 and VK_A is 0x41, so add 0x40 for the conversion - ret = ToUnicode(fl_msg.wParam + 0x40, 0, keystate, wbuf, sizeof(wbuf)/sizeof(wbuf[0]), 0); - if (ret != 0) { - // -1 means one dead character - ret = abs(ret); - wbuf[ret] = 0x0000; - - if (fl_utf8fromwc(buf, sizeof(buf), wbuf, ret) >= sizeof(buf)) { - vlog.error(_("Out of buffer space whilst converting key event")); - return XK_VoidSymbol; - } - - keyText = buf; - } - break; - default: - // Not sure how we ended up here. Do nothing... - break; - } -#elif defined(__APPLE__) - keyText = osx_event_string(); -#else - char buf[16]; - KeySym sym; - - XLookupString((XKeyEvent*)fl_xevent, buf, sizeof(buf), &sym, NULL); - - return sym; -#endif - } - - // Unknown special key? - if (keyText[0] == '\0') { - vlog.error(_("Unknown FLTK key code %d (0x%04x)"), keyCode, keyCode); - return XK_VoidSymbol; - } - - // 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 XK_VoidSymbol; - } - - ucs = fl_utf8decode(keyText, NULL, NULL); - return ucs2keysym(ucs); -} - - -void DesktopWindow::handleKeyEvent(int keyCode, const char *keyText, bool down) -{ - rdr::U32 keySym; - - if (viewOnly) - return; - - // Because of the way keyboards work, we cannot expect to have the same - // symbol on release as when pressed. This breaks the VNC protocol however, - // so we need to keep track of what keysym a key _code_ generated on press - // and send the same on release. - if (!down) { - DownMap::iterator iter; - - iter = downKeySym.find(keyCode); - if (iter == downKeySym.end()) { - vlog.error(_("Unexpected release of FLTK key code %d (0x%04x)"), keyCode, keyCode); - return; - } - - cc->writer()->keyEvent(iter->second, false); - - downKeySym.erase(iter); - - return; - } - - keySym = translateKeyEvent(keyCode, keyText); - if (keySym == XK_VoidSymbol) - return; - - downKeySym[keyCode] = keySym; - cc->writer()->keyEvent(keySym, down); -} |