void ComparingUpdateTracker::compare()
{
+ // First of all, exclude video area from both changed and copied regions.
+ // We handle video area separately and do not compare it -- we know it's
+ // being changed continuously.
+ if (!video_area.is_empty()) {
+ changed.assign_subtract(video_area);
+ copied.assign_subtract(video_area);
+ }
+
std::vector<Rect> rects;
std::vector<Rect>::iterator i;
ut->add_changed(tmp);
}
+void ClippingUpdateTracker::set_video_area(const Rect &rect) {
+ ut->set_video_area(rect.intersect(clipRect));
+}
+
// SimpleUpdateTracker
SimpleUpdateTracker::SimpleUpdateTracker(bool use_copyrect) {
return;
}
+void SimpleUpdateTracker::set_video_area(const Rect &rect)
+{
+ video_area = rect;
+}
+
+//
+// subtract() is called to mark some region as unchanged. We just remove that
+// region from both `copied' and `changed' regions. Note that `video_area' is
+// not affected intentionally; we assume that video is continuously changing,
+// so it should always be treated as "changed".
+//
+
void SimpleUpdateTracker::subtract(const Region& region) {
copied.assign_subtract(region);
changed.assign_subtract(region);
void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info, const Region& clip)
{
- copied.assign_subtract(changed);
+ changed.assign_subtract(video_area);
+ copied.assign_subtract(changed.union_(video_area));
info->changed = changed.intersect(clip);
info->copied = copied.intersect(clip);
info->copy_delta = copy_delta;
+ // FIXME: Using get_bounding_rect() is not what should actually be done!
+ // We should use the biggest inner rectangle of the `clip' instead.
+ // From the other side, `clip' is usually just a sole rectangle.
+ info->video_area = video_area.intersect(clip.get_bounding_rect());
}
void SimpleUpdateTracker::copyTo(UpdateTracker* to) const {
to->add_copied(copied, copy_delta);
if (!changed.is_empty())
to->add_changed(changed);
+ to->set_video_area(video_area);
}
Region changed;
Region copied;
Point copy_delta;
+ Rect video_area;
bool is_empty() const {
- return copied.is_empty() && changed.is_empty();
+ return copied.is_empty() && changed.is_empty() && video_area.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();
+ return copied.numRects() + changed.numRects() + !video_area.is_empty();
}
*/
};
virtual void add_changed(const Region ®ion) = 0;
virtual void add_copied(const Region &dest, const Point &delta) = 0;
+ virtual void set_video_area(const Rect &rect) = 0;
};
class ClippingUpdateTracker : public UpdateTracker {
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
+ virtual void set_video_area(const Rect &rect);
protected:
UpdateTracker* ut;
Rect clipRect;
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
+ virtual void set_video_area(const Rect &rect);
virtual void subtract(const Region& region);
// Fill the supplied UpdateInfo structure with update information
virtual void copyTo(UpdateTracker* to) const;
// Move the entire update region by an offset
- void translate(const Point& p) {changed.translate(p); copied.translate(p);}
+ void translate(const Point& p) {
+ changed.translate(p);
+ copied.translate(p);
+ video_area.translate(p);
+ }
- virtual bool is_empty() const {return changed.is_empty() && copied.is_empty();}
+ virtual bool is_empty() const {
+ return changed.is_empty() && copied.is_empty() && video_area.is_empty();
+ }
+
+ // NOTE: We do not clear video_area intentionally.
+ virtual void clear() {
+ changed.clear();
+ copied.clear();
+ }
- virtual void clear() {changed.clear(); copied.clear();};
protected:
Region changed;
Region copied;
Point copy_delta;
bool copy_enabled;
+
+ // We can track one rectangle on the screen as a "video area". We assume
+ // it is changing continuously, in whole. Thus, we don't need to detect
+ // and track individual changes in the video area -- we can assume it's
+ // always in the changed state.
+ Rect video_area;
};
}
// Get the lists of updates. Prior to exporting the data to the `ui' object,
// getUpdateInfo() will normalize the `updates' object such way that its
- // `changed' and `copied' regions would not intersect.
+ // `changed', `copied' and `video_area' regions would not intersect.
UpdateInfo ui;
updates.getUpdateInfo(&ui, requested);
// Compute the number of rectangles. Tight encoder makes the things more
// complicated as compared to the original VNC4.
writer()->setupCurrentEncoder();
- int nRects = ui.copied.numRects() + (drawRenderedCursor ? 1 : 0);
+ int nRects = (ui.copied.numRects() +
+ /* FIXME: Sending video area is not yet enabled.
+ (ui.video_area.is_empty() ? 0 : 1) +
+ */
+ (drawRenderedCursor ? 1 : 0));
std::vector<Rect> rects;
std::vector<Rect>::const_iterator i;
ui.changed.get_rects(&rects);
void add_copied(const Region& dest, const Point& delta) {
updates.add_copied(dest, delta);
}
+ void set_video_area(const Rect &rect) { updates.set_video_area(rect); }
const char* getPeerEndpoint() const {return peerEndpoint.buf;}
comparer->add_copied(dest, delta);
}
+void VNCServerST::set_video_area(const Rect &rect)
+{
+ comparer->set_video_area(rect);
+}
+
bool VNCServerST::clientsReadyForUpdate()
{
std::list<VNCSConnectionST*>::iterator ci;
if (ui.is_empty() && !(renderCursor && renderedCursorInvalid))
return;
- Region toCheck = ui.changed.union_(ui.copied);
+ Region toCheck = ui.changed.union_(ui.copied).union_(ui.video_area);
if (renderCursor) {
Rect clippedCursorRect
ci_next = ci; ci_next++;
(*ci)->add_copied(ui.copied, ui.copy_delta);
(*ci)->add_changed(ui.changed);
+ (*ci)->set_video_area(ui.video_area);
}
comparer->clear();
virtual void serverCutText(const char* str, int len);
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
+ virtual void set_video_area(const Rect &rect);
virtual bool clientsReadyForUpdate();
virtual void tryUpdate();
virtual void setCursor(int width, int height, const Point& hotspot,