]> source.dussan.org Git - tigervnc.git/commitdiff
Fade overlay in and out
authorPierre Ossman <ossman@cendio.se>
Fri, 10 Feb 2017 15:37:52 +0000 (16:37 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 10 Feb 2017 16:05:22 +0000 (17:05 +0100)
vncviewer/DesktopWindow.cxx
vncviewer/DesktopWindow.h
vncviewer/Surface.h
vncviewer/Surface_OSX.cxx
vncviewer/Surface_Win32.cxx
vncviewer/Surface_X11.cxx

index 0dc03c41b9fccad5fed3a8abcc2b8fd6a43f7740..190b39ccbde9828c3d5aa5819a56705827eecb2c 100644 (file)
@@ -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);
 }
index 1390e4f417f4f28f294eda5b179128aaaa5f9cf0..3dfaaea8eea6ac312785b6ea1a2707240c52c346 100644 (file)
@@ -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;
index 7d1646817b0ac88dc17e42437ed5d4b8c9073086..032889b4f1faa45a35ad0c22de3d6a0854529ef5 100644 (file)
@@ -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();
index 73c10f46ec689022ef309e89ce6312b3c6f0d819..2dfaa477cff1c6d4e86e27b9a75f3b754d7680d0 100644 (file)
@@ -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);
index 87b0cb2fdaf6cdf21d87b8ef1702165d8a578032..9400f536002ddf92c20660692ca9bbbb264741ee 100644 (file)
@@ -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)) {
index f36976faaf6088bfc6a8624846266e688ed5d769..3523da3d7a542304d1b1bde7e6659a29379ad9a9 100644 (file)
@@ -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);
 }