Index: build/premake/extern_libs4.lua
===================================================================
--- build/premake/extern_libs4.lua	(revision 11379)
+++ build/premake/extern_libs4.lua	(working copy)
@@ -587,6 +587,13 @@
 			})
 		end,
 	},
+	Xcursor = {
+		 link_settings = function()
+				add_default_links({
+					unix_names = { "Xcursor" },
+				})
+		 end,
+	},
 	zlib = {
 		compile_settings = function()
 			if os.is("windows") then
Index: build/premake/premake4.lua
===================================================================
--- build/premake/premake4.lua	(revision 11379)
+++ build/premake/premake4.lua	(working copy)
@@ -643,6 +643,7 @@
 			table.insert(source_dirs, "lib/sysdep/os/android")
 		else
 			table.insert(source_dirs, "lib/sysdep/os/unix/x")
+			table.insert(extern_libs, "Xcursor")
 		end
 	end
 
@@ -709,6 +710,7 @@
 
 if not os.is("windows") and not _OPTIONS["android"] then
 	table.insert(used_extern_libs, "x11")
+	table.insert(used_extern_libs, "Xcursor")
 end
 
 if not _OPTIONS["without-audio"] then
@@ -796,6 +798,8 @@
 			linkoptions { "-rdynamic" }
 		configuration { }
 
+		links { "Xcursor" }
+
 	elseif os.is("macosx") then
 		links { "pthread" }
 	end
Index: source/lib/sysdep/os/unix/unix.cpp
===================================================================
--- source/lib/sysdep/os/unix/unix.cpp	(revision 11379)
+++ source/lib/sysdep/os/unix/unix.cpp	(working copy)
@@ -45,6 +45,9 @@
 #define URL_OPEN_COMMAND "xdg-open"
 #endif
 
+#include <X11/Xcursor/Xcursor.h>
+#undef Status
+#include <SDL_syswm.h>
 
 bool sys_IsDebuggerPresent()
 {
@@ -283,38 +286,59 @@
 	return ERR::FAIL;
 }
 
-// stub for sys_cursor_create - we don't need to implement this (SDL/X11 only
-// has monochrome cursors so we need to use the software cursor anyways)
+struct sys_cursor_impl
+{
+	XcursorImage* image;
+	Cursor cursor;
+};
 
-// note: do not return ERR_NOT_IMPLEMENTED or similar because that
-// would result in WARN_ERRs.
-Status sys_cursor_create(size_t w, size_t h, void* bgra_img, size_t hx, size_t hy, sys_cursor* cursor)
+Status sys_cursor_create(int w, int h, void* bgra_img, int hx, int hy, sys_cursor* cursor)
 {
-	UNUSED2(w);
-	UNUSED2(h);
-	UNUSED2(hx);
-	UNUSED2(hy);
-	UNUSED2(bgra_img);
+	XcursorImage* image = XcursorImageCreate(w, h);
 
-	*cursor = 0;
+	std::copy(static_cast<char*>(bgra_img), static_cast<char*>(bgra_img) + 4 * w * h,
+			  reinterpret_cast<char*>(image->pixels));
+	image->xhot = hx;
+	image->yhot = hy;
+
+	SDL_SysWMinfo wminfo;
+	SDL_VERSION(&wminfo.version);
+	if (not SDL_GetWMInfo(&wminfo))
+		WARN_RETURN(ERR::FAIL);
+	sys_cursor_impl* impl = new sys_cursor_impl;
+	impl->image = image;
+	impl->cursor = XcursorImageLoadCursor(wminfo.info.x11.display, image);
+	*cursor = static_cast<sys_cursor>(impl);
 	return INFO::OK;
 }
 
 // returns a dummy value representing an empty cursor
 Status sys_cursor_create_empty(sys_cursor* cursor)
 {
-	*cursor = (void*)1; // any non-zero value, since the cursor NULL has special meaning
-	return INFO::OK;
+	static char transparent_bgra[] = { 0x0, 0x0, 0x0, 0xFF };
+
+	return sys_cursor_create(1, 1, static_cast<void*>(transparent_bgra), 0, 0, cursor);
 }
 
 // replaces the current system cursor with the one indicated. need only be
 // called once per cursor; pass 0 to restore the default.
 Status sys_cursor_set(sys_cursor cursor)
 {
-	if (cursor) // dummy empty cursor
+	if (not cursor) // restore default cursor
 		SDL_ShowCursor(SDL_DISABLE);
-	else // restore default cursor
+	else
+	{
+		SDL_SysWMinfo wminfo;
+		SDL_VERSION(&wminfo.version);
+		if (not SDL_GetWMInfo(&wminfo))
+			WARN_RETURN(ERR::FAIL);
+		
+		wminfo.info.x11.lock_func();
 		SDL_ShowCursor(SDL_ENABLE);
+		XDefineCursor(wminfo.info.x11.display, wminfo.info.x11.window,
+					  static_cast<sys_cursor_impl*>(cursor)->cursor);
+		wminfo.info.x11.unlock_func();
+	}
 
 	return INFO::OK;
 }
@@ -327,8 +351,17 @@
 	if(!cursor)
 		return INFO::OK;
 
-	SDL_ShowCursor(SDL_ENABLE);
+	sys_cursor_set(0); // restore default cursor
+	sys_cursor_impl* impl = static_cast<sys_cursor_impl*>(cursor);
 
+	XcursorImageDestroy(impl->image);
+	
+	SDL_SysWMinfo wminfo;
+	SDL_VERSION(&wminfo.version);
+	if (not SDL_GetWMInfo(&wminfo))
+		return ERR::FAIL;
+	XFreeCursor(wminfo.info.x11.display, impl->cursor);
+
 	return INFO::OK;
 }
 
Index: source/lib/res/graphics/cursor.cpp
===================================================================
--- source/lib/res/graphics/cursor.cpp	(revision 11379)
+++ source/lib/res/graphics/cursor.cpp	(working copy)
@@ -39,7 +39,7 @@
 // On Windows, allow runtime choice between system cursors and OpenGL
 // cursors (Windows = more responsive, OpenGL = more consistent with what
 // the game sees)
-#if OS_WIN
+#if OS_WIN || OS_UNIX
 # define ALLOW_SYS_CURSOR 1
 #else
 # define ALLOW_SYS_CURSOR 0
