X11 window managers are very buggy when it comes to having a window start
in full screen mode. So we'll resort to creating a normal window, and then
switching to full screen once it is mapped. Unfortunately it means we need
to handle delaying some resize handling.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4958 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 0894275..463adf3 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -53,7 +53,8 @@
 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_), firstUpdate(true),
+    delayedFullscreen(false), delayedDesktopSize(false)
 {
   Fl_Scroll *scroll = new Fl_Scroll(0, 0, w, h);
   scroll->color(FL_BLACK);
@@ -75,9 +76,16 @@
   Fl::event_dispatch(&fltkHandle);
 
 #ifdef HAVE_FLTK_FULLSCREEN
-  if (fullScreen)
+  if (fullScreen) {
+    // Hack: Window managers seem to be rather crappy at respecting
+    // fullscreen hints on initial windows. So on X11 we'll have to
+    // wait until after we've been mapped.
+#if defined(WIN32) || defined(__APPLE__)
     fullscreen_on();
-  else
+#else
+    delayedFullscreen = true;
+#endif
+  } else
 #endif
   {
     // If we are creating a window which is equal to the size on the
@@ -102,6 +110,16 @@
   // the scroll widget for things to behave sanely.
   if ((w != this->w()) || (h != this->h()))
     scroll->size(this->w(), this->h());
+
+#ifdef HAVE_FLTK_FULLSCREEN
+  if (delayedFullscreen) {
+    // Hack: Fullscreen requests may be ignored, so we need a timeout for
+    // when we should stop waiting. We also really need to wait for the
+    // resize, which can come after the fullscreen event.
+    Fl::add_timeout(0.5, handleFullscreenTimeout, this);
+    fullscreen_on();
+  }
+#endif
 }
 
 
@@ -111,6 +129,7 @@
   // again later when this object is already gone.
   Fl::remove_timeout(handleGrab, this);
   Fl::remove_timeout(handleResizeTimeout, this);
+  Fl::remove_timeout(handleFullscreenTimeout, this);
 
   OptionsDialog::removeCallback(handleOptions);
 
@@ -155,8 +174,14 @@
 void DesktopWindow::updateWindow()
 {
   if (firstUpdate) {
-    if (cc->cp.supportsSetDesktopSize)
-      remoteResize();
+    if (cc->cp.supportsSetDesktopSize) {
+      // Hack: Wait until we're in the proper mode and position until
+      // resizing things, otherwise we might send the wrong thing.
+      if (delayedFullscreen)
+        delayedDesktopSize = true;
+      else
+        handleDesktopSize();
+    }
     firstUpdate = false;
   }
 
@@ -226,8 +251,10 @@
     // a) The user has this feature turned on
     // b) The server supports it
     // c) We're not still waiting for a chance to handle DesktopSize
+    // d) We're not still waiting for startup fullscreen to kick in
     //
-    if (not firstUpdate and ::remoteResize and cc->cp.supportsSetDesktopSize) {
+    if (not firstUpdate and not delayedFullscreen and
+        ::remoteResize and cc->cp.supportsSetDesktopSize) {
       // We delay updating the remote desktop as we tend to get a flood
       // of resize events as the user is dragging the window.
       Fl::remove_timeout(handleResizeTimeout, this);
@@ -481,30 +508,32 @@
 }
 
 
+void DesktopWindow::handleDesktopSize()
+{
+  int width, height;
+
+  if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2)
+    return;
+
+  remoteResize(width, height);
+}
+
+
 void DesktopWindow::handleResizeTimeout(void *data)
 {
   DesktopWindow *self = (DesktopWindow *)data;
 
   assert(self);
 
-  self->remoteResize();
+  self->remoteResize(self->w(), self->h());
 }
 
 
-void DesktopWindow::remoteResize()
+void DesktopWindow::remoteResize(int width, int height)
 {
-  int width, height;
   ScreenSet layout;
   ScreenSet::iterator iter;
 
-  if (firstUpdate) {
-    if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2)
-      return;
-  } else {
-    width = w();
-    height = h();
-  }
-
 #ifdef HAVE_FLTK_FULLSCREEN
   if (!fullscreen_active() || (width > w()) || (height > h())) {
 #endif
@@ -690,3 +719,17 @@
     self->fullscreen_off();
 #endif
 }
+
+void DesktopWindow::handleFullscreenTimeout(void *data)
+{
+  DesktopWindow *self = (DesktopWindow *)data;
+
+  assert(self);
+
+  self->delayedFullscreen = false;
+
+  if (self->delayedDesktopSize) {
+    self->handleDesktopSize();
+    self->delayedDesktopSize = false;
+  }
+}