mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Use custom native mouse cursor on Skia/OSX port
This commit is contained in:
parent
507e0f152b
commit
162cee2870
@ -17,6 +17,8 @@
|
||||
#include "she/native_cursor.h"
|
||||
|
||||
namespace she {
|
||||
class Surface;
|
||||
|
||||
KeyScancode cocoavk_to_scancode(UInt16 vk);
|
||||
}
|
||||
|
||||
@ -48,6 +50,9 @@ public:
|
||||
- (gfx::Size)restoredSize;
|
||||
- (void)setMousePosition:(const gfx::Point&)position;
|
||||
- (BOOL)setNativeMouseCursor:(she::NativeCursor)cursor;
|
||||
- (BOOL)setNativeMouseCursor:(const she::Surface*)surface
|
||||
focus:(const gfx::Point&)focus
|
||||
scale:(const int)scale;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "she/osx/event_queue.h"
|
||||
#include "she/osx/view.h"
|
||||
#include "she/osx/window_delegate.h"
|
||||
#include "she/surface.h"
|
||||
|
||||
using namespace she;
|
||||
|
||||
@ -107,7 +108,7 @@ using namespace she;
|
||||
|
||||
- (BOOL)setNativeMouseCursor:(NativeCursor)cursor
|
||||
{
|
||||
NSCursor* nsCursor = nil;
|
||||
NSCursor* nsCursor = nullptr;
|
||||
|
||||
switch (cursor) {
|
||||
case kArrowCursor:
|
||||
@ -149,13 +150,70 @@ using namespace she;
|
||||
case kSizeWCursor:
|
||||
nsCursor = [NSCursor resizeLeftCursor];
|
||||
break;
|
||||
default:
|
||||
nsCursor = nil;
|
||||
break;
|
||||
}
|
||||
|
||||
[self.contentView setCursor:nsCursor];
|
||||
return (nsCursor != nil ? YES: NO);
|
||||
return (nsCursor ? YES: NO);
|
||||
}
|
||||
|
||||
- (BOOL)setNativeMouseCursor:(const she::Surface*)surface
|
||||
focus:(const gfx::Point&)focus
|
||||
scale:(const int)scale
|
||||
{
|
||||
ASSERT(surface);
|
||||
SurfaceFormatData format;
|
||||
surface->getFormat(&format);
|
||||
if (format.bitsPerPixel != 32)
|
||||
return NO;
|
||||
|
||||
const int w = scale*surface->width();
|
||||
const int h = scale*surface->height();
|
||||
|
||||
std::vector<uint32_t> buf(4*w*h);
|
||||
uint32_t* bits = &buf[0];
|
||||
|
||||
for (int y=0; y<h; ++y) {
|
||||
const uint32_t* ptr = (const uint32_t*)surface->getData(0, y/scale);
|
||||
for (int x=0, u=0; x<w; ++x, ++bits) {
|
||||
*bits = *ptr;
|
||||
if (++u == scale) {
|
||||
u = 0;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGDataProviderRef dataRef =
|
||||
CGDataProviderCreateWithData(nullptr, &buf[0],
|
||||
w*h*4, nullptr);
|
||||
if (!dataRef)
|
||||
return NO;
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGImageRef img =
|
||||
CGImageCreate(
|
||||
w, h, 8, 32, 4*w,
|
||||
colorSpace, kCGImageAlphaLast, dataRef,
|
||||
nullptr, false, kCGRenderingIntentDefault);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
CGDataProviderRelease(dataRef);
|
||||
|
||||
NSCursor* nsCursor = nullptr;
|
||||
if (img) {
|
||||
NSImage* image =
|
||||
[[NSImage new] initWithCGImage:img
|
||||
size:NSMakeSize(w, h)];
|
||||
CGImageRelease(img);
|
||||
|
||||
nsCursor =
|
||||
[[NSCursor new] initWithImage:image
|
||||
hotSpot:NSMakePoint(scale*focus.x,
|
||||
scale*focus.y)];
|
||||
}
|
||||
if (nsCursor)
|
||||
[self.contentView setCursor:nsCursor];
|
||||
return (nsCursor ? YES: NO);
|
||||
}
|
||||
|
||||
- (void)noResponderFor:(SEL)eventSelector
|
||||
|
@ -151,10 +151,10 @@ bool SkiaDisplay::setNativeMouseCursor(const she::Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
return m_window.setNativeMouseCursor(surface, focus, scale);
|
||||
#else
|
||||
// TODO
|
||||
// TODO impl this for Linux
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
int(Capabilities::MultipleDisplays) |
|
||||
int(Capabilities::CanResizeDisplay) |
|
||||
int(Capabilities::DisplayScale)
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
| int(Capabilities::CustomNativeMouseCursor)
|
||||
#endif
|
||||
// TODO enable this when the GPU support is ready
|
||||
|
@ -17,6 +17,7 @@ namespace she {
|
||||
|
||||
class EventQueue;
|
||||
class SkiaDisplay;
|
||||
class Surface;
|
||||
|
||||
class SkiaWindow {
|
||||
public:
|
||||
@ -39,6 +40,9 @@ public:
|
||||
void releaseMouse();
|
||||
void setMousePosition(const gfx::Point& position);
|
||||
bool setNativeMouseCursor(NativeCursor cursor);
|
||||
bool setNativeMouseCursor(const Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale);
|
||||
void updateWindow(const gfx::Rect& bounds);
|
||||
std::string getLayout() { return ""; }
|
||||
void setLayout(const std::string& layout) { }
|
||||
|
@ -100,6 +100,14 @@ public:
|
||||
return ([m_window setNativeMouseCursor:cursor] ? true: false);
|
||||
}
|
||||
|
||||
bool setNativeMouseCursor(const she::Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale) {
|
||||
return ([m_window setNativeMouseCursor:surface
|
||||
focus:focus
|
||||
scale:scale] ? true: false);
|
||||
}
|
||||
|
||||
void updateWindow(const gfx::Rect& bounds) {
|
||||
int scale = this->scale();
|
||||
NSView* view = m_window.contentView;
|
||||
@ -424,6 +432,16 @@ bool SkiaWindow::setNativeMouseCursor(NativeCursor cursor)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkiaWindow::setNativeMouseCursor(const Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale)
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->setNativeMouseCursor(surface, focus, scale);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void SkiaWindow::updateWindow(const gfx::Rect& bounds)
|
||||
{
|
||||
if (m_impl)
|
||||
|
@ -45,27 +45,6 @@ static void update_mouse_overlay(Cursor* cursor)
|
||||
{
|
||||
mouse_cursor = cursor;
|
||||
|
||||
// Check if we can use a custom native mouse in this platform
|
||||
if (!use_native_mouse_cursor &&
|
||||
support_native_custom_cursor &&
|
||||
mouse_display) {
|
||||
if (cursor) {
|
||||
if (mouse_display->setNativeMouseCursor(
|
||||
// The surface is already scaled by guiscale()
|
||||
cursor->getSurface(),
|
||||
cursor->getFocus(),
|
||||
// We scale the cursor by the she::Display scale
|
||||
mouse_display->scale())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mouse_display->setNativeMouseCursor(she::kNoCursor)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse_cursor && mouse_scares == 0) {
|
||||
if (!mouse_cursor_overlay) {
|
||||
mouse_cursor_overlay = new Overlay(
|
||||
@ -88,10 +67,35 @@ static void update_mouse_overlay(Cursor* cursor)
|
||||
}
|
||||
}
|
||||
|
||||
static bool update_custom_native_cursor(Cursor* cursor)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Check if we can use a custom native mouse in this platform
|
||||
if (!use_native_mouse_cursor &&
|
||||
support_native_custom_cursor &&
|
||||
mouse_display) {
|
||||
if (cursor) {
|
||||
result = mouse_display->setNativeMouseCursor(
|
||||
// The surface is already scaled by guiscale()
|
||||
cursor->getSurface(),
|
||||
cursor->getFocus(),
|
||||
// We scale the cursor by the she::Display scale
|
||||
mouse_display->scale());
|
||||
}
|
||||
else if (mouse_cursor_type == kOutsideDisplay) {
|
||||
result = mouse_display->setNativeMouseCursor(she::kArrowCursor);
|
||||
}
|
||||
else {
|
||||
result = mouse_display->setNativeMouseCursor(she::kNoCursor);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void update_mouse_cursor()
|
||||
{
|
||||
// Use native cursor when it's possible/available/configured to do so.
|
||||
|
||||
she::NativeCursor nativeCursor = she::kNoCursor;
|
||||
Cursor* cursor = nullptr;
|
||||
|
||||
@ -140,15 +144,18 @@ static void update_mouse_cursor()
|
||||
nativeCursor = she::kNoCursor;
|
||||
}
|
||||
|
||||
// Use a software cursor with the overlay.
|
||||
// Use a custom cursor
|
||||
if (nativeCursor == she::kNoCursor &&
|
||||
mouse_cursor_type != ui::kOutsideDisplay &&
|
||||
CurrentTheme::get()) {
|
||||
cursor = CurrentTheme::get()->getCursor(mouse_cursor_type);
|
||||
}
|
||||
|
||||
// Set internal overlay
|
||||
update_mouse_overlay(cursor);
|
||||
// Try to use a custom native cursor if it's possible
|
||||
if (!update_custom_native_cursor(cursor)) {
|
||||
// Or an overlay as last resource
|
||||
update_mouse_overlay(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
UISystem::UISystem()
|
||||
@ -171,8 +178,9 @@ UISystem::~UISystem()
|
||||
|
||||
details::exitWidgets();
|
||||
|
||||
_internal_set_mouse_display(NULL);
|
||||
update_mouse_overlay(NULL);
|
||||
_internal_set_mouse_display(nullptr);
|
||||
if (!update_custom_native_cursor(nullptr))
|
||||
update_mouse_overlay(nullptr);
|
||||
}
|
||||
|
||||
void _internal_set_mouse_display(she::Display* display)
|
||||
@ -249,7 +257,8 @@ void show_mouse_cursor()
|
||||
|
||||
void _internal_no_mouse_position()
|
||||
{
|
||||
update_mouse_overlay(NULL);
|
||||
if (!update_custom_native_cursor(nullptr))
|
||||
update_mouse_overlay(nullptr);
|
||||
}
|
||||
|
||||
void _internal_set_mouse_position(const gfx::Point& newPos)
|
||||
|
Loading…
x
Reference in New Issue
Block a user