From b6060852c4b317cd73043cdc82b652d187d952fd Mon Sep 17 00:00:00 2001
From: "Javier S. Pedro" <maemo@javispedro.com>
Date: Fri, 16 Sep 2011 20:51:27 +0200
Subject: Fixing some bugs in damage tracking on real N950

---
 declarativewatchlet.cpp     |  4 +-
 declarativewatchlet.h       | 10 ++---
 declarativewatchwrapper.cpp | 23 +++++++++---
 declarativewatchwrapper.h   |  7 +++-
 graphicswatchlet.cpp        |  2 +-
 graphicswatchlet.h          |  4 --
 main.cpp                    | 10 ++---
 metawatch.cpp               | 24 ++++++------
 metawatch.h                 | 19 ++++++----
 metawatchpaintengine.cpp    | 11 +++++-
 metawatchpaintengine.h      |  2 +
 metawatchsimulator.cpp      | 18 +++++++--
 metawatchsimulator.h        |  2 +
 testdeclarativewatchlet.qml | 90 ++++-----------------------------------------
 testwatchlet.cpp            | 25 +++++++------
 testwatchlet.h              |  9 +----
 watchlet.cpp                | 23 +++++++++++-
 watchlet.h                  | 19 +++++++---
 watchpaintengine.cpp        | 22 ++++++++---
 watchpaintengine.h          |  3 ++
 20 files changed, 163 insertions(+), 164 deletions(-)

diff --git a/declarativewatchlet.cpp b/declarativewatchlet.cpp
index 1b9c836..7e6768e 100644
--- a/declarativewatchlet.cpp
+++ b/declarativewatchlet.cpp
@@ -19,7 +19,7 @@ DeclarativeWatchlet::DeclarativeWatchlet(WatchServer* server, const QString& id)
 
 	if (!_registered) {
 		qmlRegisterUncreatableType<DeclarativeWatchWrapper>("com.javispedro.sowatch", 1, 0,
-			"Watch", "Watch is only available via attached properties");
+			"Watch", "Watch is only available via the 'watch' object");
 		_registered = true;
 	}
 
@@ -56,12 +56,14 @@ void DeclarativeWatchlet::setSource(const QUrl &url)
 
 void DeclarativeWatchlet::activate()
 {
+	Watchlet::activate();
 	_wrapper->activate();
 	_scene->update();
 }
 
 void DeclarativeWatchlet::deactivate()
 {
+	Watchlet::deactivate();
 	_wrapper->deactivate();
 }
 
diff --git a/declarativewatchlet.h b/declarativewatchlet.h
index bd42841..1e94007 100644
--- a/declarativewatchlet.h
+++ b/declarativewatchlet.h
@@ -19,17 +19,13 @@ public:
 
 	void setSource(const QUrl& url);
 
-	void activate();
-	void deactivate();
-
-signals:
-
-public slots:
-
 protected slots:
 	void handleComponentStatus(QDeclarativeComponent::Status status);
 
 protected:
+	void activate();
+	void deactivate();
+
 	static bool _registered;
 	QDeclarativeEngine* _engine;
 	QDeclarativeComponent* _component;
diff --git a/declarativewatchwrapper.cpp b/declarativewatchwrapper.cpp
index 127b6d6..384a29d 100644
--- a/declarativewatchwrapper.cpp
+++ b/declarativewatchwrapper.cpp
@@ -5,7 +5,7 @@
 using namespace sowatch;
 
 DeclarativeWatchWrapper::DeclarativeWatchWrapper(Watch* watch, QObject *parent) :
-	QObject(parent), _watch(watch)
+	QObject(parent), _watch(watch), _active(false)
 {
 
 }
@@ -15,15 +15,28 @@ QString DeclarativeWatchWrapper::model() const
 	return _watch->model();
 }
 
