aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2017-01-04 15:34:26 +0100
committerPierre Ossman <ossman@cendio.se>2017-02-10 17:05:22 +0100
commit4f0647da6a044f4d82d312a11ea8755d1aa7b63d (patch)
treea0536e88617e17ff67fe78e870756eb6953944d5
parentde6a5806d23d149d3a9ee94fc6b1d797ef864971 (diff)
downloadtigervnc-4f0647da6a044f4d82d312a11ea8755d1aa7b63d.tar.gz
tigervnc-4f0647da6a044f4d82d312a11ea8755d1aa7b63d.zip
Add overlay tip to help find the context menu
-rw-r--r--vncviewer/DesktopWindow.cxx171
-rw-r--r--vncviewer/DesktopWindow.h12
2 files changed, 173 insertions, 10 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 3da25054..0dc03c41 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -38,6 +38,7 @@
#include "Viewport.h"
#include <FL/Fl.H>
+#include <FL/Fl_Image_Surface.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
@@ -60,7 +61,8 @@ 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_), offscreen(NULL), firstUpdate(true),
+ : Fl_Window(w, h), cc(cc_), offscreen(NULL), overlay(NULL),
+ firstUpdate(true),
delayedFullscreen(false), delayedDesktopSize(false)
{
Fl_Group* group;
@@ -170,6 +172,9 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
Fl::add_timeout(0.5, handleFullscreenTimeout, this);
fullscreen_on();
}
+
+ // Show hint about menu key
+ Fl::add_timeout(0.5, menuOverlay, this);
}
@@ -181,9 +186,12 @@ DesktopWindow::~DesktopWindow()
Fl::remove_timeout(handleResizeTimeout, this);
Fl::remove_timeout(handleFullscreenTimeout, this);
Fl::remove_timeout(handleEdgeScroll, this);
+ Fl::remove_timeout(menuOverlay, this);
+ Fl::remove_timeout(clearOverlay, this);
OptionsDialog::removeCallback(handleOptions);
+ delete overlay;
delete offscreen;
// FLTK automatically deletes all child widgets, so we shouldn't touch
@@ -255,7 +263,8 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h)
}
-void DesktopWindow::setCursor(int width, int height, const Point& hotspot,
+void DesktopWindow::setCursor(int width, int height,
+ const rfb::Point& hotspot,
void* data, void* mask)
{
viewport->setCursor(width, height, hotspot, data, mask);
@@ -268,8 +277,9 @@ void DesktopWindow::draw()
int X, Y, W, H;
- // X11 needs an off screen buffer for compositing to avoid flicker
-#if !defined(WIN32) && !defined(__APPLE__)
+ // X11 needs an off screen buffer for compositing to avoid flicker,
+ // and alpha blending doesn't work for windows on Win32
+#if !defined(__APPLE__)
// Adjust offscreen surface dimensions
if ((offscreen == NULL) ||
@@ -287,6 +297,15 @@ void DesktopWindow::draw()
// Full redraw?
redraw = (damage() & ~FL_DAMAGE_CHILD);
+ // Simplify the clip region to a simple rectangle in order to
+ // properly draw all the layers even if they only partially overlap
+ if (redraw)
+ X = Y = 0;
+ else
+ fl_clip_box(0, 0, W, H, X, Y, W, H);
+ fl_push_no_clip();
+ fl_push_clip(X, Y, W, H);
+
// Redraw background only on full redraws
if (redraw) {
if (offscreen)
@@ -295,9 +314,6 @@ void DesktopWindow::draw()
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 (offscreen) {
viewport->draw(offscreen);
viewport->clear_damage();
@@ -308,14 +324,32 @@ void DesktopWindow::draw()
update_child(*viewport);
}
- fl_pop_clip();
+ // Overlay (if active)
+ if (overlay) {
+ int ox, oy, ow, oh;
+
+ ox = X = (w() - overlay->width()) / 2;
+ oy = Y = 50;
+ ow = overlay->width();
+ oh = overlay->height();
+
+ fl_clip_box(ox, oy, ow, oh, ox, oy, ow, oh);
+
+ if (offscreen)
+ overlay->blend(offscreen, ox - X, oy - Y, ox, oy, ow, oh);
+ else
+ overlay->blend(ox - X, oy - Y, ox, oy, ow, oh);
+ }
// Flush offscreen surface to screen
if (offscreen) {
- fl_clip_box(0, 0, W, H, X, Y, W, H);
+ fl_clip_box(0, 0, w(), h(), X, Y, W, H);
offscreen->draw(X, Y, X, Y, W, H);
}
+ fl_pop_clip();
+ fl_pop_clip();
+
// Finally the scrollbars
if (redraw) {
@@ -407,6 +441,123 @@ void DesktopWindow::resize(int x, int y, int w, int h)
}
+void DesktopWindow::menuOverlay(void* data)
+{
+ DesktopWindow *self;
+
+ self = (DesktopWindow*)data;
+ self->setOverlay(_("Press %s to open the context menu"),
+ (const char*)menuKey);
+}
+
+void DesktopWindow::setOverlay(const char* text, ...)
+{
+ va_list ap;
+ char textbuf[1024];
+
+ Fl_Image_Surface *surface;
+
+ Fl_RGB_Image* imageText;
+ Fl_RGB_Image* image;
+
+ unsigned char* buffer;
+
+ int x, y;
+ int w, h;
+
+ unsigned char* a;
+ const unsigned char* b;
+
+ delete overlay;
+ Fl::remove_timeout(clearOverlay, this);
+
+ va_start(ap, text);
+ vsnprintf(textbuf, sizeof(textbuf), text, ap);
+ textbuf[sizeof(textbuf)-1] = '\0';
+ va_end(ap);
+
+#if !defined(WIN32) && !defined(__APPLE__)
+ // FLTK < 1.3.5 crashes if fl_gc is unset
+ if (!fl_gc)
+ fl_gc = XDefaultGC(fl_display, 0);
+#endif
+
+ fl_font(FL_HELVETICA, FL_NORMAL_SIZE * 2);
+ fl_measure(textbuf, w, h);
+
+ // Margins
+ w += 80;
+ h += 40;
+
+ surface = new Fl_Image_Surface(w, h);
+ surface->set_current();
+
+ fl_rectf(0, 0, w, h, 0, 0, 0);
+
+ fl_font(FL_HELVETICA, FL_NORMAL_SIZE * 2);
+ fl_color(FL_WHITE);
+ fl_draw(textbuf, 40, 20 + fl_height() - fl_descent());
+
+ imageText = surface->image();
+ delete surface;
+
+ Fl_Display_Device::display_device()->set_current();
+
+ buffer = new unsigned char[w * h * 4];
+ image = new Fl_RGB_Image(buffer, w, h, 4);
+
+ a = buffer;
+ for (x = 0;x < image->w() * image->h();x++) {
+ a[0] = a[1] = a[2] = 0x40;
+ a[3] = 0xcc;
+ a += 4;
+ }
+
+ a = buffer;
+ b = (const unsigned char*)imageText->data()[0];
+ for (y = 0;y < h;y++) {
+ for (x = 0;x < w;x++) {
+ unsigned char alpha;
+ alpha = *b;
+ a[0] = (unsigned)a[0] * (255 - alpha) / 255 + alpha;
+ a[1] = (unsigned)a[1] * (255 - alpha) / 255 + alpha;
+ a[2] = (unsigned)a[2] * (255 - alpha) / 255 + alpha;
+ a[3] = 255 - (255 - a[3]) * (255 - alpha) / 255;
+ a += 4;
+ b += imageText->d();
+ }
+ if (imageText->ld() != 0)
+ b += imageText->ld() - w * imageText->d();
+ }
+
+ delete imageText;
+
+ x = (this->w() - image->w()) / 2;
+ y = 50;
+ w = image->w();
+ h = image->h();
+
+ overlay = new Surface(image);
+
+ delete image;
+
+ damage(FL_DAMAGE_USER1);
+
+ Fl::add_timeout(3.0, clearOverlay, this);
+}
+
+void DesktopWindow::clearOverlay(void *data)
+{
+ DesktopWindow *self;
+
+ self = (DesktopWindow*)data;
+ delete self->overlay;
+ self->overlay = NULL;
+
+ self->damage(FL_DAMAGE_USER1);
+}
+
+
int DesktopWindow::handle(int event)
{
switch (event) {
@@ -727,7 +878,7 @@ void DesktopWindow::remoteResize(int width, int height)
int i;
rdr::U32 id;
int sx, sy, sw, sh;
- Rect viewport_rect, screen_rect;
+ rfb::Rect viewport_rect, screen_rect;
// In full screen we report all screens that are fully covered.
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
index 073be661..1390e4f4 100644
--- a/vncviewer/DesktopWindow.h
+++ b/vncviewer/DesktopWindow.h
@@ -35,6 +35,12 @@ class Viewport;
class Fl_Scrollbar;
+#ifdef __GNUC__
+# define __printf_attr(a, b) __attribute__((__format__ (__printf__, a, b)))
+#else
+# define __printf_attr(a, b)
+#endif // __GNUC__
+
class DesktopWindow : public Fl_Window {
public:
@@ -67,6 +73,11 @@ public:
void fullscreen_on();
private:
+ static void menuOverlay(void *data);
+
+ void setOverlay(const char *text, ...) __printf_attr(2, 3);
+ static void clearOverlay(void *data);
+
static int fltkHandle(int event, Fl_Window *win);
void grabKeyboard();
@@ -97,6 +108,7 @@ private:
Fl_Scrollbar *hscroll, *vscroll;
Viewport *viewport;
Surface *offscreen;
+ Surface *overlay;
bool firstUpdate;
bool delayedFullscreen;