aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2017-02-10 16:37:52 +0100
committerPierre Ossman <ossman@cendio.se>2017-02-10 17:05:22 +0100
commit455566e8b5b2ea5bd78350769eb2d62279cc0dc6 (patch)
tree565642fe2f474b046fe0aeb2d3a50e3211fabac1 /vncviewer
parent4f0647da6a044f4d82d312a11ea8755d1aa7b63d (diff)
downloadtigervnc-455566e8b5b2ea5bd78350769eb2d62279cc0dc6.tar.gz
tigervnc-455566e8b5b2ea5bd78350769eb2d62279cc0dc6.zip
Fade overlay in and out
Diffstat (limited to 'vncviewer')
-rw-r--r--vncviewer/DesktopWindow.cxx36
-rw-r--r--vncviewer/DesktopWindow.h4
-rw-r--r--vncviewer/Surface.h4
-rw-r--r--vncviewer/Surface_OSX.cxx16
-rw-r--r--vncviewer/Surface_Win32.cxx6
-rw-r--r--vncviewer/Surface_X11.cxx46
6 files changed, 84 insertions, 28 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 0dc03c41..190b39cc 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -24,6 +24,7 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
+#include <sys/time.h>
#include <rfb/LogWriter.h>
#include <rfb/CMsgWriter.h>
@@ -187,7 +188,7 @@ DesktopWindow::~DesktopWindow()
Fl::remove_timeout(handleFullscreenTimeout, this);
Fl::remove_timeout(handleEdgeScroll, this);
Fl::remove_timeout(menuOverlay, this);
- Fl::remove_timeout(clearOverlay, this);
+ Fl::remove_timeout(updateOverlay, this);
OptionsDialog::removeCallback(handleOptions);
@@ -336,9 +337,9 @@ void DesktopWindow::draw()
fl_clip_box(ox, oy, ow, oh, ox, oy, ow, oh);
if (offscreen)
- overlay->blend(offscreen, ox - X, oy - Y, ox, oy, ow, oh);
+ overlay->blend(offscreen, ox - X, oy - Y, ox, oy, ow, oh, overlayAlpha);
else
- overlay->blend(ox - X, oy - Y, ox, oy, ow, oh);
+ overlay->blend(ox - X, oy - Y, ox, oy, ow, oh, overlayAlpha);
}
// Flush offscreen surface to screen
@@ -469,7 +470,7 @@ void DesktopWindow::setOverlay(const char* text, ...)
const unsigned char* b;
delete overlay;
- Fl::remove_timeout(clearOverlay, this);
+ Fl::remove_timeout(updateOverlay, this);
va_start(ap, text);
vsnprintf(textbuf, sizeof(textbuf), text, ap);
@@ -538,21 +539,36 @@ void DesktopWindow::setOverlay(const char* text, ...)
h = image->h();
overlay = new Surface(image);
+ overlayAlpha = 0;
+ gettimeofday(&overlayStart, NULL);
delete image;
- damage(FL_DAMAGE_USER1);
-
- Fl::add_timeout(3.0, clearOverlay, this);
+ Fl::add_timeout(1.0/60, updateOverlay, this);
}
-void DesktopWindow::clearOverlay(void *data)
+void DesktopWindow::updateOverlay(void *data)
{
DesktopWindow *self;
+ unsigned elapsed;
self = (DesktopWindow*)data;
- delete self->overlay;
- self->overlay = NULL;
+
+ elapsed = msSince(&self->overlayStart);
+
+ if (elapsed < 500) {
+ self->overlayAlpha = (unsigned)255 * elapsed / 500;
+ Fl::add_timeout(1.0/60, updateOverlay, self);
+ } else if (elapsed < 3500) {
+ self->overlayAlpha = 255;
+ Fl::add_timeout(3.0, updateOverlay, self);
+ } else if (elapsed < 4000) {
+ self->overlayAlpha = (unsigned)255 * (4000 - elapsed) / 500;
+ Fl::add_timeout(1.0/60, updateOverlay, self);
+ } else {
+ delete self->overlay;
+ self->overlay = NULL;
+ }
self->damage(FL_DAMAGE_USER1);
}
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
index 1390e4f4..3dfaaea8 100644
--- a/vncviewer/DesktopWindow.h
+++ b/vncviewer/DesktopWindow.h
@@ -76,7 +76,7 @@ private:
static void menuOverlay(void *data);
void setOverlay(const char *text, ...) __printf_attr(2, 3);
- static void clearOverlay(void *data);
+ static void updateOverlay(void *data);
static int fltkHandle(int event, Fl_Window *win);
@@ -109,6 +109,8 @@ private:
Viewport *viewport;
Surface *offscreen;
Surface *overlay;
+ unsigned char overlayAlpha;
+ struct timeval overlayStart;
bool firstUpdate;
bool delayedFullscreen;
diff --git a/vncviewer/Surface.h b/vncviewer/Surface.h
index 7d164681..032889b4 100644
--- a/vncviewer/Surface.h
+++ b/vncviewer/Surface.h
@@ -44,8 +44,8 @@ public:
void draw(int src_x, int src_y, int x, int y, int w, int h);
void draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int h);
- void blend(int src_x, int src_y, int x, int y, int w, int h);
- void blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h);
+ void blend(int src_x, int src_y, int x, int y, int w, int h, int a=255);
+ void blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a=255);
protected:
void alloc();
diff --git a/vncviewer/Surface_OSX.cxx b/vncviewer/Surface_OSX.cxx
index 73c10f46..2dfaa477 100644
--- a/vncviewer/Surface_OSX.cxx
+++ b/vncviewer/Surface_OSX.cxx
@@ -28,7 +28,8 @@
#include "Surface.h"
-static void render(CGContextRef gc, CGImageRef image, CGBlendMode mode,
+static void render(CGContextRef gc, CGImageRef image,
+ CGBlendMode mode, CGFloat alpha,
int src_x, int src_y, int src_w, int src_h,
int x, int y, int w, int h)
{
@@ -37,6 +38,7 @@ static void render(CGContextRef gc, CGImageRef image, CGBlendMode mode,
CGContextSaveGState(gc);
CGContextSetBlendMode(gc, mode);
+ CGContextSetAlpha(gc, alpha);
// We have to use clipping to partially display an image
rect.origin.x = x;
@@ -109,7 +111,7 @@ void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
src_y = height() - (src_y + h);
y = Fl_Window::current()->h() - (y + h);
- render(fl_gc, image, kCGBlendModeCopy,
+ render(fl_gc, image, kCGBlendModeCopy, 1.0,
src_x, src_y, width(), height(), x, y, w, h);
CGContextRestoreGState(fl_gc);
@@ -125,13 +127,13 @@ void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int
src_y = height() - (src_y + h);
y = dst->height() - (y + h);
- render(bitmap, image, kCGBlendModeCopy,
+ render(bitmap, image, kCGBlendModeCopy, 1.0,
src_x, src_y, width(), height(), x, y, w, h);
CGContextRelease(bitmap);
}
-void Surface::blend(int src_x, int src_y, int x, int y, int w, int h)
+void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a)
{
CGContextSaveGState(fl_gc);
@@ -143,13 +145,13 @@ void Surface::blend(int src_x, int src_y, int x, int y, int w, int h)
src_y = height() - (src_y + h);
y = Fl_Window::current()->h() - (y + h);
- render(fl_gc, image, kCGBlendModeNormal,
+ render(fl_gc, image, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, width(), height(), x, y, w, h);
CGContextRestoreGState(fl_gc);
}
-void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
+void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a)
{
CGContextRef bitmap;
@@ -159,7 +161,7 @@ void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int
src_y = height() - (src_y + h);
y = dst->height() - (y + h);
- render(bitmap, image, kCGBlendModeNormal,
+ render(bitmap, image, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, width(), height(), x, y, w, h);
CGContextRelease(bitmap);
diff --git a/vncviewer/Surface_Win32.cxx b/vncviewer/Surface_Win32.cxx
index 87b0cb2f..9400f536 100644
--- a/vncviewer/Surface_Win32.cxx
+++ b/vncviewer/Surface_Win32.cxx
@@ -89,13 +89,13 @@ void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int
DeleteDC(dstdc);
}
-void Surface::blend(int src_x, int src_y, int x, int y, int w, int h)
+void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a)
{
// Compositing doesn't work properly for window DC:s
assert(false);
}
-void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
+void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a)
{
HDC dstdc, srcdc;
BLENDFUNCTION blend;
@@ -114,7 +114,7 @@ void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
- blend.SourceConstantAlpha = 255;
+ blend.SourceConstantAlpha = a;
blend.AlphaFormat = AC_SRC_ALPHA;
if (!AlphaBlend(dstdc, x, y, w, h, srcdc, src_x, src_y, w, h, blend)) {
diff --git a/vncviewer/Surface_X11.cxx b/vncviewer/Surface_X11.cxx
index f36976fa..3523da3d 100644
--- a/vncviewer/Surface_X11.cxx
+++ b/vncviewer/Surface_X11.cxx
@@ -54,20 +54,56 @@ void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int
src_x, src_y, 0, 0, x, y, w, h);
}
-void Surface::blend(int src_x, int src_y, int x, int y, int w, int h)
+static Picture alpha_mask(int a)
{
- Picture winPict;
+ Pixmap pixmap;
+ XRenderPictFormat* format;
+ XRenderPictureAttributes rep;
+ Picture pict;
+ XRenderColor color;
+
+ if (a == 255)
+ return None;
+
+ pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
+ 1, 1, 8);
+
+ format = XRenderFindStandardFormat(fl_display, PictStandardA8);
+ rep.repeat = RepeatNormal;
+ pict = XRenderCreatePicture(fl_display, pixmap, format, CPRepeat, &rep);
+ XFreePixmap(fl_display, pixmap);
+
+ color.alpha = (unsigned)a * 65535 / 255;
+
+ XRenderFillRectangle(fl_display, PictOpSrc, pict, &color,
+ 0, 0, 1, 1);
+
+ return pict;
+}
+
+void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a)
+{
+ Picture winPict, alpha;
winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
- XRenderComposite(fl_display, PictOpOver, picture, None, winPict,
+ alpha = alpha_mask(a);
+ XRenderComposite(fl_display, PictOpOver, picture, alpha, winPict,
src_x, src_y, 0, 0, x, y, w, h);
XRenderFreePicture(fl_display, winPict);
+
+ if (alpha != None)
+ XRenderFreePicture(fl_display, alpha);
}
-void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
+void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a)
{
- XRenderComposite(fl_display, PictOpOver, picture, None, dst->picture,
+ Picture alpha;
+
+ alpha = alpha_mask(a);
+ XRenderComposite(fl_display, PictOpOver, picture, alpha, dst->picture,
src_x, src_y, 0, 0, x, y, w, h);
+ if (alpha != None)
+ XRenderFreePicture(fl_display, alpha);
}