+bool DeclarativeWatchWrapper::active() const
+{
+	return _active;
+}
+
 void DeclarativeWatchWrapper::activate()
 {
-	connect(_watch, SIGNAL(buttonPressed(int)), this, SIGNAL(buttonPressed(int)));
-	connect(_watch, SIGNAL(buttonReleased(int)), this, SIGNAL(buttonReleased(int)));
+	if (!_active) {
+		connect(_watch, SIGNAL(buttonPressed(int)), this, SIGNAL(buttonPressed(int)));
+		connect(_watch, SIGNAL(buttonReleased(int)), this, SIGNAL(buttonReleased(int)));
+		_active = true;
+		emit activeChanged();
+	}
 }
 
 void DeclarativeWatchWrapper::deactivate()
 {
-	disconnect(this, SIGNAL(buttonPressed(int)));
-	disconnect(this, SIGNAL(buttonReleased(int)));
+	if (_active) {
+		disconnect(this, SIGNAL(buttonPressed(int)));
+		disconnect(this, SIGNAL(buttonReleased(int)));
+		_active = false;
+		emit activeChanged();
+	}
 }
 
diff --git a/declarativewatchwrapper.h b/declarativewatchwrapper.h
index 09e0923..5f78e75 100644
--- a/declarativewatchwrapper.h
+++ b/declarativewatchwrapper.h
@@ -12,21 +12,24 @@ class DeclarativeWatchlet;
 class DeclarativeWatchWrapper : public QObject
 {
     Q_OBJECT
-	Q_PROPERTY(QString model READ model NOTIFY modelChanged)
+	Q_PROPERTY(QString model READ model CONSTANT)
+	Q_PROPERTY(bool active READ active NOTIFY activeChanged)
 
 public:
 	explicit DeclarativeWatchWrapper(Watch *watch, QObject *parent = 0);
 
 	Q_INVOKABLE QString model() const;
+	Q_INVOKABLE bool active() const;
 
 signals:
 	void buttonPressed(int button);
 	void buttonReleased(int button);
 
-	void modelChanged();
+	void activeChanged();
 
 protected:
 	Watch* _watch;
+	bool _active;
 
 	void activate();
 	void deactivate();
diff --git a/graphicswatchlet.cpp b/graphicswatchlet.cpp
index 130e1cc..538723a 100644
--- a/graphicswatchlet.cpp
+++ b/graphicswatchlet.cpp
@@ -35,7 +35,7 @@ void GraphicsWatchlet::sceneChanged(const QList<QRectF> &region)
 		_damaged += r.toRect();
 	}
 
-	if (!_damaged.isEmpty() && !watch()->busy()) {
+	if (!_damaged.isEmpty() && _active && !watch()->busy()) {
 		const QVector<QRect> rects = _damaged.rects();
 		QPainter p(watch());
 		foreach(const QRect& r, rects)
diff --git a/graphicswatchlet.h b/graphicswatchlet.h
index abf1da2..9754062 100644
--- a/graphicswatchlet.h
+++ b/graphicswatchlet.h
@@ -17,10 +17,6 @@ public:
 	QGraphicsScene* scene();
 	void setScene(QGraphicsScene* scene);
 
-signals:
-
-public slots:
-
 protected:
 	QGraphicsScene* _scene;
 	QRegion _damaged;
diff --git a/main.cpp b/main.cpp
index 8bad8ce..fd4347c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -16,16 +16,16 @@ static Watchlet *watchlet;
 
 int main(int argc, char *argv[])
 {
-    QApplication a(argc, argv);
+	QApplication a(argc, argv);
 
 	//watch = new MetaWatchSimulator();
 	watch = new MetaWatch(QBluetoothAddress("D0:37:61:C3:C7:99"));
 	server = new WatchServer(watch);
-	//watchlet = new TestDeclarativeWatchlet(server);
-	watchlet = new TestWatchlet(server);
+	new TestDeclarativeWatchlet(server);
+	new TestWatchlet(server);
 
-	//server->runWatchlet("com.javispedro.sowatch.testdeclarativewatchlet");
-	server->runWatchlet("com.javispedro.sowatch.testwatchlet");
+	server->runWatchlet("com.javispedro.sowatch.testdeclarativewatchlet");
+	//server->runWatchlet("com.javispedro.sowatch.testwatchlet");
 
     return a.exec();
 }
diff --git a/metawatch.cpp b/metawatch.cpp
index d523e1c..b968fad 100644
--- a/metawatch.cpp
+++ b/metawatch.cpp
@@ -128,14 +128,14 @@ void MetaWatch::update(const QList<QRect> &rects)
 		}
 	}
 
-	updateLines(1, _image, lines);
-	updateDisplay(1);
+	updateLines(ApplicationMode, _image, lines);
+	updateDisplay(ApplicationMode);
 }
 
 void MetaWatch::clear(bool white)
