void X11Window::setMouseCursor(const std::string& file, const Point& hotSpot) { std::stringstream fin; g_resources.loadFile(file, fin); apng_data apng; if(load_apng(fin, &apng) != 0) { g_logger.traceError(stdext::format("unable to load png file %s", file)); return; } if(apng.bpp != 4) { g_logger.error("the cursor png must have 4 channels"); free_apng(&apng); return; } if(apng.width != 32|| apng.height != 32) { g_logger.error("the cursor png must have 32x32 dimension"); 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) { uint32 rgba = stdext::readLE32(apng.pdata + i*4); if(rgba == 0xffffffff) { //white, background LSB_BIT_SET(maskBits, i); } else if(rgba == 0xff000000) { //black, foreground LSB_BIT_SET(mapBits, i); LSB_BIT_SET(maskBits, i); } //otherwise 0x00000000 => 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, hotSpot.x, hotSpot.y); XDefineCursor(m_display, m_window, m_cursor); XFreePixmap(m_display, cp); XFreePixmap(m_display, mp); }
int X11Window::internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot) { int width = image->getWidth(); int height = image->getHeight(); 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) { uint32 rgba = stdext::readULE32(image->getPixelData() + i*4); if(rgba == 0xffffffff) { //white, background LSB_BIT_SET(maskBits, i); } else if(rgba == 0xff000000) { //black, foreground LSB_BIT_SET(mapBits, i); LSB_BIT_SET(maskBits, i); } //otherwise 0x00000000 => alpha } Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height); Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height); Cursor cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, hotSpot.x, hotSpot.y); XFreePixmap(m_display, cp); XFreePixmap(m_display, mp); m_cursors.push_back(cursor); return m_cursors.size()-1; }