implement mouse cursor set in x11 platform

This commit is contained in:
Eduardo Bart
2012-01-11 23:12:25 -02:00
parent c1787c2a50
commit 34af633b47
7 changed files with 101 additions and 15 deletions

View File

@@ -24,6 +24,8 @@
#include <framework/core/resourcemanager.h>
#include <framework/thirdparty/apngloader.h>
#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<uchar> mapBits(numbytes, 0);
std::vector<uchar> maskBits(numbytes, 0);
for(int i=0;i<numbits;++i) {
uchar r = apng.pdata[i*4+0];
uchar g = apng.pdata[i*4+1];
uchar b = apng.pdata[i*4+2];
uchar a = apng.pdata[i*4+3];
Color color(r,g,b,a);
if(color == Fw::white) { //background
LSB_BIT_SET(maskBits, i);
} else if(color == Fw::black) { //foreground
LSB_BIT_SET(mapBits, i);
LSB_BIT_SET(maskBits, i);
} //otherwise alpha
}
free_apng(&apng);
Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height);
Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height);
m_cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, width/2, height/2);
XDefineCursor(m_display, m_window, m_cursor);
XFreePixmap(m_display, cp);
XFreePixmap(m_display, mp);
}
void X11Window::setTitle(const std::string& title)