mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
sokol: add mouse cursor support (#15111)
This commit is contained in:
parent
c1502b3c1f
commit
12d57e8e7b
24
examples/gg/cursor.v
Normal file
24
examples/gg/cursor.v
Normal file
@ -0,0 +1,24 @@
|
||||
module main
|
||||
|
||||
import gg
|
||||
import gx
|
||||
import sokol.sapp
|
||||
|
||||
fn main() {
|
||||
gg.new_context(
|
||||
bg_color: gx.white
|
||||
window_title: 'Cursor'
|
||||
frame_fn: frame
|
||||
init_fn: init
|
||||
).run()
|
||||
}
|
||||
|
||||
fn init(mut ctx gg.Context) {
|
||||
sapp.set_mouse_cursor(.ibeam)
|
||||
}
|
||||
|
||||
fn frame(mut ctx gg.Context) {
|
||||
ctx.begin()
|
||||
ctx.draw_text_def(10, 25, 'Your cursor should be an I shaped beam.')
|
||||
ctx.end()
|
||||
}
|
333
thirdparty/sokol/sokol_app.h
vendored
333
thirdparty/sokol/sokol_app.h
vendored
@ -131,13 +131,13 @@
|
||||
SUSPENDED | --- | --- | --- | YES | YES | YES | --- | TODO
|
||||
RESUMED | --- | --- | --- | YES | YES | YES | --- | TODO
|
||||
QUIT_REQUESTED | YES | YES | YES | --- | --- | --- | TODO | YES
|
||||
UPDATE_CURSOR | YES | YES | TODO | --- | --- | TODO | --- | TODO
|
||||
IME | TODO | TODO? | TODO | ??? | TODO | --- | ??? | ???
|
||||
key repeat flag | YES | YES | YES | --- | --- | YES | TODO | YES
|
||||
windowed | YES | YES | YES | --- | --- | YES | TODO | YES
|
||||
fullscreen | YES | YES | YES | YES | YES | YES | TODO | ---
|
||||
mouse hide | YES | YES | YES | --- | --- | YES | TODO | TODO
|
||||
mouse hide | YES | YES | YES | --- | --- | YES | TODO | YES
|
||||
mouse lock | YES | YES | YES | --- | --- | TODO | TODO | YES
|
||||
set cursor type | YES | YES | YES | --- | --- | YES | TODO | YES
|
||||
screen keyboard | --- | --- | --- | YES | TODO | TODO | --- | YES
|
||||
swap interval | YES | YES | YES | YES | TODO | --- | TODO | YES
|
||||
high-dpi | YES | YES | TODO | YES | YES | YES | TODO | YES
|
||||
@ -369,6 +369,23 @@
|
||||
"Really Quit?" dialog box). Note that the cleanup-callback isn't
|
||||
guaranteed to be called on the web and mobile platforms.
|
||||
|
||||
MOUSE CURSOR TYPE AND VISIBILITY
|
||||
================================
|
||||
You can show and hide the mouse cursor with
|
||||
void sapp_show_mouse(bool show)
|
||||
And to get the current shown status:
|
||||
bool sapp_mouse_shown(void)
|
||||
NOTE that hiding the mouse cursor is different and independent from
|
||||
the MOUSE/POINTER LOCK feature which will also hide the mouse pointer when
|
||||
active (MOUSE LOCK is described below).
|
||||
To change the mouse cursor to one of several predefined types, call
|
||||
the function:
|
||||
void sapp_set_mouse_cursor(sapp_mouse_cursor cursor)
|
||||
Setting the default mouse cursor SAPP_MOUSECURSOR_DEFAULT will restore
|
||||
the standard look.
|
||||
To get the currently active mouse cursor type, call:
|
||||
sapp_mouse_cursor sapp_get_mouse_cursor(void)
|
||||
|
||||
MOUSE LOCK (AKA POINTER LOCK, AKA MOUSE CAPTURE)
|
||||
================================================
|
||||
In normal mouse mode, no mouse movement events are reported when the
|
||||
@ -970,9 +987,6 @@
|
||||
- sapp_desc needs a bool whether to initialize depth-stencil surface
|
||||
- GL context initialization needs more control (at least what GL version to initialize)
|
||||
- application icon
|
||||
- the UPDATE_CURSOR event currently behaves differently between Win32 and OSX
|
||||
(Win32 sends the event each frame when the mouse moves and is inside the window
|
||||
client area, OSX sends it only once when the mouse enters the client area)
|
||||
- the Android implementation calls cleanup_cb() and destroys the egl context in onDestroy
|
||||
at the latest but should do it earlier, in onStop, as an app is "killable" after onStop
|
||||
on Android Honeycomb and later (it can't be done at the moment as the app may be started
|
||||
@ -1064,7 +1078,6 @@ typedef enum sapp_event_type {
|
||||
SAPP_EVENTTYPE_UNFOCUSED,
|
||||
SAPP_EVENTTYPE_SUSPENDED,
|
||||
SAPP_EVENTTYPE_RESUMED,
|
||||
SAPP_EVENTTYPE_UPDATE_CURSOR,
|
||||
SAPP_EVENTTYPE_QUIT_REQUESTED,
|
||||
SAPP_EVENTTYPE_CLIPBOARD_PASTED,
|
||||
SAPP_EVENTTYPE_FILES_DROPPED,
|
||||
@ -1362,7 +1375,6 @@ typedef struct sapp_desc {
|
||||
bool fullscreen; // whether the window should be created in fullscreen mode
|
||||
bool alpha; // whether the framebuffer should have an alpha channel (ignored on some platforms)
|
||||
const char* window_title; // the window title as UTF-8 encoded string
|
||||
bool user_cursor; // if true, user is expected to manage cursor image in SAPP_EVENTTYPE_UPDATE_CURSOR
|
||||
bool enable_clipboard; // enable clipboard access, default is false
|
||||
int clipboard_size; // max size of clipboard content in bytes
|
||||
bool enable_dragndrop; // enable file dropping (drag'n'drop), default is false
|
||||
@ -1413,6 +1425,25 @@ typedef struct sapp_html5_fetch_request {
|
||||
void* user_data; /* optional userdata pointer */
|
||||
} sapp_html5_fetch_request;
|
||||
|
||||
/*
|
||||
sapp_mouse_cursor
|
||||
Predefined cursor image definitions, set with sapp_set_mouse_cursor(sapp_mouse_cursor cursor)
|
||||
*/
|
||||
typedef enum sapp_mouse_cursor {
|
||||
SAPP_MOUSECURSOR_DEFAULT = 0, // equivalent with system default cursor
|
||||
SAPP_MOUSECURSOR_ARROW,
|
||||
SAPP_MOUSECURSOR_IBEAM,
|
||||
SAPP_MOUSECURSOR_CROSSHAIR,
|
||||
SAPP_MOUSECURSOR_POINTING_HAND,
|
||||
SAPP_MOUSECURSOR_RESIZE_EW,
|
||||
SAPP_MOUSECURSOR_RESIZE_NS,
|
||||
SAPP_MOUSECURSOR_RESIZE_NWSE,
|
||||
SAPP_MOUSECURSOR_RESIZE_NESW,
|
||||
SAPP_MOUSECURSOR_RESIZE_ALL,
|
||||
SAPP_MOUSECURSOR_NOT_ALLOWED,
|
||||
_SAPP_MOUSECURSOR_NUM,
|
||||
} sapp_mouse_cursor;
|
||||
|
||||
/* user-provided functions */
|
||||
extern sapp_desc sokol_main(int argc, char* argv[]);
|
||||
|
||||
@ -1452,6 +1483,10 @@ SOKOL_APP_API_DECL bool sapp_mouse_shown(void);
|
||||
SOKOL_APP_API_DECL void sapp_lock_mouse(bool lock);
|
||||
/* return true if in mouse-pointer-lock mode (this may toggle a few frames later) */
|
||||
SOKOL_APP_API_DECL bool sapp_mouse_locked(void);
|
||||
/* set mouse cursor type */
|
||||
SOKOL_APP_API_DECL void sapp_set_mouse_cursor(sapp_mouse_cursor cursor);
|
||||
/* get current mouse cursor type */
|
||||
SOKOL_APP_API_DECL sapp_mouse_cursor sapp_get_mouse_cursor(void);
|
||||
/* return the userdata pointer optionally provided in sapp_desc */
|
||||
SOKOL_APP_API_DECL void* sapp_userdata(void);
|
||||
/* return a copy of the sapp_desc structure */
|
||||
@ -1796,6 +1831,7 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/cursorfont.h> /* XC_* font cursors */
|
||||
#include <X11/Xmd.h> /* CARD32 */
|
||||
#include <dlfcn.h> /* dlopen, dlsym, dlclose */
|
||||
#include <limits.h> /* LONG_MAX */
|
||||
@ -2047,6 +2083,7 @@ typedef struct {
|
||||
_sapp_macos_app_delegate* app_dlg;
|
||||
_sapp_macos_window_delegate* win_dlg;
|
||||
_sapp_macos_view* view;
|
||||
NSCursor* cursors[_SAPP_MOUSECURSOR_NUM];
|
||||
#if defined(SOKOL_METAL)
|
||||
id<MTLDevice> mtl_device;
|
||||
#endif
|
||||
@ -2165,6 +2202,7 @@ typedef struct {
|
||||
HDC dc;
|
||||
HICON big_icon;
|
||||
HICON small_icon;
|
||||
HCURSOR cursors[_SAPP_MOUSECURSOR_NUM];
|
||||
UINT orig_codepage;
|
||||
LONG mouse_locked_x, mouse_locked_y;
|
||||
bool is_win10_or_greater;
|
||||
@ -2386,6 +2424,7 @@ typedef struct {
|
||||
Colormap colormap;
|
||||
Window window;
|
||||
Cursor hidden_cursor;
|
||||
Cursor cursors[_SAPP_MOUSECURSOR_NUM];
|
||||
int window_state;
|
||||
float dpi;
|
||||
unsigned char error_code;
|
||||
@ -2487,6 +2526,7 @@ typedef struct {
|
||||
bool shown;
|
||||
bool locked;
|
||||
bool pos_valid;
|
||||
sapp_mouse_cursor current_cursor;
|
||||
} _sapp_mouse_t;
|
||||
|
||||
typedef struct {
|
||||
@ -3094,6 +3134,28 @@ _SOKOL_PRIVATE void _sapp_macos_discard_state(void) {
|
||||
_SAPP_OBJC_RELEASE(_sapp.macos.window);
|
||||
}
|
||||
|
||||
// undocumented methods for creating cursors (see GLFW 3.4 and imgui_impl_osx.mm)
|
||||
@interface NSCursor()
|
||||
+ (id)_windowResizeNorthWestSouthEastCursor;
|
||||
+ (id)_windowResizeNorthEastSouthWestCursor;
|
||||
+ (id)_windowResizeNorthSouthCursor;
|
||||
+ (id)_windowResizeEastWestCursor;
|
||||
@end
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_macos_init_cursors(void) {
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_DEFAULT] = nil; // not a bug
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_ARROW] = [NSCursor arrowCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_IBEAM] = [NSCursor IBeamCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_CROSSHAIR] = [NSCursor crosshairCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_POINTING_HAND] = [NSCursor pointingHandCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_RESIZE_EW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_RESIZE_NS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_RESIZE_NWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_RESIZE_NESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_RESIZE_ALL] = [NSCursor closedHandCursor];
|
||||
_sapp.macos.cursors[SAPP_MOUSECURSOR_NOT_ALLOWED] = [NSCursor operationNotAllowedCursor];
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_macos_run(const sapp_desc* desc) {
|
||||
_sapp_init_state(desc);
|
||||
_sapp_macos_init_keytable();
|
||||
@ -3296,14 +3358,34 @@ _SOKOL_PRIVATE void _sapp_macos_lock_mouse(bool lock) {
|
||||
*/
|
||||
if (_sapp.mouse.locked) {
|
||||
CGAssociateMouseAndMouseCursorPosition(NO);
|
||||
CGDisplayHideCursor(kCGDirectMainDisplay);
|
||||
[NSCursor hide];
|
||||
}
|
||||
else {
|
||||
CGDisplayShowCursor(kCGDirectMainDisplay);
|
||||
[NSCursor unhide];
|
||||
CGAssociateMouseAndMouseCursorPosition(YES);
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_macos_update_cursor(sapp_mouse_cursor cursor, bool shown) {
|
||||
// show/hide cursor only if visibility status has changed (required because show/hide stacks)
|
||||
if (shown != _sapp.mouse.shown) {
|
||||
if (shown) {
|
||||
[NSCursor unhide];
|
||||
}
|
||||
else {
|
||||
[NSCursor hide];
|
||||
}
|
||||
}
|
||||
// update cursor type
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
if (_sapp.macos.cursors[cursor]) {
|
||||
[_sapp.macos.cursors[cursor] set];
|
||||
}
|
||||
else {
|
||||
[[NSCursor arrowCursor] set];
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_macos_set_icon(const sapp_icon_desc* icon_desc, int num_images) {
|
||||
NSDockTile* dock_tile = NSApp.dockTile;
|
||||
const int wanted_width = (int) dock_tile.size.width;
|
||||
@ -3351,6 +3433,7 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) {
|
||||
@implementation _sapp_macos_app_delegate
|
||||
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
|
||||
_SOKOL_UNUSED(aNotification);
|
||||
_sapp_macos_init_cursors();
|
||||
if (_sapp.fullscreen) {
|
||||
NSRect screen_rect = NSScreen.mainScreen.frame;
|
||||
_sapp.window_width = screen_rect.size.width;
|
||||
@ -3911,12 +3994,6 @@ _SOKOL_PRIVATE void _sapp_macos_poll_input_events() {
|
||||
_sapp_macos_mods(event));
|
||||
}
|
||||
}
|
||||
- (void)cursorUpdate:(NSEvent*)event {
|
||||
_SOKOL_UNUSED(event);
|
||||
if (_sapp.desc.user_cursor) {
|
||||
_sapp_macos_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
#endif /* MacOS */
|
||||
@ -4599,6 +4676,36 @@ _SOKOL_PRIVATE void _sapp_emsc_update_mouse_lock_state(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// set mouse cursor type
|
||||
EM_JS(void, sapp_js_set_cursor, (int cursor_type, int shown), {
|
||||
if (Module.sapp_emsc_target) {
|
||||
var cursor;
|
||||
if (shown === 0) {
|
||||
cursor = "none";
|
||||
}
|
||||
else switch (cursor_type) {
|
||||
case 0: cursor = "auto"; break; // SAPP_MOUSECURSOR_DEFAULT
|
||||
case 1: cursor = "default"; break; // SAPP_MOUSECURSOR_ARROW
|
||||
case 2: cursor = "text"; break; // SAPP_MOUSECURSOR_IBEAM
|
||||
case 3: cursor = "crosshair"; break; // SAPP_MOUSECURSOR_CROSSHAIR
|
||||
case 4: cursor = "pointer"; break; // SAPP_MOUSECURSOR_POINTING_HAND
|
||||
case 5: cursor = "ew-resize"; break; // SAPP_MOUSECURSOR_RESIZE_EW
|
||||
case 6: cursor = "ns-resize"; break; // SAPP_MOUSECURSOR_RESIZE_NS
|
||||
case 7: cursor = "nwse-resize"; break; // SAPP_MOUSECURSOR_RESIZE_NWSE
|
||||
case 8: cursor = "nesw-resize"; break; // SAPP_MOUSECURSOR_RESIZE_NESW
|
||||
case 9: cursor = "all-scroll"; break; // SAPP_MOUSECURSOR_RESIZE_ALL
|
||||
case 10: cursor = "not-allowed"; break; // SAPP_MOUSECURSOR_NOT_ALLOWED
|
||||
default: cursor = "auto"; break;
|
||||
}
|
||||
Module.sapp_emsc_target.style.cursor = cursor;
|
||||
}
|
||||
});
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_update_cursor(sapp_mouse_cursor cursor, bool shown) {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
sapp_js_set_cursor((int)cursor, shown ? 1 : 0);
|
||||
}
|
||||
|
||||
/* JS helper functions to update browser tab favicon */
|
||||
EM_JS(void, sapp_js_clear_favicon, (void), {
|
||||
var link = document.getElementById('sokol-app-favicon');
|
||||
@ -6211,9 +6318,73 @@ _SOKOL_PRIVATE void _sapp_win32_toggle_fullscreen(void) {
|
||||
SetWindowPos(_sapp.win32.hwnd, HWND_TOP, mr.left + rect.left, mr.top + rect.top, win_width, win_height, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_win32_show_mouse(bool visible) {
|
||||
/* NOTE: this function is only called when the mouse visibility actually changes */
|
||||
ShowCursor((BOOL)visible);
|
||||
_SOKOL_PRIVATE void _sapp_win32_init_cursor(sapp_mouse_cursor cursor) {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
// NOTE: the OCR_* constants are only defined if OEMRESOURCE is defined
|
||||
// before windows.h is included, but we can't guarantee that because
|
||||
// the sokol_app.h implementation may be included with other implementations
|
||||
// in the same compilation unit
|
||||
int id = 0;
|
||||
switch (cursor) {
|
||||
case SAPP_MOUSECURSOR_ARROW: id = 32512; break; // OCR_NORMAL
|
||||
case SAPP_MOUSECURSOR_IBEAM: id = 32513; break; // OCR_IBEAM
|
||||
case SAPP_MOUSECURSOR_CROSSHAIR: id = 32515; break; // OCR_CROSS
|
||||
case SAPP_MOUSECURSOR_POINTING_HAND: id = 32649; break; // OCR_HAND
|
||||
case SAPP_MOUSECURSOR_RESIZE_EW: id = 32644; break; // OCR_SIZEWE
|
||||
case SAPP_MOUSECURSOR_RESIZE_NS: id = 32645; break; // OCR_SIZENS
|
||||
case SAPP_MOUSECURSOR_RESIZE_NWSE: id = 32642; break; // OCR_SIZENWSE
|
||||
case SAPP_MOUSECURSOR_RESIZE_NESW: id = 32643; break; // OCR_SIZENESW
|
||||
case SAPP_MOUSECURSOR_RESIZE_ALL: id = 32646; break; // OCR_SIZEALL
|
||||
case SAPP_MOUSECURSOR_NOT_ALLOWED: id = 32648; break; // OCR_NO
|
||||
default: break;
|
||||
}
|
||||
if (id != 0) {
|
||||
_sapp.win32.cursors[cursor] = (HCURSOR)LoadImageW(NULL, MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE|LR_SHARED);
|
||||
}
|
||||
// fallback: default cursor
|
||||
if (0 == _sapp.win32.cursors[cursor]) {
|
||||
// 32512 => IDC_ARROW
|
||||
_sapp.win32.cursors[cursor] = LoadCursorW(NULL, MAKEINTRESOURCEW(32512));
|
||||
}
|
||||
SOKOL_ASSERT(0 != _sapp.win32.cursors[cursor]);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_win32_init_cursors(void) {
|
||||
for (int i = 0; i < _SAPP_MOUSECURSOR_NUM; i++) {
|
||||
_sapp_win32_init_cursor((sapp_mouse_cursor)i);
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sapp_win32_cursor_in_content_area(void) {
|
||||
POINT pos;
|
||||
if (!GetCursorPos(&pos)) {
|
||||
return false;
|
||||
}
|
||||
if (WindowFromPoint(pos) != _sapp.win32.hwnd) {
|
||||
return false;
|
||||
}
|
||||
RECT area;
|
||||
GetClientRect(_sapp.win32.hwnd, &area);
|
||||
ClientToScreen(_sapp.win32.hwnd, (POINT*)&area.left);
|
||||
ClientToScreen(_sapp.win32.hwnd, (POINT*)&area.right);
|
||||
return PtInRect(&area, pos);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_win32_update_cursor(sapp_mouse_cursor cursor, bool shown, bool skip_area_test) {
|
||||
// NOTE: when called from WM_SETCURSOR, the area test would be redundant
|
||||
if (!skip_area_test) {
|
||||
if (!_sapp_win32_cursor_in_content_area()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!shown) {
|
||||
SetCursor(NULL);
|
||||
}
|
||||
else {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
SOKOL_ASSERT(0 != _sapp.win32.cursors[cursor]);
|
||||
SetCursor(_sapp.win32.cursors[cursor]);
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_win32_capture_mouse(uint8_t btn_mask) {
|
||||
@ -6517,11 +6688,9 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM
|
||||
_sapp_win32_uwp_app_event(SAPP_EVENTTYPE_UNFOCUSED);
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
if (_sapp.desc.user_cursor) {
|
||||
if (LOWORD(lParam) == HTCLIENT) {
|
||||
_sapp_win32_uwp_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR);
|
||||
return 1;
|
||||
}
|
||||
if (LOWORD(lParam) == HTCLIENT) {
|
||||
_sapp_win32_update_cursor(_sapp.mouse.current_cursor, _sapp.mouse.shown, true);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
@ -6997,6 +7166,7 @@ _SOKOL_PRIVATE void _sapp_win32_run(const sapp_desc* desc) {
|
||||
_sapp_win32_uwp_init_keytable();
|
||||
_sapp_win32_uwp_utf8_to_wide(_sapp.window_title, _sapp.window_title_wide, sizeof(_sapp.window_title_wide));
|
||||
_sapp_win32_init_dpi();
|
||||
_sapp_win32_init_cursors();
|
||||
_sapp_win32_create_window();
|
||||
sapp_set_icon(&desc->icon);
|
||||
#if defined(SOKOL_D3D11)
|
||||
@ -7136,13 +7306,26 @@ _SOKOL_PRIVATE void _sapp_uwp_configure_dpi(float monitor_dpi) {
|
||||
_sapp.dpi_scale = _sapp.uwp.dpi.content_scale;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_uwp_show_mouse(bool visible) {
|
||||
_SOKOL_PRIVATE void _sapp_uwp_update_cursor(sapp_mouse_cursor cursor, bool shown) {
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
|
||||
/* NOTE: this function is only called when the mouse visibility actually changes */
|
||||
CoreWindow::GetForCurrentThread().PointerCursor(visible ?
|
||||
CoreCursor(CoreCursorType::Arrow, 0) :
|
||||
CoreCursor(nullptr));
|
||||
CoreCursor uwp_cursor(nullptr);
|
||||
if (shown) {
|
||||
switch (cursor) {
|
||||
case SAPP_MOUSECURSOR_ARROW: uwp_cursor = CoreCursor(CoreCursorType::Arrow, 0); break;
|
||||
case SAPP_MOUSECURSOR_IBEAM: uwp_cursor = CoreCursor(CoreCursorType::IBeam, 0); break;
|
||||
case SAPP_MOUSECURSOR_CROSSHAIR: uwp_cursor = CoreCursor(CoreCursorType::Cross, 0); break;
|
||||
case SAPP_MOUSECURSOR_POINTING_HAND: uwp_cursor = CoreCursor(CoreCursorType::Hand, 0); break;
|
||||
case SAPP_MOUSECURSOR_RESIZE_EW: uwp_cursor = CoreCursor(CoreCursorType::SizeWestEast, 0); break;
|
||||
case SAPP_MOUSECURSOR_RESIZE_NS: uwp_cursor = CoreCursor(CoreCursorType::SizeNorthSouth, 0); break;
|
||||
case SAPP_MOUSECURSOR_RESIZE_NWSE: uwp_cursor = CoreCursor(CoreCursorType::SizeNorthwestSoutheast, 0); break;
|
||||
case SAPP_MOUSECURSOR_RESIZE_NESW: uwp_cursor = CoreCursor(CoreCursorType::SizeNortheastSouthwest, 0); break;
|
||||
case SAPP_MOUSECURSOR_RESIZE_ALL: uwp_cursor = CoreCursor(CoreCursorType::SizeAll, 0); break;
|
||||
case SAPP_MOUSECURSOR_NOT_ALLOWED: uwp_cursor = CoreCursor(CoreCursorType::UniversalNo, 0); break;
|
||||
default: uwp_cursor = CoreCursor(CoreCursorType::Arrow, 0); break;
|
||||
}
|
||||
}
|
||||
CoreWindow::GetForCurrentThread().PointerCursor(uwp_cursor);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE uint32_t _sapp_uwp_mods(winrt::Windows::UI::Core::CoreWindow const& sender_window) {
|
||||
@ -10022,19 +10205,72 @@ _SOKOL_PRIVATE void _sapp_x11_create_hidden_cursor(void) {
|
||||
XcursorImageDestroy(img);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_create_standard_cursor(sapp_mouse_cursor cursor, const char* name, const char* theme, int size, uint32_t fallback_native) {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
SOKOL_ASSERT(_sapp.x11.display);
|
||||
if (theme) {
|
||||
XcursorImage* img = XcursorLibraryLoadImage(name, theme, size);
|
||||
if (img) {
|
||||
_sapp.x11.cursors[cursor] = XcursorImageLoadCursor(_sapp.x11.display, img);
|
||||
XcursorImageDestroy(img);
|
||||
}
|
||||
}
|
||||
if (0 == _sapp.x11.cursors[cursor]) {
|
||||
_sapp.x11.cursors[cursor] = XCreateFontCursor(_sapp.x11.display, fallback_native);
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_create_cursors(void) {
|
||||
SOKOL_ASSERT(_sapp.x11.display);
|
||||
const char* cursor_theme = XcursorGetTheme(_sapp.x11.display);
|
||||
const int size = XcursorGetDefaultSize(_sapp.x11.display);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_ARROW, "default", cursor_theme, size, XC_left_ptr);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_IBEAM, "text", cursor_theme, size, XC_xterm);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_CROSSHAIR, "crosshair", cursor_theme, size, XC_crosshair);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_POINTING_HAND, "pointer", cursor_theme, size, XC_hand2);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_RESIZE_EW, "ew-resize", cursor_theme, size, XC_sb_h_double_arrow);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_RESIZE_NS, "ns-resize", cursor_theme, size, XC_sb_v_double_arrow);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_RESIZE_NWSE, "nwse-resize", cursor_theme, size, 0);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_RESIZE_NESW, "nesw-resize", cursor_theme, size, 0);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_RESIZE_ALL, "all-scroll", cursor_theme, size, XC_fleur);
|
||||
_sapp_x11_create_standard_cursor(SAPP_MOUSECURSOR_NOT_ALLOWED, "no-allowed", cursor_theme, size, 0);
|
||||
_sapp_x11_create_hidden_cursor();
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_destroy_cursors(void) {
|
||||
SOKOL_ASSERT(_sapp.x11.display);
|
||||
if (_sapp.x11.hidden_cursor) {
|
||||
XFreeCursor(_sapp.x11.display, _sapp.x11.hidden_cursor);
|
||||
_sapp.x11.hidden_cursor = 0;
|
||||
}
|
||||
for (int i = 0; i < _SAPP_MOUSECURSOR_NUM; i++) {
|
||||
if (_sapp.x11.cursors[i]) {
|
||||
XFreeCursor(_sapp.x11.display, _sapp.x11.cursors[i]);
|
||||
_sapp.x11.cursors[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_toggle_fullscreen(void) {
|
||||
_sapp.fullscreen = !_sapp.fullscreen;
|
||||
_sapp_x11_set_fullscreen(_sapp.fullscreen);
|
||||
_sapp_x11_query_window_size();
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_show_mouse(bool show) {
|
||||
if (show) {
|
||||
XUndefineCursor(_sapp.x11.display, _sapp.x11.window);
|
||||
_SOKOL_PRIVATE void _sapp_x11_update_cursor(sapp_mouse_cursor cursor, bool shown) {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
if (shown) {
|
||||
if (_sapp.x11.cursors[cursor]) {
|
||||
XDefineCursor(_sapp.x11.display, _sapp.x11.window, _sapp.x11.cursors[cursor]);
|
||||
}
|
||||
else {
|
||||
XUndefineCursor(_sapp.x11.display, _sapp.x11.window);
|
||||
}
|
||||
}
|
||||
else {
|
||||
XDefineCursor(_sapp.x11.display, _sapp.x11.window, _sapp.x11.hidden_cursor);
|
||||
}
|
||||
XFlush(_sapp.x11.display);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_x11_lock_mouse(bool lock) {
|
||||
@ -10927,7 +11163,7 @@ _SOKOL_PRIVATE void _sapp_linux_run(const sapp_desc* desc) {
|
||||
_sapp_x11_query_system_dpi();
|
||||
_sapp.dpi_scale = _sapp.x11.dpi / 96.0f;
|
||||
_sapp_x11_init_extensions();
|
||||
_sapp_x11_create_hidden_cursor();
|
||||
_sapp_x11_create_cursors();
|
||||
_sapp_glx_init();
|
||||
Visual* visual = 0;
|
||||
int depth = 0;
|
||||
@ -10968,6 +11204,7 @@ _SOKOL_PRIVATE void _sapp_linux_run(const sapp_desc* desc) {
|
||||
_sapp_call_cleanup();
|
||||
_sapp_glx_destroy_context();
|
||||
_sapp_x11_destroy_window();
|
||||
_sapp_x11_destroy_cursors();
|
||||
XCloseDisplay(_sapp.x11.display);
|
||||
_sapp_discard_state();
|
||||
}
|
||||
@ -11128,13 +11365,15 @@ SOKOL_API_IMPL void sapp_toggle_fullscreen(void) {
|
||||
SOKOL_API_IMPL void sapp_show_mouse(bool show) {
|
||||
if (_sapp.mouse.shown != show) {
|
||||
#if defined(_SAPP_MACOS)
|
||||
_sapp_macos_show_mouse(show);
|
||||
_sapp_macos_update_cursor(_sapp.mouse.current_cursor, show);
|
||||
#elif defined(_SAPP_WIN32)
|
||||
_sapp_win32_show_mouse(show);
|
||||
_sapp_win32_update_cursor(_sapp.mouse.current_cursor, show, false);
|
||||
#elif defined(_SAPP_LINUX)
|
||||
_sapp_x11_show_mouse(show);
|
||||
_sapp_x11_update_cursor(_sapp.mouse.current_cursor, show);
|
||||
#elif defined(_SAPP_UWP)
|
||||
_sapp_uwp_show_mouse(show);
|
||||
_sapp_uwp_update_cursor(_sapp.mouse.current_cursor, show);
|
||||
#elif defined(_SAPP_EMSCRIPTEN)
|
||||
_sapp_emsc_update_cursor(_sapp.mouse.current_cursor, show);
|
||||
#endif
|
||||
_sapp.mouse.shown = show;
|
||||
}
|
||||
@ -11162,6 +11401,28 @@ SOKOL_API_IMPL bool sapp_mouse_locked(void) {
|
||||
return _sapp.mouse.locked;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL void sapp_set_mouse_cursor(sapp_mouse_cursor cursor) {
|
||||
SOKOL_ASSERT((cursor >= 0) && (cursor < _SAPP_MOUSECURSOR_NUM));
|
||||
if (_sapp.mouse.current_cursor != cursor) {
|
||||
#if defined(_SAPP_MACOS)
|
||||
_sapp_macos_update_cursor(cursor, _sapp.mouse.shown);
|
||||
#elif defined(_SAPP_WIN32)
|
||||
_sapp_win32_update_cursor(cursor, _sapp.mouse.shown, false);
|
||||
#elif defined(_SAPP_LINUX)
|
||||
_sapp_x11_update_cursor(cursor, _sapp.mouse.shown);
|
||||
#elif defined(_SAPP_UWP)
|
||||
_sapp_uwp_update_cursor(cursor, _sapp.mouse.shown);
|
||||
#elif defined(_SAPP_EMSCRIPTEN)
|
||||
_sapp_emsc_update_cursor(cursor, _sapp.mouse.shown);
|
||||
#endif
|
||||
_sapp.mouse.current_cursor = cursor;
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL sapp_mouse_cursor sapp_get_mouse_cursor(void) {
|
||||
return _sapp.mouse.current_cursor;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL void sapp_request_quit(void) {
|
||||
_sapp.quit_requested = true;
|
||||
}
|
||||
|
@ -36,6 +36,20 @@ pub enum MouseButton {
|
||||
middle = 2
|
||||
}
|
||||
|
||||
pub enum MouseCursor {
|
||||
default = C.SAPP_MOUSECURSOR_DEFAULT
|
||||
arrow = C.SAPP_MOUSECURSOR_ARROW
|
||||
ibeam = C.SAPP_MOUSECURSOR_IBEAM
|
||||
crosshair = C.SAPP_MOUSECURSOR_CROSSHAIR
|
||||
pointing_hand = C.SAPP_MOUSECURSOR_POINTING_HAND
|
||||
resize_ew = C.SAPP_MOUSECURSOR_RESIZE_EW
|
||||
resize_ns = C.SAPP_MOUSECURSOR_RESIZE_NS
|
||||
resize_nwse = C.SAPP_MOUSECURSOR_RESIZE_NWSE
|
||||
resize_nesw = C.SAPP_MOUSECURSOR_RESIZE_NESW
|
||||
resize_all = C.SAPP_MOUSECURSOR_RESIZE_ALL
|
||||
not_allowed = C.SAPP_MOUSECURSOR_NOT_ALLOWED
|
||||
}
|
||||
|
||||
pub enum Modifier {
|
||||
shift = 1 //(1<<0)
|
||||
ctrl = 2 //(1<<1)
|
||||
|
@ -97,6 +97,12 @@ pub fn show_mouse(visible bool) {
|
||||
C.sapp_show_mouse(visible)
|
||||
}
|
||||
|
||||
// set mouse cursor
|
||||
[inline]
|
||||
pub fn set_mouse_cursor(cursor MouseCursor) {
|
||||
C.sapp_set_mouse_cursor(cursor)
|
||||
}
|
||||
|
||||
// show or hide the mouse cursor
|
||||
[inline]
|
||||
pub fn mouse_shown() bool {
|
||||
|
@ -44,6 +44,9 @@ fn C.sapp_show_mouse(visible bool)
|
||||
// return true if the mouse cursor is shown
|
||||
fn C.sapp_mouse_shown() bool
|
||||
|
||||
// set mouse cursor
|
||||
fn C.sapp_set_mouse_cursor(cursor MouseCursor)
|
||||
|
||||
// lock or unlock the mouse cursor
|
||||
fn C.sapp_lock_mouse(locked bool)
|
||||
|
||||
|
@ -54,7 +54,6 @@ pub:
|
||||
fullscreen bool // whether the window should be created in fullscreen mode
|
||||
alpha bool // whether the framebuffer should have an alpha channel (ignored on some platforms)
|
||||
window_title &char // the window title as UTF-8 encoded string
|
||||
user_cursor bool // if true, user is expected to manage cursor image in SAPP_EVENTTYPE_UPDATE_CURSOR
|
||||
enable_clipboard bool // enable clipboard access, default is false
|
||||
clipboard_size int // max size of clipboard content in bytes
|
||||
enable_dragndrop bool // enable file dropping (drag'n'drop), default is false
|
||||
|
Loading…
Reference in New Issue
Block a user