From ff473402c15c45e3a501508d65dcb781d9aa8f44 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 4 Jul 2012 11:27:47 +0000 Subject: [PATCH] Make it possible to dynamically resize the size of the session, when resizing the viewer window, or when entering or leaving fullscreen mode. Initial work done by Arthur Huillet and clohr. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4924 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- vncviewer/CConn.cxx | 32 ---------- vncviewer/DesktopWindow.cxx | 123 ++++++++++++++++++++++++++---------- vncviewer/DesktopWindow.h | 6 ++ vncviewer/parameters.cxx | 4 ++ vncviewer/parameters.h | 1 + 5 files changed, 99 insertions(+), 67 deletions(-) diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index 405cd979..25e17efc 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -304,43 +304,11 @@ void CConn::framebufferUpdateEnd() desktop->updateWindow(); if (firstUpdate) { - int width, height; - // We need fences to make extra update requests and continuous // updates "safe". See fence() for the next step. if (cp.supportsFence) writer()->writeFence(fenceFlagRequest | fenceFlagSyncNext, 0, NULL); - if (cp.supportsSetDesktopSize && - sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) == 2) { - ScreenSet layout; - - layout = cp.screenLayout; - - if (layout.num_screens() == 0) - layout.add_screen(rfb::Screen()); - else if (layout.num_screens() != 1) { - ScreenSet::iterator iter; - - while (true) { - iter = layout.begin(); - ++iter; - - if (iter == layout.end()) - break; - - 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; - - writer()->writeSetDesktopSize(width, height, layout); - } - firstUpdate = false; } diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index d2975dc0..29053916 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -26,12 +26,14 @@ #include #include +#include #include "DesktopWindow.h" #include "OptionsDialog.h" #include "i18n.h" #include "parameters.h" #include "vncviewer.h" +#include "CConn.h" #include #include @@ -51,18 +53,15 @@ static rfb::LogWriter vlog("DesktopWindow"); DesktopWindow::DesktopWindow(int w, int h, const char *name, const rfb::PixelFormat& serverPF, CConn* cc_) - : Fl_Window(w, h) + : Fl_Window(w, h), cc(cc_), firstUpdate(true) { - // Allow resize - size_range(100, 100, w, h); - Fl_Scroll *scroll = new Fl_Scroll(0, 0, w, h); scroll->color(FL_BLACK); // Automatically adjust the scroll box to the window resizable(scroll); - viewport = new Viewport(w, h, serverPF, cc_); + viewport = new Viewport(w, h, serverPF, cc); scroll->end(); @@ -76,11 +75,9 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, Fl::event_dispatch(&fltkHandle); #ifdef HAVE_FLTK_FULLSCREEN - if (fullScreen) { - // See comment in DesktopWindow::handleOptions - size_range(100, 100, 0, 0); + if (fullScreen) fullscreen(); - } else + else #endif { // If we are creating a window which is equal to the size on the @@ -106,6 +103,7 @@ DesktopWindow::~DesktopWindow() // Unregister all timeouts in case they get a change tro trigger // again later when this object is already gone. Fl::remove_timeout(handleGrab, this); + Fl::remove_timeout(handleResizeTimeout, this); OptionsDialog::removeCallback(handleOptions); @@ -149,6 +147,12 @@ void DesktopWindow::setColourMapEntries(int firstColour, int nColours, void DesktopWindow::updateWindow() { + if (firstUpdate) { + if (cc->cp.supportsSetDesktopSize) + remoteResize(); + firstUpdate = false; + } + viewport->updateWindow(); } @@ -158,9 +162,6 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) if ((new_w == viewport->w()) && (new_h == viewport->h())) return; - // Turn off size limitations for a bit while we juggle things around - size_range(100, 100, 0, 0); - // If we're letting the viewport match the window perfectly, then // keep things that way for the new size, otherwise just keep things // like they are. @@ -186,12 +187,6 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) // to make sure the viewport is centered. repositionViewport(); - // Update allowed resize range -#ifdef HAVE_FLTK_FULLSCREEN - if (!fullscreen_active()) -#endif - size_range(100, 100, new_w, new_h); - // repositionViewport() makes sure the scroll widget notices any changes // in position, but it might be just the size that changes so we also // need a poke here as well. @@ -210,6 +205,20 @@ void DesktopWindow::resize(int x, int y, int w, int h) { Fl_Window::resize(x, y, w, h); + // Try to get the remote size to match our window size, provided + // the following conditions are true: + // + // 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 + // + if (not firstUpdate 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); + Fl::add_timeout(0.5, handleResizeTimeout, this); + } + // Deal with some scrolling corner cases repositionViewport(); } @@ -222,18 +231,6 @@ int DesktopWindow::handle(int event) case FL_FULLSCREEN: fullScreen.setParam(fullscreen_active()); - if (!fullscreen_active()) { - size_range(100, 100, viewport->w(), viewport->h()); - size(viewport->w(), viewport->h()); - } else { - // We need to turn off the size limitations for proper - // fullscreen support, but in case fullscreen is activated via - // the WM, this is a bit of a problem. In practice, it seems to - // work to change the size limits after we have recieved the - // FL_FULLSCREEN event, at least with my Metacity. - size_range(100, 100, 0, 0); - } - if (!fullscreenSystemKeys) break; @@ -383,6 +380,65 @@ void DesktopWindow::handleGrab(void *data) } +void DesktopWindow::handleResizeTimeout(void *data) +{ + DesktopWindow *self = (DesktopWindow *)data; + + assert(self); + + self->remoteResize(); +} + + +void DesktopWindow::remoteResize() +{ + int width, height; + ScreenSet layout; + + if (firstUpdate) { + if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2) + return; + } else { + width = w(); + height = h(); + } + + layout = cc->cp.screenLayout; + + if (layout.num_screens() == 0) + layout.add_screen(rfb::Screen()); + else if (layout.num_screens() != 1) { + ScreenSet::iterator iter; + + while (true) { + iter = layout.begin(); + ++iter; + + if (iter == layout.end()) + break; + + 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; + + // 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); + + cc->writer()->writeSetDesktopSize(width, height, layout); +} + + void DesktopWindow::repositionViewport() { int new_x, new_y; @@ -442,12 +498,9 @@ void DesktopWindow::handleOptions(void *data) else self->ungrabKeyboard(); - if (fullScreen && !self->fullscreen_active()) { - // Some WMs (Metacity) apparently requires that the size limits - // are removed before fullscreen - self->size_range(100, 100, 0, 0); + if (fullScreen && !self->fullscreen_active()) self->fullscreen(); - } else if (!fullScreen && self->fullscreen_active()) + else if (!fullScreen && self->fullscreen_active()) self->fullscreen_off(); #endif } diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h index fbb5f954..3fe9c866 100644 --- a/vncviewer/DesktopWindow.h +++ b/vncviewer/DesktopWindow.h @@ -86,6 +86,9 @@ private: static void handleGrab(void *data); + static void handleResizeTimeout(void *data); + void remoteResize(); + void repositionViewport(); static void handleClose(Fl_Widget *wnd, void *data); @@ -93,7 +96,10 @@ private: static void handleOptions(void *data); private: + CConn* cc; Viewport *viewport; + + bool firstUpdate; }; #endif diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx index e8314787..7df173b8 100644 --- a/vncviewer/parameters.cxx +++ b/vncviewer/parameters.cxx @@ -68,6 +68,10 @@ BoolParameter fullScreen("FullScreen", "Full screen mode", false); StringParameter desktopSize("DesktopSize", "Reconfigure desktop size on the server on " "connect (if possible)", ""); +BoolParameter remoteResize("RemoteResize", + "Dynamically resize the remote desktop size as " + "the size of the local client window changes. " + "(Does not work with all servers)", true); BoolParameter viewOnly("ViewOnly", "Don't send any mouse or keyboard events to the server", diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h index d07d4eaa..ce122e74 100644 --- a/vncviewer/parameters.h +++ b/vncviewer/parameters.h @@ -39,6 +39,7 @@ extern rfb::IntParameter qualityLevel; extern rfb::BoolParameter fullScreen; extern rfb::StringParameter desktopSize; +extern rfb::BoolParameter remoteResize; extern rfb::BoolParameter viewOnly; extern rfb::BoolParameter shared; -- 2.39.5