From 34af633b47faee97432b42931d202b3c45603a4f Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 11 Jan 2012 23:12:25 -0200 Subject: [PATCH] implement mouse cursor set in x11 platform --- modules/client_tibiafiles | 2 +- src/framework/luafunctions.cpp | 2 + src/framework/platform/platformwindow.h | 4 +- src/framework/platform/win32window.cpp | 15 +++-- src/framework/platform/win32window.h | 2 + src/framework/platform/x11window.cpp | 89 ++++++++++++++++++++++--- src/framework/platform/x11window.h | 2 + 7 files changed, 101 insertions(+), 15 deletions(-) diff --git a/modules/client_tibiafiles b/modules/client_tibiafiles index dd648e14..9beb17da 160000 --- a/modules/client_tibiafiles +++ b/modules/client_tibiafiles @@ -1 +1 @@ -Subproject commit dd648e1431171bffe091b748744395780df7eba1 +Subproject commit 9beb17daaeb170c127c39c5a5e4feb9d95ebed92 diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 6387a19d..3d907325 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -333,9 +333,11 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("g_window", "show", std::bind(&PlatformWindow::show, &g_window)); g_lua.bindClassStaticFunction("g_window", "hide", std::bind(&PlatformWindow::hide, &g_window)); g_lua.bindClassStaticFunction("g_window", "maximize", std::bind(&PlatformWindow::maximize, &g_window)); + g_lua.bindClassStaticFunction("g_window", "restoreMouseCursor", std::bind(&PlatformWindow::restoreMouseCursor, &g_window)); g_lua.bindClassStaticFunction("g_window", "showMouse", std::bind(&PlatformWindow::showMouse, &g_window)); g_lua.bindClassStaticFunction("g_window", "hideMouse", std::bind(&PlatformWindow::hideMouse, &g_window)); g_lua.bindClassStaticFunction("g_window", "setTitle", std::bind(&PlatformWindow::setTitle, &g_window, _1)); + g_lua.bindClassStaticFunction("g_window", "setMouseCursor", std::bind(&PlatformWindow::setMouseCursor, &g_window, _1)); g_lua.bindClassStaticFunction("g_window", "setMinimumSize", std::bind(&PlatformWindow::setMinimumSize, &g_window, _1)); g_lua.bindClassStaticFunction("g_window", "setFullscreen", std::bind(&PlatformWindow::setFullscreen, &g_window, _1)); g_lua.bindClassStaticFunction("g_window", "setVerticalSync", std::bind(&PlatformWindow::setVerticalSync, &g_window, _1)); diff --git a/src/framework/platform/platformwindow.h b/src/framework/platform/platformwindow.h index cc2c25fe..020bcf11 100644 --- a/src/framework/platform/platformwindow.h +++ b/src/framework/platform/platformwindow.h @@ -42,10 +42,12 @@ public: virtual void maximize() = 0; virtual void poll() = 0; virtual void swapBuffers() = 0; + virtual void restoreMouseCursor() = 0; virtual void showMouse() = 0; - virtual void displayFatalError(const std::string& message) { } virtual void hideMouse() = 0; + virtual void displayFatalError(const std::string& message) { } + virtual void setMouseCursor(const std::string& file) = 0; virtual void setTitle(const std::string& title) = 0; virtual void setMinimumSize(const Size& minimumSize) = 0; virtual void setFullscreen(bool fullscreen) = 0; diff --git a/src/framework/platform/win32window.cpp b/src/framework/platform/win32window.cpp index 35193acd..a8604f4c 100644 --- a/src/framework/platform/win32window.cpp +++ b/src/framework/platform/win32window.cpp @@ -526,6 +526,16 @@ void WIN32Window::hideMouse() ShowCursor(false); } +void WIN32Window::displayFatalError(const std::string& message) +{ + MessageBoxA(m_window, message.c_str(), "FATAL ERROR", MB_OK | MB_ICONERROR); +} + +void WIN32Window::setMouseCursor(const std::string& file) +{ + +} + void WIN32Window::setTitle(const std::string& title) { SetWindowTextA(m_window, title.c_str()); @@ -662,8 +672,3 @@ std::string WIN32Window::getPlatformType() { return "WIN32-WGL"; } - -void WIN32Window::displayFatalError(const std::string& message) -{ - MessageBoxA(m_window, message.c_str(), "FATAL ERROR", MB_OK | MB_ICONERROR); -} diff --git a/src/framework/platform/win32window.h b/src/framework/platform/win32window.h index 47936be8..1389f5e6 100644 --- a/src/framework/platform/win32window.h +++ b/src/framework/platform/win32window.h @@ -56,10 +56,12 @@ public: void maximize(); void poll(); void swapBuffers(); + void restoreMouseCursor(); void showMouse(); void hideMouse(); void displayFatalError(const std::string& message); + void setMouseCursor(const std::string& file); void setTitle(const std::string& title); void setMinimumSize(const Size& minimumSize); void setFullscreen(bool fullscreen); diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index 5c4fc920..d03ced63 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -24,6 +24,8 @@ #include #include +#define LSB_BIT_SET(p, n) (p[(n)/8] |= (1 <<((n)%8))) + X11Window::X11Window() { m_display = 0; @@ -728,6 +730,25 @@ void X11Window::swapBuffers() } void X11Window::showMouse() +{ + restoreMouseCursor(); +} + +void X11Window::hideMouse() +{ + if(m_cursor != None) + restoreMouseCursor(); + + char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8); + XColor black = {0}; + black.flags = DoRed | DoGreen | DoBlue; + m_cursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0); + XFreePixmap(m_display, pix); + XDefineCursor(m_display, m_window, m_cursor); +} + +void X11Window::restoreMouseCursor() { XUndefineCursor(m_display, m_window); if(m_cursor != None) { @@ -736,17 +757,69 @@ void X11Window::showMouse() } } -void X11Window::hideMouse() +void X11Window::setMouseCursor(const std::string& file) { - if(m_cursor == None) { - char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8); - XColor black = {0}; - black.flags = DoRed | DoGreen | DoBlue; - m_cursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0); - XFreePixmap(m_display, pix); + std::stringstream fin; + g_resources.loadFile(file, fin); + + apng_data apng; + if(load_apng(fin, &apng) != 0) { + logTraceError("unable to load png file ", file); + return; } + + if(apng.bpp != 4) { + logError("the cursor png must have 4 channels"); + free_apng(&apng); + return; + } + + if(apng.width % 8 != 0 || apng.height % 8 != 0) { + logError("the cursor png must have dimensions multiple of 8"); + free_apng(&apng); + return; + } + + if(m_cursor != None) + restoreMouseCursor(); + + int width = apng.width; + int height = apng.height; + int numbits = width * height; + int numbytes = (width * height)/8; + + XColor bg, fg; + bg.red = 255 << 8; + bg.green = 255 << 8; + bg.blue = 255 << 8; + fg.red = 0; + fg.green = 0; + fg.blue = 0; + + std::vector mapBits(numbytes, 0); + std::vector maskBits(numbytes, 0); + + for(int i=0;i