Revision: 4935
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4935&view=rev
Author:   ossman_
Date:     2012-07-13 11:22:55 +0000 (Fri, 13 Jul 2012)
Log Message:
-----------
Implement client side multi-head support. Requires a FLTK patched to support
fullscreen over multiple monitors. Will properly report screen configuration
to the server, provided the server supports it.

Modified Paths:
--------------
    trunk/CMakeLists.txt
    trunk/config.h.in
    trunk/vncviewer/DesktopWindow.cxx
    trunk/vncviewer/DesktopWindow.h
    trunk/vncviewer/OptionsDialog.cxx
    trunk/vncviewer/OptionsDialog.h
    trunk/vncviewer/Viewport.cxx
    trunk/vncviewer/parameters.cxx
    trunk/vncviewer/parameters.h

Modified: trunk/CMakeLists.txt
===================================================================
--- trunk/CMakeLists.txt        2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/CMakeLists.txt        2012-07-13 11:22:55 UTC (rev 4935)
@@ -289,6 +289,9 @@
   # FLTK STR #2816
   check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** 
v) { Fl_Window::default_icons(0, 0); return 0; }" HAVE_FLTK_ICONS)
 
+  # FLTK STR #2860
+  check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** 
v) { void (Fl_Window::*foo)(int,int,int,int) = &Fl_Window::fullscreen_screens; 
return 0; }" HAVE_FLTK_FULLSCREEN_SCREENS)
+
   set(CMAKE_REQUIRED_INCLUDES)
   set(CMAKE_REQUIRED_LIBRARIES)
 endif()

Modified: trunk/config.h.in
===================================================================
--- trunk/config.h.in   2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/config.h.in   2012-07-13 11:22:55 UTC (rev 4935)
@@ -19,6 +19,7 @@
 #cmakedefine HAVE_FLTK_CLIPBOARD
 #cmakedefine HAVE_FLTK_MEDIAKEYS
 #cmakedefine HAVE_FLTK_FULLSCREEN
+#cmakedefine HAVE_FLTK_FULLSCREEN_SCREENS
 #cmakedefine HAVE_FLTK_CURSOR
 #cmakedefine HAVE_FLTK_ICONS
 #cmakedefine HAVE_ACTIVE_DESKTOP_H

Modified: trunk/vncviewer/DesktopWindow.cxx
===================================================================
--- trunk/vncviewer/DesktopWindow.cxx   2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/DesktopWindow.cxx   2012-07-13 11:22:55 UTC (rev 4935)
@@ -76,7 +76,7 @@
 
 #ifdef HAVE_FLTK_FULLSCREEN
   if (fullScreen)
-    fullscreen();
+    fullscreen_on();
   else
 #endif
   {
@@ -295,6 +295,54 @@
 }
 
 
