mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
ebiten: add more cursor shapes
This change adds these new cursor shapes: * CursorShapeNESWResize * CursorShapeNWSEResize * CursorShapeMove * CursorShapeNotAllowed Closes #2476
This commit is contained in:
parent
269b557e38
commit
91e1c0ea29
16
cursor.go
16
cursor.go
@ -33,10 +33,14 @@ type CursorShapeType = ui.CursorShape
|
||||
|
||||
// CursorShapeTypes
|
||||
const (
|
||||
CursorShapeDefault CursorShapeType = ui.CursorShapeDefault
|
||||
CursorShapeText CursorShapeType = ui.CursorShapeText
|
||||
CursorShapeCrosshair CursorShapeType = ui.CursorShapeCrosshair
|
||||
CursorShapePointer CursorShapeType = ui.CursorShapePointer
|
||||
CursorShapeEWResize CursorShapeType = ui.CursorShapeEWResize
|
||||
CursorShapeNSResize CursorShapeType = ui.CursorShapeNSResize
|
||||
CursorShapeDefault CursorShapeType = CursorShapeType(ui.CursorShapeDefault)
|
||||
CursorShapeText CursorShapeType = CursorShapeType(ui.CursorShapeText)
|
||||
CursorShapeCrosshair CursorShapeType = CursorShapeType(ui.CursorShapeCrosshair)
|
||||
CursorShapePointer CursorShapeType = CursorShapeType(ui.CursorShapePointer)
|
||||
CursorShapeEWResize CursorShapeType = CursorShapeType(ui.CursorShapeEWResize)
|
||||
CursorShapeNSResize CursorShapeType = CursorShapeType(ui.CursorShapeNSResize)
|
||||
CursorShapeNESWResize CursorShapeType = CursorShapeType(ui.CursorShapeNESWResize)
|
||||
CursorShapeNWSEResize CursorShapeType = CursorShapeType(ui.CursorShapeNWSEResize)
|
||||
CursorShapeMove CursorShapeType = CursorShapeType(ui.CursorShapeMove)
|
||||
CursorShapeNotAllowed CursorShapeType = CursorShapeType(ui.CursorShapeNotAllowed)
|
||||
)
|
||||
|
@ -33,6 +33,7 @@ const (
|
||||
type Game struct {
|
||||
grids map[image.Rectangle]ebiten.CursorShapeType
|
||||
gridColors map[image.Rectangle]color.Color
|
||||
cursor ebiten.CursorShapeType
|
||||
}
|
||||
|
||||
func (g *Game) Update() error {
|
||||
@ -44,7 +45,12 @@ func (g *Game) Update() error {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Call SetCursorShape only when this is changed to test Ebitengine remembers the current cursor correctly even when it is hidden.
|
||||
if g.cursor != cursor {
|
||||
ebiten.SetCursorShape(cursor)
|
||||
g.cursor = cursor
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyC) {
|
||||
switch ebiten.CursorMode() {
|
||||
@ -76,6 +82,14 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: EW Resize")
|
||||
case ebiten.CursorShapeNSResize:
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: NS Resize")
|
||||
case ebiten.CursorShapeNESWResize:
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: NESW Resize")
|
||||
case ebiten.CursorShapeNWSEResize:
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: NWSE Resize")
|
||||
case ebiten.CursorShapeMove:
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: Move")
|
||||
case ebiten.CursorShapeNotAllowed:
|
||||
ebitenutil.DebugPrint(screen, "CursorShape: Not Allowed")
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,18 +103,25 @@ func main() {
|
||||
image.Rect(100, 100, 200, 200): ebiten.CursorShapeDefault,
|
||||
image.Rect(200, 100, 300, 200): ebiten.CursorShapeText,
|
||||
image.Rect(300, 100, 400, 200): ebiten.CursorShapeCrosshair,
|
||||
image.Rect(100, 200, 200, 300): ebiten.CursorShapePointer,
|
||||
image.Rect(200, 200, 300, 300): ebiten.CursorShapeEWResize,
|
||||
image.Rect(300, 200, 400, 300): ebiten.CursorShapeNSResize,
|
||||
image.Rect(400, 100, 500, 200): ebiten.CursorShapePointer,
|
||||
image.Rect(100, 200, 200, 300): ebiten.CursorShapeEWResize,
|
||||
image.Rect(200, 200, 300, 300): ebiten.CursorShapeNSResize,
|
||||
image.Rect(300, 200, 400, 300): ebiten.CursorShapeNESWResize,
|
||||
image.Rect(400, 200, 500, 300): ebiten.CursorShapeNWSEResize,
|
||||
image.Rect(100, 300, 200, 400): ebiten.CursorShapeMove,
|
||||
image.Rect(200, 300, 300, 400): ebiten.CursorShapeNotAllowed,
|
||||
},
|
||||
gridColors: map[image.Rectangle]color.Color{},
|
||||
}
|
||||
for rect, c := range g.grids {
|
||||
clr := color.RGBA{0x40, 0x40, 0x40, 0xff}
|
||||
if c%2 == 0 {
|
||||
switch c % 3 {
|
||||
case 0:
|
||||
clr.R = 0x80
|
||||
} else {
|
||||
case 1:
|
||||
clr.G = 0x80
|
||||
case 2:
|
||||
clr.B = 0x80
|
||||
}
|
||||
g.gridColors[rect] = clr
|
||||
}
|
||||
|
@ -1728,18 +1728,64 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (shape == GLFW_ARROW_CURSOR)
|
||||
SEL cursorSelector = NULL;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
cursorSelector = NSSelectorFromString(@"_windowResizeEastWestCursor");
|
||||
break;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
cursorSelector = NSSelectorFromString(@"_windowResizeNorthSouthCursor");
|
||||
break;
|
||||
case GLFW_RESIZE_NWSE_CURSOR:
|
||||
cursorSelector = NSSelectorFromString(@"_windowResizeNorthWestSouthEastCursor");
|
||||
break;
|
||||
case GLFW_RESIZE_NESW_CURSOR:
|
||||
cursorSelector = NSSelectorFromString(@"_windowResizeNorthEastSouthWestCursor");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cursorSelector && [NSCursor respondsToSelector:cursorSelector])
|
||||
{
|
||||
id object = [NSCursor performSelector:cursorSelector];
|
||||
if ([object isKindOfClass:[NSCursor class]])
|
||||
cursor->ns.object = object;
|
||||
}
|
||||
|
||||
if (!cursor->ns.object)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
cursor->ns.object = [NSCursor arrowCursor];
|
||||
else if (shape == GLFW_IBEAM_CURSOR)
|
||||
break;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
cursor->ns.object = [NSCursor IBeamCursor];
|
||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
||||
break;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
cursor->ns.object = [NSCursor crosshairCursor];
|
||||
else if (shape == GLFW_HAND_CURSOR)
|
||||
break;
|
||||
case GLFW_HAND_CURSOR:
|
||||
cursor->ns.object = [NSCursor pointingHandCursor];
|
||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeLeftRightCursor];
|
||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeUpDownCursor];
|
||||
break;
|
||||
case GLFW_RESIZE_ALL_CURSOR:
|
||||
{
|
||||
// Use the OS's resource: https://stackoverflow.com/a/21786835/5435443
|
||||
NSString *cursorName = @"move";
|
||||
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
|
||||
NSImage *image = [[NSImage alloc] initByReferencingFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
|
||||
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
||||
cursor->ns.object = [[NSCursor alloc] initWithImage:image
|
||||
hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue],
|
||||
[[info valueForKey:@"hoty"] doubleValue])];
|
||||
break;
|
||||
}
|
||||
case GLFW_NOT_ALLOWED_CURSOR:
|
||||
cursor->ns.object = [NSCursor operationNotAllowedCursor];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cursor->ns.object)
|
||||
{
|
||||
|
@ -964,6 +964,12 @@ extern "C" {
|
||||
#define GLFW_VRESIZE_CURSOR 0x00036006
|
||||
/*! @} */
|
||||
|
||||
// Added in GLFW v3.4.
|
||||
#define GLFW_RESIZE_NWSE_CURSOR 0x00036007
|
||||
#define GLFW_RESIZE_NESW_CURSOR 0x00036008
|
||||
#define GLFW_RESIZE_ALL_CURSOR 0x00036009
|
||||
#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A
|
||||
|
||||
#define GLFW_CONNECTED 0x00040001
|
||||
#define GLFW_DISCONNECTED 0x00040002
|
||||
|
||||
|
@ -470,7 +470,11 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
||||
shape != GLFW_CROSSHAIR_CURSOR &&
|
||||
shape != GLFW_HAND_CURSOR &&
|
||||
shape != GLFW_HRESIZE_CURSOR &&
|
||||
shape != GLFW_VRESIZE_CURSOR)
|
||||
shape != GLFW_VRESIZE_CURSOR &&
|
||||
shape != GLFW_RESIZE_NWSE_CURSOR &&
|
||||
shape != GLFW_RESIZE_NESW_CURSOR &&
|
||||
shape != GLFW_RESIZE_ALL_CURSOR &&
|
||||
shape != GLFW_NOT_ALLOWED_CURSOR)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
|
||||
return NULL;
|
||||
|
@ -1823,28 +1823,6 @@ const struct wl_data_device_listener dataDeviceListener =
|
||||
dataDeviceHandleSelection,
|
||||
};
|
||||
|
||||
// Translates a GLFW standard cursor to a theme cursor name
|
||||
//
|
||||
static char *translateCursorShape(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
return "left_ptr";
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
return "xterm";
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
return "crosshair";
|
||||
case GLFW_HAND_CURSOR:
|
||||
return "hand2";
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
return "sb_h_double_arrow";
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
return "sb_v_double_arrow";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwAddSeatListenerWayland(struct wl_seat* seat)
|
||||
{
|
||||
wl_seat_add_listener(seat, &seatListener, NULL);
|
||||
@ -2392,26 +2370,101 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
struct wl_cursor* standardCursor;
|
||||
// See GLFW 3.4 implementation.
|
||||
const char* name = NULL;
|
||||
|
||||
standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
||||
translateCursorShape(shape));
|
||||
if (!standardCursor)
|
||||
// Try the XDG names first
|
||||
switch (shape)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Standard cursor \"%s\" not found",
|
||||
translateCursorShape(shape));
|
||||
return GLFW_FALSE;
|
||||
case GLFW_ARROW_CURSOR:
|
||||
name = "default";
|
||||
break;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
name = "text";
|
||||
break;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
name = "crosshair";
|
||||
break;
|
||||
case GLFW_HAND_CURSOR:
|
||||
name = "pointer";
|
||||
break;
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
name = "ew-resize";
|
||||
break;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
name = "ns-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_NWSE_CURSOR:
|
||||
name = "nwse-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_NESW_CURSOR:
|
||||
name = "nesw-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_ALL_CURSOR:
|
||||
name = "all-scroll";
|
||||
break;
|
||||
case GLFW_NOT_ALLOWED_CURSOR:
|
||||
name = "not-allowed";
|
||||
break;
|
||||
}
|
||||
|
||||
cursor->wl.cursor = standardCursor;
|
||||
cursor->wl.currentImage = 0;
|
||||
cursor->wl.cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name);
|
||||
|
||||
if (_glfw.wl.cursorThemeHiDPI)
|
||||
{
|
||||
standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
|
||||
translateCursorShape(shape));
|
||||
cursor->wl.cursorHiDPI = standardCursor;
|
||||
cursor->wl.cursorHiDPI =
|
||||
wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, name);
|
||||
}
|
||||
|
||||
if (!cursor->wl.cursor)
|
||||
{
|
||||
// Fall back to the core X11 names
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
name = "left_ptr";
|
||||
break;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
name = "xterm";
|
||||
break;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
name = "crosshair";
|
||||
break;
|
||||
case GLFW_HAND_CURSOR:
|
||||
name = "hand2";
|
||||
break;
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
name = "sb_h_double_arrow";
|
||||
break;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
name = "sb_v_double_arrow";
|
||||
break;
|
||||
case GLFW_RESIZE_ALL_CURSOR:
|
||||
name = "fleur";
|
||||
break;
|
||||
default:
|
||||
//_glfwInputError(GLFW_CURSOR_UNAVAILABLE,
|
||||
// "Wayland: Standard cursor shape unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
cursor->wl.cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name);
|
||||
if (!cursor->wl.cursor)
|
||||
{
|
||||
//_glfwInputError(GLFW_CURSOR_UNAVAILABLE,
|
||||
// "Wayland: Failed to create standard cursor \"%s\"",
|
||||
// name);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (_glfw.wl.cursorThemeHiDPI)
|
||||
{
|
||||
if (!cursor->wl.cursorHiDPI)
|
||||
{
|
||||
cursor->wl.cursorHiDPI =
|
||||
wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
@ -741,6 +741,12 @@ static GLFWbool initExtensions(void)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
|
||||
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
|
||||
_glfw.x11.xcursor.GetTheme = (PFN_XcursorGetTheme)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorGetTheme");
|
||||
_glfw.x11.xcursor.GetDefaultSize = (PFN_XcursorGetDefaultSize)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorGetDefaultSize");
|
||||
_glfw.x11.xcursor.LibraryLoadImage = (PFN_XcursorLibraryLoadImage)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorLibraryLoadImage");
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
|
@ -87,9 +87,15 @@ typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
|
||||
typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
|
||||
typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
|
||||
typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
|
||||
typedef char* (* PFN_XcursorGetTheme)(Display*);
|
||||
typedef int (* PFN_XcursorGetDefaultSize)(Display*);
|
||||
typedef XcursorImage* (* PFN_XcursorLibraryLoadImage)(const char*,const char*,int);
|
||||
#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
|
||||
#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
|
||||
#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
|
||||
#define XcursorGetTheme _glfw.x11.xcursor.GetTheme
|
||||
#define XcursorGetDefaultSize _glfw.x11.xcursor.GetDefaultSize
|
||||
#define XcursorLibraryLoadImage _glfw.x11.xcursor.LibraryLoadImage
|
||||
|
||||
typedef Bool (* PFN_XineramaIsActive)(Display*);
|
||||
typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
|
||||
@ -327,6 +333,9 @@ typedef struct _GLFWlibraryX11
|
||||
PFN_XcursorImageCreate ImageCreate;
|
||||
PFN_XcursorImageDestroy ImageDestroy;
|
||||
PFN_XcursorImageLoadCursor ImageLoadCursor;
|
||||
PFN_XcursorGetTheme GetTheme;
|
||||
PFN_XcursorGetDefaultSize GetDefaultSize;
|
||||
PFN_XcursorLibraryLoadImage LibraryLoadImage;
|
||||
} xcursor;
|
||||
|
||||
struct {
|
||||
|
@ -2908,22 +2908,90 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
int native = 0;
|
||||
// See GLFW 3.4 implementation.
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
char* theme = XcursorGetTheme(_glfw.x11.display);
|
||||
if (theme)
|
||||
{
|
||||
const int size = XcursorGetDefaultSize(_glfw.x11.display);
|
||||
const char* name = NULL;
|
||||
|
||||
if (shape == GLFW_ARROW_CURSOR)
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
name = "default";
|
||||
break;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
name = "text";
|
||||
break;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
name = "crosshair";
|
||||
break;
|
||||
case GLFW_HAND_CURSOR:
|
||||
name = "pointer";
|
||||
break;
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
name = "ew-resize";
|
||||
break;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
name = "ns-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_NWSE_CURSOR:
|
||||
name = "nwse-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_NESW_CURSOR:
|
||||
name = "nesw-resize";
|
||||
break;
|
||||
case GLFW_RESIZE_ALL_CURSOR:
|
||||
name = "all-scroll";
|
||||
break;
|
||||
case GLFW_NOT_ALLOWED_CURSOR:
|
||||
name = "not-allowed";
|
||||
break;
|
||||
}
|
||||
|
||||
XcursorImage* image = XcursorLibraryLoadImage(name, theme, size);
|
||||
if (image)
|
||||
{
|
||||
cursor->x11.handle = XcursorImageLoadCursor(_glfw.x11.display, image);
|
||||
XcursorImageDestroy(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cursor->x11.handle)
|
||||
{
|
||||
unsigned int native = 0;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
native = XC_left_ptr;
|
||||
else if (shape == GLFW_IBEAM_CURSOR)
|
||||
break;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
native = XC_xterm;
|
||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
||||
break;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
native = XC_crosshair;
|
||||
else if (shape == GLFW_HAND_CURSOR)
|
||||
break;
|
||||
case GLFW_HAND_CURSOR:
|
||||
native = XC_hand2;
|
||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
||||
break;
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
native = XC_sb_h_double_arrow;
|
||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
||||
break;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
native = XC_sb_v_double_arrow;
|
||||
else
|
||||
break;
|
||||
case GLFW_RESIZE_ALL_CURSOR:
|
||||
native = XC_fleur;
|
||||
break;
|
||||
default:
|
||||
//_glfwInputError(GLFW_CURSOR_UNAVAILABLE,
|
||||
// "X11: Standard cursor shape unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
|
||||
if (!cursor->x11.handle)
|
||||
@ -2932,6 +3000,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
"X11: Failed to create standard cursor");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
@ -141,4 +141,10 @@ const (
|
||||
HandCursor = StandardCursor(0x00036004)
|
||||
HResizeCursor = StandardCursor(0x00036005)
|
||||
VResizeCursor = StandardCursor(0x00036006)
|
||||
|
||||
// v3.4
|
||||
ResizeNWSECursor = StandardCursor(0x00036007)
|
||||
ResizeNESWCursor = StandardCursor(0x00036008)
|
||||
ResizeAllCursor = StandardCursor(0x00036009)
|
||||
NotAllowedCursor = StandardCursor(0x0003600A)
|
||||
)
|
||||
|
@ -104,8 +104,12 @@ const (
|
||||
_OCR_CROSS = 32515
|
||||
_OCR_HAND = 32649
|
||||
_OCR_IBEAM = 32513
|
||||
_OCR_NO = 32648
|
||||
_OCR_NORMAL = 32512
|
||||
_OCR_SIZEALL = 32646
|
||||
_OCR_SIZENESW = 32643
|
||||
_OCR_SIZENS = 32645
|
||||
_OCR_SIZENWSE = 32642
|
||||
_OCR_SIZEWE = 32644
|
||||
_PM_NOREMOVE = 0x0000
|
||||
_PM_REMOVE = 0x0001
|
||||
|
@ -289,6 +289,12 @@ const (
|
||||
HandCursor StandardCursor = 0x00036004
|
||||
HResizeCursor StandardCursor = 0x00036005
|
||||
VResizeCursor StandardCursor = 0x00036006
|
||||
|
||||
// v3.4
|
||||
ResizeNWSECursor StandardCursor = 0x00036007
|
||||
ResizeNESWCursor StandardCursor = 0x00036008
|
||||
ResizeAllCursor StandardCursor = 0x00036009
|
||||
NotAllowedCursor StandardCursor = 0x0003600A
|
||||
)
|
||||
|
||||
type Error int
|
||||
|
@ -351,7 +351,11 @@ func CreateStandardCursor(shape StandardCursor) (*Cursor, error) {
|
||||
shape != CrosshairCursor &&
|
||||
shape != HandCursor &&
|
||||
shape != HResizeCursor &&
|
||||
shape != VResizeCursor {
|
||||
shape != VResizeCursor &&
|
||||
shape != ResizeNWSECursor &&
|
||||
shape != ResizeNESWCursor &&
|
||||
shape != ResizeAllCursor &&
|
||||
shape != NotAllowedCursor {
|
||||
return nil, fmt.Errorf("goglfw: invalid standard cursor 0x%08X: %w", shape, InvalidEnum)
|
||||
}
|
||||
|
||||
|
@ -2242,6 +2242,14 @@ func (c *Cursor) platformCreateStandardCursor(shape StandardCursor) error {
|
||||
id = _OCR_SIZEWE
|
||||
case VResizeCursor:
|
||||
id = _OCR_SIZENS
|
||||
case ResizeNWSECursor: // v3.4
|
||||
id = _OCR_SIZENWSE
|
||||
case ResizeNESWCursor: // v3.4
|
||||
id = _OCR_SIZENESW
|
||||
case ResizeAllCursor: // v3.4
|
||||
id = _OCR_SIZEALL
|
||||
case NotAllowedCursor: // v3.4
|
||||
id = _OCR_NO
|
||||
default:
|
||||
return fmt.Errorf("goglfw: invalid shape: %d", shape)
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ const (
|
||||
CursorShapePointer
|
||||
CursorShapeEWResize
|
||||
CursorShapeNSResize
|
||||
CursorShapeNESWResize
|
||||
CursorShapeNWSEResize
|
||||
CursorShapeMove
|
||||
CursorShapeNotAllowed
|
||||
)
|
||||
|
||||
type WindowResizingMode int
|
||||
|
@ -201,6 +201,10 @@ func initialize() error {
|
||||
glfwSystemCursors[CursorShapePointer] = glfw.CreateStandardCursor(glfw.HandCursor)
|
||||
glfwSystemCursors[CursorShapeEWResize] = glfw.CreateStandardCursor(glfw.HResizeCursor)
|
||||
glfwSystemCursors[CursorShapeNSResize] = glfw.CreateStandardCursor(glfw.VResizeCursor)
|
||||
glfwSystemCursors[CursorShapeNESWResize] = glfw.CreateStandardCursor(glfw.ResizeNESWCursor)
|
||||
glfwSystemCursors[CursorShapeNWSEResize] = glfw.CreateStandardCursor(glfw.ResizeNWSECursor)
|
||||
glfwSystemCursors[CursorShapeMove] = glfw.CreateStandardCursor(glfw.ResizeAllCursor)
|
||||
glfwSystemCursors[CursorShapeNotAllowed] = glfw.CreateStandardCursor(glfw.NotAllowedCursor)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -614,7 +618,7 @@ func (u *userInterfaceImpl) SetCursorMode(mode CursorMode) {
|
||||
u.mainThread.Call(func() {
|
||||
u.window.SetInputMode(glfw.CursorMode, driverCursorModeToGLFWCursorMode(mode))
|
||||
if mode == CursorModeVisible {
|
||||
u.setNativeCursor(u.getCursorShape())
|
||||
u.window.SetCursor(glfwSystemCursors[u.getCursorShape()])
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -632,7 +636,7 @@ func (u *userInterfaceImpl) SetCursorShape(shape CursorShape) {
|
||||
return
|
||||
}
|
||||
u.mainThread.Call(func() {
|
||||
u.setNativeCursor(shape)
|
||||
u.window.SetCursor(glfwSystemCursors[shape])
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -218,17 +218,13 @@ var (
|
||||
|
||||
var (
|
||||
sel_alloc = objc.RegisterName("alloc")
|
||||
sel_arrowCursor = objc.RegisterName("arrowCursor")
|
||||
sel_class = objc.RegisterName("class")
|
||||
sel_collectionBehavior = objc.RegisterName("collectionBehavior")
|
||||
sel_crosshairCursor = objc.RegisterName("crosshairCursor")
|
||||
sel_delegate = objc.RegisterName("delegate")
|
||||
sel_IBeamCursor = objc.RegisterName("IBeamCursor")
|
||||
sel_init = objc.RegisterName("init")
|
||||
sel_initWithOrigDelegate = objc.RegisterName("initWithOrigDelegate:")
|
||||
sel_mouseLocation = objc.RegisterName("mouseLocation")
|
||||
sel_performSelector = objc.RegisterName("performSelector:")
|
||||
sel_pointingHandCursor = objc.RegisterName("pointingHandCursor")
|
||||
sel_set = objc.RegisterName("set")
|
||||
sel_setCollectionBehavior = objc.RegisterName("setCollectionBehavior:")
|
||||
sel_setDelegate = objc.RegisterName("setDelegate:")
|
||||
@ -242,8 +238,6 @@ var (
|
||||
sel_windowDidResignKey = objc.RegisterName("windowDidResignKey:")
|
||||
sel_windowDidResize = objc.RegisterName("windowDidResize:")
|
||||
sel_windowDidChangeOcclusionState = objc.RegisterName("windowDidChangeOcclusionState:")
|
||||
sel_windowResizeEastWestCursor = objc.RegisterName("_windowResizeEastWestCursor")
|
||||
sel_windowResizeNorthSouthCursor = objc.RegisterName("_windowResizeNorthSouthCursor")
|
||||
sel_windowShouldClose = objc.RegisterName("windowShouldClose:")
|
||||
sel_windowWillEnterFullScreen = objc.RegisterName("windowWillEnterFullScreen:")
|
||||
sel_windowWillExitFullScreen = objc.RegisterName("windowWillExitFullScreen:")
|
||||
@ -303,26 +297,6 @@ func (u *userInterfaceImpl) isNativeFullscreen() bool {
|
||||
return cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) setNativeCursor(shape CursorShape) {
|
||||
NSCursor := objc.ID(class_NSCursor).Send(sel_class)
|
||||
cursor := NSCursor.Send(sel_performSelector, sel_arrowCursor)
|
||||
switch shape {
|
||||
case 0:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_arrowCursor)
|
||||
case 1:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_IBeamCursor)
|
||||
case 2:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_crosshairCursor)
|
||||
case 3:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_pointingHandCursor)
|
||||
case 4:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_windowResizeEastWestCursor)
|
||||
case 5:
|
||||
cursor = NSCursor.Send(sel_performSelector, sel_windowResizeNorthSouthCursor)
|
||||
}
|
||||
cursor.Send(sel_set)
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
||||
// TODO: If the window is transparent, we should use GLFW's windowed fullscreen (#1822, #1857).
|
||||
// However, if the user clicks the green button, should this window be in native fullscreen mode?
|
||||
|
@ -200,11 +200,6 @@ func (u *userInterfaceImpl) isNativeFullscreen() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) setNativeCursor(shape CursorShape) {
|
||||
// TODO: Use native API in the future (#1571)
|
||||
u.window.SetCursor(glfwSystemCursors[shape])
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
||||
return false
|
||||
}
|
||||
|
@ -189,11 +189,6 @@ func (u *userInterfaceImpl) isNativeFullscreen() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) setNativeCursor(shape CursorShape) {
|
||||
// TODO: Use native API in the future (#1571)
|
||||
u.window.SetCursor(glfwSystemCursors[shape])
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
||||
return false
|
||||
}
|
||||
|
@ -67,6 +67,14 @@ func driverCursorShapeToCSSCursor(cursor CursorShape) string {
|
||||
return "ew-resize"
|
||||
case CursorShapeNSResize:
|
||||
return "ns-resize"
|
||||
case CursorShapeNESWResize:
|
||||
return "nesw-resize"
|
||||
case CursorShapeNWSEResize:
|
||||
return "nwse-resize"
|
||||
case CursorShapeMove:
|
||||
return "move"
|
||||
case CursorShapeNotAllowed:
|
||||
return "not-allowed"
|
||||
}
|
||||
return "auto"
|
||||
}
|
||||
|
2
run.go
2
run.go
@ -378,6 +378,8 @@ func CursorShape() CursorShapeType {
|
||||
|
||||
// SetCursorShape sets the cursor shape.
|
||||
//
|
||||
// If the platform doesn't implement the given shape, the default cursor shape is used.
|
||||
//
|
||||
// SetCursorShape is concurrent-safe.
|
||||
func SetCursorShape(shape CursorShapeType) {
|
||||
ui.Get().SetCursorShape(shape)
|
||||
|
Loading…
Reference in New Issue
Block a user