Implement mouse cursor

Signed-off-by: Vojtech Bocek <vbocek@gmail.com>

Change-Id: I66d6db7b3ed9cca50b469d125b36224332e06913
diff --git a/gui/Android.mk b/gui/Android.mk
index ac0b203..29d99f7 100644
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -22,7 +22,8 @@
     keyboard.cpp \
     input.cpp \
     blanktimer.cpp \
-    partitionlist.cpp
+    partitionlist.cpp \
+    mousecursor.cpp
 
 ifneq ($(TWRP_CUSTOM_KEYBOARD),)
   LOCAL_SRC_FILES += $(TWRP_CUSTOM_KEYBOARD)
diff --git a/gui/devices/1024x600/res/images/cursor.png b/gui/devices/1024x600/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1024x600/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1024x600/res/ui.xml b/gui/devices/1024x600/res/ui.xml
index f1ec144..4597fb3 100755
--- a/gui/devices/1024x600/res/ui.xml
+++ b/gui/devices/1024x600/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="50" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/1024x768/res/images/cursor.png b/gui/devices/1024x768/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1024x768/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1024x768/res/ui.xml b/gui/devices/1024x768/res/ui.xml
index 73b531b..84f4702 100644
--- a/gui/devices/1024x768/res/ui.xml
+++ b/gui/devices/1024x768/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="50" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/1080x1920/res/images/cursor.png b/gui/devices/1080x1920/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml
index 15b9878..3ab69a6 100644
--- a/gui/devices/1080x1920/res/ui.xml
+++ b/gui/devices/1080x1920/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -191,6 +192,12 @@
 		<variable name="slidervalue_sliderh" value="90" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/1200x1920/res/images/cursor.png b/gui/devices/1200x1920/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1200x1920/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1200x1920/res/ui.xml b/gui/devices/1200x1920/res/ui.xml
index c77c341..5aedca8 100644
--- a/gui/devices/1200x1920/res/ui.xml
+++ b/gui/devices/1200x1920/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -194,6 +195,12 @@
 		<variable name="slidervalue_sliderh" value="90" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/1280x800/res/images/cursor.png b/gui/devices/1280x800/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1280x800/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1280x800/res/ui.xml b/gui/devices/1280x800/res/ui.xml
index dbfcd60..c7d9148 100644
--- a/gui/devices/1280x800/res/ui.xml
+++ b/gui/devices/1280x800/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="60" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/1920x1200/res/images/cursor.png b/gui/devices/1920x1200/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml
index e4bfd69..dbd6a0b 100644
--- a/gui/devices/1920x1200/res/ui.xml
+++ b/gui/devices/1920x1200/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="80" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/2560x1600/res/images/cursor.png b/gui/devices/2560x1600/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/2560x1600/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/2560x1600/res/ui.xml b/gui/devices/2560x1600/res/ui.xml
index f53f7b4..0a501af 100644
--- a/gui/devices/2560x1600/res/ui.xml
+++ b/gui/devices/2560x1600/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="90" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/320x480/res/images/cursor.png b/gui/devices/320x480/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/320x480/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/320x480/res/ui.xml b/gui/devices/320x480/res/ui.xml
index 9f0d5a3..3c3b73d 100644
--- a/gui/devices/320x480/res/ui.xml
+++ b/gui/devices/320x480/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -186,6 +187,12 @@
 		<variable name="slidervalue_sliderh" value="20" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="1" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/480x800/res/images/cursor.png b/gui/devices/480x800/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/480x800/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml
index 416f6b9..32c90d9 100644
--- a/gui/devices/480x800/res/ui.xml
+++ b/gui/devices/480x800/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -186,6 +187,12 @@
 		<variable name="slidervalue_sliderh" value="40" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="1.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="%backgroundcolor%" />
diff --git a/gui/devices/480x854/res/images/cursor.png b/gui/devices/480x854/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/480x854/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/480x854/res/ui.xml b/gui/devices/480x854/res/ui.xml
index 687300a..a835770 100644
--- a/gui/devices/480x854/res/ui.xml
+++ b/gui/devices/480x854/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -185,6 +186,12 @@
 		<variable name="slidervalue_sliderh" value="40" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="1.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="%backgroundcolor%" />
