aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/DesktopWindow.cxx
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2017-01-02 19:49:52 +0100
committerPierre Ossman <ossman@cendio.se>2017-02-10 17:05:20 +0100
commit3d74d88806d09f3a899be5d8f1df8ec20ed9a14d (patch)
treea2a86607aa8dda47559c5be82fadad9247844193 /vncviewer/DesktopWindow.cxx
parent403ac27d2377df4fed8bf5039125f6d89aaa6955 (diff)
downloadtigervnc-3d74d88806d09f3a899be5d8f1df8ec20ed9a14d.tar.gz
tigervnc-3d74d88806d09f3a899be5d8f1df8ec20ed9a14d.zip
Render on a temporary surface when needed
Some platforms draw directly to the screen, which means that updates will flicker if we draw multiple layers. Prevent this by first composing the update on a hidden surface.
Diffstat (limited to 'vncviewer/DesktopWindow.cxx')
-rw-r--r--vncviewer/DesktopWindow.cxx54
1 files changed, 36 insertions, 18 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 707628ee..3da25054 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -34,6 +34,7 @@
#include "parameters.h"
#include "vncviewer.h"
#include "CConn.h"
+#include "Surface.h"
#include "Viewport.h"
#include <FL/Fl.H>
@@ -59,7 +60,7 @@ 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_), firstUpdate(true),
+ : Fl_Window(w, h), cc(cc_), offscreen(NULL), firstUpdate(true),
delayedFullscreen(false), delayedDesktopSize(false)
{
Fl_Group* group;
@@ -183,6 +184,8 @@ DesktopWindow::~DesktopWindow()
OptionsDialog::removeCallback(handleOptions);
+ delete offscreen;
+
// FLTK automatically deletes all child widgets, so we shouldn't touch
// them ourselves here
}
@@ -263,7 +266,19 @@ void DesktopWindow::draw()
{
bool redraw;
- int W, H;
+ int X, Y, W, H;
+
+ // X11 needs an off screen buffer for compositing to avoid flicker
+#if !defined(WIN32) && !defined(__APPLE__)
+
+ // Adjust offscreen surface dimensions
+ if ((offscreen == NULL) ||
+ (offscreen->width() != w()) || (offscreen->height() != h())) {
+ delete offscreen;
+ offscreen = new Surface(w(), h());
+ }
+
+#endif
// Active area inside scrollbars
W = w() - (vscroll->visible() ? vscroll->w() : 0);
@@ -274,30 +289,33 @@ void DesktopWindow::draw()
// Redraw background only on full redraws
if (redraw) {
- if (viewport->h() < h()) {
- fl_rectf(0, 0, W, viewport->y(), 40, 40, 40);
- fl_rectf(0, viewport->y() + viewport->h(), W,
- h() - (viewport->y() + viewport->h()),
- 40, 40, 40);
- }
- if (viewport->w() < w()) {
- fl_rectf(0, 0, viewport->x(), H, 40, 40, 40);
- fl_rectf(viewport->x() + viewport->w(), 0,
- w() - (viewport->x() + viewport->w()),
- H, 40, 40, 40);
- }
+ if (offscreen)
+ offscreen->clear(40, 40, 40);
+ else
+ fl_rectf(0, 0, W, H, 40, 40, 40);
}
// Make sure the viewport isn't trampling on the scrollbars
fl_push_clip(0, 0, W, H);
- if (redraw)
- draw_child(*viewport);
- else
- update_child(*viewport);
+ if (offscreen) {
+ viewport->draw(offscreen);
+ viewport->clear_damage();
+ } else {
+ if (redraw)
+ draw_child(*viewport);
+ else
+ update_child(*viewport);
+ }
fl_pop_clip();
+ // Flush offscreen surface to screen
+ if (offscreen) {
+ fl_clip_box(0, 0, W, H, X, Y, W, H);
+ offscreen->draw(X, Y, X, Y, W, H);
+ }
+
// Finally the scrollbars
if (redraw) {