include_directories(${CMAKE_SOURCE_DIR}/common/rfb)
add_library(tx STATIC
- TXWindow.cxx
- TXScrollbar.cxx
- TXViewport.cxx
- TXImage.cxx
- TXMenu.cxx)
+ TXWindow.cxx)
target_link_libraries(tx ${X11_LIBRARIES})
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXEntry.h
-//
-// A TXEntry allows you to enter a single line of text in a window. The entry
-// must be tall enough to contain a line of text - if not then it will be
-// resized appropriately. If the passwd argument to the constructor is true,
-// then the text in the entry will be replaced by asterisks on the screen.
-//
-
-#ifndef __TXENTRY_H__
-#define __TXENTRY_H__
-
-#include "TXWindow.h"
-#include <X11/keysym.h>
-
-#ifndef XK_ISO_Left_Tab
-#define XK_ISO_Left_Tab 0xFE20
-#endif
-#ifndef XK_KP_Delete
-#define XK_KP_Delete 0xFF9F
-#endif
-
-// TXEntryCallback's entryCallback() method is called when one of three special
-// key presses have happened: Enter/Return, forward tab, or backward tab.
-class TXEntry;
-class TXEntryCallback {
-public:
- enum Detail { ENTER, NEXT_FOCUS, PREV_FOCUS };
- virtual void entryCallback(TXEntry* entry, Detail detail, Time time)=0;
-};
-
-
-class TXEntry : public TXWindow, public TXEventHandler {
-public:
-
- TXEntry(Display* dpy_, TXEntryCallback* cb_=0,
- TXWindow* parent_=0, bool passwd_=false, int w=1, int h=1)
- : TXWindow(dpy_, w, h, parent_), cb(cb_),
- passwd(passwd_), disabled_(false), gotFocus(false)
- {
- setEventHandler(this);
- gc = XCreateGC(dpy, win(), 0, 0);
- addEventMask(ExposureMask | KeyPressMask | FocusChangeMask
- | ButtonPressMask);
- text[0] = 0;
- int textHeight = (defaultFS->ascent + defaultFS->descent);
- int newHeight = __rfbmax(height(), textHeight + yPad*2 + bevel*2);
- if (height() < newHeight) {
- resize(width(), newHeight);
- }
- }
-
- virtual ~TXEntry() {
- XFreeGC(dpy, gc);
- // overwrite memory used to store password - not critical, but can avoid
- // accidental exposure of a password in uninitialised memory.
- if (passwd)
- memset(text, 0, maxLen);
- }
-
- // getText() gets the text in the entry.
- const char* getText() { return text; }
-
- // setText() sets the text in the entry.
- void setText(const char* text_) {
- strncpy(text, text_, maxLen-1);
- text[maxLen-1] = 0;
- paint();
- }
-
- // disabled() sets or queries the disabled state of the entry. A disabled
- // entry cannot have text entered into it.
- void disabled(bool b) { disabled_ = b; paint(); }
- bool disabled() { return disabled_; }
-
-private:
- void paint() {
- if (disabled_)
- drawBevel(gc, 0, 0, width(), height(), bevel, disabledBg,darkBg,lightBg);
- else
- drawBevel(gc, 0, 0, width(), height(), bevel, enabledBg, darkBg,lightBg);
- char* str = text;
- char stars[maxLen];
- if (passwd) {
- int i;
- for (i = 0; i < (int)strlen(text); i++) stars[i] = '*';
- stars[i] = 0;
- str = stars;
- }
- int tw = XTextWidth(defaultFS, str, strlen(str));
- int startx = bevel + xPad;
- if (startx + tw > width() - 2*bevel) {
- startx = width() - 2*bevel - tw;
- }
- XDrawString(dpy, win(), defaultGC, startx,
- (height() + defaultFS->ascent - defaultFS->descent) / 2,
- str, strlen(str));
- if (!disabled_ && gotFocus)
- XDrawLine(dpy, win(), defaultGC, startx+tw,
- (height() - defaultFS->ascent - defaultFS->descent) / 2,
- startx+tw,
- (height() + defaultFS->ascent + defaultFS->descent) / 2);
- }
-
- virtual void handleEvent(TXWindow* w, XEvent* ev) {
- switch (ev->type) {
- case Expose:
- paint();
- break;
-
- case FocusIn:
- gotFocus = true;
- paint();
- break;
-
- case FocusOut:
- gotFocus = false;
- paint();
- break;
-
- case ButtonPress:
- if (!disabled_)
- XSetInputFocus(dpy, win(), RevertToParent, ev->xbutton.time);
- break;
-
- case KeyPress:
- {
- if (disabled_ || !gotFocus) break;
- KeySym keysym;
- XComposeStatus compose;
- char buf[10];
- int count = XLookupString(&ev->xkey, buf, 10, &keysym, &compose);
- if (count >= 1 && buf[0] >= ' ' && buf[0] <= '~') {
- if (strlen(text) + count >= maxLen) {
- XBell(dpy, 0);
- } else {
- strncat(text, buf, count);
- paint();
- }
- } else if (keysym == XK_BackSpace || keysym == XK_Delete ||
- keysym == XK_KP_Delete) {
- if (strlen(text) > 0) {
- text[strlen(text)-1] = 0;
- paint();
- }
- } else if (keysym == XK_Return || keysym == XK_KP_Enter ||
- keysym == XK_Linefeed) {
- if (cb) cb->entryCallback(this, TXEntryCallback::ENTER,
- ev->xkey.time);
- } else if ((keysym == XK_Tab || keysym == XK_KP_Tab)
- && !(ev->xkey.state & ShiftMask))
- {
- if (cb) cb->entryCallback(this, TXEntryCallback::NEXT_FOCUS,
- ev->xkey.time);
- } else if (((keysym == XK_Tab || keysym == XK_KP_Tab)
- && (ev->xkey.state & ShiftMask))
- || keysym == XK_ISO_Left_Tab)
- {
- if (cb) cb->entryCallback(this, TXEntryCallback::PREV_FOCUS,
- ev->xkey.time);
- }
- }
- }
- }
- GC gc;
- enum { maxLen = 256 };
- char text[maxLen];
- TXEntryCallback* cb;
- bool passwd;
- bool disabled_;
- bool gotFocus;
-};
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXImage.cxx
-//
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <list>
-#include <rfb/TransImageGetter.h>
-#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
-#include "TXWindow.h"
-#include "TXImage.h"
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("TXImage");
-
-TXImage::TXImage(Display* d, int width, int height, Visual* vis_, int depth_)
- : xim(0), dpy(d), vis(vis_), depth(depth_), tig(0), cube(0)
-{
-#ifdef HAVE_MITSHM
- shminfo = 0;
-#endif
- width_ = width;
- height_ = height;
- for (int i = 0; i < 256; i++)
- colourMap[i].r = colourMap[i].g = colourMap[i].b = 0;
-
- if (!vis)
- vis = DefaultVisual(dpy,DefaultScreen(dpy));
- if (!depth)
- depth = DefaultDepth(dpy,DefaultScreen(dpy));
-
- createXImage();
- getNativePixelFormat(vis, depth);
- colourmap = this;
- format.bpp = 0; // just make it different to any valid format, so that...
- setPF(nativePF); // ...setPF() always works
-}
-
-TXImage::~TXImage()
-{
- if (data != (rdr::U8*)xim->data) delete [] data;
- destroyXImage();
- delete tig;
- delete cube;
-}
-
-void TXImage::resize(int w, int h)
-{
- if (w == width() && h == height()) return;
-
- int oldStrideBytes = getStride() * (format.bpp/8);
- int rowsToCopy = __rfbmin(h, height());
- int bytesPerRow = __rfbmin(w, width()) * (format.bpp/8);
- rdr::U8* oldData = 0;
- bool allocData = false;
-
- if (data != (rdr::U8*)xim->data) {
- oldData = (rdr::U8*)data;
- allocData = true;
- } else {
- oldData = new rdr::U8[xim->bytes_per_line * height()];
- memcpy(oldData, xim->data, xim->bytes_per_line * height());
- }
-
- destroyXImage();
- width_ = w;
- height_ = h;
- createXImage();
-
- if (allocData)
- data = new rdr::U8[width() * height() * (format.bpp/8)];
- else
- data = (rdr::U8*)xim->data;
-
- int newStrideBytes = getStride() * (format.bpp/8);
- for (int i = 0; i < rowsToCopy; i++)
- memcpy((rdr::U8*)data + newStrideBytes * i, oldData + oldStrideBytes * i,
- bytesPerRow);
- delete [] oldData;
-}
-
-void TXImage::setPF(const PixelFormat& newPF)
-{
- if (newPF.equal(format)) return;
- format = newPF;
-
- if (data != (rdr::U8*)xim->data) delete [] data;
- delete tig;
- tig = 0;
-
- if (format.equal(nativePF) && format.trueColour) {
- data = (rdr::U8*)xim->data;
- } else {
- data = new rdr::U8[width() * height() * (format.bpp/8)];
- tig = new TransImageGetter();
- tig->init(this, nativePF, 0, cube);
- }
-}
-
-int TXImage::getStride() const
-{
- if (data == (rdr::U8*)xim->data)
- return xim->bytes_per_line / (xim->bits_per_pixel / 8);
- else
- return width();
-}
-
-void TXImage::put(Window win, GC gc, const rfb::Rect& r)
-{
- if (r.is_empty()) return;
- int x = r.tl.x;
- int y = r.tl.y;
- int w = r.width();
- int h = r.height();
- if (data != (rdr::U8*)xim->data) {
- rdr::U8* ximDataStart = ((rdr::U8*)xim->data + y * xim->bytes_per_line
- + x * (xim->bits_per_pixel / 8));
- tig->getImage(ximDataStart, r,
- xim->bytes_per_line / (xim->bits_per_pixel / 8));
- }
-#ifdef HAVE_MITSHM
- if (usingShm()) {
- XShmPutImage(dpy, win, gc, xim, x, y, x, y, w, h, False);
- return;
- }
-#endif
- XPutImage(dpy, win, gc, xim, x, y, x, y, w, h);
-}
-
-void TXImage::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs)
-{
- for (int i = 0; i < nColours; i++) {
- colourMap[firstColour+i].r = rgbs[i*3];
- colourMap[firstColour+i].g = rgbs[i*3+1];
- colourMap[firstColour+i].b = rgbs[i*3+2];
- }
-}
-
-void TXImage::updateColourMap()
-{
- if (tig != 0)
- tig->setColourMapEntries(0, 0);
-}
-
-void TXImage::lookup(int index, int* r, int* g, int* b)
-{
- *r = colourMap[index].r;
- *g = colourMap[index].g;
- *b = colourMap[index].b;
-}
-
-#ifdef HAVE_MITSHM
-static bool caughtError = false;
-
-static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error)
-{
- caughtError = true;
- return 0;
-}
-
-class TXImageCleanup {
-public:
- std::list<TXImage*> images;
- ~TXImageCleanup() {
- while (!images.empty())
- delete images.front();
- }
-};
-
-static TXImageCleanup imageCleanup;
-#endif
-
-void TXImage::createXImage()
-{
-#ifdef HAVE_MITSHM
- int major, minor;
- Bool pixmaps;
-
- if (XShmQueryVersion(dpy, &major, &minor, &pixmaps)) {
- shminfo = new XShmSegmentInfo;
-
- xim = XShmCreateImage(dpy, vis, depth, ZPixmap,
- 0, shminfo, width(), height());
-
- if (xim) {
- shminfo->shmid = shmget(IPC_PRIVATE,
- xim->bytes_per_line * xim->height,
- IPC_CREAT|0777);
-
- if (shminfo->shmid != -1) {
- shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0);
-
- if (shminfo->shmaddr != (char *)-1) {
-
- shminfo->readOnly = False;
-
- XErrorHandler oldHdlr = XSetErrorHandler(XShmAttachErrorHandler);
- XShmAttach(dpy, shminfo);
- XSync(dpy, False);
- XSetErrorHandler(oldHdlr);
-
- if (!caughtError) {
- vlog.debug("Using shared memory XImage");
- imageCleanup.images.push_back(this);
- return;
- }
-
- shmdt(shminfo->shmaddr);
- } else {
- vlog.error("shmat failed");
- perror("shmat");
- }
-
- shmctl(shminfo->shmid, IPC_RMID, 0);
- } else {
- vlog.error("shmget failed");
- perror("shmget");
- }
-
- XDestroyImage(xim);
- xim = 0;
- } else {
- vlog.error("XShmCreateImage failed");
- }
-
- delete shminfo;
- shminfo = 0;
- }
-#endif
-
- xim = XCreateImage(dpy, vis, depth, ZPixmap,
- 0, 0, width(), height(), BitmapPad(dpy), 0);
-
- xim->data = (char*)malloc(xim->bytes_per_line * xim->height);
- if (!xim->data) {
- vlog.error("malloc failed");
- exit(1);
- }
-}
-
-void TXImage::destroyXImage()
-{
-#ifdef HAVE_MITSHM
- if (shminfo) {
- vlog.debug("Freeing shared memory XImage");
- shmdt(shminfo->shmaddr);
- shmctl(shminfo->shmid, IPC_RMID, 0);
- delete shminfo;
- shminfo = 0;
- imageCleanup.images.remove(this);
- }
-#endif
- // XDestroyImage() will free(xim->data) if appropriate
- if (xim) XDestroyImage(xim);
- xim = 0;
-}
-
-
-static bool supportedBPP(int bpp) {
- return (bpp == 8 || bpp == 16 || bpp == 32);
-}
-
-static int depth2bpp(Display* dpy, int depth)
-{
- int nformats;
- XPixmapFormatValues* format = XListPixmapFormats(dpy, &nformats);
-
- int i;
- for (i = 0; i < nformats; i++)
- if (format[i].depth == depth) break;
-
- if (i == nformats || !supportedBPP(format[i].bits_per_pixel))
- throw rfb::Exception("Error: couldn't find suitable pixmap format");
-
- int bpp = format[i].bits_per_pixel;
- XFree(format);
- return bpp;
-}
-
-void TXImage::getNativePixelFormat(Visual* vis, int depth)
-{
- int bpp;
- int trueColour, bigEndian;
- int redShift, greenShift, blueShift;
- int redMax, greenMax, blueMax;
-
- cube = 0;
-
- bpp = depth2bpp(dpy, depth);
- bigEndian = (ImageByteOrder(dpy) == MSBFirst);
- trueColour = (vis->c_class == TrueColor);
-
- vlog.info("Using default colormap and visual, %sdepth %d.",
- (vis->c_class == TrueColor) ? "TrueColor, " :
- ((vis->c_class == PseudoColor) ? "PseudoColor, " : ""),
- depth);
-
- redShift = ffs(vis->red_mask) - 1;
- greenShift = ffs(vis->green_mask) - 1;
- blueShift = ffs(vis->blue_mask) - 1;
- redMax = vis->red_mask >> redShift;
- greenMax = vis->green_mask >> greenShift;
- blueMax = vis->blue_mask >> blueShift;
-
- nativePF = PixelFormat(bpp, depth, bigEndian, trueColour,
- redMax, greenMax, blueMax,
- redShift, greenShift, blueShift);
-
- if (!trueColour) {
- XColor xc[256];
- cube = new rfb::ColourCube(6,6,6);
- int r;
- for (r = 0; r < cube->nRed; r++) {
- for (int g = 0; g < cube->nGreen; g++) {
- for (int b = 0; b < cube->nBlue; b++) {
- int i = (r * cube->nGreen + g) * cube->nBlue + b;
- xc[i].red = r * 65535 / (cube->nRed-1);
- xc[i].green = g * 65535 / (cube->nGreen-1);
- xc[i].blue = b * 65535 / (cube->nBlue-1);
- }
- }
- }
-
- TXWindow::getColours(dpy, xc, cube->size());
-
- for (r = 0; r < cube->nRed; r++) {
- for (int g = 0; g < cube->nGreen; g++) {
- for (int b = 0; b < cube->nBlue; b++) {
- int i = (r * cube->nGreen + g) * cube->nBlue + b;
- cube->set(r, g, b, xc[i].pixel);
- }
- }
- }
- }
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXImage.h
-//
-// A TXImage represents a rectangular off-screen image in any RFB pixel format.
-// By default it will use the "native" pixel format for the screen, which will
-// be an 8-bit colourmap unless the X display is TrueColor. The pixel format
-// can be changed via the setPF() method. The pixel data is accessible via the
-// data member inherited from FullFramePixelBuffer, or can be set via the
-// fillRect(), imageRect(), copyRect() and maskRect() methods, also inherited
-// from PixelBuffer. A rectangle of the image can be drawn into an X Window
-// via the put() method. If using a colourmap, the setColourMapEntries() and
-// updateColourMap() methods must be called to set up the colourmap as
-// appropriate.
-
-
-#ifndef __TXIMAGE_H__
-#define __TXIMAGE_H__
-
-#include <X11/Xlib.h>
-#include <rfb/PixelBuffer.h>
-#include <rfb/ColourMap.h>
-#include <rfb/ColourCube.h>
-#ifdef HAVE_MITSHM
-#include <X11/extensions/XShm.h>
-#endif
-
-namespace rfb { class TransImageGetter; }
-
-class TXImage : public rfb::FullFramePixelBuffer, public rfb::ColourMap {
-public:
- TXImage(Display* dpy, int width, int height, Visual* vis=0, int depth=0);
- ~TXImage();
-
- // resize() resizes the image, preserving the image data where possible.
- void resize(int w, int h);
-
- // put causes the given rectangle to be drawn onto the given window.
- void put(Window win, GC gc, const rfb::Rect& r);
-
- // setColourMapEntries() changes some of the entries in the colourmap.
- // However these settings won't take effect until updateColourMap() is
- // called. This is because recalculating the internal translation table can
- // be expensive.
- void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs);
- void updateColourMap();
-
-#ifdef HAVE_MITSHM
- bool usingShm() { return shminfo; }
-#else
- bool usingShm() { return 0; }
-#endif
-
- // PixelBuffer methods
- // width(), height(), getPF() etc are inherited from PixelBuffer
- virtual void setPF(const rfb::PixelFormat& pf);
- virtual int getStride() const;
-
-private:
-
- // ColourMap method
- virtual void lookup(int index, int* r, int* g, int* b);
-
- void createXImage();
- void destroyXImage();
- void getNativePixelFormat(Visual* vis, int depth);
-
- XImage* xim;
- Display* dpy;
- Visual* vis;
- int depth;
-#ifdef HAVE_MITSHM
- XShmSegmentInfo* shminfo;
-#endif
- rfb::TransImageGetter* tig;
- rfb::Colour colourMap[256];
- rfb::PixelFormat nativePF;
- rfb::ColourCube* cube;
-};
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXMenu.cxx
-//
-
-#include "TXMenu.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <rfb/util.h>
-#include <X11/keysym.h>
-
-TXMenu::TXMenu(Display* dpy_, TXMenuCallback* cb_, int w, int h,
- TXWindow* parent_)
- : TXWindow(dpy_, w, h, parent_), cb(cb_), nEntries(0),
- highlight(-1)
-{
- setEventHandler(this);
- gc = XCreateGC(dpy, win(), 0, 0);
- addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | EnterWindowMask | LeaveWindowMask);
-}
-
-TXMenu::~TXMenu()
-{
- XFreeGC(dpy, gc);
- for (int i = 0; i < nEntries; i++)
- delete [] text[i];
-}
-
-inline int TXMenu::entryHeight(int i)
-{
- if (text[i])
- return defaultFS->ascent + defaultFS->descent + bevel*2 + yPad*2;
- else
- return yPad*2 + 1;
-}
-
-void TXMenu::addEntry(const char* text_, long id_)
-{
- assert(nEntries < maxEntries);
- text[nEntries] = rfb::strDup(text_);
- checked[nEntries] = false;
- id[nEntries++] = id_;
- int tw = 0;
- if (text_)
- tw = XTextWidth(defaultFS, text_, strlen(text_));
- int newWidth = width();
- if (tw + bevel*2 + xPad*5 + tickSize > width())
- newWidth = tw + bevel*2 + xPad*5 + tickSize;
- int newHeight = 0;
- for (int i = 0; i < nEntries; i++)
- newHeight += entryHeight(i);
- resize(newWidth, newHeight);
-}
-
-void TXMenu::check(long id_, bool checked_)
-{
- for (int i = 0; i < nEntries; i++) {
- if (id[i] == id_) {
- checked[i] = checked_;
- break;
- }
- }
-}
-
-void TXMenu::paint()
-{
- int y = 0;
- for (int i = 0; i < nEntries; i++) {
- if (text[i]) {
- if (i == highlight)
- drawBevel(gc, 0, y, width(), entryHeight(i), bevel,
- defaultBg, darkBg, lightBg);
- else
- XClearArea(dpy, win(), 0, y, width(), entryHeight(i), false);
- if (checked[i])
- XCopyPlane(dpy, tick, win(), defaultGC, 0, 0, tickSize, tickSize,
- bevel + xPad,
- y + bevel + yPad + defaultFS->ascent - tickSize, 1);
-
- XDrawImageString(dpy, win(), defaultGC, bevel + xPad*2 + tickSize,
- y + bevel + yPad + defaultFS->ascent,
- text[i], strlen(text[i]));
- } else {
- XDrawLine(dpy, win(), defaultGC, bevel + xPad, y + entryHeight(i) / 2,
- width() - bevel - xPad, y + entryHeight(i) / 2);
- }
- y += entryHeight(i);
- }
-}
-
-void TXMenu::handleEvent(TXWindow* w, XEvent* ev)
-{
- switch (ev->type) {
- case Expose:
- paint();
- break;
-
- case ButtonRelease:
- {
- int y = ev->xmotion.y;
- int entryY = 0;
- for (int i = 0; i < nEntries; i++) {
- if (y >= entryY && y <= entryY + entryHeight(i)) {
- if (cb && text[i])
- cb->menuSelect(id[i], this);
- break;
- }
- entryY += entryHeight(i);
- }
- highlight = -1;
- paint();
- break;
- }
-
- case ButtonPress:
- case MotionNotify:
- {
- int y = ev->xmotion.y;
- int entryY = 0;
- for (int i = 0; i < nEntries; i++) {
- if (y >= entryY && y <= entryY + entryHeight(i)) {
- if (highlight != i) {
- highlight = i;
- paint();
- }
- break;
- }
- entryY += entryHeight(i);
- }
- break;
- }
-
- case KeyPress:
- {
- KeySym ks;
- char str[256];
- XLookupString(&ev->xkey, str, 256, &ks, NULL);
- if (ks == XK_Escape) {
- highlight = -1;
- unmap();
- } else if (ks == XK_Down || ks == XK_Up) {
- if (nEntries < 1) break;
- if (highlight < 0)
- highlight = (ks == XK_Down ? nEntries-1 : 0);
- int start = highlight;
- int inc = (ks == XK_Down ? 1 : nEntries-1);
- do {
- highlight = (highlight + inc) % nEntries;
- } while (highlight != start && !text[highlight]);
- paint();
- } else if (ks == XK_space || ks == XK_KP_Space ||
- ks == XK_Return || ks == XK_KP_Enter) {
- if (cb && highlight >= 0 && text[highlight])
- cb->menuSelect(id[highlight], this);
- highlight = -1;
- paint();
- }
- break;
- }
-
- case EnterNotify:
- case LeaveNotify:
- highlight = -1;
- paint();
- break;
- }
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXMenu.h
-//
-// A TXMenu consists of multiple entries which can be added one at a time.
-// Each entry consists of some text, and has an associated integer identifier.
-// A callback is made when a menu entry is selected.
-//
-
-#ifndef __TXMENU_H__
-#define __TXMENU_H__
-
-#include "TXWindow.h"
-
-// TXMenuCallback's menuSelect() method is called when a particular menu entry
-// is selected. The id argument identifies the menu entry.
-class TXMenu;
-class TXMenuCallback {
-public:
- virtual void menuSelect(long id, TXMenu* menu)=0;
-};
-
-class TXMenu : public TXWindow, public TXEventHandler {
-public:
- TXMenu(Display* dpy_, TXMenuCallback* cb=0, int width=1, int height=1,
- TXWindow* parent_=0);
- virtual ~TXMenu();
-
- // addEntry() adds an entry to the end of the menu with the given text and
- // identifier.
- void addEntry(const char* text, long id);
-
- // check() sets whether the given menu entry should have a tick next to it.
- void check(long id, bool checked);
-
-private:
- int entryHeight(int i);
- virtual void handleEvent(TXWindow* w, XEvent* ev);
- void paint();
-
- GC gc;
- TXMenuCallback* cb;
- enum { maxEntries = 64 };
- char* text[maxEntries];
- long id[maxEntries];
- bool checked[maxEntries];
- int nEntries;
- int highlight;
-};
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXMsgBox.h
-//
-// A TXMsgBox is a specialised pop-up dialog window, designed to present
-// the user with a small amount of textual information, and potentially to
-// obtain their response.
-// TXMsgBoxes are always modal, and may have an Ok button, Ok+Cancel buttons,
-// or Yes+No buttons.
-// The MsgBox helper function creates a TXMsgBox on the fly, runs it, and
-// returns the result.
-//
-
-#ifndef __TXMSGBOX_H__
-#define __TXMSGBOX_H__
-
-#include "TXDialog.h"
-#include "TXLabel.h"
-#include "TXButton.h"
-
-enum TXMsgBoxFlags {
- MB_OK = 0,
- MB_OKCANCEL = 1,
- MB_YESNO = 4,
- MB_ICONERROR = 0x10,
- MB_ICONQUESTION = 0x20,
- MB_ICONWARNING = 0x30,
- MB_ICONINFORMATION = 0x40,
- MB_DEFBUTTON1 = 0,
- MB_DEFBUTTON2 = 0x100
-};
-
-class TXMsgBox : public TXDialog, public TXButtonCallback {
-public:
- TXMsgBox(Display* dpy, const char* text, unsigned int flags, const char* title=0)
- : TXDialog(dpy, 1, 1, "Message", true),
- textLabel(dpy, "", this),
- okButton(dpy, "OK", this, this, 60),
- cancelButton(dpy, "Cancel", this, this, 60)
- {
- textLabel.xPad = 8;
- textLabel.move(0, yPad*4);
- textLabel.setText(text);
- resize(textLabel.width(),
- textLabel.height() + okButton.height() + yPad*12);
-
- switch (flags & 0x30) {
- case MB_ICONERROR:
- toplevel("Error", this); break;
- case MB_ICONQUESTION:
- toplevel("Question", this); break;
- case MB_ICONWARNING:
- toplevel("Warning", this); break;
- case MB_ICONINFORMATION:
- toplevel("Information", this); break;
- default:
- if (title)
- toplevel(title, this);
- break;
- };
-
- switch (flags & 0x7) {
- default:
- okButton.move((width() - okButton.width()) / 2,
- height() - yPad*4 - okButton.height());
- cancelButton.unmap();
- break;
- case MB_OKCANCEL:
- case MB_YESNO:
-
- okButton.move(((width()/2) - okButton.width()) / 2,
- height() - yPad*4 - okButton.height());
- cancelButton.move(((width()*3/2) - cancelButton.width()) / 2,
- height() - yPad*4 - cancelButton.height());
- if ((flags & 0x7) == MB_YESNO) {
- okButton.setText("Yes");
- cancelButton.setText("No");
- }
- break;
- };
-
- setBorderWidth(1);
- }
-
- virtual void buttonActivate(TXButton* b) {
- ok = (b == &okButton);
- done = true;
- unmap();
- }
-
- TXLabel textLabel;
- TXButton okButton;
- TXButton cancelButton;
-};
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXScrollbar.cxx
-//
-
-#include "TXScrollbar.h"
-#include <stdio.h>
-#include <assert.h>
-
-TXScrollbar::TXScrollbar(Display* dpy_, int width, int height, bool vert,
- TXScrollbarCallback* cb_, TXWindow* parent_)
- : TXWindow(dpy_, width, height, parent_), cb(cb_), vertical(vert),
- clickedInThumb(false)
-{
- setEventHandler(this);
- gc = XCreateGC(dpy, win(), 0, 0);
- addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask |
- ButtonMotionMask);
- setBg(scrollbarBg);
- limit[0] = len[0] = limit[1] = len[1] = 1;
- start[0] = start[1] = 0;
-}
-
-TXScrollbar::~TXScrollbar()
-{
- XFreeGC(dpy, gc);
-}
-
-void TXScrollbar::set(int limit_, int start_, int len_, bool vert)
-{
- assert(limit_ > 0 && len_ >= 0 && len_ <= limit_);
-
- if (start_ < 0) start_ = 0;
- if (start_ > limit_ - len_) start_ = limit_ - len_;
-
- if (limit[vert] != limit_ || start[vert] != start_ || len[vert] != len_) {
- limit[vert] = limit_;
- start[vert] = start_;
- len[vert] = len_;
- paint();
- }
-}
-
-void TXScrollbar::paint()
-{
- int x = scaleToBarX(start[0]);
- int y = scaleToBarY(start[1]);
- int w = scaleToBarX(len[0]);
- int h = scaleToBarY(len[1]);
- if (y > 0) XClearArea(dpy, win(), 0, 0, 0, y, false);
- if (x > 0) XClearArea(dpy, win(), 0, y, x, y+h, false);
- XClearArea(dpy, win(), x+w, y, 0, y+h, false);
- XClearArea(dpy, win(), 0, y+h, 0, 0, false);
- drawBevel(gc, x, y, w, h, bevel, defaultBg, lightBg, darkBg);
-}
-
-void TXScrollbar::handleEvent(TXWindow* w, XEvent* ev)
-{
- switch (ev->type) {
- case Expose:
- paint();
- break;
-
- case ButtonPress:
- {
- xDown = ev->xbutton.x;
- yDown = ev->xbutton.y;
- xStart = start[0];
- yStart = start[1];
- bool clickedInThumbX = false;
- if (xDown < scaleToBarX(start[0])) {
- set(limit[0], start[0] - len[0], len[0], false);
- } else if (xDown >= scaleToBarX(start[0]+len[0])) {
- set(limit[0], start[0] + len[0], len[0], false);
- } else {
- clickedInThumbX = true;
- }
- bool clickedInThumbY = false;
- if (yDown < scaleToBarY(start[1])) {
- set(limit[1], start[1] - len[1], len[1], true);
- } else if (yDown >= scaleToBarY(start[1]+len[1])) {
- set(limit[1], start[1] + len[1], len[1], true);
- } else {
- clickedInThumbY = true;
- }
- clickedInThumb = clickedInThumbX && clickedInThumbY;
- if (cb) cb->scrollbarPos(start[0], start[1], this);
- }
- break;
-
- case ButtonRelease:
- case MotionNotify:
- while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev));
- if (clickedInThumb) {
- int dx = ev->xmotion.x - xDown;
- int dy = ev->xmotion.y - yDown;
- set(limit[0], xStart + barToScaleX(dx), len[0], false);
- set(limit[1], yStart + barToScaleY(dy), len[1], true);
- if (cb) cb->scrollbarPos(start[0], start[1], this);
- }
- break;
- }
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXScrollbar.h
-//
-// A TXScrollbar represents a range of values starting at start, of length len,
-// between zero and limit. The vertical argument to the constructor says
-// whether the scrollbar is horizontal or vertical.
-//
-// In fact it can represent a range in each dimension but usually one of the
-// dimensions is fixed, according to the vertical flag (for a vertical
-// scrollbar, the horizontal dimension is fixed, and vice-versa).
-//
-// The TXScrollbarCallback argument is an object which will be notified when
-// the user has attempted to move the scrollbar. The x and y arguments to the
-// scrollbarPos() method give the start values in the respective dimensions.
-// They are guaranteed to be between 0 and limit-len.
-//
-
-#ifndef __TXSCROLLBAR_H__
-#define __TXSCROLLBAR_H__
-
-#include "TXWindow.h"
-
-class TXScrollbarCallback;
-
-class TXScrollbar : public TXWindow, public TXEventHandler {
-public:
- TXScrollbar(Display* dpy_, int width=1, int height=1, bool vertical=false,
- TXScrollbarCallback* cb=0, TXWindow* parent_=0);
- virtual ~TXScrollbar();
-
- // set() sets the limit, start and length of the range represented by the
- // scrollbar. The values of limit and len passed in must be valid
- // (i.e. limit > 0 and 0 <= len <= limit). Values of start are clipped to
- // the range 0 to limit-len.
- void set(int limit, int start, int len) { set(limit, start, len, vertical); }
-
- // set() with an extra argument vert can be used to represent a range in both
- // dimensions simultaneously.
- void set(int limit, int start, int len, bool vert);
-
- virtual void handleEvent(TXWindow* w, XEvent* ev);
-
-private:
- int scaleToBarX(int x) { return (x * width() + limit[0]/2) / limit[0]; }
- int scaleToBarY(int y) { return (y * height() + limit[1]/2) / limit[1]; }
- int barToScaleX(int x) { return (x * limit[0] + width()/2) / width(); }
- int barToScaleY(int y) { return (y * limit[1] + height()/2) / height(); }
- void paint();
-
- GC gc;
- TXScrollbarCallback* cb;
- int limit[2];
- int start[2];
- int len[2];
- int xDown, yDown;
- int xStart, yStart;
- bool vertical;
- bool clickedInThumb;
-};
-
-class TXScrollbarCallback {
-public:
- virtual void scrollbarPos(int x, int y, TXScrollbar* sb)=0;
-};
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXViewport.cxx
-//
-
-#include "TXViewport.h"
-#include <stdio.h>
-
-TXViewport::TXViewport(Display* dpy_, int w, int h, TXWindow* parent_)
- : TXWindow(dpy_, w, h, parent_), child(0), hScrollbar(0),
- vScrollbar(0), scrollbarSize(15), xOff(0), yOff(0), bumpScrollTimer(this),
- bumpScroll(false), needXScrollbar(false), needYScrollbar(false),
- bumpScrollX(0), bumpScrollY(0)
-{
- clipper = new TXWindow(dpy, width()-scrollbarSize, height()-scrollbarSize,
- this);
- clipper->setBg(black);
- hScrollbar = new TXScrollbar(dpy, width()-scrollbarSize, scrollbarSize,
- false, this, this);
- vScrollbar = new TXScrollbar(dpy, scrollbarSize, height()-scrollbarSize,
- true, this, this);
-}
-
-TXViewport::~TXViewport()
-{
- delete clipper;
- delete hScrollbar;
- delete vScrollbar;
-}
-
-void TXViewport::setChild(TXWindow* child_)
-{
- child = child_;
- XReparentWindow(dpy, child->win(), clipper->win(), 0, 0);
- xOff = yOff = 0;
- child->map();
- resizeNotify();
-}
-
-bool TXViewport::setOffset(int x, int y)
-{
- if (clipper->width() >= child->width()) {
- x = (clipper->width() - child->width()) / 2;
- } else {
- if (x > 0) x = 0;
- if (x + child->width() < clipper->width())
- x = clipper->width() - child->width();
- }
-
- if (clipper->height() >= child->height()) {
- y = (clipper->height() - child->height()) / 2;
- } else {
- if (y > 0) y = 0;
- if (y + child->height() < clipper->height())
- y = clipper->height() - child->height();
- }
-
- if (x != xOff || y != yOff) {
- xOff = x;
- yOff = y;
- child->move(xOff, yOff);
- return true;
- }
-
- return false;
-}
-
-void TXViewport::setBumpScroll(bool b)
-{
- bumpScroll = b;
- resizeNotify();
-}
-
-// Note: bumpScrollEvent() only works if the viewport is positioned at 0,0 and
-// is the same width and height as the screen.
-bool TXViewport::bumpScrollEvent(XMotionEvent* ev)
-{
- if (!bumpScroll) return false;
- int bumpScrollPixels = 20;
- bumpScrollX = bumpScrollY = 0;
-
- if (ev->x_root == width()-1) bumpScrollX = -bumpScrollPixels;
- else if (ev->x_root == 0) bumpScrollX = bumpScrollPixels;
- if (ev->y_root == height()-1) bumpScrollY = -bumpScrollPixels;
- else if (ev->y_root == 0) bumpScrollY = bumpScrollPixels;
-
- if (bumpScrollX || bumpScrollY) {
- if (bumpScrollTimer.isStarted()) return true;
- if (setOffset(xOff + bumpScrollX, yOff + bumpScrollY)) {
- bumpScrollTimer.start(25);
- return true;
- }
- }
-
- bumpScrollTimer.stop();
- return false;
-}
-
-bool TXViewport::handleTimeout(rfb::Timer* timer) {
- return setOffset(xOff + bumpScrollX, yOff + bumpScrollY);
-}
-
-void TXViewport::resizeNotify()
-{
- int winMaxWidth, winMaxHeight;
-
- winMaxWidth = child->width();
- winMaxHeight = child->height();
-
- needXScrollbar = false;
- needYScrollbar = false;
- if (!bumpScroll && height() > scrollbarSize && width() > scrollbarSize) {
- needXScrollbar = (width() < child->width());
- needYScrollbar = (height() < child->height());
- // Adding an horizontal scrollbar occupies space, which might cause the
- // need to add a vertical scrollbar, and vice-versa. These additional
- // checks should solve this problem
- if (needXScrollbar && (height() - scrollbarSize < child->height()))
- needYScrollbar = true;
- if (needYScrollbar && (width() - scrollbarSize < child->width()))
- needXScrollbar = true;
- }
-
- if (needXScrollbar)
- winMaxHeight += scrollbarSize;
- if (needYScrollbar)
- winMaxWidth += scrollbarSize;
- setMaxSize(winMaxWidth, winMaxHeight);
-
- if (needXScrollbar && needYScrollbar) {
- clipper->resize(width()-scrollbarSize, height()-scrollbarSize);
- hScrollbar->map();
- vScrollbar->map();
- } else if (needXScrollbar) {
- clipper->resize(width(), height()-scrollbarSize);
- hScrollbar->map();
- vScrollbar->unmap();
- } else if (needYScrollbar) {
- clipper->resize(width()-scrollbarSize, height());
- hScrollbar->unmap();
- vScrollbar->map();
- } else {
- clipper->resize(width(), height());
- hScrollbar->unmap();
- vScrollbar->unmap();
- }
-
- setOffset(xOff, yOff);
-
- if (needXScrollbar) {
- hScrollbar->move(0, height()-scrollbarSize);
- hScrollbar->resize(width()-scrollbarSize, scrollbarSize);
- hScrollbar->set(child->width(), -xOff, width()-scrollbarSize);
- }
-
- if (needYScrollbar) {
- vScrollbar->move(width()-scrollbarSize, 0);
- vScrollbar->resize(scrollbarSize, height()-scrollbarSize);
- vScrollbar->set(child->height(), -yOff, height()-scrollbarSize);
- }
-}
-
-void TXViewport::scrollbarPos(int x, int y, TXScrollbar* sb)
-{
- if (sb == hScrollbar) {
- x = -x;
- y = yOff;
- } else {
- x = xOff;
- y = -y;
- }
- setOffset(x, y);
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// TXViewport.h
-//
-// A TXViewport allows a large window to be viewed by adding scrollbars to the
-// right and bottom if necessary. It also has a bump-scroll mode where there
-// are no scrollbars, and scrolling is achieved by bumping up against the edge
-// of the screen instead. Note that this only works when the viewport fills
-// the entire screen. If the child window is smaller than the viewport, it is
-// always positioned centrally in the viewport.
-
-#ifndef __TXVIEWPORT_H__
-#define __TXVIEWPORT_H__
-
-#include <rfb/Timer.h>
-#include "TXWindow.h"
-#include "TXScrollbar.h"
-
-class TXViewport : public TXWindow, public TXScrollbarCallback,
- public rfb::Timer::Callback {
-public:
- TXViewport(Display* dpy_, int width, int height, TXWindow* parent_=0);
- virtual ~TXViewport();
-
- // setChild() sets the child window which is to be viewed in the viewport.
- void setChild(TXWindow* child_);
-
- // setOffset() sets the position of the child in the viewport. Note that the
- // offsets are negative. For example when the offset is (-100,-30), position
- // (100,30) in the child window is at the top-left of the viewport. The
- // offsets given are clipped to keep the child window filling the viewport
- // (except where the child window is smaller than the viewport, in which case
- // it is always positioned centrally in the viewport). It returns true if
- // the child was repositioned.
- bool setOffset(int x, int y);
-
- // setBumpScroll() puts the viewport in bump-scroll mode.
- void setBumpScroll(bool b);
-
- // bumpScrollEvent() can be called with a MotionNotify event which may
- // potentially be against the edge of the screen. It returns true if the
- // event was used for bump-scrolling, false if it should be processed
- // normally.
- bool bumpScrollEvent(XMotionEvent* ev);
-
-private:
- virtual void resizeNotify();
- virtual void scrollbarPos(int x, int y, TXScrollbar* sb);
- virtual bool handleTimeout(rfb::Timer* timer);
- TXWindow* clipper;
- TXWindow* child;
- TXScrollbar* hScrollbar;
- TXScrollbar* vScrollbar;
- const int scrollbarSize;
- int xOff, yOff;
- rfb::Timer bumpScrollTimer;
- bool bumpScroll;
- bool needXScrollbar;
- bool needYScrollbar;
- int bumpScrollX, bumpScrollY;
-};
-#endif