diff --git a/gui/devices/540x960/res/images/cursor.png b/gui/devices/540x960/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/540x960/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/540x960/res/ui.xml b/gui/devices/540x960/res/ui.xml
index b11c3dc..0a43beb 100644
--- a/gui/devices/540x960/res/ui.xml
+++ b/gui/devices/540x960/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -186,6 +187,12 @@
 		<variable name="slidervalue_sliderh" value="45" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="1.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/720x1280/res/images/cursor.png b/gui/devices/720x1280/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/720x1280/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/720x1280/res/ui.xml b/gui/devices/720x1280/res/ui.xml
index 573bebd..37003da 100644
--- a/gui/devices/720x1280/res/ui.xml
+++ b/gui/devices/720x1280/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -191,6 +192,12 @@
 		<variable name="slidervalue_sliderh" value="60" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/800x1280/res/images/cursor.png b/gui/devices/800x1280/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/800x1280/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/800x1280/res/ui.xml b/gui/devices/800x1280/res/ui.xml
index fd63d90..31006e6 100755
--- a/gui/devices/800x1280/res/ui.xml
+++ b/gui/devices/800x1280/res/ui.xml
@@ -39,6 +39,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -187,6 +188,12 @@
 		<variable name="slidervalue_sliderh" value="60" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="2.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/devices/800x480/res/images/cursor.png b/gui/devices/800x480/res/images/cursor.png
new file mode 100644
index 0000000..32c8ae1
--- /dev/null
+++ b/gui/devices/800x480/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/800x480/res/ui.xml b/gui/devices/800x480/res/ui.xml
index 87a3543..8f881d7 100755
--- a/gui/devices/800x480/res/ui.xml
+++ b/gui/devices/800x480/res/ui.xml
@@ -38,6 +38,7 @@
 		<resource name="keyboard2" type="image" filename="keyboard2" />
 		<resource name="keyboard3" type="image" filename="keyboard3" />
 		<resource name="keyboard4" type="image" filename="keyboard4" />
+		<resource name="cursor" type="image" filename="cursor" />
 	</resources>
 
 	<variables>
@@ -205,6 +206,12 @@
 		<variable name="slidervalue_sliderh" value="40" />
 	</variables>
 
+	<mousecursor>
+		<placement w="15" h="15" />
+		<background color="#FFFF00FF" resource="cursor" />
+		<speed multiplier="1.5" />
+	</mousecursor>
+
 	<templates>
 		<template name="header">
 			<background color="#000000FF" />
diff --git a/gui/gui.cpp b/gui/gui.cpp
index e9efc1d..2098342 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -186,6 +186,7 @@
 	static struct timeval touchStart;
 	HardwareKeyboard kb;
 	string seconds;
+	MouseCursor *cursor = PageManager::GetMouseCursor();
 
 #ifndef TW_NO_SCREEN_TIMEOUT
 	//start screen timeout threads
@@ -329,7 +330,47 @@
 #ifdef _EVENT_LOGGING
 			LOGERR("TOUCH_KEY: %d\n", ev.code);
 #endif
-			if (ev.value != 0)
+			// Left mouse button
+			if(ev.code == BTN_LEFT)
+			{
+				if(ev.value == 1)
+				{
+					cursor->GetPos(x, y);
+
+					if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
+						state = 1;
+					drag = 1;
+					touch_and_hold = 1;
+					dontwait = 1;
+					key_repeat = 0;
+					gettimeofday(&touchStart, NULL);
+				}
+				else if(drag == 1)
+				{
+					if (state == 0)
+					{
+						cursor->GetPos(x, y);
+
+						PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
+
+						touch_and_hold = 0;
+						touch_repeat = 0;
+						if (!key_repeat)
+							dontwait = 0;
+					}
+					state = 0;
+					drag = 0;
+				}
+			}
+			// side mouse button, often used for "back" function
+			else if(ev.code == BTN_SIDE)
+			{
+				if(ev.value == 1)
+					kb.KeyDown(KEY_BACK);
+				else
+					kb.KeyUp(KEY_BACK);
+			}
+			else if (ev.value != 0)
 			{
 				// This is a key press
 				if (kb.KeyDown(ev.code))
@@ -367,6 +408,26 @@
 #endif
 			}
 		}