-{
+{qDebug() << "MWclear" << white;
 	if (_socket->state() != QBluetoothSocket::ConnectedState) return;
-	loadTemplate(1, white ? 1 : 0);
+	loadTemplate(ApplicationMode, white ? 1 : 0);
 }
 
 void MetaWatch::vibrate(bool on)
@@ -214,7 +214,7 @@ void MetaWatch::handleMessage(const Message &msg)
 	}
 }
 
-void MetaWatch::updateLine(int mode, const QImage& image, int line)
+void MetaWatch::updateLine(Mode mode, const QImage& image, int line)
 {
 	Message msg(WriteBuffer, QByteArray(13, 0), (1 << 4) | (mode & 0xF));
 	const char * scanLine = (const char *) image.constScanLine(line);
@@ -225,7 +225,7 @@ void MetaWatch::updateLine(int mode, const QImage& image, int line)
 	send(msg);
 }
 
-void MetaWatch::updateLines(int mode, const QImage& image, int lineA, int lineB)
+void MetaWatch::updateLines(Mode mode, const QImage& image, int lineA, int lineB)
 {
 	Message msg(WriteBuffer, QByteArray(26, 0), mode & 0xF);
 	const char * scanLine = (const char *) image.constScanLine(lineA);
@@ -240,7 +240,7 @@ void MetaWatch::updateLines(int mode, const QImage& image, int lineA, int lineB)
 	send(msg);
 }
 
-void MetaWatch::updateLines(int mode, const QImage& image, const QVector<bool>& lines)
+void MetaWatch::updateLines(Mode mode, const QImage& image, const QVector<bool>& lines)
 {
 	int lineCount = lines.count(true);
 	int lineA = -1;
@@ -269,7 +269,7 @@ void MetaWatch::updateLines(int mode, const QImage& image, const QVector<bool>&
 	}
 }
 
-void MetaWatch::configureWatchMode(int mode, int timeout, bool invert)
+void MetaWatch::configureWatchMode(Mode mode, int timeout, bool invert)
 {
 	Message msg(ConfigureMode, QByteArray(2, 0), mode & 0xF);
 	msg.data[0] = timeout;
@@ -277,14 +277,14 @@ void MetaWatch::configureWatchMode(int mode, int timeout, bool invert)
 	send(msg);
 }
 
-void MetaWatch::updateDisplay(int mode, bool copy)
+void MetaWatch::updateDisplay(Mode mode, bool copy)
 {
 	Message msg(UpdateDisplay, QByteArray(),
 				(copy ? 0x10 : 0) | (mode & 0xF));
 	send(msg);
 }
 
-void MetaWatch::loadTemplate(int mode, int templ)
+void MetaWatch::loadTemplate(Mode mode, int templ)
 {
 	Message msg(LoadTemplate, QByteArray(1, templ), mode & 0xF);
 	send(msg);
@@ -292,7 +292,7 @@ void MetaWatch::loadTemplate(int mode, int templ)
 
 void MetaWatch::handleStatusChange(const Message &msg)
 {
-	qDebug() << "watch status changed";
+	qDebug() << "watch status changed" << msg.data.size();
 }
 
 void MetaWatch::handleButtonEvent(const Message &msg)
@@ -310,7 +310,7 @@ void MetaWatch::socketConnected()
 	_partialReceived.data.clear();
 	_buttonState = 0;
 	setDateTime(QDateTime::currentDateTime());
-	configureWatchMode(1);
+	configureWatchMode(ApplicationMode);
 	emit connected();
 }
 
diff --git a/metawatch.h b/metawatch.h
index 2ec56f9..80a1894 100644
--- a/metawatch.h
+++ b/metawatch.h
@@ -16,7 +16,7 @@ namespace sowatch
 class MetaWatch : public Watch
 {
     Q_OBJECT
-	Q_ENUMS(MessageType)
+	Q_ENUMS(MessageType Mode)
 
 public:
 	explicit MetaWatch(const QBluetoothAddress& address, QObject *parent = 0);
@@ -62,6 +62,11 @@ public:
 		Accelerometer = 0xea
 	};
 
+	enum Mode {
+		IdleMode = 0,
+		ApplicationMode = 1
+	};
+
 protected:
 	QBluetoothSocket* _socket;
 
@@ -90,12 +95,12 @@ protected:
 	void send(const Message& msg);
 	void handleMessage(const Message& msg);
 
