bool is_empty() const {
return copied.is_empty() && changed.is_empty();
}
+ // NOTE: We do not ever use UpdateInfo::numRects(), because Tight encoding
+ // complicates computing the number of rectangles.
+ /*
int numRects() const {
return copied.numRects() + changed.numRects();
}
+ */
};
class UpdateTracker {
virtual void add_copied(const Region &dest, const Point &delta);
protected:
UpdateTracker* ut;
- Region clipRect;
+ Rect clipRect;
};
class SimpleUpdateTracker : public UpdateTracker {
virtual void subtract(const Region& region);
// Fill the supplied UpdateInfo structure with update information
+ // FIXME: Provide getUpdateInfo() with no clipping, for better efficiency.
virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn);
// Copy the contained updates to another tracker
virtual void copyTo(UpdateTracker* to) const;
-
- // Get the changed/copied regions
- const Region& get_changed() const {return changed;}
- const Region& get_copied() const {return copied;}
- const Point& get_delta() const {return copy_delta;}
-
// Move the entire update region by an offset
void translate(const Point& p) {changed.translate(p); copied.translate(p);}
{
if (state() != RFBSTATE_NORMAL || requested.is_empty()) return;
+ updates.enable_copyrect(cp.useCopyRect);
+
server->checkUpdate();
+ // Get the lists of updates. Prior to exporting the data to the `update' object,
+ // getUpdateInfo() will normalize the `updates' object such way that its
+ // `changed' and `copied' regions would not intersect.
+
+ UpdateInfo update;
+ updates.getUpdateInfo(&update, requested);
+ bool needNewUpdateInfo = false;
+
// If the previous position of the rendered cursor overlaps the source of the
// copy, then when the copy happens the corresponding rectangle in the
// destination will be wrong, so add it to the changed region.
- if (!updates.get_copied().is_empty() && !renderedCursorRect.is_empty()) {
- Rect bogusCopiedCursor = (renderedCursorRect.translate(updates.get_delta())
+ if (!update.copied.is_empty() && !renderedCursorRect.is_empty()) {
+ Rect bogusCopiedCursor = (renderedCursorRect.translate(update.copy_delta)
.intersect(server->pb->getRect()));
- if (!updates.get_copied().intersect(bogusCopiedCursor).is_empty()) {
+ if (!update.copied.intersect(bogusCopiedCursor).is_empty()) {
updates.add_changed(bogusCopiedCursor);
+ needNewUpdateInfo = true;
}
}
if (removeRenderedCursor) {
updates.add_changed(renderedCursorRect);
+ needNewUpdateInfo = true;
renderedCursorRect.clear();
removeRenderedCursor = false;
}
if (updates.is_empty() && !writer()->needFakeUpdate() && !drawRenderedCursor)
return;
+ // The `updates' object could change, make sure we have valid update info.
+
+ if (needNewUpdateInfo)
+ updates.getUpdateInfo(&update, requested);
+
// If the client needs a server-side rendered cursor, work out the cursor
// rectangle. If it's empty then don't bother drawing it, but if it overlaps
// with the update region, we need to draw the rendered cursor regardless of
if (renderedCursorRect.is_empty()) {
drawRenderedCursor = false;
- } else if (!updates.get_changed().union_(updates.get_copied())
+ } else if (!update.changed.union_(update.copied)
.intersect(renderedCursorRect).is_empty()) {
drawRenderedCursor = true;
}
// the same bit of screen twice, but we have the overhead of a more complex
// region.
- //if (drawRenderedCursor)
+ //if (drawRenderedCursor) {
// updates.subtract(renderedCursorRect);
+ // updates.getUpdateInfo(&update, requested);
+ //}
}
- UpdateInfo update;
- updates.enable_copyrect(cp.useCopyRect);
- updates.getUpdateInfo(&update, requested);
if (!update.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {
// Compute the number of rectangles. Tight encoder makes the things more
- // complicated as compared to the original RealVNC.
+ // complicated as compared to the original VNC4.
writer()->setupCurrentEncoder();
int nRects = update.copied.numRects() + (drawRenderedCursor ? 1 : 0);
std::vector<Rect> rects;
update.changed.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++) {
if (i->width() && i->height())
- nRects += writer()->getNumRects(*i);
+ nRects += writer()->getNumRects(*i);
}
writer()->writeFramebufferUpdateStart(nRects);
void VNCServerST::checkUpdate()
{
+ UpdateInfo ui;
+ comparer->getUpdateInfo(&ui, pb->getRect());
+
bool renderCursor = needRenderedCursor();
- if (comparer->is_empty() && !(renderCursor && renderedCursorInvalid))
+ if (ui.is_empty() && !(renderCursor && renderedCursorInvalid))
return;
- Region toCheck = comparer->get_changed().union_(comparer->get_copied());
+ Region toCheck = ui.changed.union_(ui.copied);
if (renderCursor) {
Rect clippedCursorRect
std::list<VNCSConnectionST*>::iterator ci, ci_next;
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
ci_next = ci; ci_next++;
- (*ci)->add_copied(comparer->get_copied(), comparer->get_delta());
- (*ci)->add_changed(comparer->get_changed());
+ (*ci)->add_copied(ui.copied, ui.copy_delta);
+ (*ci)->add_changed(ui.changed);
}
comparer->clear();