+		else if(ev.type == EV_REL)
+		{
+#ifdef _EVENT_LOGGING
+			LOGERR("EV_REL %d %d\n", ev.code, ev.value);
+#endif
+			if(ev.code == REL_X)
+				cursor->Move(ev.value, 0);
+			else if(ev.code == REL_Y)
+				cursor->Move(0, ev.value);
+
+			if(drag == 1) {
+				cursor->GetPos(x, y);
+#ifdef _EVENT_LOGGING
+				LOGERR("TOUCH_DRAG: %d, %d\n", x, y);
+#endif
+				if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
+					state = 1;
+				key_repeat = 0;
+			}
+        }
 	}
 	return NULL;
 }
diff --git a/gui/mousecursor.cpp b/gui/mousecursor.cpp
new file mode 100644
index 0000000..1c22356
--- /dev/null
+++ b/gui/mousecursor.cpp
@@ -0,0 +1,154 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+MouseCursor::MouseCursor(int resX, int resY)
+{
+	ResetData(resX, resY);
+}
+
+MouseCursor::~MouseCursor()
+{
+}
+
+void MouseCursor::ResetData(int resX, int resY)
+{
+	m_resX = resX;
+	m_resY = resY;
+	m_moved = false;
+	m_speedMultiplier = 2.5f;
+	m_image = NULL;
+	m_present = false;
+
+	ConvertStrToColor("red", &m_color);
+
+	SetRenderPos(resX/2, resY/2, 10, 10);
+}
+
+void MouseCursor::LoadData(xml_node<>* node)
+{
+	xml_attribute<>* attr;
+	xml_node<>* child;
+
+	child = node->first_node("placement");
+	if(child)
+		LoadPlacement(child, &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+
+	child = node->first_node("background");
+	if(child)
+	{
+		attr = child->first_attribute("color");
+		if(attr)
+			ConvertStrToColor(attr->value(), &m_color);
+
+		attr = child->first_attribute("resource");
+		if(attr)
+		{
+			m_image = PageManager::FindResource(attr->value());
+			if(m_image)
+			{
+				mRenderW = gr_get_width(m_image->GetResource());
+				mRenderH = gr_get_height(m_image->GetResource());
+			}
+		}
+	}
+
+	child = node->first_node("speed");
+	if(child)
+	{
+		attr = child->first_attribute("multiplier");
+		if(attr)
+			m_speedMultiplier = atof(attr->value());
+	}
+}
+
+int MouseCursor::Render(void)
+{
+	if(!m_present)
+		return 0;
+
+	if(m_image)
+	{
+		gr_blit(m_image->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+	}
+	else
+	{
+		gr_color(m_color.red, m_color.green, m_color.blue, m_color.alpha);
+		gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+	}
+	return 0;
+}
+
+int MouseCursor::Update(void)
+{
+	if(m_present != ev_has_mouse())
+	{
+		m_present = ev_has_mouse();
+		if(m_present)
+			SetRenderPos(m_resX/2, m_resY/2);
+		return 2;
+	}
+
+	if(m_present && m_moved)
+	{
+		m_moved = false;
+		return 2;
+	}
+	return 0;
+}
+
+int MouseCursor::SetRenderPos(int x, int y, int w, int h)
+{
+	if(x == mRenderX && y == mRenderY)
+		m_moved = true;
+
+	return RenderObject::SetRenderPos(x, y, w, h);
+}
+
+void MouseCursor::Move(int deltaX, int deltaY)
+{
+	if(deltaX != 0)
+	{
+		mRenderX += deltaX*m_speedMultiplier;
+		mRenderX = (std::min)(mRenderX, m_resX);
+		mRenderX = (std::max)(mRenderX, 0);
+
+		m_moved = true;
+	}
+
+	if(deltaY != 0)
+	{
+		mRenderY += deltaY*m_speedMultiplier;
+		mRenderY = (std::min)(mRenderY, m_resY);
+		mRenderY = (std::max)(mRenderY, 0);
+
+		m_moved = true;
+	}
+}
+
+void MouseCursor::GetPos(int& x, int& y)
+{
+	x = mRenderX;
+	y = mRenderY;
+}
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 1053113..e8110b0 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -978,6 +978,31 @@
 	int lineW;
 };
 
+class MouseCursor : public RenderObject
+{
+public:
+	MouseCursor(int posX, int posY);
+	virtual ~MouseCursor();
+
+	virtual int Render(void);
+	virtual int Update(void);
+	virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+	void Move(int deltaX, int deltaY);
+	void GetPos(int& x, int& y);
+	void LoadData(xml_node<>* node);
+	void ResetData(int resX, int resY);
+
+private:
+	int m_resX;
+	int m_resY;
+	bool m_moved;
+	float m_speedMultiplier;
+	COLOR m_color;
+	Resource *m_image;
+	bool m_present;
+};
+
 // Helper APIs
 bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w = NULL, int* h = NULL, RenderObject::Placement* placement = NULL);
 
