diff options
| author | Andre Weissflog <floooh@gmail.com> | 2020-09-23 18:27:25 +0200 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2020-09-23 18:27:25 +0200 |
| commit | e326a8fdd33cf7173e539e5ce88eff00a2346ea2 (patch) | |
| tree | 278e6fbe9948a59e3149f479623bcd4c8e199abf | |
| parent | e6f433ab0cc957f4eda99c60b2c5aece8f83f056 (diff) | |
| parent | 12cfb6e9ff0b4fd6f23326ea91e0ecb9737e6db0 (diff) | |
merge latest changes from master
| -rw-r--r-- | README.md | 11 | ||||
| -rw-r--r-- | sokol_app.h | 64 | ||||
| -rw-r--r-- | sokol_audio.h | 30 |
3 files changed, 86 insertions, 19 deletions
@@ -6,7 +6,7 @@ Simple [STB-style](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) cross-platform libraries for C and C++, written in C. -[See what's new](#updates) (**31-Aug-2020**: sokol_gfx.h and sokol_app.h automatically select D3D11 C++ or C API) +[See what's new](#updates) (**22-Sep-2020** sokol_app.h win32: mouse input SetCapture/ReleaseCapture) [Live Samples](https://floooh.github.io/sokol-html5/index.html) via WASM. @@ -460,6 +460,15 @@ Mainly some "missing features" for desktop apps: # Updates +- **22-Sep-2020**: + A small fix in sokol_app.h's Win32 backend: when a mouse button is pressed, + mouse input is now 'captured' by calling SetCapture(), and when the last + mouse button is released, ReleaseCapture() is called. This also provides + mouse events outside the window area as long as a mouse button is pressed, + which is useful for windowed UI applicactions (this is not the same as the + more 'rigorous' and explicit pointer-lock feature which is more useful for + camera-controls) + - **31-Aug-2020**: Internal change: The D3D11/DXGI backend code in sokol_gfx.h and sokol_app.h now use the D3D11 and DXGI C++-APIs when the implementation is compiled as diff --git a/sokol_app.h b/sokol_app.h index f0080d59..926fbfb8 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -1366,6 +1366,7 @@ inline int sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } typedef struct { uint32_t flags_changed_store; + uint8_t mouse_buttons; NSWindow* window; NSTrackingArea* tracking_area; _sapp_macos_app_delegate* app_dlg; @@ -1487,6 +1488,7 @@ typedef struct { bool in_create_window; bool iconified; bool mouse_tracked; + uint8_t mouse_capture_mask; _sapp_win32_dpi_t dpi; bool raw_input_mousepos_valid; LONG raw_input_mousepos_x; @@ -1676,6 +1678,7 @@ typedef struct { } _sapp_xi_t; typedef struct { + uint8_t mouse_buttons; Display* display; int screen; Window root; @@ -2918,34 +2921,55 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { [super updateTrackingAreas]; } - (void)mouseEntered:(NSEvent*)event { - _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + /* don't send mouse enter/leave while dragging (so that it behaves the same as + on Windows while SetCapture is active + */ + if (0 == _sapp.macos.mouse_buttons) { + _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + } } - (void)mouseExited:(NSEvent*)event { - _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + if (0 == _sapp.macos.mouse_buttons) { + _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + } } - (void)mouseDown:(NSEvent*)event { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons |= (1<<SAPP_MOUSEBUTTON_LEFT); } - (void)mouseUp:(NSEvent*)event { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_LEFT, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons &= ~(1<<SAPP_MOUSEBUTTON_LEFT); } - (void)rightMouseDown:(NSEvent*)event { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_RIGHT, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons |= (1<<SAPP_MOUSEBUTTON_RIGHT); } - (void)rightMouseUp:(NSEvent*)event { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_RIGHT, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons &= ~(1<<SAPP_MOUSEBUTTON_RIGHT); } - (void)otherMouseDown:(NSEvent*)event { if (2 == event.buttonNumber) { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_MIDDLE, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons |= (1<<SAPP_MOUSEBUTTON_MIDDLE); } } - (void)otherMouseUp:(NSEvent*)event { if (2 == event.buttonNumber) { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_MIDDLE, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons &= (1<<SAPP_MOUSEBUTTON_MIDDLE); + } +} +- (void)otherMouseDragged:(NSEvent*)event { + if (2 == event.buttonNumber) { + if (_sapp.mouse.locked) { + _sapp.mouse.dx = [event deltaX]; + _sapp.mouse.dy = [event deltaY]; + } + _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_MIDDLE, _sapp_macos_mod(event.modifierFlags)); } } -// FIXME: otherMouseDragged? - (void)mouseMoved:(NSEvent*)event { if (_sapp.mouse.locked) { _sapp.mouse.dx = [event deltaX]; @@ -5060,6 +5084,22 @@ _SOKOL_PRIVATE void _sapp_win32_show_mouse(bool visible) { ShowCursor((BOOL)visible); } +_SOKOL_PRIVATE void _sapp_win32_capture_mouse(uint8_t btn_mask) { + if (0 == _sapp.win32.mouse_capture_mask) { + SetCapture(_sapp.win32.hwnd); + } + _sapp.win32.mouse_capture_mask |= btn_mask; +} + +_SOKOL_PRIVATE void _sapp_win32_release_mouse(uint8_t btn_mask) { + if (0 != _sapp.win32.mouse_capture_mask) { + _sapp.win32.mouse_capture_mask &= ~btn_mask; + if (0 == _sapp.win32.mouse_capture_mask) { + ReleaseCapture(); + } + } +} + _SOKOL_PRIVATE void _sapp_win32_lock_mouse(bool lock) { if (lock == _sapp.mouse.locked) { return; @@ -5067,6 +5107,7 @@ _SOKOL_PRIVATE void _sapp_win32_lock_mouse(bool lock) { _sapp.mouse.dx = 0.0f; _sapp.mouse.dy = 0.0f; _sapp.mouse.locked = lock; + _sapp_win32_release_mouse(0xFF); if (_sapp.mouse.locked) { /* store the current mouse position, so it can be restored when unlocked */ POINT pos; @@ -5276,21 +5317,27 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM break; case WM_LBUTTONDOWN: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT); + _sapp_win32_capture_mouse(1<<SAPP_MOUSEBUTTON_LEFT); break; case WM_RBUTTONDOWN: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_RIGHT); + _sapp_win32_capture_mouse(1<<SAPP_MOUSEBUTTON_RIGHT); break; case WM_MBUTTONDOWN: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_MIDDLE); + _sapp_win32_capture_mouse(1<<SAPP_MOUSEBUTTON_MIDDLE); break; case WM_LBUTTONUP: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_LEFT); + _sapp_win32_release_mouse(1<<SAPP_MOUSEBUTTON_LEFT); break; case WM_RBUTTONUP: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_RIGHT); + _sapp_win32_release_mouse(1<<SAPP_MOUSEBUTTON_RIGHT); break; case WM_MBUTTONUP: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_MIDDLE); + _sapp_win32_release_mouse(1<<SAPP_MOUSEBUTTON_MIDDLE); break; case WM_MOUSEMOVE: if (!_sapp.mouse.locked) { @@ -9046,6 +9093,7 @@ _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) { const uint32_t mods = _sapp_x11_mod(event->xbutton.state); if (btn != SAPP_MOUSEBUTTON_INVALID) { _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, btn, mods); + _sapp.x11.mouse_buttons |= (1 << btn); } else { /* might be a scroll event */ @@ -9063,14 +9111,20 @@ _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) { const sapp_mousebutton btn = _sapp_x11_translate_button(event); if (btn != SAPP_MOUSEBUTTON_INVALID) { _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, btn, _sapp_x11_mod(event->xbutton.state)); + _sapp.x11.mouse_buttons &= ~(1 << btn); } } break; case EnterNotify: - _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + /* don't send enter/leave events while mouse button held down */ + if (0 == _sapp.x11.mouse_buttons) { + _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + } break; case LeaveNotify: - _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + if (0 == _sapp.x11.mouse_buttons) { + _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + } break; case MotionNotify: if (!_sapp.mouse.locked) { diff --git a/sokol_audio.h b/sokol_audio.h index dd6d2d63..bf7e4a71 100644 --- a/sokol_audio.h +++ b/sokol_audio.h @@ -1187,11 +1187,13 @@ _SOKOL_PRIVATE void _saudio_wasapi_release(void) { } _SOKOL_PRIVATE bool _saudio_backend_init(void) { - REFERENCE_TIME dur; - if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED))) { - SOKOL_LOG("sokol_audio wasapi: CoInitializeEx failed"); - return false; - } + /* CoInitializeEx could have been called elsewhere already, in which + case the function returns with S_FALSE (thus it doesn't make much + sense to check the result) + */ + HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED); + _SOKOL_UNUSED(hr); + _saudio.backend.thread.buffer_end_event = CreateEvent(0, FALSE, FALSE, 0); if (0 == _saudio.backend.thread.buffer_end_event) { SOKOL_LOG("sokol_audio wasapi: failed to create buffer_end_event"); @@ -1228,15 +1230,17 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) { fmt.wBitsPerSample = 16; fmt.nBlockAlign = (fmt.nChannels * fmt.wBitsPerSample) / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; - dur = (REFERENCE_TIME) - (((double)_saudio.buffer_frames) / (((double)_saudio.sample_rate) * (1.0/10000000.0))); - if (FAILED(IAudioClient_Initialize(_saudio.backend.audio_client, - AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY, - dur, 0, &fmt, 0))) + /* extra scope block to silence warning about goto skipping variable declaration */ { - SOKOL_LOG("sokol_audio wasapi: audio client initialize failed"); - goto error; + REFERENCE_TIME dur = (REFERENCE_TIME) (((double)_saudio.buffer_frames) / (((double)_saudio.sample_rate) * (1.0/10000000.0))); + if (FAILED(IAudioClient_Initialize(_saudio.backend.audio_client, + AUDCLNT_SHAREMODE_SHARED, + AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY, + dur, 0, &fmt, 0))) + { + SOKOL_LOG("sokol_audio wasapi: audio client initialize failed"); + goto error; + } } if (FAILED(IAudioClient_GetBufferSize(_saudio.backend.audio_client, &_saudio.backend.thread.dst_buffer_frames))) { SOKOL_LOG("sokol_audio wasapi: audio client get buffer size failed"); |