+void DesktopWindow::fullscreen_on()
+{
+#ifdef HAVE_FLTK_FULLSCREEN
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+  if (not fullScreenAllMonitors)
+    fullscreen_screens(-1, -1, -1, -1);
+  else {
+    int top, bottom, left, right;
+    int top_y, bottom_y, left_x, right_x;
+
+    int sx, sy, sw, sh;
+
+    top = bottom = left = right = 0;
+
+    Fl::screen_xywh(sx, sy, sw, sh, 0);
+    top_y = sy;
+    bottom_y = sy + sh;
+    left_x = sx;
+    right_x = sx + sw;
+
+    for (int i = 1;i < Fl::screen_count();i++) {
+      Fl::screen_xywh(sx, sy, sw, sh, i);
+      if (sy < top_y) {
+        top = i;
+        top_y = sy;
+      }
+      if ((sy + sh) > bottom_y) {
+        bottom = i;
+        bottom_y = sy + sh;
+      }
+      if (sx < left_x) {
+        left = i;
+        left_x = sx;
+      }
+      if ((sx + sw) > right_x) {
+        right = i;
+        right_x = sx + sw;
+      }
+    }
+
+    fullscreen_screens(top, bottom, left, right);
+  }
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
+
+  fullscreen();
+#endif // HAVE_FLTK_FULLSCREEN
+}
+
 void DesktopWindow::grabKeyboard()
 {
   // Grabbing the keyboard is fairly safe as FLTK reroutes events to the
@@ -394,6 +442,7 @@
 {
   int width, height;
   ScreenSet layout;
+  ScreenSet::iterator iter;
 
   if (firstUpdate) {
     if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2)
@@ -403,38 +452,104 @@
     height = h();
   }
 
-  layout = cc->cp.screenLayout;
+#ifdef HAVE_FLTK_FULLSCREEN
+  if (!fullscreen_active()) {
+#endif
+    // In windowed mode we just report a single virtual screen that
+    // covers the entire framebuffer.
 
-  if (layout.num_screens() == 0)
-    layout.add_screen(rfb::Screen());
-  else if (layout.num_screens() != 1) {
-    ScreenSet::iterator iter;
+    layout = cc->cp.screenLayout;
 
-    while (true) {
-      iter = layout.begin();
-      ++iter;
+    // Not sure why we have no screens, but adding a new one should be
+    // safe as there is nothing to conflict with...
+    if (layout.num_screens() == 0)
+      layout.add_screen(rfb::Screen());
+    else if (layout.num_screens() != 1) {
+      // More than one screen. Remove all but the first (which we
+      // assume is the "primary").
 
-      if (iter == layout.end())
-        break;
+      while (true) {
+        iter = layout.begin();
+        ++iter;
 
-      layout.remove_screen(iter->id);
+        if (iter == layout.end())
+          break;
+
+        layout.remove_screen(iter->id);
+      }
     }
+
+    // Resize the remaining single screen to the complete framebuffer
+    layout.begin()->dimensions.tl.x = 0;
+    layout.begin()->dimensions.tl.y = 0;
+    layout.begin()->dimensions.br.x = width;
+    layout.begin()->dimensions.br.y = height;
+#ifdef HAVE_FLTK_FULLSCREEN
+  } else {
+    int i;
+    rdr::U32 id;
+    int sx, sy, sw, sh;
+
+    // In full screen we report all screens that are fully covered.
+
+    // If we can find a matching screen in the existing set, we use
+    // that, otherwise we create a brand new screen.
+    //
+    // FIXME: We should really track screens better so we can handle
+    //        a resized one.
+    //
+    for (i = 0;i < Fl::screen_count();i++) {
+      Fl::screen_xywh(sx, sy, sw, sh, i);
+
+      // Look for perfectly matching existing screen...
+      for (iter = cc->cp.screenLayout.begin();
+           iter != cc->cp.screenLayout.end(); ++iter) {
+        if ((iter->dimensions.tl.x == sx) &&
+            (iter->dimensions.tl.y == sy) &&
+            (iter->dimensions.width() == sw) &&
+            (iter->dimensions.height() == sh))
+          break;
+      }
+
+      // Found it?
+      if (iter != cc->cp.screenLayout.end()) {
+        layout.add_screen(*iter);
+        continue;
+      }
+
+      // Need to add a new one, which means we need to find an unused id
+      while (true) {
+        id = rand();
+        for (iter = cc->cp.screenLayout.begin();
+             iter != cc->cp.screenLayout.end(); ++iter) {
+          if (iter->id == id)
+            break;
+        }
+
+        if (iter == cc->cp.screenLayout.end())
+          break;
+      }
+
+      layout.add_screen(rfb::Screen(id, sx, sy, sw, sh, 0));
+    }
   }
+#endif
 
-  layout.begin()->dimensions.tl.x = 0;
-  layout.begin()->dimensions.tl.y = 0;
-  layout.begin()->dimensions.br.x = width;
-  layout.begin()->dimensions.br.y = height;
-
   // Do we actually change anything?
   if ((width == cc->cp.width) &&
       (height == cc->cp.height) &&
       (layout == cc->cp.screenLayout))
     return;
 
-  vlog.debug("Requesting framebuffer resize from %dx%d to %dx%d",
-             cc->cp.width, cc->cp.height, width, height);
+  vlog.debug("Requesting framebuffer resize from %dx%d to %dx%d (%d screens)",
+             cc->cp.width, cc->cp.height, width, height, layout.num_screens());
 
+  if (!layout.validate(width, height)) {
+    vlog.error("Invalid screen layout computed for resize request!");
+    layout.debug_print();
+    return;
+  }
+
   cc->writer()->writeSetDesktopSize(width, height, layout);
 }
 
@@ -499,7 +614,7 @@
     self->ungrabKeyboard();
 
   if (fullScreen && !self->fullscreen_active())
-    self->fullscreen();
+    self->fullscreen_on();
   else if (!fullScreen && self->fullscreen_active())
     self->fullscreen_off();
 #endif

Modified: trunk/vncviewer/DesktopWindow.h
===================================================================
--- trunk/vncviewer/DesktopWindow.h     2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/DesktopWindow.h     2012-07-13 11:22:55 UTC (rev 4935)
@@ -78,6 +78,8 @@
 
   int handle(int event);
 
+  void fullscreen_on();
+
 private:
   static int fltkHandle(int event, Fl_Window *win);
 

Modified: trunk/vncviewer/OptionsDialog.cxx
===================================================================
--- trunk/vncviewer/OptionsDialog.cxx   2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/OptionsDialog.cxx   2012-07-13 11:22:55 UTC (rev 4935)
@@ -288,6 +288,9 @@
   remoteResizeCheckbox->value(remoteResize);
 #ifdef HAVE_FLTK_FULLSCREEN
   fullScreenCheckbox->value(fullScreen);
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+  fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
 #endif // HAVE_FLTK_FULLSCREEN
 
   handleDesktopSize(desktopSizeCheckbox, this);
@@ -393,6 +396,9 @@
   remoteResize.setParam(remoteResizeCheckbox->value());
 #ifdef HAVE_FLTK_FULLSCREEN
   fullScreen.setParam(fullScreenCheckbox->value());
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+  fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
 #endif // HAVE_FLTK_FULLSCREEN
 
   /* Misc. */
@@ -760,6 +766,16 @@
                                                   _("Full-screen mode")));
   ty += CHECK_HEIGHT + TIGHT_MARGIN;
 
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+
+  fullScreenAllMonitorsCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
+                                                      CHECK_MIN_WIDTH,
+                                                      CHECK_HEIGHT,
+                                                      _("Enable full-screen 
mode over all monitors")));
+  ty += CHECK_HEIGHT + TIGHT_MARGIN;
+
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
+
 #endif // HAVE_FLTK_FULLSCREEN
 
   group->end();

Modified: trunk/vncviewer/OptionsDialog.h
===================================================================
--- trunk/vncviewer/OptionsDialog.h     2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/OptionsDialog.h     2012-07-13 11:22:55 UTC (rev 4935)
@@ -114,6 +114,7 @@
   Fl_Int_Input *desktopHeightInput;
   Fl_Check_Button *remoteResizeCheckbox;
   Fl_Check_Button *fullScreenCheckbox;
+  Fl_Check_Button *fullScreenAllMonitorsCheckbox;
 
   /* Misc. */
   Fl_Check_Button *sharedCheckbox;

Modified: trunk/vncviewer/Viewport.cxx
===================================================================
--- trunk/vncviewer/Viewport.cxx        2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/Viewport.cxx        2012-07-13 11:22:55 UTC (rev 4935)
@@ -920,7 +920,7 @@
     if (window()->fullscreen_active())
       window()->fullscreen_off();
     else
-      window()->fullscreen();
+      ((DesktopWindow*)window())->fullscreen_on();
     break;
 #endif
   case ID_RESIZE:

Modified: trunk/vncviewer/parameters.cxx
===================================================================
--- trunk/vncviewer/parameters.cxx      2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/parameters.cxx      2012-07-13 11:22:55 UTC (rev 4935)
@@ -66,6 +66,11 @@
 
 #ifdef HAVE_FLTK_FULLSCREEN
 BoolParameter fullScreen("FullScreen", "Full screen mode", false);
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+BoolParameter fullScreenAllMonitors("FullScreenAllMonitors",
+                                    "Enable full screen over all monitors",
+                                    true);
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
 #endif // HAVE_FLTK_FULLSCREEN
 StringParameter desktopSize("DesktopSize",
                             "Reconfigure desktop size on the server on "

Modified: trunk/vncviewer/parameters.h
===================================================================
--- trunk/vncviewer/parameters.h        2012-07-13 11:18:55 UTC (rev 4934)
+++ trunk/vncviewer/parameters.h        2012-07-13 11:22:55 UTC (rev 4935)
@@ -39,6 +39,9 @@
 
 #ifdef HAVE_FLTK_FULLSCREEN
 extern rfb::BoolParameter fullScreen;
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+extern rfb::BoolParameter fullScreenAllMonitors;
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
 #endif // HAVE_FLTK_FULLSCREEN
 extern rfb::StringParameter desktopSize;
 extern rfb::BoolParameter remoteResize;

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to