x11/skia: Support changing custom RGBA mouse cursors

This commit is contained in:
David Capello 2018-08-08 11:53:27 -03:00
parent a061ce160b
commit b981818134
3 changed files with 69 additions and 10 deletions

View File

@ -201,7 +201,7 @@ if(USE_SKIA_BACKEND)
${X11_LIBRARIES})
if(UNIX AND NOT APPLE)
target_link_libraries(she fontconfig)
target_link_libraries(she fontconfig Xcursor)
endif()
endif()

View File

@ -13,6 +13,7 @@
#include "base/string.h"
#include "gfx/rect.h"
#include "she/event.h"
#include "she/surface.h"
#include "she/x11/keys.h"
#include "she/x11/x11.h"
@ -130,6 +131,7 @@ X11Window::X11Window(::Display* display, int width, int height, int scale)
: m_display(display)
, m_gc(nullptr)
, m_cursor(None)
, m_xcursorImage(nullptr)
, m_xic(nullptr)
, m_scale(scale)
{
@ -173,6 +175,8 @@ X11Window::X11Window(::Display* display, int width, int height, int scale)
X11Window::~X11Window()
{
if (m_xcursorImage != None)
XcursorImageDestroy(m_xcursorImage);
if (m_xic)
XDestroyIC(m_xic);
XFreeGC(m_display, m_gc);
@ -320,25 +324,77 @@ bool X11Window::setNativeMouseCursor(NativeCursor cursor)
break;
}
if (m_cursor != None) {
if (m_cursor != empty_xcursor) // Don't delete empty_xcursor
XFreeCursor(m_display, m_cursor);
m_cursor = None;
}
if (xcursor != None) {
m_cursor = xcursor;
XDefineCursor(m_display, m_window, xcursor);
return true;
}
else
return false;
return setX11Cursor(xcursor);
}
bool X11Window::setNativeMouseCursor(const she::Surface* surface,
const gfx::Point& focus,
const int scale)
{
ASSERT(surface);
// This X11 server doesn't support ARGB cursors.
if (!XcursorSupportsARGB(m_display))
return false;
SurfaceFormatData format;
surface->getFormat(&format);
// Only for 32bpp surfaces
if (format.bitsPerPixel != 32)
return false;
const int w = scale*surface->width();
const int h = scale*surface->height();
Cursor xcursor = None;
if (m_xcursorImage == None ||
m_xcursorImage->width != XcursorDim(w) ||
m_xcursorImage->height != XcursorDim(h)) {
if (m_xcursorImage != None)
XcursorImageDestroy(m_xcursorImage);
m_xcursorImage = XcursorImageCreate(w, h);
}
if (m_xcursorImage != None) {
XcursorPixel* dst = m_xcursorImage->pixels;
for (int y=0; y<h; ++y) {
const uint32_t* src = (const uint32_t*)surface->getData(0, y/scale);
for (int x=0, u=0; x<w; ++x, ++dst) {
uint32_t c = *src;
*dst =
(((c & format.alphaMask) >> format.alphaShift) << 24) |
(((c & format.redMask ) >> format.redShift ) << 16) |
(((c & format.greenMask) >> format.greenShift) << 8) |
(((c & format.blueMask ) >> format.blueShift ));
if (++u == scale) {
u = 0;
++src;
}
}
}
m_xcursorImage->xhot = scale*focus.x + scale/2;
m_xcursorImage->yhot = scale*focus.y + scale/2;
xcursor = XcursorImageLoadCursor(m_display,
m_xcursorImage);
}
return setX11Cursor(xcursor);
}
bool X11Window::setX11Cursor(::Cursor xcursor)
{
if (m_cursor != None) {
if (m_cursor != empty_xcursor) // Don't delete empty_xcursor
XFreeCursor(m_display, m_cursor);
m_cursor = None;
}
if (xcursor != None) {
m_cursor = xcursor;
XDefineCursor(m_display, m_window, xcursor);
return true;
}
else
return false;
}

View File

@ -12,8 +12,9 @@
#include "gfx/size.h"
#include "she/native_cursor.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xcursor/Xcursor.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <cstring>
@ -62,6 +63,7 @@ protected:
virtual void resizeDisplay(const gfx::Size& sz) = 0;
private:
bool setX11Cursor(::Cursor xcursor);
static void addWindow(X11Window* window);
static void removeWindow(X11Window* window);
@ -69,6 +71,7 @@ private:
::Window m_window;
::GC m_gc;
::Cursor m_cursor;
::XcursorImage* m_xcursorImage;
::XIC m_xic;
int m_scale;
};