diff --git a/gui/pages.cpp b/gui/pages.cpp
index d662f18..dc9edc7 100644
--- a/gui/pages.cpp
+++ b/gui/pages.cpp
@@ -54,6 +54,7 @@
 std::map<std::string, PageSet*> PageManager::mPageSets;
 PageSet* PageManager::mCurrentSet;
 PageSet* PageManager::mBaseSet = NULL;
+MouseCursor *PageManager::mMouseCursor = NULL;
 
 // Helper routine to convert a string to a color declaration
 int ConvertStrToColor(std::string str, COLOR* color)
@@ -550,6 +551,11 @@
 	if (child)
 		LoadVariables(child);
 
+	LOGINFO("Loading mouse cursor...\n");
+	child = parent->first_node("mousecursor");
+	if(child)
+		PageManager::LoadCursorData(child);
+
 	LOGINFO("Loading pages...\n");
 	// This may be NULL if no templates are present
 	templates = parent->first_node("templates");
@@ -849,6 +855,9 @@
 	if (iter == mPageSets.end())
 		return -1;
 
+	if(mMouseCursor)
+		mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
+
 	PageSet* set = (*iter).second;
 	mPageSets.erase(iter);
 
@@ -924,7 +933,25 @@
 
 int PageManager::Render(void)
 {
-	return (mCurrentSet ? mCurrentSet->Render() : -1);
+	int res = (mCurrentSet ? mCurrentSet->Render() : -1);
+	if(mMouseCursor)
+		mMouseCursor->Render();
+	return res;
+}
+
+MouseCursor *PageManager::GetMouseCursor()
+{
+	if(!mMouseCursor)
+		mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
+	return mMouseCursor;
+}
+
+void PageManager::LoadCursorData(xml_node<>* node)
+{
+	if(!mMouseCursor)
+		mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
+
+	mMouseCursor->LoadData(node);
 }
 
 int PageManager::Update(void)
@@ -933,7 +960,16 @@
 	if(blankTimer.IsScreenOff())
 		return 0;
 #endif
-	return (mCurrentSet ? mCurrentSet->Update() : -1);
+
+	int res = (mCurrentSet ? mCurrentSet->Update() : -1);
+
+	if(mMouseCursor)
+	{
+		int c_res = mMouseCursor->Update();
+		if(c_res > res)
+			res = c_res;
+	}
+	return res;
 }
 
 int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
diff --git a/gui/pages.hpp b/gui/pages.hpp
index a37cdb9..2a2ef2c 100644
--- a/gui/pages.hpp
+++ b/gui/pages.hpp
@@ -28,6 +28,7 @@
 class RenderObject;
 class ActionObject;
 class InputObject;
+class MouseCursor;
 
 class Page
 {
@@ -130,6 +131,9 @@
 	static int SetKeyBoardFocus(int inFocus);
 	static int NotifyVarChange(std::string varName, std::string value);
 
+	static MouseCursor *GetMouseCursor();
+	static void LoadCursorData(xml_node<>* node);
+
 protected:
 	static PageSet* FindPackage(std::string name);
 
@@ -137,6 +141,7 @@
 	static std::map<std::string, PageSet*> mPageSets;
 	static PageSet* mCurrentSet;
 	static PageSet* mBaseSet;
+	static MouseCursor *mMouseCursor;
 };
 
 #endif  // _PAGES_HEADER_HPP