-	void updateLine(int mode, const QImage& image, int line);
-	void updateLines(int mode, const QImage& image, int lineA, int lineB);
-	void updateLines(int mode, const QImage& image, const QVector<bool>& lines);
-	void configureWatchMode(int mode, int timeout = 10, bool invert = false);
-	void updateDisplay(int mode, bool copy = true);
-	void loadTemplate(int mode, int templ);
+	void updateLine(Mode mode, const QImage& image, int line);
+	void updateLines(Mode mode, const QImage& image, int lineA, int lineB);
+	void updateLines(Mode mode, const QImage& image, const QVector<bool>& lines);
+	void configureWatchMode(Mode mode, int timeout = 10, bool invert = false);
+	void updateDisplay(Mode mode, bool copy = true);
+	void loadTemplate(Mode mode, int templ);
 
 	void handleStatusChange(const Message& msg);
 	void handleButtonEvent(const Message& msg);
diff --git a/metawatchpaintengine.cpp b/metawatchpaintengine.cpp
index 96e78a7..71ad452 100644
--- a/metawatchpaintengine.cpp
+++ b/metawatchpaintengine.cpp
@@ -14,7 +14,7 @@ void MetaWatchPaintEngine::drawRects(const QRectF *rects, int rectCount)
 	int i;
 	for (i = 0; i < rectCount; i++) {
 		const QRectF& r = rects[i];
-		if (_hasBrush && r.toRect() == _imageRect && (_isBrushBlack | _isBrushWhite)) {
+		if (_hasBrush && fillsEntireImage(r.toRect()) && (_isBrushBlack | _isBrushWhite)) {
 			_watch->clear(_isBrushWhite);
 			_damaged = QRegion();
 			continue;
@@ -37,7 +37,7 @@ void MetaWatchPaintEngine::drawRects(const QRect *rects, int rectCount)
 	int i;
 	for (i = 0; i < rectCount; i++) {
 		const QRect& r = rects[i];
-		if (_hasBrush && r == _imageRect && (_isBrushBlack | _isBrushWhite)) {
+		if (_hasBrush && fillsEntireImage(r) && (_isBrushBlack | _isBrushWhite)) {
 			_watch->clear(_isBrushWhite);
 			_damaged = QRegion();
 			continue;
@@ -73,3 +73,10 @@ void MetaWatchPaintEngine::updateState(const QPaintEngineState &state)
 		}
 	}
 }
+
+bool MetaWatchPaintEngine::fillsEntireImage(const QRect& rect)
+{
+	return rect == _imageRect &&
+			(!_clipEnabled ||
+			 (_clipRegion.numRects() == 1 && _clipRegion.rects().at(0) == _imageRect));
+}
diff --git a/metawatchpaintengine.h b/metawatchpaintengine.h
index 7c76beb..efc3d6e 100644
--- a/metawatchpaintengine.h
+++ b/metawatchpaintengine.h
@@ -21,6 +21,8 @@ public:
 	void updateState(const QPaintEngineState &state);
 
 protected:
+	bool fillsEntireImage(const QRect& rect);
+
 	MetaWatch* _watch;
 	QRect _imageRect;
 	bool _isBrushBlack;
diff --git a/metawatchsimulator.cpp b/metawatchsimulator.cpp
index 1cf7def..11b938a 100644
--- a/metawatchsimulator.cpp
+++ b/metawatchsimulator.cpp
@@ -4,13 +4,15 @@
 #include "metawatchsimulator.h"
 
 #define SIMULATE_DAMAGES 1
+#define SIMULATE_FRAMERATE 1
 
 using namespace sowatch;
 
 MetaWatchSimulator::MetaWatchSimulator(QObject *parent) :
 	WatchSimulator(QImage(96, 96, QImage::Format_Mono), parent),
 	_screen(96, 96),
-	_form(new MetaWatchSimulatorForm)
+	_form(new MetaWatchSimulatorForm),
+	_nextFrame(QTime::currentTime())
 {
 	_form->showNormal();
 	connect(_form, SIGNAL(destroyed()), SIGNAL(disconnected()));
@@ -35,7 +37,11 @@ bool MetaWatchSimulator::isConnected() const
 
 bool MetaWatchSimulator::busy() const
 {
+#if SIMULATE_FRAMERATE
+	return _nextFrame > QTime::currentTime();
+#else
 	return false;
+#endif
 }
 
 void MetaWatchSimulator::update(const QList<QRect> &rects)
@@ -44,7 +50,7 @@ void MetaWatchSimulator::update(const QList<QRect> &rects)
 	const QRect imageRect = _image.rect();
 	QPainter p;
 	QVector<bool> rows(96, false);
-	unsigned total = 0;
+	unsigned total = 0, totalRows;
 
 	p.begin(&_screen);
 	foreach (const QRect& rect, rects) {
@@ -58,15 +64,19 @@ void MetaWatchSimulator::update(const QList<QRect> &rects)
 	}
 	p.end();
 
+	totalRows = rows.count(true);
+
 	_form->refreshScreen(_screen);
 
-	qDebug() << "updated " << total << " pixels " << rows.count(true) << " lines";
+	qDebug() << "updated " << total << " pixels " << totalRows << " lines";
+	_nextFrame = QTime::currentTime().addMSecs(((totalRows / 2) + 1) * 30);
 #else
 	_form->refreshScreen(QPixmap::fromImage(_image));
+	_nextFrame = QTime::currentTime().addMSecs(30);
 #endif
 }
 
 void MetaWatchSimulator::vibrate(bool on)
 {
-
+	qDebug() << "vibrate" << on;
 }
diff --git a/metawatchsimulator.h b/metawatchsimulator.h
index 22ca4b0..674c3c6 100644
--- a/metawatchsimulator.h
+++ b/metawatchsimulator.h
@@ -1,6 +1,7 @@
 #ifndef METAWATCHSIMULATOR_H
 #define METAWATCHSIMULATOR_H
 
+#include <QtCore/QTime>
 #include "watchsimulator.h"
 #include "metawatchsimulatorform.h"
 
@@ -23,6 +24,7 @@ public:
 protected:
 	QPixmap _screen;
 	MetaWatchSimulatorForm* _form;
+	QTime _nextFrame;
 };
 
 }
diff --git a/testdeclarativewatchlet.qml b/testdeclarativewatchlet.qml
index 08a3b06..04d8167 100644
--- a/testdeclarativewatchlet.qml
+++ b/testdeclarativewatchlet.qml
@@ -5,6 +5,10 @@ Rectangle {
 	width: 96
 	height: 96
 
+	Text {
+		text: watch.model
+	}
+
 	Image {
 		anchors.centerIn: parent
 		source: "qt.png"
@@ -14,91 +18,11 @@ Rectangle {
 			origin { x: width / 4; y: 0; }
 			RotationAnimation on angle {
 				loops: Animation.Infinite
-				running: true
-				duration: 10000
+				running: watch.active
+				duration: 6000
 				from: 0
-				to: 360
+				to: 180
 			}
 		}
 	}
-
-	/*color: "white"
-
-	Rectangle {
-		width: 90
-		height: 90
-
-		color: "black"
-
-		Rectangle {
-			width: 10
-			height: 10
-
-			x: 0
-			y: 0
-
-			SequentialAnimation on y {
-				loops: Animation.Infinite
-				NumberAnimation { from: 0; to: 60; duration: 1000 }
-				NumberAnimation { from: 60; to: 0; duration: 1000 }
-			}
-		}
-
-		Rectangle {
-			width: 10
-			height: 10
-
-			x: 80
-			y: 00
-
-			SequentialAnimation on y {
-				loops: Animation.Infinite
-				NumberAnimation { from: 0; to: 60; duration: 1000 }
-			}
-		}
-
-		Rectangle {
-			width: 10
-			height: 10
-			x: 10
-			y: 10
-
-			SequentialAnimation on visible {
-				loops: Animation.Infinite
-				PropertyAnimation { to: false; duration: 1000 }
-				PropertyAnimation { to: true; duration: 1000 }
-			}
-		}
-
-		Rectangle {
-			id: big1
-			width: 20
-			height: 20
-			x: 40
-			y: 40
-
-			color: "white"
-			visible: false
-		}
-
-		Text {
-			id: name
-			x: 20
-			text: "hello"
-			color: "white"
-
-			SequentialAnimation on y {
-				loops: Animation.Infinite
-				NumberAnimation { from: 0; to: 60; duration: 1000 }
-				NumberAnimation { from: 60; to: 0; duration: 1000 }
-			}
-		}
-
-		Connections {
-			target: watch
-			onButtonPressed: {
-				console.log(button);
-			}
-		}
-	}*/
 }
diff --git a/testwatchlet.cpp b/testwatchlet.cpp
index b29eb0f..ffc4097 100644
--- a/testwatchlet.cpp
+++ b/testwatchlet.cpp
@@ -11,9 +11,21 @@ TestWatchlet::TestWatchlet(WatchServer* server) :
 {
 	_timer->setInterval(50);
 	connect(_timer, SIGNAL(timeout()), SLOT(interv()));
+	connect(this, SIGNAL(activated()), SLOT(handleActivated()));
+	connect(this, SIGNAL(deactivated()), SLOT(handleDeactivated()));
 }
 
-void TestWatchlet::activate()
+void TestWatchlet::interv()
+{
+	QPainter p(watch());
+	//p.fillRect(8, _y, 8, 1, Qt::black);
+	_y = (_y + 1) % watch()->height();
+	p.fillRect(0, _y, _y, 2, Qt::black);
+	//p.fillRect(0, 0, watch()->width(), watch()->height(), Qt::black);
+}
+
+
+void TestWatchlet::handleActivated()
 {
 	qDebug() << "test watchlet activated";
 	QPainter p(watch());
@@ -21,17 +33,8 @@ void TestWatchlet::activate()
 	_timer->start();
 }
 
-void TestWatchlet::deactivate()
+void TestWatchlet::handleDeactivated()
 {
 	_timer->stop();
 	qDebug() << "test watchlet deactivated";
 }
-
-void TestWatchlet::interv()
-{
-	QPainter p(watch());
-	//p.fillRect(8, _y, 8, 1, Qt::black);
-	_y = (_y + 1) % watch()->height();
-	p.fillRect(0, _y, _y, 2, Qt::black);
-	//p.fillRect(0, 0, watch()->width(), watch()->height(), Qt::black);
-}
diff --git a/testwatchlet.h b/testwatchlet.h
index 75568ca..caa68da 100644
--- a/testwatchlet.h
+++ b/testwatchlet.h
@@ -13,15 +13,10 @@ class TestWatchlet : public Watchlet
 public:
 	explicit TestWatchlet(WatchServer* server);
 
-	void activate();
-	void deactivate();
-
-signals:
-
-public slots:
-
 protected slots:
 	void interv();
+	void handleActivated();
+	void handleDeactivated();
 
 private:
 	QTimer *_timer;
diff --git a/watchlet.cpp b/watchlet.cpp
index 2e76d5e..6d7fe68 100644
--- a/watchlet.cpp
+++ b/watchlet.cpp
@@ -4,7 +4,7 @@
 using namespace sowatch;
 
 Watchlet::Watchlet(WatchServer *server, const QString& id) :
-	QObject(server), _id(id), _server(server)
+	QObject(server), _id(id), _active(false), _server(server)
 {
 	_server->registerWatchlet(this);
 }
@@ -19,7 +19,26 @@ Watch* Watchlet::watch()
 	return _server->watch();
 }
 
