aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2020-09-23 18:27:25 +0200
committerAndre Weissflog <floooh@gmail.com>2020-09-23 18:27:25 +0200
commite326a8fdd33cf7173e539e5ce88eff00a2346ea2 (patch)
tree278e6fbe9948a59e3149f479623bcd4c8e199abf
parente6f433ab0cc957f4eda99c60b2c5aece8f83f056 (diff)
parent12cfb6e9ff0b4fd6f23326ea91e0ecb9737e6db0 (diff)
merge latest changes from master
-rw-r--r--README.md11
-rw-r--r--sokol_app.h64
-rw-r--r--sokol_audio.h30
3 files changed, 86 insertions, 19 deletions
diff --git a/README.md b/README.md
index 229a6cac..f763fade 100644
--- a/README.md
+++ b/README.md
@@ -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");