diff --git a/minuitwrp/events.c b/minuitwrp/events.c
index aecaf8f..94942ba 100644
--- a/minuitwrp/events.c
+++ b/minuitwrp/events.c
@@ -20,8 +20,11 @@
 #include <dirent.h>
 #include <sys/poll.h>
 #include <limits.h>
-
 #include <linux/input.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 
 #include "../common.h"
 
@@ -95,6 +98,9 @@
 static struct pollfd ev_fds[MAX_DEVICES];
 static struct ev evs[MAX_DEVICES];
 static unsigned ev_count = 0;
+static struct timeval lastInputStat;
+static unsigned long lastInputMTime;
+static int has_mouse = 0;
 
 static inline int ABS(int x) {
     return x<0?-x:x;
@@ -239,12 +245,41 @@
     return 0;
 }
 
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x)  ((x)%BITS_PER_LONG)
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array)	((array[LONG(bit)] >> OFF(bit)) & 1)
+static void check_mouse(int fd)
+{
+	if(has_mouse)
+		return;
+
+	unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
+	memset(bit, 0, sizeof(bit));
+	ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
+
+	if(!test_bit(EV_REL, bit[0]))
+		return;
+
+	ioctl(fd, EVIOCGBIT(EV_REL, KEY_MAX), bit[EV_REL]);
+	if(test_bit(REL_X, bit[EV_REL]) && test_bit(REL_Y, bit[EV_REL]))
+		has_mouse = 1;
+}
+
+int ev_has_mouse(void)
+{
+	return has_mouse;
+}
+
 int ev_init(void)
 {
     DIR *dir;
     struct dirent *de;
     int fd;
 
+    has_mouse = 0;
+
 	dir = opendir("/dev/input");
     if(dir != 0) {
         while((de = readdir(dir))) {
@@ -260,23 +295,32 @@
             /* Load virtualkeys if there are any */
 			vk_init(&evs[ev_count]);
 
+            check_mouse(fd);
+
             ev_count++;
             if(ev_count == MAX_DEVICES) break;
         }
+        closedir(dir);
     }
 
+    struct stat st;
+    if(stat("/dev/input", &st) >= 0)
+        lastInputMTime = st.st_mtime;
+    gettimeofday(&lastInputStat, NULL);
+
     return 0;
 }
 
 void ev_exit(void)
 {
-    while (ev_count-- > 0) {
-	if (evs[ev_count].vk_count) {
-		free(evs[ev_count].vks);
-		evs[ev_count].vk_count = 0;
+	while (ev_count-- > 0) {
+		if (evs[ev_count].vk_count) {
+			free(evs[ev_count].vks);
+			evs[ev_count].vk_count = 0;
+		}
+		close(ev_fds[ev_count].fd);
 	}
-        close(ev_fds[ev_count].fd);
-    }
+	ev_count = 0;
 }
 
 static int vk_inside_display(__s32 value, struct input_absinfo *info, int screen_size)
@@ -629,9 +673,25 @@
 {
     int r;
     unsigned n;
+    struct timeval curr;
 
     do {
-        r = poll(ev_fds, ev_count, dont_wait ? 0 : -1);
+        gettimeofday(&curr, NULL);
+        if(curr.tv_sec - lastInputStat.tv_sec >= 2)
+        {
+            struct stat st;
+            stat("/dev/input", &st);
+            if (st.st_mtime > lastInputMTime)
+            {
+                LOGI("Reloading input devices\n");
+                ev_exit();
+                ev_init();
+                lastInputMTime = st.st_mtime;
+            }
+            lastInputStat = curr;
+        }
+
+        r = poll(ev_fds, ev_count, 0);
 
         if(r > 0) {
             for(n = 0; n < ev_count; n++) {
@@ -644,6 +704,8 @@
                 }
             }
         }
+
+        usleep(1000);
     } while(dont_wait == 0);
 
     return -1;
diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h
index 5f02d4a..bbdfdfb 100644
--- a/minuitwrp/minui.h
+++ b/minuitwrp/minui.h
@@ -58,6 +58,7 @@
 int ev_init(void);
 void ev_exit(void);
 int ev_get(struct input_event *ev, unsigned dont_wait);
+int ev_has_mouse(void);
 
 // Resources