-QString Watchlet::id()
+QString Watchlet::id() const
 {
 	return _id;
 }
+
+bool Watchlet::isActive() const
+{
+	return _active;
+}
+
+void Watchlet::activate()
+{
+	_active = true;
+	emit activeChanged();
+	emit activated();
+}
+
+void Watchlet::deactivate()
+{
+	_active = false;
+	emit activeChanged();
+	emit deactivated();
+}
diff --git a/watchlet.h b/watchlet.h
index fd2c7f4..f018fa1 100644
--- a/watchlet.h
+++ b/watchlet.h
@@ -12,7 +12,8 @@ class WatchServer;
 class Watchlet : public QObject
 {
     Q_OBJECT
-	Q_PROPERTY(QString id READ id)
+	Q_PROPERTY(QString id READ id CONSTANT)
+	Q_PROPERTY(bool isActive READ isActive NOTIFY activeChanged)
 
 public:
 	explicit Watchlet(WatchServer *server, const QString& id);
@@ -20,14 +21,22 @@ public:
 	WatchServer* server();
 	Watch* watch();
 
-	QString id();
+	Q_INVOKABLE QString id() const;
+	Q_INVOKABLE bool isActive() const;
+
+signals:
+	void activeChanged();
+	void activated();
+	void deactivated();
 
 protected:
-	virtual void activate() = 0;
-	virtual void deactivate() = 0;
+	virtual void activate();
+	virtual void deactivate();
+
+	const QString _id;
+	bool _active;
 
 private:
-	QString _id;
 	WatchServer* _server;
 
 friend class WatchServer;
diff --git a/watchpaintengine.cpp b/watchpaintengine.cpp
index f506da7..18cfb60 100644
--- a/watchpaintengine.cpp
+++ b/watchpaintengine.cpp
@@ -11,6 +11,7 @@ WatchPaintEngine::WatchPaintEngine(Watch* watch, QImage* image)
 	  _watch(watch), _painter(),
 	  _hasPen(false), _hasBrush(false), _clipEnabled(false)
 {
+	Q_UNUSED(image);
 }
 
 bool WatchPaintEngine::begin(QPaintDevice *pdev)
@@ -30,18 +31,23 @@ bool WatchPaintEngine::end()
 	return ret;
 }
 
