summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2012-07-13 11:22:55 +0000
committerPierre Ossman <ossman@cendio.se>2012-07-13 11:22:55 +0000
commitaae3891bc7380c23322214b9e2781b636c3d7199 (patch)
treea8cb23609213f033c42b3486eb2871f686504aad
parentc314d08990d063d064498c654d0b4652437a304f (diff)
downloadtigervnc-aae3891bc7380c23322214b9e2781b636c3d7199.tar.gz
tigervnc-aae3891bc7380c23322214b9e2781b636c3d7199.zip
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. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4935 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r--CMakeLists.txt3
-rw-r--r--config.h.in1
-rw-r--r--vncviewer/DesktopWindow.cxx155
-rw-r--r--vncviewer/DesktopWindow.h2
-rw-r--r--vncviewer/OptionsDialog.cxx16
-rw-r--r--vncviewer/OptionsDialog.h1
-rw-r--r--vncviewer/Viewport.cxx2
-rw-r--r--vncviewer/parameters.cxx5
-rw-r--r--vncviewer/parameters.h3
9 files changed, 167 insertions, 21 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9cf3dd32..c375314a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -289,6 +289,9 @@ if(FLTK_FOUND)
# 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()
diff --git a/config.h.in b/config.h.in
index a11ec10b..55cd652d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 29053916..78a94b60 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -76,7 +76,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
#ifdef HAVE_FLTK_FULLSCREEN
if (fullScreen)
- fullscreen();
+ fullscreen_on();
else
#endif
{
@@ -295,6 +295,54 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
}
+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 @@ void DesktopWindow::remoteResize()
{
int width, height;
ScreenSet layout;
+ ScreenSet::iterator iter;
if (firstUpdate) {
if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2)
@@ -403,28 +452,88 @@ void DesktopWindow::remoteResize()
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.
+
+ layout = cc->cp.screenLayout;
- if (layout.num_screens() == 0)
- layout.add_screen(rfb::Screen());
- else if (layout.num_screens() != 1) {
- ScreenSet::iterator 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").
- while (true) {
- iter = layout.begin();
- ++iter;
+ while (true) {
+ iter = layout.begin();
+ ++iter;
- if (iter == layout.end())
- break;
+ if (iter == layout.end())
+ break;
- layout.remove_screen(iter->id);
+ layout.remove_screen(iter->id);
+ }
}
- }
- layout.begin()->dimensions.tl.x = 0;
- layout.begin()->dimensions.tl.y = 0;
- layout.begin()->dimensions.br.x = width;
- layout.begin()->dimensions.br.y = height;
+ // 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
// Do we actually change anything?
if ((width == cc->cp.width) &&
@@ -432,8 +541,14 @@ void DesktopWindow::remoteResize()
(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 @@ void DesktopWindow::handleOptions(void *data)
self->ungrabKeyboard();
if (fullScreen && !self->fullscreen_active())
- self->fullscreen();
+ self->fullscreen_on();
else if (!fullScreen && self->fullscreen_active())
self->fullscreen_off();
#endif
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
index 3fe9c866..2a4613c7 100644
--- a/vncviewer/DesktopWindow.h
+++ b/vncviewer/DesktopWindow.h
@@ -78,6 +78,8 @@ public:
int handle(int event);
+ void fullscreen_on();
+
private:
static int fltkHandle(int event, Fl_Window *win);
diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx
index c82079f5..df9f3554 100644
--- a/vncviewer/OptionsDialog.cxx
+++ b/vncviewer/OptionsDialog.cxx
@@ -288,6 +288,9 @@ void OptionsDialog::loadOptions(void)
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 @@ void OptionsDialog::storeOptions(void)
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 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
_("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();
diff --git a/vncviewer/OptionsDialog.h b/vncviewer/OptionsDialog.h
index c26c0c91..b3ac0156 100644
--- a/vncviewer/OptionsDialog.h
+++ b/vncviewer/OptionsDialog.h
@@ -114,6 +114,7 @@ protected:
Fl_Int_Input *desktopHeightInput;
Fl_Check_Button *remoteResizeCheckbox;
Fl_Check_Button *fullScreenCheckbox;
+ Fl_Check_Button *fullScreenAllMonitorsCheckbox;
/* Misc. */
Fl_Check_Button *sharedCheckbox;
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index a80b8efe..43b39d4f 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -920,7 +920,7 @@ void Viewport::popupContextMenu()
if (window()->fullscreen_active())
window()->fullscreen_off();
else
- window()->fullscreen();
+ ((DesktopWindow*)window())->fullscreen_on();
break;
#endif
case ID_RESIZE:
diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx
index 4407bd95..22fa1ac5 100644
--- a/vncviewer/parameters.cxx
+++ b/vncviewer/parameters.cxx
@@ -66,6 +66,11 @@ IntParameter qualityLevel("QualityLevel",
#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 "
diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h
index a935ea0e..59909d11 100644
--- a/vncviewer/parameters.h
+++ b/vncviewer/parameters.h
@@ -39,6 +39,9 @@ extern rfb::IntParameter qualityLevel;
#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;