summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2009-03-25 10:32:07 +0000
committerPierre Ossman <ossman@cendio.se>2009-03-25 10:32:07 +0000
commit9760ff6ef9b538b92e93d9eb8db1b342eb3fc9d6 (patch)
treeafdb2367f00c98e3709a11e431569a27325dc475
parentd6d1994cff97bda9602b02e4161aec8774be2d64 (diff)
downloadtigervnc-9760ff6ef9b538b92e93d9eb8db1b342eb3fc9d6.tar.gz
tigervnc-9760ff6ef9b538b92e93d9eb8db1b342eb3fc9d6.zip
Try to update an entire FramebufferUpdate in one go, avoiding tears.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3717 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r--unix/vncviewer/DesktopWindow.cxx36
-rw-r--r--unix/vncviewer/DesktopWindow.h18
2 files changed, 34 insertions, 20 deletions
diff --git a/unix/vncviewer/DesktopWindow.cxx b/unix/vncviewer/DesktopWindow.cxx
index 89198596..36f96fc7 100644
--- a/unix/vncviewer/DesktopWindow.cxx
+++ b/unix/vncviewer/DesktopWindow.cxx
@@ -65,7 +65,7 @@ static rfb::LogWriter vlog("DesktopWindow");
DesktopWindow::DesktopWindow(Display* dpy, int w, int h,
const rfb::PixelFormat& serverPF,
CConn* cc_, TXWindow* parent)
- : TXWindow(dpy, w, h, parent), cc(cc_), im(0),
+ : TXWindow(dpy, w, h, parent), cc(cc_), im(0), updateTimer(this),
cursorVisible(false), cursorAvailable(false), currentSelectionTime(0),
newSelection(0), gettingInitialSelectionTime(true),
newServerCutText(false), serverCutText_(0),
@@ -216,7 +216,6 @@ void DesktopWindow::hideLocalCursor()
if (cursorVisible) {
cursorVisible = false;
im->imageRect(cursorBackingRect, cursorBacking.data);
- im->put(win(), gc, cursorBackingRect);
}
}
@@ -238,7 +237,6 @@ void DesktopWindow::showLocalCursor()
im->getImage(cursorBacking.data, cursorBackingRect);
im->maskRect(cursorRect, cursor.data, cursor.mask.buf);
- im->put(win(), gc, cursorBackingRect);
}
}
@@ -266,19 +264,11 @@ void DesktopWindow::serverCutText(const char* str, rdr::U32 len)
}
-// Call XSync() at the end of an update. We do this because we'd like to
-// ensure that the current update has actually been drawn by the X server
-// before the next update arrives - this is necessary for copyRect to
-// behave correctly. In particular, if part of the source of a copyRect is
-// not actually displayed in the window, then XCopyArea results in
-// GraphicsExpose events, which require us to draw from the off-screen
-// image. By the time XSync returns, the GraphicsExpose events will be in
-// Xlib's queue, so hopefully will be processed before the next update.
-// Possibly we should process the GraphicsExpose events here explicitly?
+// Update the actual window with the changed parts of the framebuffer.
void DesktopWindow::framebufferUpdateEnd()
{
- XSync(dpy, False);
+ updateWindow();
}
@@ -297,7 +287,7 @@ void DesktopWindow::invertRect(const Rect& r)
}
}
}
- im->put(win(), gc, r);
+ damageRect(r);
}
@@ -311,6 +301,22 @@ void DesktopWindow::resize(int w, int h)
}
+// Copy the areas of the framebuffer that have been changed (damaged)
+// to the displayed window.
+
+void DesktopWindow::updateWindow()
+{
+ Rect r;
+
+ updateTimer.stop();
+
+ r = damage.get_bounding_rect();
+ damage.clear();
+
+ im->put(win(), gc, r);
+}
+
+
bool DesktopWindow::handleTimeout(rfb::Timer* timer)
{
if (timer == &setColourMapEntriesTimer) {
@@ -320,6 +326,8 @@ bool DesktopWindow::handleTimeout(rfb::Timer* timer)
if (!viewOnly) {
cc->writer()->pointerEvent(lastPointerPos, lastButtonMask);
}
+ } else if (timer == &updateTimer) {
+ updateWindow();
}
return false;
}
diff --git a/unix/vncviewer/DesktopWindow.h b/unix/vncviewer/DesktopWindow.h
index fe5ef82a..433ac33b 100644
--- a/unix/vncviewer/DesktopWindow.h
+++ b/unix/vncviewer/DesktopWindow.h
@@ -24,6 +24,7 @@
#include <rfb/Cursor.h>
#include <rfb/Rect.h>
+#include <rfb/Region.h>
#include <rfb/Timer.h>
#include "TXWindow.h"
#include "TXViewport.h"
@@ -61,13 +62,13 @@ public:
void fillRect(const rfb::Rect& r, rfb::Pixel pix) {
if (r.overlaps(cursorBackingRect)) hideLocalCursor();
im->fillRect(r, pix);
- im->put(win(), gc, r);
+ damageRect(r);
showLocalCursor();
}
void imageRect(const rfb::Rect& r, void* pixels) {
if (r.overlaps(cursorBackingRect)) hideLocalCursor();
im->imageRect(r, pixels);
- im->put(win(), gc, r);
+ damageRect(r);
showLocalCursor();
}
void copyRect(const rfb::Rect& r, int srcX, int srcY) {
@@ -75,11 +76,8 @@ public:
cursorBackingRect.overlaps(rfb::Rect(srcX, srcY,
srcX+r.width(), srcY+r.height())))
hideLocalCursor();
- if (im->usingShm())
- XSync(dpy, False);
im->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY));
- XCopyArea(dpy, win(), win(), gc, srcX, srcY,
- r.width(), r.height(), r.tl.x, r.tl.y);
+ damageRect(r);
showLocalCursor();
}
void invertRect(const rfb::Rect& r);
@@ -97,12 +95,20 @@ private:
void createXCursors();
void hideLocalCursor();
void showLocalCursor();
+ void damageRect(const rfb::Rect& r) {
+ damage.assign_union(rfb::Region(r));
+ if (!updateTimer.isStarted())
+ updateTimer.start(100);
+ };
+ void updateWindow();
bool handleTimeout(rfb::Timer* timer);
void handlePointerEvent(const rfb::Point& pos, int buttonMask);
CConn* cc;
TXImage* im;
GC gc;
+ rfb::Region damage;
+ rfb::Timer updateTimer;
::Cursor dotCursor, noCursor, localXCursor;
rfb::Cursor cursor;