-void WatchPaintEngine::damageRect(const QRect &r)
+void WatchPaintEngine::damageMappedRect(const QRect &r)
 {
 	if (_clipEnabled) {
-		_damaged += _clipRegion.intersect(r);
+		_damaged += _clipRegion.intersected(r);
 	} else {
 		_damaged += r;
 	}
 }
 
+void WatchPaintEngine::damageRect(const QRect &r)
+{
+	damageMappedRect(_transform.mapRect(r));
+}
+
 void WatchPaintEngine::damageRect(const QRectF &r)
 {
-	damageRect(r.toRect());
+	damageMappedRect(_transform.mapRect(r).toRect());
 }
 
 void WatchPaintEngine::damagePenStroke(const QLineF &line)
@@ -65,6 +71,7 @@ void WatchPaintEngine::updateClipRegion(const QRegion& region, Qt::ClipOperation
 	switch(op) {
 		case Qt::NoClip:
 			_clipEnabled = false;
+			_clipRegion = QRegion(0, 0, _watch->width(), _watch->height());
 			break;
 		case Qt::ReplaceClip:
 			_clipEnabled = true;
@@ -83,10 +90,14 @@ void WatchPaintEngine::updateClipRegion(const QRegion& region, Qt::ClipOperation
 
 void WatchPaintEngine::drawEllipse(const QRectF &r)
 {
+	damageRect(r);
+	_painter.drawEllipse(r);
 }
 
 void WatchPaintEngine::drawEllipse(const QRect &r)
 {
+	damageRect(r);
+	_painter.drawEllipse(r);
 }
 
 void WatchPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags)
@@ -258,14 +269,12 @@ void WatchPaintEngine::updateState(const QPaintEngineState &state)
 	}
 	if (flags & QPaintEngine::DirtyClipPath)
 	{
-		_clipEnabled = true;
 		QRegion region = state.clipPath().boundingRect().toRect();
 		updateClipRegion(region, state.clipOperation());
 		_painter.setClipPath(state.clipPath(), state.clipOperation());
 	}
 	if (flags & QPaintEngine::DirtyClipRegion)
 	{
-		_clipEnabled = true;
 		updateClipRegion(state.clipRegion(), state.clipOperation());
 		_painter.setClipRegion(state.clipRegion(), state.clipOperation());
 	}
@@ -290,6 +299,7 @@ void WatchPaintEngine::updateState(const QPaintEngineState &state)
 	}
 	if (flags & QPaintEngine::DirtyTransform)
 	{
-		_painter.setTransform(state.transform());
+		_transform = state.transform();
+		_painter.setTransform(_transform);
 	}
 }
diff --git a/watchpaintengine.h b/watchpaintengine.h
index 59010c0..14181fa 100644
--- a/watchpaintengine.h
+++ b/watchpaintengine.h
@@ -36,6 +36,7 @@ public:
 	void updateState(const QPaintEngineState &state);
 
 protected:
+	void damageMappedRect(const QRect& r);
 	void damageRect(const QRect& r);
 	void damageRect(const QRectF& r);
 	void damagePenStroke(const QLineF& line);
@@ -52,6 +53,8 @@ protected:
 
 	bool _clipEnabled;
 	QRegion _clipRegion;
+
+	QTransform _transform;
 };
 
 }
-- 
cgit v1.2.3