Implement server side support for SetDesktopSize.
It has some warts, but should be feature complete. Most of the magic happens
in the desktop class though.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3713 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 7edac56..ec01074 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -252,50 +252,83 @@
// VNCServer methods
-void VNCServerST::setPixelBuffer(PixelBuffer* pb_)
+void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout)
{
pb = pb_;
delete comparer;
comparer = 0;
- if (pb) {
- comparer = new ComparingUpdateTracker(pb);
- cursor.setPF(pb->getPF());
- renderedCursor.setPF(pb->getPF());
+ screenLayout = layout;
- // Check that the screen layout is still valid
- if (!screenLayout.validate(pb->width(), pb->height())) {
- Rect fbRect;
- ScreenSet::iterator iter, iter_next;
-
- fbRect.setXYWH(0, 0, pb->width(), pb->height());
-
- for (iter = screenLayout.begin();iter != screenLayout.end();iter = iter_next) {
- iter_next = iter; ++iter_next;
- if (iter->dimensions.enclosed_by(fbRect))
- continue;
- iter->dimensions = iter->dimensions.intersect(fbRect);
- if (iter->dimensions.is_empty()) {
- slog.info("Removing screen %d (%x) as it is completely outside the new framebuffer",
- (int)iter->id, (unsigned)iter->id);
- screenLayout.remove_screen(iter->id);
- }
- }
- }
-
- if (screenLayout.num_screens() == 0) {
- // Boot strap the screen layout
- screenLayout.add_screen(Screen(0, 0, 0, pb->width(), pb->height(), 0));
- }
-
- std::list<VNCSConnectionST*>::iterator ci, ci_next;
- for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
- ci_next = ci; ci_next++;
- (*ci)->pixelBufferChange();
- }
- } else {
+ if (!pb) {
if (desktopStarted)
throw Exception("setPixelBuffer: null PixelBuffer when desktopStarted?");
+ return;
+ }
+
+ comparer = new ComparingUpdateTracker(pb);
+ cursor.setPF(pb->getPF());
+ renderedCursor.setPF(pb->getPF());
+
+ // Make sure that we have at least one screen
+ if (screenLayout.num_screens() == 0)
+ screenLayout.add_screen(Screen(0, 0, 0, pb->width(), pb->height(), 0));
+
+ std::list<VNCSConnectionST*>::iterator ci, ci_next;
+ for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
+ ci_next = ci; ci_next++;
+ (*ci)->pixelBufferChange();
+ // Since the new pixel buffer means an ExtendedDesktopSize needs to
+ // be sent anyway, we don't need to call screenLayoutChange.
+ }
+}
+
+void VNCServerST::setPixelBuffer(PixelBuffer* pb_)
+{
+ ScreenSet layout;
+
+ if (!pb_) {
+ if (desktopStarted)
+ throw Exception("setPixelBuffer: null PixelBuffer when desktopStarted?");
+ return;
+ }
+
+ layout = screenLayout;
+
+ // Check that the screen layout is still valid
+ if (!layout.validate(pb_->width(), pb_->height())) {
+ Rect fbRect;
+ ScreenSet::iterator iter, iter_next;
+
+ fbRect.setXYWH(0, 0, pb_->width(), pb_->height());
+
+ for (iter = layout.begin();iter != layout.end();iter = iter_next) {
+ iter_next = iter; ++iter_next;
+ if (iter->dimensions.enclosed_by(fbRect))
+ continue;
+ iter->dimensions = iter->dimensions.intersect(fbRect);
+ if (iter->dimensions.is_empty()) {
+ slog.info("Removing screen %d (%x) as it is completely outside the new framebuffer",
+ (int)iter->id, (unsigned)iter->id);
+ layout.remove_screen(iter->id);
+ }
+ }
+ }
+
+ setPixelBuffer(pb_, layout);
+}
+
+void VNCServerST::setScreenLayout(const ScreenSet& layout)
+{
+ if (!pb)
+ throw Exception("setScreenLayout: new screen layout without a PixelBuffer");
+ if (!layout.validate(pb->width(), pb->height()))
+ throw Exception("setScreenLayout: invalid screen layout");
+
+ std::list<VNCSConnectionST*>::iterator ci, ci_next;
+ for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
+ ci_next = ci; ci_next++;
+ (*ci)->screenLayoutChange(reasonServer);
}
}
@@ -571,3 +604,13 @@
}
}
+void VNCServerST::notifyScreenLayoutChange(VNCSConnectionST* requester)
+{
+ std::list<VNCSConnectionST*>::iterator ci, ci_next;
+ for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
+ ci_next = ci; ci_next++;
+ if ((*ci) == requester)
+ continue;
+ (*ci)->screenLayoutChange(reasonOtherClient);
+ }
+}