mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-03 21:46:20 +00:00
x11/skia: Support changing custom RGBA mouse cursors
This commit is contained in:
parent
a061ce160b
commit
b981818134
@ -201,7 +201,7 @@ if(USE_SKIA_BACKEND)
|
|||||||
${X11_LIBRARIES})
|
${X11_LIBRARIES})
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
target_link_libraries(she fontconfig)
|
target_link_libraries(she fontconfig Xcursor)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "base/string.h"
|
#include "base/string.h"
|
||||||
#include "gfx/rect.h"
|
#include "gfx/rect.h"
|
||||||
#include "she/event.h"
|
#include "she/event.h"
|
||||||
|
#include "she/surface.h"
|
||||||
#include "she/x11/keys.h"
|
#include "she/x11/keys.h"
|
||||||
#include "she/x11/x11.h"
|
#include "she/x11/x11.h"
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ X11Window::X11Window(::Display* display, int width, int height, int scale)
|
|||||||
: m_display(display)
|
: m_display(display)
|
||||||
, m_gc(nullptr)
|
, m_gc(nullptr)
|
||||||
, m_cursor(None)
|
, m_cursor(None)
|
||||||
|
, m_xcursorImage(nullptr)
|
||||||
, m_xic(nullptr)
|
, m_xic(nullptr)
|
||||||
, m_scale(scale)
|
, m_scale(scale)
|
||||||
{
|
{
|
||||||
@ -173,6 +175,8 @@ X11Window::X11Window(::Display* display, int width, int height, int scale)
|
|||||||
|
|
||||||
X11Window::~X11Window()
|
X11Window::~X11Window()
|
||||||
{
|
{
|
||||||
|
if (m_xcursorImage != None)
|
||||||
|
XcursorImageDestroy(m_xcursorImage);
|
||||||
if (m_xic)
|
if (m_xic)
|
||||||
XDestroyIC(m_xic);
|
XDestroyIC(m_xic);
|
||||||
XFreeGC(m_display, m_gc);
|
XFreeGC(m_display, m_gc);
|
||||||
@ -320,25 +324,77 @@ bool X11Window::setNativeMouseCursor(NativeCursor cursor)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cursor != None) {
|
return setX11Cursor(xcursor);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X11Window::setNativeMouseCursor(const she::Surface* surface,
|
bool X11Window::setNativeMouseCursor(const she::Surface* surface,
|
||||||
const gfx::Point& focus,
|
const gfx::Point& focus,
|
||||||
const int scale)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,9 @@
|
|||||||
#include "gfx/size.h"
|
#include "gfx/size.h"
|
||||||
#include "she/native_cursor.h"
|
#include "she/native_cursor.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -62,6 +63,7 @@ protected:
|
|||||||
virtual void resizeDisplay(const gfx::Size& sz) = 0;
|
virtual void resizeDisplay(const gfx::Size& sz) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool setX11Cursor(::Cursor xcursor);
|
||||||
static void addWindow(X11Window* window);
|
static void addWindow(X11Window* window);
|
||||||
static void removeWindow(X11Window* window);
|
static void removeWindow(X11Window* window);
|
||||||
|
|
||||||
@ -69,6 +71,7 @@ private:
|
|||||||
::Window m_window;
|
::Window m_window;
|
||||||
::GC m_gc;
|
::GC m_gc;
|
||||||
::Cursor m_cursor;
|
::Cursor m_cursor;
|
||||||
|
::XcursorImage* m_xcursorImage;
|
||||||
::XIC m_xic;
|
::XIC m_xic;
|
||||||
int m_scale;
|
int m_scale;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user