diff options
Diffstat (limited to '3rdparty/bgfx/examples/common/entry')
21 files changed, 1337 insertions, 832 deletions
diff --git a/3rdparty/bgfx/examples/common/entry/cmd.cpp b/3rdparty/bgfx/examples/common/entry/cmd.cpp index 4c68be9b51c..51742b8eb89 100644 --- a/3rdparty/bgfx/examples/common/entry/cmd.cpp +++ b/3rdparty/bgfx/examples/common/entry/cmd.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include <bx/allocator.h> @@ -29,12 +29,24 @@ struct CmdContext void add(const char* _name, ConsoleFn _fn, void* _userData) { - uint32_t cmd = bx::hash<bx::HashMurmur2A>(_name, (uint32_t)bx::strLen(_name) ); - BX_CHECK(m_lookup.end() == m_lookup.find(cmd), "Command \"%s\" already exist.", _name); + const uint32_t cmd = bx::hash<bx::HashMurmur2A>(_name, (uint32_t)bx::strLen(_name) ); + BX_ASSERT(m_lookup.end() == m_lookup.find(cmd), "Command \"%s\" already exist.", _name); + Func fn = { _fn, _userData }; m_lookup.insert(stl::make_pair(cmd, fn) ); } + void remove(const char* _name) + { + const uint32_t cmd = bx::hash<bx::HashMurmur2A>(_name, (uint32_t)bx::strLen(_name) ); + + CmdLookup::iterator it = m_lookup.find(cmd); + if (it != m_lookup.end() ) + { + m_lookup.erase(it); + } + } + void exec(const char* _cmd) { for (bx::StringView next(_cmd); !next.isEmpty(); _cmd = next.getPtr() ) @@ -105,6 +117,11 @@ void cmdAdd(const char* _name, ConsoleFn _fn, void* _userData) s_cmdContext->add(_name, _fn, _userData); } +void cmdRemove(const char* _name) +{ + s_cmdContext->remove(_name); +} + void cmdExec(const char* _format, ...) { char tmp[2048]; diff --git a/3rdparty/bgfx/examples/common/entry/cmd.h b/3rdparty/bgfx/examples/common/entry/cmd.h index 27523d153c0..fe219424edd 100644 --- a/3rdparty/bgfx/examples/common/entry/cmd.h +++ b/3rdparty/bgfx/examples/common/entry/cmd.h @@ -1,6 +1,6 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef CMD_H_HEADER_GUARD @@ -19,6 +19,9 @@ void cmdShutdown(); void cmdAdd(const char* _name, ConsoleFn _fn, void* _userData = NULL); /// +void cmdRemove(const char* _name); + +/// void cmdExec(const char* _format, ...); #endif // CMD_H_HEADER_GUARD diff --git a/3rdparty/bgfx/examples/common/entry/dbg.h b/3rdparty/bgfx/examples/common/entry/dbg.h index 2a50e7a5813..bafe4a51447 100644 --- a/3rdparty/bgfx/examples/common/entry/dbg.h +++ b/3rdparty/bgfx/examples/common/entry/dbg.h @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef DBG_H_HEADER_GUARD diff --git a/3rdparty/bgfx/examples/common/entry/dialog.cpp b/3rdparty/bgfx/examples/common/entry/dialog.cpp new file mode 100644 index 00000000000..8c1bf9731e7 --- /dev/null +++ b/3rdparty/bgfx/examples/common/entry/dialog.cpp @@ -0,0 +1,243 @@ +/* + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#include <bx/allocator.h> +#include <bx/filepath.h> +#include <bx/string.h> +#include <bx/readerwriter.h> +#include <bx/process.h> + +#include "dialog.h" + +#if BX_PLATFORM_WINDOWS +typedef uintptr_t (__stdcall *LPOFNHOOKPROC)(void*, uint32_t, uintptr_t, uint64_t); + +struct OPENFILENAMEA +{ + uint32_t structSize; + void* hwndOwner; + void* hinstance; + const char* filter; + const char* customFilter; + uint32_t maxCustomFilter; + uint32_t filterIndex; + const char* file; + uint32_t maxFile; + const char* fileTitle; + uint32_t maxFileTitle; + const char* initialDir; + const char* title; + uint32_t flags; + uint16_t fileOffset; + uint16_t fileExtension; + const char* defExt; + uintptr_t customData; + LPOFNHOOKPROC hook; + const char* templateName; + void* reserved0; + uint32_t reserved1; + uint32_t flagsEx; +}; + +extern "C" bool __stdcall GetOpenFileNameA(OPENFILENAMEA* _ofn); +extern "C" bool __stdcall GetSaveFileNameA(OPENFILENAMEA * _ofn); +extern "C" void* __stdcall GetModuleHandleA(const char* _moduleName); +extern "C" uint32_t __stdcall GetModuleFileNameA(void* _module, char* _outFilePath, uint32_t _size); +extern "C" void* __stdcall ShellExecuteA(void* _hwnd, void* _operation, void* _file, void* _parameters, void* _directory, int32_t _showCmd); + +#endif // BX_PLATFORM_WINDOWS + +void openUrl(const bx::StringView& _url) +{ + char tmp[4096]; + +#if BX_PLATFORM_WINDOWS +# define OPEN "" +#elif BX_PLATFORM_OSX +# define OPEN "open " +#else +# define OPEN "xdg-open " +#endif // BX_PLATFORM_OSX + + bx::snprintf(tmp, BX_COUNTOF(tmp), OPEN "%.*s", _url.getLength(), _url.getPtr() ); + +#undef OPEN + +#if BX_PLATFORM_WINDOWS + void* result = ShellExecuteA(NULL, NULL, tmp, NULL, NULL, false); + BX_UNUSED(result); +#elif !BX_PLATFORM_IOS + int32_t result = system(tmp); + BX_UNUSED(result); +#endif // BX_PLATFORM_* +} + +class Split +{ +public: + Split(const bx::StringView& _str, char _ch) + : m_str(_str) + , m_token(_str.getPtr(), bx::strFind(_str, _ch).getPtr() ) + , m_ch(_ch) + { + } + + bx::StringView next() + { + bx::StringView result = m_token; + m_token = bx::strTrim( + bx::StringView(m_token.getTerm()+1, bx::strFind(bx::StringView(m_token.getTerm()+1, m_str.getTerm() ), m_ch).getPtr() ) + , " \t\n" + ); + return result; + } + + bool isDone() const + { + return m_token.isEmpty(); + } + +private: + const bx::StringView& m_str; + bx::StringView m_token; + char m_ch; +}; + +#if BX_PLATFORM_WINDOWS +extern "C" typedef bool(__stdcall* OPENFILENAMEFUNCTION)(OPENFILENAMEA* _ofn); +static const struct { OPENFILENAMEFUNCTION m_function; uint32_t m_flags; } +s_getFileNameA[] = +{ + { GetOpenFileNameA, /* OFN_EXPLORER */ 0x00080000 | /* OFN_DONTADDTORECENT */ 0x02000000 | /* OFN_FILEMUSTEXIST */ 0x00001000 }, + { GetSaveFileNameA, /* OFN_EXPLORER */ 0x00080000 | /* OFN_DONTADDTORECENT */ 0x02000000 }, +}; +BX_STATIC_ASSERT(BX_COUNTOF(s_getFileNameA) == FileSelectionDialogType::Count); +#endif + +#if !BX_PLATFORM_OSX +bool openFileSelectionDialog( + bx::FilePath& _inOutFilePath + , FileSelectionDialogType::Enum _type + , const bx::StringView& _title + , const bx::StringView& _filter + ) +{ +#if BX_PLATFORM_LINUX + char tmp[4096]; + bx::StaticMemoryBlockWriter writer(tmp, sizeof(tmp) ); + + bx::Error err; + bx::write(&writer, &err + , "--file-selection%s --title \"%.*s\" --filename \"%s\"" + , FileSelectionDialogType::Save == _type ? " --save" : "" + , _title.getLength() + , _title.getPtr() + , _inOutFilePath.getCPtr() + ); + + for (bx::LineReader lr(_filter); !lr.isDone();) + { + const bx::StringView line = lr.next(); + + bx::write(&writer, &err + , " --file-filter \"%.*s\"" + , line.getLength() + , line.getPtr() + ); + } + + bx::write(&writer, '\0', &err); + + if (err.isOk() ) + { + bx::ProcessReader pr; + + if (bx::open(&pr, "zenity", tmp, &err) ) + { + char buffer[1024]; + int32_t total = bx::read(&pr, buffer, sizeof(buffer), &err); + bx::close(&pr); + + if (0 == pr.getExitCode() ) + { + _inOutFilePath.set(bx::strRTrim(bx::StringView(buffer, total), "\n\r") ); + return true; + } + } + } +#elif BX_PLATFORM_WINDOWS + if (_type < 0 || _type >= BX_COUNTOF(s_getFileNameA)) + return false; + + char out[bx::kMaxFilePath] = { '\0' }; + + OPENFILENAMEA ofn; + bx::memSet(&ofn, 0, sizeof(ofn) ); + ofn.structSize = sizeof(OPENFILENAMEA); + ofn.initialDir = _inOutFilePath.getCPtr(); + ofn.file = out; + ofn.maxFile = sizeof(out); + ofn.flags = s_getFileNameA[_type].m_flags; + + char tmp[4096]; + bx::StaticMemoryBlockWriter writer(tmp, sizeof(tmp) ); + + bx::Error err; + + ofn.title = tmp; + bx::write(&writer, &err, "%.*s", _title.getLength(), _title.getPtr() ); + bx::write(&writer, '\0', &err); + + ofn.filter = tmp + uint32_t(bx::seek(&writer) ); + + for (bx::LineReader lr(_filter); !lr.isDone() && err.isOk();) + { + const bx::StringView line = lr.next(); + const bx::StringView sep = bx::strFind(line, '|'); + + if (!sep.isEmpty() ) + { + bx::write(&writer, bx::strTrim(bx::StringView(line.getPtr(), sep.getPtr() ), " "), &err); + bx::write(&writer, '\0', &err); + + bool first = true; + + for (Split split(bx::strTrim(bx::StringView(sep.getPtr()+1, line.getTerm() ), " "), ' '); !split.isDone() && err.isOk();) + { + const bx::StringView token = split.next(); + if (!first) + { + bx::write(&writer, ';', &err); + } + + first = false; + bx::write(&writer, token, &err); + } + + bx::write(&writer, '\0', &err); + } + else + { + bx::write(&writer, line, &err); + bx::write(&writer, '\0', &err); + bx::write(&writer, '\0', &err); + } + } + + bx::write(&writer, '\0', &err); + + if (err.isOk() + && s_getFileNameA[_type].m_function(&ofn)) + { + _inOutFilePath.set(ofn.file); + return true; + } +#else + BX_UNUSED(_inOutFilePath, _type, _title, _filter); +#endif // BX_PLATFORM_LINUX + + return false; +} +#endif // !BX_PLATFORM_OSX diff --git a/3rdparty/bgfx/examples/common/entry/dialog.h b/3rdparty/bgfx/examples/common/entry/dialog.h new file mode 100644 index 00000000000..8c13d2be636 --- /dev/null +++ b/3rdparty/bgfx/examples/common/entry/dialog.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#ifndef DIALOG_H_HEADER_GUARD +#define DIALOG_H_HEADER_GUARD + +namespace bx { class FilePath; class StringView; } + +struct FileSelectionDialogType +{ + enum Enum + { + Open, + Save, + + Count + }; +}; + +/// +bool openFileSelectionDialog( + bx::FilePath& _inOutFilePath + , FileSelectionDialogType::Enum _type + , const bx::StringView& _title + , const bx::StringView& _filter = "All Files | *" + ); + +/// +void openUrl(const bx::StringView& _url); + +#endif // DIALOG_H_HEADER_GUARD diff --git a/3rdparty/bgfx/examples/common/entry/dialog_darwin.mm b/3rdparty/bgfx/examples/common/entry/dialog_darwin.mm new file mode 100644 index 00000000000..c80a7a91d11 --- /dev/null +++ b/3rdparty/bgfx/examples/common/entry/dialog_darwin.mm @@ -0,0 +1,152 @@ +/* + * Copyright 2019-2019 Attila Kocsis. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#include "entry_p.h" +#if BX_PLATFORM_OSX + +#include <bx/allocator.h> +#include <bx/filepath.h> +#include <bx/string.h> +#include <bx/readerwriter.h> +#include <bx/process.h> +#include <bx/semaphore.h> + +#import <AppKit/AppKit.h> + +#include "dialog.h" + +class Split +{ +public: + Split(const bx::StringView& _str, char _ch) + : m_str(_str) + , m_token(_str.getPtr(), bx::strFind(_str, _ch).getPtr() ) + , m_ch(_ch) + { + } + + bx::StringView next() + { + bx::StringView result = m_token; + m_token = bx::strTrim( + bx::StringView(m_token.getTerm()+1, bx::strFind(bx::StringView(m_token.getTerm()+1, m_str.getTerm() ), m_ch).getPtr()) + , " \t\n" + ); + return result; + } + + bool isDone() const + { + return m_token.isEmpty(); + } + +private: + const bx::StringView& m_str; + bx::StringView m_token; + char m_ch; +}; + +bool openFileSelectionDialog( + bx::FilePath& _inOutFilePath + , FileSelectionDialogType::Enum _type + , const bx::StringView& _title + , const bx::StringView& _filter + ) +{ + NSMutableArray* fileTypes = [NSMutableArray arrayWithCapacity:10]; + + for (bx::LineReader lr(_filter); !lr.isDone();) + { + const bx::StringView line = lr.next(); + const bx::StringView sep = bx::strFind(line, '|'); + + if (!sep.isEmpty() ) + { + for (Split split(bx::strTrim(bx::StringView(sep.getPtr()+1, line.getTerm() ), " "), ' ') + ; !split.isDone() + ; + ) + { + const bx::StringView token = split.next(); + + if (token.getLength() >= 3 + && token.getPtr()[0] == '*' + && token.getPtr()[1] == '.' + && bx::isAlphaNum(token.getPtr()[2]) ) + { + NSString* extension = [[NSString alloc] initWithBytes:token.getPtr()+2 length:token.getLength()-2 encoding:NSASCIIStringEncoding]; + [fileTypes addObject: extension]; + } + } + } + } + + __block NSString* fileName = nil; + + void (^invokeDialog)(void) = + ^{ + NSSavePanel* panel = nil; + + if (FileSelectionDialogType::Open == _type) + { + NSOpenPanel* openPanel = [NSOpenPanel openPanel]; + openPanel.canChooseFiles = TRUE; + openPanel.allowsMultipleSelection = FALSE; + openPanel.canChooseDirectories = FALSE; + panel = openPanel; + } + else + { + panel = [NSSavePanel savePanel]; + } + + panel.message = [[NSString alloc] initWithBytes:_title.getPtr() length:_title.getLength() encoding:NSASCIIStringEncoding]; + panel.directoryURL = [NSURL URLWithString:@(_inOutFilePath.getCPtr())]; + panel.allowedFileTypes = fileTypes; + + if ([panel runModal] == NSModalResponseOK) + { + NSURL* url = [panel URL]; + + if (nil != url) + { + fileName = [url path]; + [fileName retain]; + } + } + + [panel close]; + }; + + if ([NSThread isMainThread]) + { + invokeDialog(); + } + else + { + bx::Semaphore semaphore; + bx::Semaphore* psemaphore = &semaphore; + + CFRunLoopPerformBlock( + [[NSRunLoop mainRunLoop] getCFRunLoop] + , kCFRunLoopCommonModes + , ^{ + invokeDialog(); + psemaphore->post(); + }); + semaphore.wait(); + } + + if (fileName != nil) + { + _inOutFilePath.set([fileName UTF8String]); + [fileName release]; + return true; + } + + return false; +} + +#endif // BX_PLATFORM_OSX diff --git a/3rdparty/bgfx/examples/common/entry/entry.cpp b/3rdparty/bgfx/examples/common/entry/entry.cpp index 44c9dfd604b..dc3e97488ea 100644 --- a/3rdparty/bgfx/examples/common/entry/entry.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include <bx/bx.h> @@ -46,7 +46,7 @@ namespace entry virtual bool open(const bx::FilePath& _filePath, bx::Error* _err) override { String filePath(s_currentDir); - filePath.append(_filePath.get() ); + filePath.append(_filePath); return super::open(filePath.getPtr(), _err); } }; @@ -59,7 +59,7 @@ namespace entry virtual bool open(const bx::FilePath& _filePath, bool _append, bx::Error* _err) override { String filePath(s_currentDir); - filePath.append(_filePath.get() ); + filePath.append(_filePath); return super::open(filePath.getPtr(), _append, _err); } }; @@ -189,7 +189,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const char* getName(Key::Enum _key) { - BX_CHECK(_key < Key::Count, "Invalid key %d.", _key); + BX_ASSERT(_key < Key::Count, "Invalid key %d.", _key); return s_keyName[_key]; } @@ -352,9 +352,6 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { entry::Key::GamepadStart, entry::Modifier::None, 1, NULL, "graphics stats" }, { entry::Key::F1, entry::Modifier::LeftShift, 1, NULL, "graphics stats 0\ngraphics text 0" }, { entry::Key::F3, entry::Modifier::None, 1, NULL, "graphics wireframe" }, - { entry::Key::F4, entry::Modifier::None, 1, NULL, "graphics hmd" }, - { entry::Key::F4, entry::Modifier::LeftShift, 1, NULL, "graphics hmdrecenter" }, - { entry::Key::F4, entry::Modifier::LeftCtrl, 1, NULL, "graphics hmddbg" }, { entry::Key::F6, entry::Modifier::None, 1, NULL, "graphics profiler" }, { entry::Key::F7, entry::Modifier::None, 1, NULL, "graphics vsync" }, { entry::Key::F8, entry::Modifier::None, 1, NULL, "graphics msaa" }, @@ -446,11 +443,27 @@ BX_PRAGMA_DIAGNOSTIC_POP(); return bx::kExitFailure; } - AppI::AppI(const char* _name, const char* _description) + struct AppInternal { - m_name = _name; - m_description = _description; - m_next = s_apps; + AppI* m_next; + const char* m_name; + const char* m_description; + const char* m_url; + }; + + static ptrdiff_t s_offset = 0; + + AppI::AppI(const char* _name, const char* _description, const char* _url) + { + BX_STATIC_ASSERT(sizeof(AppInternal) <= sizeof(m_internal) ); + s_offset = BX_OFFSETOF(AppI, m_internal); + + AppInternal* ai = (AppInternal*)m_internal; + + ai->m_name = _name; + ai->m_description = _description; + ai->m_url = _url; + ai->m_next = s_apps; s_apps = this; s_numApps++; @@ -466,7 +479,8 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { if (NULL != prev) { - prev->m_next = next; + AppInternal* ai = bx::addressOf<AppInternal>(prev, s_offset); + ai->m_next = next; } else { @@ -482,17 +496,26 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const char* AppI::getName() const { - return m_name; + AppInternal* ai = (AppInternal*)m_internal; + return ai->m_name; } const char* AppI::getDescription() const { - return m_description; + AppInternal* ai = (AppInternal*)m_internal; + return ai->m_description; + } + + const char* AppI::getUrl() const + { + AppInternal* ai = (AppInternal*)m_internal; + return ai->m_url; } AppI* AppI::getNext() { - return m_next; + AppInternal* ai = (AppInternal*)m_internal; + return ai->m_next; } AppI* getFirstApp() @@ -510,8 +533,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); _app->init(_argc, _argv, s_width, s_height); bgfx::frame(); - WindowHandle defaultWindow = { 0 }; - setWindowSize(defaultWindow, s_width, s_height); + setWindowSize(kDefaultWindowHandle, s_width, s_height); #if BX_PLATFORM_EMSCRIPTEN s_app = _app; @@ -557,9 +579,15 @@ BX_PRAGMA_DIAGNOSTIC_POP(); for (ii = 1; ii < s_numApps; ++ii) { AppI* app = apps[ii-1]; - app->m_next = apps[ii]; + + AppInternal* ai = bx::addressOf<AppInternal>(app, s_offset); + ai->m_next = apps[ii]; + } + + { + AppInternal* ai = bx::addressOf<AppInternal>(apps[s_numApps-1], s_offset); + ai->m_next = NULL; } - apps[s_numApps-1]->m_next = NULL; BX_FREE(g_allocator, apps); } @@ -580,14 +608,12 @@ BX_PRAGMA_DIAGNOSTIC_POP(); inputInit(); inputAddBindings("bindings", s_bindings); - entry::WindowHandle defaultWindow = { 0 }; - bx::FilePath fp(_argv[0]); char title[bx::kMaxFilePath]; bx::strCopy(title, BX_COUNTOF(title), fp.getBaseName() ); - entry::setWindowTitle(defaultWindow, title); - setWindowSize(defaultWindow, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT); + entry::setWindowTitle(kDefaultWindowHandle, title); + setWindowSize(kDefaultWindowHandle, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT); sortApps(); @@ -653,6 +679,8 @@ restart: bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse) { + bool needReset = s_reset != _reset; + s_debug = _debug; s_reset = _reset; @@ -739,7 +767,9 @@ restart: handle = size->m_handle; _width = size->m_width; _height = size->m_height; - _reset = !s_reset; // force reset + BX_TRACE("Window resize event: %d: %dx%d", handle, _width, _height); + + needReset = true; } break; @@ -752,7 +782,7 @@ restart: case Event::DropFile: { const DropFileEvent* drop = static_cast<const DropFileEvent*>(ev); - DBG("%s", drop->m_filePath.get() ); + DBG("%s", drop->m_filePath.getCPtr() ); } break; @@ -765,10 +795,13 @@ restart: } while (NULL != ev); + needReset |= _reset != s_reset; + if (handle.idx == 0 - && _reset != s_reset) + && needReset) { _reset = s_reset; + BX_TRACE("bgfx::reset(%d, %d, 0x%x)", _width, _height, _reset) bgfx::reset(_width, _height, _reset); inputSetMouseResolution(uint16_t(_width), uint16_t(_height) ); } @@ -783,6 +816,8 @@ restart: bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset) { + bool needReset = s_reset != _reset; + s_debug = _debug; s_reset = _reset; @@ -891,10 +926,8 @@ restart: win.m_handle = size->m_handle; win.m_width = size->m_width; win.m_height = size->m_height; - _reset = win.m_handle.idx == 0 - ? !s_reset - : _reset - ; // force reset + + needReset = win.m_handle.idx == 0 ? true : needReset; } break; @@ -943,9 +976,12 @@ restart: } } - if (_reset != s_reset) + needReset |= _reset != s_reset; + + if (needReset) { _reset = s_reset; + BX_TRACE("bgfx::reset(%d, %d, 0x%x)", s_window[0].m_width, s_window[0].m_height, _reset) bgfx::reset(s_window[0].m_width, s_window[0].m_height, _reset); inputSetMouseResolution(uint16_t(s_window[0].m_width), uint16_t(s_window[0].m_height) ); } @@ -994,3 +1030,18 @@ extern "C" bool entry_process_events(uint32_t* _width, uint32_t* _height, uint32 { return entry::processEvents(*_width, *_height, *_debug, *_reset, NULL); } + +extern "C" void* entry_get_default_native_window_handle() +{ + return entry::getNativeWindowHandle(entry::kDefaultWindowHandle); +} + +extern "C" void* entry_get_native_display_handle() +{ + return entry::getNativeDisplayHandle(); +} + +extern "C" bgfx::NativeWindowHandleType::Enum entry_get_native_window_handle_type() +{ + return entry::getNativeWindowHandleType(entry::kDefaultWindowHandle); +} diff --git a/3rdparty/bgfx/examples/common/entry/entry.h b/3rdparty/bgfx/examples/common/entry/entry.h index 75cbeb26ca3..443066e304f 100644 --- a/3rdparty/bgfx/examples/common/entry/entry.h +++ b/3rdparty/bgfx/examples/common/entry/entry.h @@ -1,12 +1,13 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef ENTRY_H_HEADER_GUARD #define ENTRY_H_HEADER_GUARD #include "dbg.h" +#include <bgfx/bgfx.h> #include <bx/bx.h> #include <bx/filepath.h> #include <bx/string.h> @@ -24,25 +25,31 @@ extern "C" int _main_(int _argc, char** _argv); #endif // ENTRY_CONFIG_IMPLEMENT_MAIN #if ENTRY_CONFIG_IMPLEMENT_MAIN -#define ENTRY_IMPLEMENT_MAIN(_app, _name, _description) \ +#define ENTRY_IMPLEMENT_MAIN(_app, ...) \ int _main_(int _argc, char** _argv) \ { \ - _app app(_name, _description); \ + _app app(__VA_ARGS__); \ return entry::runApp(&app, _argc, _argv); \ } #else -#define ENTRY_IMPLEMENT_MAIN(_app, _name, _description) \ - _app s_ ## _app ## App(_name, _description) +#define ENTRY_IMPLEMENT_MAIN(_app, ...) \ + _app s_ ## _app ## App(__VA_ARGS__) #endif // ENTRY_CONFIG_IMPLEMENT_MAIN +/// +#define ENTRY_HANDLE(_name) \ + struct _name { uint16_t idx; }; \ + inline bool isValid(_name _handle) { return UINT16_MAX != _handle.idx; } + namespace entry { - struct WindowHandle { uint16_t idx; }; - inline bool isValid(WindowHandle _handle) { return UINT16_MAX != _handle.idx; } + ENTRY_HANDLE(WindowHandle); + ENTRY_HANDLE(GamepadHandle); - struct GamepadHandle { uint16_t idx; }; - inline bool isValid(GamepadHandle _handle) { return UINT16_MAX != _handle.idx; } + /// + constexpr WindowHandle kDefaultWindowHandle = { 0 }; + /// struct MouseButton { enum Enum @@ -56,6 +63,7 @@ namespace entry }; }; + /// struct GamepadAxis { enum Enum @@ -71,6 +79,7 @@ namespace entry }; }; + /// struct Modifier { enum Enum @@ -87,6 +96,7 @@ namespace entry }; }; + /// struct Key { enum Enum @@ -198,6 +208,7 @@ namespace entry }; }; + /// struct Suspend { enum Enum @@ -211,8 +222,10 @@ namespace entry }; }; + /// const char* getName(Key::Enum _key); + /// struct MouseState { MouseState() @@ -232,6 +245,7 @@ namespace entry uint8_t m_buttons[entry::MouseButton::Count]; }; + /// struct GamepadState { GamepadState() @@ -242,22 +256,55 @@ namespace entry int32_t m_axis[entry::GamepadAxis::Count]; }; + /// bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse = NULL); + /// bx::FileReaderI* getFileReader(); + + /// bx::FileWriterI* getFileWriter(); + + /// bx::AllocatorI* getAllocator(); + /// WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags = ENTRY_WINDOW_FLAG_NONE, const char* _title = ""); + + /// void destroyWindow(WindowHandle _handle); + + /// void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y); + + /// void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height); + + /// void setWindowTitle(WindowHandle _handle, const char* _title); + + /// void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled); + + /// void toggleFullscreen(WindowHandle _handle); + + /// void setMouseLock(WindowHandle _handle, bool _lock); + + /// + void* getNativeWindowHandle(WindowHandle _handle); + + /// + void* getNativeDisplayHandle(); + + /// + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle); + + /// void setCurrentDir(const char* _dir); + /// struct WindowState { WindowState() @@ -276,13 +323,15 @@ namespace entry bx::FilePath m_dropFile; }; + /// bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset); + /// class BX_NO_VTABLE AppI { public: /// - AppI(const char* _name, const char* _description); + AppI(const char* _name, const char* _description, const char* _url = "https://bkaradzic.github.io/bgfx/index.html"); /// virtual ~AppI() = 0; @@ -303,13 +352,13 @@ namespace entry const char* getDescription() const; /// - AppI* getNext(); + const char* getUrl() const; - AppI* m_next; + /// + AppI* getNext(); private: - const char* m_name; - const char* m_description; + BX_ALIGN_DECL(16, uintptr_t) m_internal[4]; }; /// diff --git a/3rdparty/bgfx/examples/common/entry/entry_android.cpp b/3rdparty/bgfx/examples/common/entry/entry_android.cpp index 644ed4aca4c..a99735b6df5 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_android.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_android.cpp @@ -1,14 +1,12 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" #if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_ANDROID -#include <bgfx/platform.h> - #include <bx/thread.h> #include <bx/file.h> @@ -29,18 +27,6 @@ extern "C" namespace entry { - /// - inline void androidSetWindow(::ANativeWindow* _window) - { - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = _window; - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); - } - struct GamepadRemap { uint16_t m_keyCode; @@ -108,18 +94,18 @@ namespace entry virtual bool open(const bx::FilePath& _filePath, bx::Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, bx::kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } - m_file = AAssetManager_open(m_assetManager, _filePath.get(), AASSET_MODE_RANDOM); + m_file = AAssetManager_open(m_assetManager, _filePath.getCPtr(), AASSET_MODE_RANDOM); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file."); + BX_ERROR_SET(_err, bx::kErrorReaderWriterOpen, "FileReader: Failed to open file."); return false; } @@ -139,22 +125,22 @@ namespace entry virtual int64_t seek(int64_t _offset, bx::Whence::Enum _whence) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); return AAsset_seek64(m_file, _offset, _whence); } virtual int32_t read(void* _data, int32_t _size, bx::Error* _err) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = (int32_t)AAsset_read(m_file, _data, _size); if (size != _size) { if (0 == AAsset_getRemainingLength(m_file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF."); + BX_ERROR_SET(_err, bx::kErrorReaderWriterEof, "FileReader: EOF."); } return size >= 0 ? size : 0; @@ -197,8 +183,8 @@ namespace entry , 0 ); - const char* const argv[1] = { "android.so" }; - m_mte.m_argc = 1; + static const char* const argv[] = { "android.so" }; + m_mte.m_argc = BX_COUNTOF(argv); m_mte.m_argv = argv; while (0 == m_app->destroyRequested) @@ -233,7 +219,6 @@ namespace entry if (m_window != m_app->window) { m_window = m_app->window; - androidSetWindow(m_window); int32_t width = ANativeWindow_getWidth(m_window); int32_t height = ANativeWindow_getHeight(m_window); @@ -550,12 +535,33 @@ namespace entry BX_UNUSED(_handle, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + if (kDefaultWindowHandle.idx == _handle.idx) + { + return s_ctx.m_window; + } + + return NULL; + } + + void* getNativeDisplayHandle() + { + return NULL; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } + int32_t MainThreadEntry::threadFunc(bx::Thread* _thread, void* _userData) { BX_UNUSED(_thread); int32_t result = chdir("/sdcard/bgfx/examples/runtime"); - BX_CHECK(0 == result, "Failed to chdir to dir. android.permission.WRITE_EXTERNAL_STORAGE?", errno); + BX_ASSERT(0 == result, "Failed to chdir to dir. android.permission.WRITE_EXTERNAL_STORAGE?", errno); MainThreadEntry* self = (MainThreadEntry*)_userData; result = main(self->m_argc, self->m_argv); diff --git a/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp b/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp index 5e81dd9aece..4c699f23a5e 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -15,6 +15,7 @@ #endif // GLFW_VERSION_MINOR < 2 #if BX_PLATFORM_LINUX || BX_PLATFORM_BSD +# define GLFW_EXPOSE_NATIVE_WAYLAND # define GLFW_EXPOSE_NATIVE_X11 # define GLFW_EXPOSE_NATIVE_GLX #elif BX_PLATFORM_OSX @@ -40,7 +41,14 @@ namespace entry static void* glfwNativeWindowHandle(GLFWwindow* _window) { # if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - return (void*)(uintptr_t)glfwGetX11Window(_window); + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) + { + return glfwGetWaylandWindow(_window); + } + else + { + return (void*)(uintptr_t)glfwGetX11Window(_window); + } # elif BX_PLATFORM_OSX return glfwGetCocoaWindow(_window); # elif BX_PLATFORM_WINDOWS @@ -48,23 +56,6 @@ namespace entry # endif // BX_PLATFORM_ } - static void glfwSetWindow(GLFWwindow* _window) - { - bgfx::PlatformData pd; -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - pd.ndt = glfwGetX11Display(); -# elif BX_PLATFORM_OSX - pd.ndt = NULL; -# elif BX_PLATFORM_WINDOWS - pd.ndt = NULL; -# endif // BX_PLATFORM_WINDOWS - pd.nwh = glfwNativeWindowHandle(_window); - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); - } - static uint8_t translateKeyModifiers(int _glfw) { uint8_t modifiers = 0; @@ -412,29 +403,28 @@ namespace entry glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); WindowHandle handle = { m_windowAlloc.alloc() }; - m_windows[0] = glfwCreateWindow(ENTRY_DEFAULT_WIDTH + m_window[0] = glfwCreateWindow(ENTRY_DEFAULT_WIDTH , ENTRY_DEFAULT_HEIGHT , "bgfx" , NULL , NULL ); - if (!m_windows[0]) + if (!m_window[0]) { DBG("glfwCreateWindow failed!"); glfwTerminate(); return bx::kExitFailure; } - glfwSetKeyCallback(m_windows[0], keyCb); - glfwSetCharCallback(m_windows[0], charCb); - glfwSetScrollCallback(m_windows[0], scrollCb); - glfwSetCursorPosCallback(m_windows[0], cursorPosCb); - glfwSetMouseButtonCallback(m_windows[0], mouseButtonCb); - glfwSetWindowSizeCallback(m_windows[0], windowSizeCb); - glfwSetDropCallback(m_windows[0], dropFileCb); + glfwSetKeyCallback(m_window[0], keyCb); + glfwSetCharCallback(m_window[0], charCb); + glfwSetScrollCallback(m_window[0], scrollCb); + glfwSetCursorPosCallback(m_window[0], cursorPosCb); + glfwSetMouseButtonCallback(m_window[0], mouseButtonCb); + glfwSetWindowSizeCallback(m_window[0], windowSizeCb); + glfwSetDropCallback(m_window[0], dropFileCb); - glfwSetWindow(m_windows[0]); m_eventQueue.postSizeEvent(handle, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT); for (uint32_t ii = 0; ii < ENTRY_CONFIG_MAX_GAMEPADS; ++ii) @@ -451,10 +441,10 @@ namespace entry m_thread.init(MainThreadEntry::threadFunc, &m_mte); - while (NULL != m_windows[0] - && !glfwWindowShouldClose(m_windows[0])) + while (NULL != m_window[0] + && !glfwWindowShouldClose(m_window[0])) { - glfwWaitEvents(); + glfwWaitEventsTimeout(0.016); for (uint32_t ii = 0; ii < ENTRY_CONFIG_MAX_GAMEPADS; ++ii) { @@ -494,7 +484,7 @@ namespace entry glfwSetWindowSizeCallback(window, windowSizeCb); glfwSetDropCallback(window, dropFileCb); - m_windows[msg->m_handle.idx] = window; + m_window[msg->m_handle.idx] = window; m_eventQueue.postSizeEvent(msg->m_handle, msg->m_width, msg->m_height); m_eventQueue.postWindowEvent(msg->m_handle, glfwNativeWindowHandle(window)); } @@ -504,31 +494,31 @@ namespace entry { if (isValid(msg->m_handle) ) { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; m_eventQueue.postWindowEvent(msg->m_handle); glfwDestroyWindow(window); - m_windows[msg->m_handle.idx] = NULL; + m_window[msg->m_handle.idx] = NULL; } } break; case GLFW_WINDOW_SET_TITLE: { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; glfwSetWindowTitle(window, msg->m_title.c_str()); } break; case GLFW_WINDOW_SET_POS: { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; glfwSetWindowPos(window, msg->m_x, msg->m_y); } break; case GLFW_WINDOW_SET_SIZE: { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; glfwSetWindowSize(window, msg->m_width, msg->m_height); } break; @@ -541,7 +531,7 @@ namespace entry case GLFW_WINDOW_TOGGLE_FULL_SCREEN: { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; if (glfwGetWindowMonitor(window) ) { glfwSetWindowMonitor(window @@ -578,7 +568,7 @@ namespace entry case GLFW_WINDOW_MOUSE_LOCK: { - GLFWwindow* window = m_windows[msg->m_handle.idx]; + GLFWwindow* window = m_window[msg->m_handle.idx]; if (msg->m_value) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); @@ -598,7 +588,7 @@ namespace entry m_eventQueue.postExitEvent(); m_thread.shutdown(); - glfwDestroyWindow(m_windows[0]); + glfwDestroyWindow(m_window[0]); glfwTerminate(); return m_thread.getExitCode(); @@ -610,7 +600,7 @@ namespace entry for (uint32_t ii = 0, num = m_windowAlloc.getNumHandles(); ii < num; ++ii) { uint16_t idx = m_windowAlloc.getHandleAt(ii); - if (_window == m_windows[idx]) + if (_window == m_window[idx]) { WindowHandle handle = { idx }; return handle; @@ -635,7 +625,7 @@ namespace entry EventQueue m_eventQueue; bx::Mutex m_lock; - GLFWwindow* m_windows[ENTRY_CONFIG_MAX_WINDOWS]; + GLFWwindow* m_window[ENTRY_CONFIG_MAX_WINDOWS]; bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc; GamepadGLFW m_gamepad[ENTRY_CONFIG_MAX_GAMEPADS]; @@ -758,13 +748,11 @@ namespace entry const Event* poll() { - glfwPostEmptyEvent(); return s_ctx.m_eventQueue.poll(); } const Event* poll(WindowHandle _handle) { - glfwPostEmptyEvent(); return s_ctx.m_eventQueue.poll(_handle); } @@ -784,7 +772,6 @@ namespace entry msg->m_title = _title; msg->m_handle.idx = s_ctx.m_windowAlloc.alloc(); s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); return msg->m_handle; } @@ -793,7 +780,6 @@ namespace entry Msg* msg = new Msg(GLFW_WINDOW_DESTROY); msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); } void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) @@ -803,7 +789,6 @@ namespace entry msg->m_y = _y; msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); } void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) @@ -813,7 +798,6 @@ namespace entry msg->m_height = _height; msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); } void setWindowTitle(WindowHandle _handle, const char* _title) @@ -822,7 +806,6 @@ namespace entry msg->m_title = _title; msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); } void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled) @@ -835,7 +818,6 @@ namespace entry Msg* msg = new Msg(GLFW_WINDOW_TOGGLE_FULL_SCREEN); msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); } void setMouseLock(WindowHandle _handle, bool _lock) @@ -844,7 +826,43 @@ namespace entry msg->m_value = _lock; msg->m_handle = _handle; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); + } + + void* getNativeWindowHandle(WindowHandle _handle) + { + return glfwNativeWindowHandle(s_ctx.m_window[_handle.idx]); + } + + void* getNativeDisplayHandle() + { +# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) + { + return glfwGetWaylandDisplay(); + } + else + { + return glfwGetX11Display(); + } +# else + return NULL; +# endif // BX_PLATFORM_* + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { +# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) + { + return bgfx::NativeWindowHandleType::Wayland; + } + else + { + return bgfx::NativeWindowHandleType::Default; + } +# else + return bgfx::NativeWindowHandleType::Default; +# endif // BX_PLATFORM_* } int32_t MainThreadEntry::threadFunc(bx::Thread* _thread, void* _userData) @@ -858,7 +876,6 @@ namespace entry Msg* msg = new Msg(GLFW_WINDOW_DESTROY); msg->m_handle.idx = 0; s_ctx.m_msgs.push(msg); - glfwPostEmptyEvent(); return result; } diff --git a/3rdparty/bgfx/examples/common/entry/entry_asmjs.cpp b/3rdparty/bgfx/examples/common/entry/entry_html5.cpp index 4434e41c9e6..d33879229f9 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_asmjs.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_html5.cpp @@ -1,12 +1,14 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" #if BX_PLATFORM_EMSCRIPTEN +#include <bgfx/platform.h> + #include <emscripten.h> #include <emscripten/html5.h> @@ -15,10 +17,17 @@ extern "C" void entry_emscripten_yield() // emscripten_sleep(0); } +#define _EMSCRIPTEN_CHECK(_check, _call) \ + BX_MACRO_BLOCK_BEGIN \ + EMSCRIPTEN_RESULT __result__ = _call; \ + _check(EMSCRIPTEN_RESULT_SUCCESS == __result__, #_call " FAILED 0x%08x\n", (uint32_t)__result__); \ + BX_UNUSED(__result__); \ + BX_MACRO_BLOCK_END + +#define EMSCRIPTEN_CHECK(_call) _EMSCRIPTEN_CHECK(BX_ASSERT, _call) + namespace entry { - static WindowHandle s_defaultWindow = { 0 }; - static uint8_t s_translateKey[256]; struct Context @@ -88,17 +97,19 @@ namespace entry int32_t run(int _argc, const char* const* _argv) { - emscripten_set_mousedown_callback("#canvas", this, true, mouseCb); - emscripten_set_mouseup_callback("#canvas", this, true, mouseCb); - emscripten_set_mousemove_callback("#canvas", this, true, mouseCb); + static const char* canvas = "#canvas"; + + EMSCRIPTEN_CHECK(emscripten_set_mousedown_callback(canvas, this, true, mouseCb) ); + EMSCRIPTEN_CHECK(emscripten_set_mouseup_callback(canvas, this, true, mouseCb) ); + EMSCRIPTEN_CHECK(emscripten_set_mousemove_callback(canvas, this, true, mouseCb) ); - emscripten_set_wheel_callback("#canvas", this, true, wheelCb); + EMSCRIPTEN_CHECK(emscripten_set_wheel_callback(canvas, this, true, wheelCb) ); - emscripten_set_keypress_callback(NULL, this, true, keyCb); - emscripten_set_keydown_callback(NULL, this, true, keyCb); - emscripten_set_keyup_callback(NULL, this, true, keyCb); + EMSCRIPTEN_CHECK(emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, keyCb) ); + EMSCRIPTEN_CHECK(emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, keyCb) ); + EMSCRIPTEN_CHECK(emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, keyCb) ); - emscripten_set_resize_callback(0, this, true, resizeCb); + EMSCRIPTEN_CHECK(emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, resizeCb) ); EmscriptenFullscreenStrategy fullscreenStrategy = {}; fullscreenStrategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT; @@ -107,11 +118,11 @@ namespace entry fullscreenStrategy.canvasResizedCallback = canvasResizeCb; fullscreenStrategy.canvasResizedCallbackUserData = this; - emscripten_request_fullscreen_strategy("#canvas", false, &fullscreenStrategy); + EMSCRIPTEN_CHECK(emscripten_request_fullscreen_strategy(canvas, false, &fullscreenStrategy) ); - emscripten_set_focus_callback(NULL, this, true, focusCb); - emscripten_set_focusin_callback(NULL, this, true, focusCb); - emscripten_set_focusout_callback(NULL, this, true, focusCb); + EMSCRIPTEN_CHECK(emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, focusCb) ); + EMSCRIPTEN_CHECK(emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, focusCb) ); + EMSCRIPTEN_CHECK(emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, this, true, focusCb) ); int32_t result = main(_argc, _argv); return result; @@ -134,51 +145,58 @@ namespace entry static Context s_ctx; - EM_BOOL Context::mouseCb(int eventType, const EmscriptenMouseEvent* event, void* userData) + EM_BOOL Context::mouseCb(int32_t _eventType, const EmscriptenMouseEvent* _event, void* _userData) { - BX_UNUSED(userData); + BX_UNUSED(_userData); - if (event) + if (_event) { - switch (eventType) + switch (_eventType) { case EMSCRIPTEN_EVENT_MOUSEMOVE: - { - s_ctx.m_mx = event->canvasX; - s_ctx.m_my = event->canvasY; - s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll); + s_ctx.m_mx = _event->targetX; + s_ctx.m_my = _event->targetY; + s_ctx.m_eventQueue.postMouseEvent(kDefaultWindowHandle, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll); return true; - } + case EMSCRIPTEN_EVENT_MOUSEDOWN: case EMSCRIPTEN_EVENT_MOUSEUP: case EMSCRIPTEN_EVENT_DBLCLICK: - { - s_ctx.m_mx = event->canvasX; - s_ctx.m_my = event->canvasY; - MouseButton::Enum mb = (event->button == 2) ? MouseButton::Right : ((event->button == 1) ? MouseButton::Middle : MouseButton::Left); - s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll, mb, (eventType != EMSCRIPTEN_EVENT_MOUSEUP)); + s_ctx.m_mx = _event->targetX; + s_ctx.m_my = _event->targetY; + MouseButton::Enum mb = _event->button == 2 + ? MouseButton::Right : ( (_event->button == 1) + ? MouseButton::Middle : MouseButton::Left) + ; + s_ctx.m_eventQueue.postMouseEvent( + kDefaultWindowHandle + , s_ctx.m_mx + , s_ctx.m_my + , s_ctx.m_scroll + , mb + , (_eventType != EMSCRIPTEN_EVENT_MOUSEUP) + ); return true; - } } } return false; } - EM_BOOL Context::wheelCb(int eventType, const EmscriptenWheelEvent* event, void* userData) + EM_BOOL Context::wheelCb(int32_t _eventType, const EmscriptenWheelEvent* _event, void* _userData) { - BX_UNUSED(userData); + BX_UNUSED(_userData); - if (event) + if (_event) { - switch (eventType) + switch (_eventType) { case EMSCRIPTEN_EVENT_WHEEL: { - s_ctx.m_scrollf += event->deltaY; + s_ctx.m_scrollf += _event->deltaY; s_ctx.m_scroll = (int32_t)s_ctx.m_scrollf; - s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll); + s_ctx.m_eventQueue.postMouseEvent(kDefaultWindowHandle, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll); return true; } } @@ -187,83 +205,90 @@ namespace entry return false; } - uint8_t translateModifiers(const EmscriptenKeyboardEvent* event) + uint8_t translateModifiers(const EmscriptenKeyboardEvent* _event) { uint8_t mask = 0; - if (event->shiftKey) + if (_event->shiftKey) + { mask |= Modifier::LeftShift | Modifier::RightShift; + } - if (event->altKey) + if (_event->altKey) + { mask |= Modifier::LeftAlt | Modifier::RightAlt; + } - if (event->ctrlKey) + if (_event->ctrlKey) + { mask |= Modifier::LeftCtrl | Modifier::RightCtrl; + } - if (event->metaKey) + if (_event->metaKey) + { mask |= Modifier::LeftMeta | Modifier::RightMeta; + } return mask; } - Key::Enum handleKeyEvent(const EmscriptenKeyboardEvent* event, uint8_t* specialKeys, uint8_t* _pressedChar) + Key::Enum handleKeyEvent(const EmscriptenKeyboardEvent* _event, uint8_t* _specialKeys, uint8_t* _pressedChar) { - *_pressedChar = (uint8_t)event->keyCode; + *_pressedChar = uint8_t(_event->keyCode); - int keyCode = (int)event->keyCode; - *specialKeys = translateModifiers(event); + int32_t keyCode = int32_t(_event->keyCode); + *_specialKeys = translateModifiers(_event); - if (event->charCode == 0) + if (_event->charCode == 0) { switch (keyCode) { - case 112: return Key::F1; - case 113: return Key::F2; - case 114: return Key::F3; - case 115: return Key::F4; - case 116: return Key::F5; - case 117: return Key::F6; - case 118: return Key::F7; - case 119: return Key::F8; - case 120: return Key::F9; - case 121: return Key::F10; - case 122: return Key::F11; - case 123: return Key::F12; - - case 37: return Key::Left; - case 39: return Key::Right; - case 38: return Key::Up; - case 40: return Key::Down; + case 112: return Key::F1; + case 113: return Key::F2; + case 114: return Key::F3; + case 115: return Key::F4; + case 116: return Key::F5; + case 117: return Key::F6; + case 118: return Key::F7; + case 119: return Key::F8; + case 120: return Key::F9; + case 121: return Key::F10; + case 122: return Key::F11; + case 123: return Key::F12; + + case 37: return Key::Left; + case 39: return Key::Right; + case 38: return Key::Up; + case 40: return Key::Down; } } // if this is a unhandled key just return None if (keyCode < 256) { - return (Key::Enum)s_translateKey[keyCode]; + return Key::Enum(s_translateKey[keyCode]); } return Key::None; } - EM_BOOL Context::keyCb(int eventType, const EmscriptenKeyboardEvent *event, void *userData) + EM_BOOL Context::keyCb(int32_t _eventType, const EmscriptenKeyboardEvent* _event, void* _userData) { - BX_UNUSED(userData); + BX_UNUSED(_userData); - if (event) + if (_event) { uint8_t modifiers = 0; uint8_t pressedChar[4]; - Key::Enum key = handleKeyEvent(event, &modifiers, &pressedChar[0]); + Key::Enum key = handleKeyEvent(_event, &modifiers, &pressedChar[0]); // Returning true means that we take care of the key (instead of the default behavior) if (key != Key::None) { - switch (eventType) + switch (_eventType) { case EMSCRIPTEN_EVENT_KEYPRESS: case EMSCRIPTEN_EVENT_KEYDOWN: - { if (key == Key::KeyQ && (modifiers & Modifier::RightMeta) ) { s_ctx.m_eventQueue.postExitEvent(); @@ -271,17 +296,15 @@ namespace entry else { enum { ShiftMask = Modifier::LeftShift|Modifier::RightShift }; - s_ctx.m_eventQueue.postCharEvent(s_defaultWindow, 1, pressedChar); - s_ctx.m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, true); + s_ctx.m_eventQueue.postCharEvent(kDefaultWindowHandle, 1, pressedChar); + s_ctx.m_eventQueue.postKeyEvent(kDefaultWindowHandle, key, modifiers, true); return true; } break; - } + case EMSCRIPTEN_EVENT_KEYUP: - { - s_ctx.m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, false); + s_ctx.m_eventQueue.postKeyEvent(kDefaultWindowHandle, key, modifiers, false); return true; - } } } @@ -289,47 +312,41 @@ namespace entry return false; } - EM_BOOL Context::resizeCb(int eventType, const EmscriptenUiEvent* event, void* userData) + EM_BOOL Context::resizeCb(int32_t _eventType, const EmscriptenUiEvent* _event, void* _userData) { - BX_UNUSED(eventType, event, userData); + BX_UNUSED(_eventType, _event, _userData); return false; } - EM_BOOL Context::canvasResizeCb(int eventType, const void* reserved, void* userData) + EM_BOOL Context::canvasResizeCb(int32_t _eventType, const void* _reserved, void* _userData) { - BX_UNUSED(eventType, reserved, userData); + BX_UNUSED(_eventType, _reserved, _userData); return false; } - EM_BOOL Context::focusCb(int eventType, const EmscriptenFocusEvent* event, void* userData) + EM_BOOL Context::focusCb(int32_t _eventType, const EmscriptenFocusEvent* _event, void* _userData) { - printf("focusCb %d", eventType); - BX_UNUSED(event, userData); + BX_UNUSED(_event, _userData); - if (event) + if (_event) { - switch (eventType) + switch (_eventType) { case EMSCRIPTEN_EVENT_BLUR: - { - s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend); + s_ctx.m_eventQueue.postSuspendEvent(kDefaultWindowHandle, Suspend::DidSuspend); return true; - } + case EMSCRIPTEN_EVENT_FOCUS: - { - s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume); + s_ctx.m_eventQueue.postSuspendEvent(kDefaultWindowHandle, Suspend::DidResume); return true; - } + case EMSCRIPTEN_EVENT_FOCUSIN: - { - s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume); + s_ctx.m_eventQueue.postSuspendEvent(kDefaultWindowHandle, Suspend::WillResume); return true; - } + case EMSCRIPTEN_EVENT_FOCUSOUT: - { - s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend); + s_ctx.m_eventQueue.postSuspendEvent(kDefaultWindowHandle, Suspend::WillSuspend); return true; - } } } @@ -395,6 +412,27 @@ namespace entry { BX_UNUSED(_handle, _lock); } + + void* getNativeWindowHandle(WindowHandle _handle) + { + if (kDefaultWindowHandle.idx == _handle.idx) + { + return (void*)"#canvas"; + } + + return NULL; + } + + void* getNativeDisplayHandle() + { + return NULL; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } } int main(int _argc, const char* const* _argv) diff --git a/3rdparty/bgfx/examples/common/entry/entry_ios.mm b/3rdparty/bgfx/examples/common/entry/entry_ios.mm index 569e99f51bd..8592a33c43e 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_ios.mm +++ b/3rdparty/bgfx/examples/common/entry/entry_ios.mm @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -14,7 +14,7 @@ #if __IPHONE_8_0 && !TARGET_IPHONE_SIMULATOR // check if sdk/target supports metal # import <Metal/Metal.h> # import <QuartzCore/CAMetalLayer.h> -//# define HAS_METAL_SDK +# define HAS_METAL_SDK #endif #include <bgfx/platform.h> @@ -38,8 +38,8 @@ namespace entry { Context(uint32_t _width, uint32_t _height) { - const char* const argv[1] = { "ios" }; - m_mte.m_argc = 1; + static const char* const argv[] = { "ios" }; + m_mte.m_argc = BX_COUNTOF(argv); m_mte.m_argv = argv; m_eventQueue.postSizeEvent(s_defaultWindow, _width, _height); @@ -57,6 +57,7 @@ namespace entry MainThreadEntry m_mte; bx::Thread m_thread; + void* m_window; EventQueue m_eventQueue; }; @@ -145,16 +146,31 @@ namespace entry BX_UNUSED(_handle, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + if (kDefaultWindowHandle.idx == _handle.idx) + { + return s_ctx.m_window; + } + + return NULL; + } + + void* getNativeDisplayHandle() + { + return NULL; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } + } // namespace entry using namespace entry; -#ifdef HAS_METAL_SDK -static id<MTLDevice> m_device = NULL; -#else -static void* m_device = NULL; -#endif - @interface ViewController : UIViewController @end @implementation ViewController @@ -177,13 +193,14 @@ static void* m_device = NULL; + (Class)layerClass { #ifdef HAS_METAL_SDK + static id<MTLDevice> device = NULL; Class metalClass = NSClassFromString(@"CAMetalLayer"); //is metal runtime sdk available if ( metalClass != nil) { - m_device = MTLCreateSystemDefaultDevice(); // is metal supported on this device (is there a better way to do this - without creating device ?) - if (m_device) + device = MTLCreateSystemDefaultDevice(); // is metal supported on this device (is there a better way to do this - without creating device ?) + if (NULL != device) { - [m_device retain]; + [device retain]; return metalClass; } } @@ -201,13 +218,7 @@ static void* m_device = NULL; return nil; } - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = self.layer; - pd.context = m_device; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); + s_ctx->m_window = self.layer; return self; } @@ -226,7 +237,7 @@ static void* m_device = NULL; m_displayLink = [self.window.screen displayLinkWithTarget:self selector:@selector(renderFrame)]; //[m_displayLink setFrameInterval:1]; //[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - // [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop]]; + //[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop]]; [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; } } diff --git a/3rdparty/bgfx/examples/common/entry/entry_noop.cpp b/3rdparty/bgfx/examples/common/entry/entry_noop.cpp index a7157d77ef2..5e4bb0fafa4 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_noop.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_noop.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -67,6 +67,23 @@ namespace entry BX_UNUSED(_handle, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + BX_UNUSED(_handle); + return NULL; + } + + void* getNativeDisplayHandle() + { + return NULL; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } + } // namespace entry int main(int _argc, const char* const* _argv) diff --git a/3rdparty/bgfx/examples/common/entry/entry_osx.mm b/3rdparty/bgfx/examples/common/entry/entry_osx.mm index 9bd53fb1362..98869d7df04 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_osx.mm +++ b/3rdparty/bgfx/examples/common/entry/entry_osx.mm @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -30,7 +30,6 @@ @interface Window : NSObject<NSWindowDelegate> { - uint32_t windowCount; } + (Window*)sharedDelegate; @@ -46,18 +45,6 @@ namespace entry { - /// - inline void osxSetNSWindow(void* _window, void* _nsgl = NULL) - { - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = _window; - pd.context = _nsgl; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); - } - static uint8_t s_translateKey[256]; struct MainThreadEntry @@ -86,21 +73,22 @@ namespace entry } MainThreadEntry* self = (MainThreadEntry*)_userData; - return main(self->m_argc, self->m_argv); + uint32_t result = main(self->m_argc, self->m_argv); + [NSApp terminate:nil]; + return result; } }; struct Context { Context() - : m_windowsCreated(0) - , m_scrollf(0.0f) + : m_scrollf(0.0f) , m_mx(0) , m_my(0) , m_scroll(0) , m_style(0) , m_exit(false) - , m_fullscreen(false) + , m_mouseLock(NULL) { s_translateKey[27] = Key::Esc; s_translateKey[uint8_t('\r')] = Key::Return; @@ -151,6 +139,11 @@ namespace entry s_translateKey[uint8_t(ch)] = s_translateKey[uint8_t(ch - ' ')] = Key::KeyA + (ch - 'a'); } + + for(int ii=0; ii<ENTRY_CONFIG_MAX_WINDOWS; ++ii) + { + m_window[ii] = NULL; + } } NSEvent* waitEvent() @@ -190,13 +183,54 @@ namespace entry *outY = bx::clamp(y, 0, int32_t(adjustFrame.size.height) ); } + void setMousePos(NSWindow* _window, int _x, int _y) + { + NSRect originalFrame = [_window frame]; + NSRect adjustFrame = [_window contentRectForFrameRect: originalFrame]; + + adjustFrame.origin.y = NSMaxY(NSScreen.screens[0].frame) - NSMaxY(adjustFrame); + + CGWarpMouseCursorPosition(CGPointMake(_x + adjustFrame.origin.x, _y + adjustFrame.origin.y)); + CGAssociateMouseAndMouseCursorPosition(YES); + } + + void setMouseLock(NSWindow* _window, bool _lock) + { + NSWindow* newMouseLock = _lock ? _window : NULL; + + if ( m_mouseLock != newMouseLock ) + { + if ( _lock ) + { + NSRect originalFrame = [_window frame]; + NSRect adjustFrame = [_window contentRectForFrameRect: originalFrame]; + + m_cmx = (int)adjustFrame.size.width / 2; + m_cmy = (int)adjustFrame.size.height / 2; + + setMousePos(_window, m_cmx, m_cmy); + [NSCursor hide]; + } + else + { + [NSCursor unhide]; + } + m_mouseLock = newMouseLock; + } + } + + uint8_t translateModifiers(int flags) { return 0 - | (0 != (flags & NSEventModifierFlagShift ) ) ? Modifier::LeftShift | Modifier::RightShift : 0 - | (0 != (flags & NSEventModifierFlagOption ) ) ? Modifier::LeftAlt | Modifier::RightAlt : 0 - | (0 != (flags & NSEventModifierFlagControl) ) ? Modifier::LeftCtrl | Modifier::RightCtrl : 0 - | (0 != (flags & NSEventModifierFlagCommand) ) ? Modifier::LeftMeta | Modifier::RightMeta : 0 + | ( (0 != (flags & NX_DEVICELSHIFTKEYMASK) ) ? Modifier::LeftShift : 0) + | ( (0 != (flags & NX_DEVICERSHIFTKEYMASK) ) ? Modifier::RightShift : 0) + | ( (0 != (flags & NX_DEVICELALTKEYMASK) ) ? Modifier::LeftAlt : 0) + | ( (0 != (flags & NX_DEVICERALTKEYMASK) ) ? Modifier::RightAlt : 0) + | ( (0 != (flags & NX_DEVICELCTLKEYMASK) ) ? Modifier::LeftCtrl : 0) + | ( (0 != (flags & NX_DEVICERCTLKEYMASK) ) ? Modifier::RightCtrl : 0) + | ( (0 != (flags & NX_DEVICELCMDKEYMASK) ) ? Modifier::LeftMeta : 0) + | ( (0 != (flags & NX_DEVICERCMDKEYMASK) ) ? Modifier::RightMeta : 0) ; } @@ -258,8 +292,18 @@ namespace entry { NSEventType eventType = [event type]; - NSWindow *window = [NSApp keyWindow]; - WindowHandle handle = handleFromWindow(window); + NSWindow *window = [event window]; + WindowHandle handle = {UINT16_MAX}; + if (nil != window) + { + handle = findHandle(window); + } + if (!isValid(handle)) + { + [NSApp sendEvent:event]; + [NSApp updateWindows]; + return true; + } switch (eventType) { @@ -268,6 +312,15 @@ namespace entry case NSEventTypeRightMouseDragged: case NSEventTypeOtherMouseDragged: getMousePos(window, &m_mx, &m_my); + + if (window == m_mouseLock) + { + m_mx -= m_cmx; + m_my -= m_cmy; + + setMousePos(window, m_cmx, m_cmy); + } + m_eventQueue.postMouseEvent(handle, m_mx, m_my, m_scroll); break; @@ -367,7 +420,7 @@ namespace entry void windowDidResize(NSWindow *window) { - WindowHandle handle = handleFromWindow(window); + WindowHandle handle = findHandle(window); NSRect originalFrame = [window frame]; NSRect rect = [window contentRectForFrameRect: originalFrame]; uint32_t width = uint32_t(rect.size.width); @@ -381,14 +434,14 @@ namespace entry void windowDidBecomeKey(NSWindow *window) { - WindowHandle handle = handleFromWindow(window); + WindowHandle handle = findHandle(window); m_eventQueue.postSuspendEvent(handle, Suspend::WillResume); m_eventQueue.postSuspendEvent(handle, Suspend::DidResume); } void windowDidResignKey(NSWindow *window) { - WindowHandle handle = handleFromWindow(window); + WindowHandle handle = findHandle(window); m_eventQueue.postSuspendEvent(handle, Suspend::WillSuspend); m_eventQueue.postSuspendEvent(handle, Suspend::DidSuspend); } @@ -442,8 +495,6 @@ namespace entry m_windowFrame = [m_window[0] frame]; - osxSetNSWindow(m_window[0]); - MainThreadEntry mte; mte.m_argc = _argc; mte.m_argv = _argv; @@ -459,13 +510,13 @@ namespace entry while (!(m_exit = [dg applicationHasTerminated]) ) { - @autoreleasepool - { - bgfx::renderFrame(); - } + bgfx::renderFrame(); - while (dispatchEvent(peekEvent() ) ) + @autoreleasepool { + while (dispatchEvent(peekEvent() ) ) + { + } } } @@ -477,31 +528,28 @@ namespace entry return 0; } - bool isValid(WindowHandle _handle) + WindowHandle findHandle(NSWindow *_window) { - return m_windowAlloc.isValid(_handle.idx); - } - - WindowHandle handleFromWindow(NSWindow *window) - { - uint16_t windowIdx = 0; - for (uint16_t i = 0; i < m_windowsCreated; i++) + bx::MutexScope scope(m_lock); + for (uint16_t ii = 0, num = m_windowAlloc.getNumHandles(); ii < num; ++ii) { - if (window == m_window[i]) + uint16_t idx = m_windowAlloc.getHandleAt(ii); + if (_window == m_window[idx]) { - windowIdx = i; - break; + WindowHandle handle = { idx }; + return handle; } } - WindowHandle handle = { windowIdx }; - return handle; + + WindowHandle invalid = { UINT16_MAX }; + return invalid; } EventQueue m_eventQueue; + bx::Mutex m_lock; bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc; NSWindow* m_window[ENTRY_CONFIG_MAX_WINDOWS]; - SInt32 m_windowsCreated; NSRect m_windowFrame; float m_scrollf; @@ -510,7 +558,10 @@ namespace entry int32_t m_scroll; int32_t m_style; bool m_exit; - bool m_fullscreen; + + NSWindow* m_mouseLock; + int32_t m_cmx; + int32_t m_cmy; }; static Context s_ctx; @@ -534,104 +585,111 @@ namespace entry { BX_UNUSED(_flags); - uint16_t handleIdx = IncrementAtomic(&s_ctx.m_windowsCreated); + bx::MutexScope scope(s_ctx.m_lock); + WindowHandle handle = { s_ctx.m_windowAlloc.alloc() }; - if (handleIdx >= ENTRY_CONFIG_MAX_WINDOWS) + if (UINT16_MAX != handle.idx) { - return { UINT16_MAX }; - } + void (^createWindowBlock)(void) = ^(void) { + NSRect rect = NSMakeRect(_x, _y, _width, _height); + NSWindow* window = [ + [NSWindow alloc] + initWithContentRect:rect + styleMask:s_ctx.m_style + backing:NSBackingStoreBuffered defer:NO + ]; + NSString* appName = [NSString stringWithUTF8String:_title]; + [window setTitle:appName]; + [window makeKeyAndOrderFront:window]; + [window setAcceptsMouseMovedEvents:YES]; + [window setBackgroundColor:[NSColor blackColor]]; + [[Window sharedDelegate] windowCreated:window]; + + s_ctx.m_window[handle.idx] = window; - WindowHandle handle = { handleIdx }; - - void (^createWindowBlock)(void) = ^(void) { - s_ctx.m_windowAlloc.alloc(); - NSRect rect = NSMakeRect(_x, _y, _width, _height); - NSWindow* window = [[NSWindow alloc] - initWithContentRect:rect - styleMask:s_ctx.m_style - backing:NSBackingStoreBuffered defer:NO - ]; - NSString* appName = [NSString stringWithUTF8String:_title]; - [window setTitle:appName]; - [window makeKeyAndOrderFront:window]; - [window setAcceptsMouseMovedEvents:YES]; - [window setBackgroundColor:[NSColor blackColor]]; - [[Window sharedDelegate] windowCreated:window]; - - s_ctx.m_window[handleIdx] = window; - - if(s_ctx.m_windowsCreated > 1) - { s_ctx.m_eventQueue.postSizeEvent(handle, _width, _height); s_ctx.m_eventQueue.postWindowEvent(handle, window); - } - }; + }; - if ([NSThread isMainThread]) - { - createWindowBlock(); - } - else - { - dispatch_async(dispatch_get_main_queue(), createWindowBlock); + if ([NSThread isMainThread]) + { + createWindowBlock(); + } + else + { + dispatch_async(dispatch_get_main_queue(), createWindowBlock); + } } return handle; } - void destroyWindow(WindowHandle _handle) + void destroyWindow(WindowHandle _handle, bool _closeWindow) { - if (s_ctx.isValid(_handle) ) + if (isValid(_handle)) { dispatch_async(dispatch_get_main_queue() - , ^{ - [s_ctx.m_window[_handle.idx] performClose: nil]; - }); + , ^(void){ + NSWindow *window = s_ctx.m_window[_handle.idx]; + if ( NULL != window) + { + s_ctx.m_eventQueue.postWindowEvent(_handle); + s_ctx.m_window[_handle.idx] = NULL; + if ( _closeWindow ) + { + [window close]; + } + + if (0 == _handle.idx) + { + [NSApp terminate:nil]; + } + } + }); + + bx::MutexScope scope(s_ctx.m_lock); + s_ctx.m_windowAlloc.free(_handle.idx); } } + void destroyWindow(WindowHandle _handle) + { + destroyWindow(_handle, true); + } + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) { - if (s_ctx.isValid(_handle) ) - { - NSWindow* window = s_ctx.m_window[_handle.idx]; - NSScreen* screen = [window screen]; + dispatch_async(dispatch_get_main_queue() + , ^{ + NSWindow* window = s_ctx.m_window[_handle.idx]; + NSScreen* screen = [window screen]; - NSRect screenRect = [screen frame]; - CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + NSRect screenRect = [screen frame]; + CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - NSPoint position = { float(_x), screenRect.size.height - menuBarHeight - float(_y) }; + NSPoint position = { float(_x), screenRect.size.height - menuBarHeight - float(_y) }; - dispatch_async(dispatch_get_main_queue() - , ^{ [window setFrameTopLeftPoint: position]; }); - } } void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { - if (s_ctx.isValid(_handle) ) - { - NSSize size = { float(_width), float(_height) }; - dispatch_async(dispatch_get_main_queue() + NSSize size = { float(_width), float(_height) }; + dispatch_async(dispatch_get_main_queue() , ^{ [s_ctx.m_window[_handle.idx] setContentSize: size]; }); - } } void setWindowTitle(WindowHandle _handle, const char* _title) { - if (s_ctx.isValid(_handle) ) - { - NSString* title = [[NSString alloc] initWithCString:_title encoding:1]; - dispatch_async(dispatch_get_main_queue() + NSString* title = [[NSString alloc] initWithCString:_title encoding:1]; + dispatch_async(dispatch_get_main_queue() , ^{ [s_ctx.m_window[_handle.idx] setTitle: title]; + [title release]; }); - [title release]; - } } void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled) @@ -641,42 +699,36 @@ namespace entry void toggleFullscreen(WindowHandle _handle) { - if (s_ctx.isValid(_handle) ) - { - NSWindow* window = s_ctx.m_window[_handle.idx]; - NSScreen* screen = [window screen]; - NSRect screenRect = [screen frame]; + dispatch_async(dispatch_get_main_queue() + , ^{ + NSWindow* window = s_ctx.m_window[_handle.idx]; + [window toggleFullScreen:nil]; + }); + } - if (!s_ctx.m_fullscreen) - { - s_ctx.m_style &= ~NSWindowStyleMaskTitled; - dispatch_async(dispatch_get_main_queue() - , ^{ - [NSMenu setMenuBarVisible: false]; - [window setStyleMask: s_ctx.m_style]; - [window setFrame:screenRect display:YES]; - }); + void setMouseLock(WindowHandle _handle, bool _lock) + { + dispatch_async(dispatch_get_main_queue() + , ^{ + NSWindow* window = s_ctx.m_window[_handle.idx]; + s_ctx.setMouseLock(window, _lock); + }); + } - s_ctx.m_fullscreen = true; - } - else - { - s_ctx.m_style |= NSWindowStyleMaskTitled; - dispatch_async(dispatch_get_main_queue() - , ^{ - [NSMenu setMenuBarVisible: true]; - [window setStyleMask: s_ctx.m_style]; - [window setFrame:s_ctx.m_windowFrame display:YES]; - }); + void* getNativeWindowHandle(WindowHandle _handle) + { + return s_ctx.m_window[_handle.idx]; + } - s_ctx.m_fullscreen = false; - } - } + void* getNativeDisplayHandle() + { + return NULL; } - void setMouseLock(WindowHandle _handle, bool _lock) + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) { - BX_UNUSED(_handle, _lock); + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; } } // namespace entry @@ -732,7 +784,6 @@ namespace entry return nil; } - self->windowCount = 0; return self; } @@ -741,31 +792,22 @@ namespace entry assert(window); [window setDelegate:self]; - - assert(self->windowCount < ~0u); - self->windowCount += 1; } - (void)windowWillClose:(NSNotification*)notification { BX_UNUSED(notification); + NSWindow *window = [notification object]; + + [window setDelegate:nil]; + + destroyWindow(entry::s_ctx.findHandle(window), false); } - (BOOL)windowShouldClose:(NSWindow*)window { assert(window); - - [window setDelegate:nil]; - - assert(self->windowCount); - self->windowCount -= 1; - - if (self->windowCount == 0) - { - [NSApp terminate:self]; - return false; - } - + BX_UNUSED(window); return true; } diff --git a/3rdparty/bgfx/examples/common/entry/entry_p.h b/3rdparty/bgfx/examples/common/entry/entry_p.h index 6776610b636..3c01e3459c8 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_p.h +++ b/3rdparty/bgfx/examples/common/entry/entry_p.h @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef ENTRY_PRIVATE_H_HEADER_GUARD @@ -18,7 +18,7 @@ #endif // ENTRY_CONFIG_USE_NOOP #ifndef ENTRY_CONFIG_USE_SDL -# define ENTRY_CONFIG_USE_SDL BX_PLATFORM_STEAMLINK +# define ENTRY_CONFIG_USE_SDL 0 #endif // ENTRY_CONFIG_USE_SDL #ifndef ENTRY_CONFIG_USE_GLFW diff --git a/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp b/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp index d582b034e5e..bbcdb069257 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp @@ -1,15 +1,16 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" #if ENTRY_CONFIG_USE_SDL -#if BX_PLATFORM_WINDOWS +#if BX_PLATFORM_LINUX || BX_PLATFORM_BSD +#elif BX_PLATFORM_WINDOWS # define SDL_MAIN_HANDLED -#endif // BX_PLATFORM_WINDOWS +#endif #include <bx/os.h> @@ -34,35 +35,32 @@ BX_PRAGMA_DIAGNOSTIC_POP() namespace entry { - inline bool sdlSetWindow(SDL_Window* _window) + /// + static void* sdlNativeWindowHandle(SDL_Window* _window) { SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); if (!SDL_GetWindowWMInfo(_window, &wmi) ) { - return false; + return NULL; } - bgfx::PlatformData pd; # if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - pd.ndt = wmi.info.x11.display; - pd.nwh = (void*)(uintptr_t)wmi.info.x11.window; -# elif BX_PLATFORM_OSX - pd.ndt = NULL; - pd.nwh = wmi.info.cocoa.window; + if (wmi.subsystem == SDL_SYSWM_WAYLAND) + { + return (void*)wmi.info.wl.surface; + } + else + { + return (void*)wmi.info.x11.window; + } +# elif BX_PLATFORM_OSX || BX_PLATFORM_IOS + return wmi.info.cocoa.window; # elif BX_PLATFORM_WINDOWS - pd.ndt = NULL; - pd.nwh = wmi.info.win.window; -# elif BX_PLATFORM_STEAMLINK - pd.ndt = wmi.info.vivante.display; - pd.nwh = wmi.info.vivante.window; + return wmi.info.win.window; +# elif BX_PLATFORM_ANDROID + return wmi.info.android.window; # endif // BX_PLATFORM_ - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); - - return true; } static uint8_t translateKeyModifiers(uint16_t _sdl) @@ -102,7 +100,7 @@ namespace entry static void initTranslateKey(uint16_t _sdl, Key::Enum _key) { - BX_CHECK(_sdl < BX_COUNTOF(s_translateKey), "Out of bounds %d.", _sdl); + BX_ASSERT(_sdl < BX_COUNTOF(s_translateKey), "Out of bounds %d.", _sdl); s_translateKey[_sdl&0xff] = (uint8_t)_key; } @@ -252,27 +250,6 @@ namespace entry static int32_t threadFunc(bx::Thread* _thread, void* _userData); }; - /// - static void* sdlNativeWindowHandle(SDL_Window* _window) - { - SDL_SysWMinfo wmi; - SDL_VERSION(&wmi.version); - if (!SDL_GetWindowWMInfo(_window, &wmi) ) - { - return NULL; - } - -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - return (void*)wmi.info.x11.window; -# elif BX_PLATFORM_OSX - return wmi.info.cocoa.window; -# elif BX_PLATFORM_WINDOWS - return wmi.info.win.window; -# elif BX_PLATFORM_STEAMLINK - return wmi.info.vivante.window; -# endif // BX_PLATFORM_ - } - struct Msg { Msg() @@ -479,14 +456,13 @@ namespace entry s_userEventStart = SDL_RegisterEvents(7); - sdlSetWindow(m_window[0]); bgfx::renderFrame(); m_thread.init(MainThreadEntry::threadFunc, &m_mte); // Force window resolution... WindowHandle defaultWindow = { 0 }; - setWindowSize(defaultWindow, m_width, m_height, true); + entry::setWindowSize(defaultWindow, m_width, m_height); SDL_EventState(SDL_DROPFILE, SDL_ENABLE); @@ -502,7 +478,7 @@ namespace entry bx::AllocatorI* allocator = getAllocator(); uint32_t size = (uint32_t)bx::getSize(reader); void* data = BX_ALLOC(allocator, size + 1); - bx::read(reader, data, size); + bx::read(reader, data, size, bx::ErrorAssert{}); bx::close(reader); ((char*)data)[size] = '\0'; @@ -664,7 +640,15 @@ namespace entry case SDL_WINDOWEVENT_SIZE_CHANGED: { WindowHandle handle = findHandle(wev.windowID); - setWindowSize(handle, wev.data1, wev.data2); + uint32_t width = wev.data1; + uint32_t height = wev.data2; + if (width != m_width + || height != m_height) + { + m_width = width; + m_height = height; + m_eventQueue.postSizeEvent(handle, m_width, m_height); + } } break; @@ -909,7 +893,7 @@ namespace entry Msg* msg = (Msg*)uev.data2; if (isValid(handle) ) { - setWindowSize(handle, msg->m_width, msg->m_height); + SDL_SetWindowSize(m_window[handle.idx], msg->m_width, msg->m_height); } delete msg; } @@ -981,20 +965,6 @@ namespace entry return invalid; } - void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height, bool _force = false) - { - if (_width != m_width - || _height != m_height - || _force) - { - m_width = _width; - m_height = _height; - - SDL_SetWindowSize(m_window[_handle.idx], m_width, m_height); - m_eventQueue.postSizeEvent(_handle, m_width, m_height); - } - } - GamepadHandle findGamepad(SDL_JoystickID _jid) { for (uint32_t ii = 0, num = m_gamepadAlloc.getNumHandles(); ii < num; ++ii) @@ -1095,6 +1065,7 @@ namespace entry void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { + // Function to set the window size programmatically from the examples/tools. Msg* msg = new Msg; msg->m_width = _width; msg->m_height = _height; @@ -1128,6 +1099,47 @@ namespace entry sdlPostEvent(SDL_USER_WINDOW_MOUSE_LOCK, _handle, NULL, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + return sdlNativeWindowHandle(s_ctx.m_window[_handle.idx]); + } + + void* getNativeDisplayHandle() + { + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(s_ctx.m_window[0], &wmi) ) + { + return NULL; + } +# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + if (wmi.subsystem == SDL_SYSWM_WAYLAND) + return wmi.info.wl.display; + else + return wmi.info.x11.display; +# else + return NULL; +# endif // BX_PLATFORM_* + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(s_ctx.m_window[_handle.idx], &wmi) ) + { + return bgfx::NativeWindowHandleType::Default; + } +# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + if (wmi.subsystem == SDL_SYSWM_WAYLAND) + return bgfx::NativeWindowHandleType::Wayland; + else + return bgfx::NativeWindowHandleType::Default; +# else + return bgfx::NativeWindowHandleType::Default; +# endif // BX_PLATFORM_* + } + int32_t MainThreadEntry::threadFunc(bx::Thread* _thread, void* _userData) { BX_UNUSED(_thread); diff --git a/3rdparty/bgfx/examples/common/entry/entry_windows.cpp b/3rdparty/bgfx/examples/common/entry/entry_windows.cpp index 845c039b451..e731977737e 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_windows.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_windows.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -18,10 +18,12 @@ #include <tinystl/allocator.h> #include <tinystl/string.h> +#include <tinystl/vector.h> #include <windows.h> #include <windowsx.h> #include <xinput.h> +#include <shellapi.h> #ifndef XINPUT_GAMEPAD_GUIDE # define XINPUT_GAMEPAD_GUIDE 0x400 @@ -33,13 +35,14 @@ namespace entry { - /// - inline void winSetHwnd(::HWND _window) + typedef tinystl::vector<WCHAR> WSTRING; + + inline WSTRING UTF8ToUTF16(const char *utf8_str) { - bgfx::PlatformData pd; - bx::memSet(&pd, 0, sizeof(pd) ); - pd.nwh = _window; - bgfx::setPlatformData(pd); + int len = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, NULL, 0); + WSTRING utf16(len); + MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, utf16.data(), len); + return utf16; } typedef DWORD (WINAPI* PFN_XINPUT_GET_STATE)(DWORD dwUserIndex, XINPUT_STATE* pState); @@ -359,6 +362,7 @@ namespace entry , m_init(false) , m_exit(false) { + m_surrogate = 0; bx::memSet(s_translateKey, 0, sizeof(s_translateKey) ); s_translateKey[VK_ESCAPE] = Key::Esc; s_translateKey[VK_RETURN] = Key::Return; @@ -456,7 +460,7 @@ namespace entry HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL); - WNDCLASSEXA wnd; + WNDCLASSEXW wnd; bx::memSet(&wnd, 0, sizeof(wnd) ); wnd.cbSize = sizeof(wnd); wnd.style = CS_HREDRAW | CS_VREDRAW; @@ -464,9 +468,9 @@ namespace entry wnd.hInstance = instance; wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); wnd.hCursor = LoadCursor(NULL, IDC_ARROW); - wnd.lpszClassName = "bgfx"; + wnd.lpszClassName = L"bgfx"; wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION); - RegisterClassExA(&wnd); + RegisterClassExW(&wnd); m_windowAlloc.alloc(); m_hwnd[0] = CreateWindowExA( @@ -489,8 +493,6 @@ namespace entry | ENTRY_WINDOW_FLAG_FRAME ; - winSetHwnd(m_hwnd[0]); - adjust(m_hwnd[0], ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, true); clear(m_hwnd[0]); @@ -521,10 +523,10 @@ namespace entry s_xinput.update(m_eventQueue); WaitForInputIdle(GetCurrentProcess(), 16); - while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) ) + while (0 != PeekMessageW(&msg, NULL, 0U, 0U, PM_REMOVE) ) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageW(&msg); } } @@ -548,8 +550,8 @@ namespace entry case WM_USER_WINDOW_CREATE: { Msg* msg = (Msg*)_lparam; - HWND hwnd = CreateWindowA("bgfx" - , msg->m_title.c_str() + HWND hwnd = CreateWindowW(L"bgfx" + , UTF8ToUTF16(msg->m_title.c_str()).data() , WS_OVERLAPPEDWINDOW|WS_VISIBLE , msg->m_x , msg->m_y @@ -560,6 +562,8 @@ namespace entry , (HINSTANCE)GetModuleHandle(NULL) , 0 ); + + adjust(hwnd, msg->m_width, msg->m_height, true); clear(hwnd); m_hwnd[_wparam] = hwnd; @@ -590,7 +594,7 @@ namespace entry case WM_USER_WINDOW_SET_TITLE: { Msg* msg = (Msg*)_lparam; - SetWindowTextA(m_hwnd[_wparam], msg->m_title.c_str() ); + SetWindowTextW(m_hwnd[_wparam], UTF8ToUTF16(msg->m_title.c_str()).data() ); delete msg; } break; @@ -842,20 +846,40 @@ namespace entry case WM_CHAR: { + WCHAR utf16[2] = { (WCHAR)_wparam }; uint8_t utf8[4] = {}; - uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8 - , 0 - , (LPCWSTR)&_wparam - , 1 - , (LPSTR)utf8 - , BX_COUNTOF(utf8) - , NULL - , NULL - ); - if (0 != len) + + if (utf16[0] >= 0xD800 && utf16[0] <= 0xDBFF) { + m_surrogate = utf16[0]; + } + else { - WindowHandle handle = findHandle(_hwnd); - m_eventQueue.postCharEvent(handle, len, utf8); + int utf16_len; + if (utf16[0] >= 0xDC00 && utf16[0] <= 0xDFFF) { + utf16[1] = utf16[0]; + utf16[0] = m_surrogate; + m_surrogate = 0; + utf16_len = 2; + } + else + { + utf16_len = 1; + } + + uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8 + , 0 + , utf16 + , utf16_len + , (LPSTR)utf8 + , BX_COUNTOF(utf8) + , NULL + , NULL + ); + if (0 != len) + { + WindowHandle handle = findHandle(_hwnd); + m_eventQueue.postCharEvent(handle, len, utf8); + } } } break; @@ -864,8 +888,10 @@ namespace entry { HDROP drop = (HDROP)_wparam; char tmp[bx::kMaxFilePath]; - uint32_t result = DragQueryFileA(drop, 0, tmp, sizeof(tmp) ); + WCHAR utf16[bx::kMaxFilePath]; + uint32_t result = DragQueryFileW(drop, 0, utf16, bx::kMaxFilePath); BX_UNUSED(result); + WideCharToMultiByte(CP_UTF8, 0, utf16, -1, tmp, bx::kMaxFilePath, NULL, NULL); WindowHandle handle = findHandle(_hwnd); m_eventQueue.postDropFileEvent(handle, tmp); } @@ -876,7 +902,7 @@ namespace entry } } - return DefWindowProc(_hwnd, _id, _wparam, _lparam); + return DefWindowProcW(_hwnd, _id, _wparam, _lparam); } WindowHandle findHandle(HWND _hwnd) @@ -905,6 +931,7 @@ namespace entry SelectObject(hdc, brush); FillRect(hdc, &rect, brush); ReleaseDC(_hwnd, hdc); + DeleteObject(brush); } void adjust(HWND _hwnd, uint32_t _width, uint32_t _height, bool _windowFrame) @@ -993,7 +1020,9 @@ namespace entry void setMouseLock(HWND _hwnd, bool _lock) { - if (_hwnd != m_mouseLock) + HWND newMouseLock = _lock ? _hwnd : 0; + + if (newMouseLock != m_mouseLock) { if (_lock) { @@ -1008,13 +1037,14 @@ namespace entry ShowCursor(true); } - m_mouseLock = _hwnd; + m_mouseLock = newMouseLock; } } static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam); EventQueue m_eventQueue; + WCHAR m_surrogate; bx::Mutex m_lock; bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc; @@ -1133,6 +1163,22 @@ namespace entry PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + return s_ctx.m_hwnd[_handle.idx]; + } + + void* getNativeDisplayHandle() + { + return NULL; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } + int32_t MainThreadEntry::threadFunc(bx::Thread* /*_thread*/, void* _userData) { MainThreadEntry* self = (MainThreadEntry*)_userData; diff --git a/3rdparty/bgfx/examples/common/entry/entry_winrt.cx b/3rdparty/bgfx/examples/common/entry/entry_winrt.cx deleted file mode 100644 index 76270e99770..00000000000 --- a/3rdparty/bgfx/examples/common/entry/entry_winrt.cx +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2011-2016 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause - */ - -#include "entry_p.h" - -#if BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE - -#include <bgfx/platform.h> -#include <bx/thread.h> -#include <bx/math.h> -#include <Unknwn.h> - -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::ApplicationModel::Activation; -using namespace Windows::UI::Core; -using namespace Windows::UI::Input; -using namespace Windows::System; -using namespace Windows::Foundation; -#if BX_PLATFORM_WINRT -using namespace Windows::Graphics::Display; -#endif // BX_PLATFORM_WINRT -using namespace Platform; - -static const char* const g_emptyArgs[] = { "app.exe", "", "" }; -static entry::WindowHandle g_defaultWindow = { 0 }; -static entry::EventQueue g_eventQueue; - -/// -inline void winrtSetWindow(::IUnknown* _window) -{ - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = _window; - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); -} - -ref class App sealed : public IFrameworkView -{ -public: - App() - : m_windowVisible(true) - , m_windowClosed(false) - { - } - - // IFrameworkView Methods. - virtual void Initialize(CoreApplicationView^ applicationView) - { - applicationView->Activated += ref new - TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated); - - CoreApplication::Suspending += ref new - EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending); - - CoreApplication::Resuming += ref new - EventHandler<Platform::Object^>(this, &App::OnResuming); - } - - virtual void SetWindow(CoreWindow^ window) - { - window->VisibilityChanged += ref new - TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged); - - window->Closed += ref new - TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed); - - winrtSetWindow(reinterpret_cast<IUnknown*>(window) ); - } - - virtual void Load(String^ entryPoint) - { - } - - virtual void Run() - { - bgfx::renderFrame(); - - bx::Thread thread; - thread.init(MainThreadFunc, nullptr); - - CoreWindow^ window = CoreWindow::GetForCurrentThread(); - auto bounds = window->Bounds; - -#if BX_PLATFORM_WINRT - auto dpi = DisplayInformation::GetForCurrentView()->LogicalDpi; - static const float dipsPerInch = 96.0f; - g_eventQueue.postSizeEvent(g_defaultWindow - , lround(bx::floor(bounds.Width * dpi / dipsPerInch + 0.5f) ) - , lround(bx::floor(bounds.Height * dpi / dipsPerInch + 0.5f) ) - ); -#endif // BX_PLATFORM_WINRT - - while (!m_windowClosed) - { - if (m_windowVisible) - { - window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - } - else - { - window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); - } - - bgfx::renderFrame(); - } - - g_eventQueue.postExitEvent(); - - while (bgfx::RenderFrame::NoContext != bgfx::renderFrame() ) {}; - - thread.shutdown(); - } - - virtual void Uninitialize() - { - } - -private: - bool m_windowVisible; - bool m_windowClosed; - - void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) - { - CoreWindow::GetForCurrentThread()->Activate(); - } - - void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) - { - m_windowVisible = args->Visible; - } - - void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) - { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); - BX_UNUSED(deferral); - } - - void OnResuming(Platform::Object^ sender, Platform::Object^ args) - { - } - - void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) - { - m_windowClosed = true; - } - - static int32_t MainThreadFunc(bx::Thread*, void*) - { - return entry::main(BX_COUNTOF(g_emptyArgs), g_emptyArgs); - } -}; - -ref class AppSource sealed : IFrameworkViewSource -{ -public: - virtual IFrameworkView^ CreateView() - { - return ref new App(); - } -}; - -namespace entry -{ - const Event* poll() - { - return g_eventQueue.poll(); - } - - const Event* poll(WindowHandle _handle) - { - return g_eventQueue.poll(_handle); - } - - void release(const Event* _event) - { - g_eventQueue.release(_event); - } - - WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) - { - BX_UNUSED(_x, _y, _width, _height, _flags, _title); - WindowHandle handle = { UINT16_MAX }; - return handle; - } - - void destroyWindow(WindowHandle _handle) - { - BX_UNUSED(_handle); - } - - void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) - { - BX_UNUSED(_handle, _x, _y); - } - - void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) - { - BX_UNUSED(_handle, _width, _height); - } - - void setWindowTitle(WindowHandle _handle, const char* _title) - { - BX_UNUSED(_handle, _title); - } - - void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled) - { - BX_UNUSED(_handle, _flags, _enabled); - } - - void toggleFullscreen(WindowHandle _handle) - { - BX_UNUSED(_handle); - } - - void setMouseLock(WindowHandle _handle, bool _lock) - { - BX_UNUSED(_handle, _lock); - } -} - -[MTAThread] -int main(Array<String^>^) -{ - auto appSource = ref new AppSource(); - CoreApplication::Run(appSource); - return 0; -} - -#endif // BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE diff --git a/3rdparty/bgfx/examples/common/entry/entry_x11.cpp b/3rdparty/bgfx/examples/common/entry/entry_x11.cpp index 6bfd3192caa..407a1d9e5dc 100644 --- a/3rdparty/bgfx/examples/common/entry/entry_x11.cpp +++ b/3rdparty/bgfx/examples/common/entry/entry_x11.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "entry_p.h" @@ -12,8 +12,6 @@ #include <X11/keysymdef.h> #include <X11/Xlib.h> // will include X11 which #defines None... Don't mess with order of includes. #include <X11/Xutil.h> -#include <bgfx/platform.h> - #include <unistd.h> // syscall #undef None @@ -31,18 +29,6 @@ namespace entry static const char* s_applicationName = "BGFX"; static const char* s_applicationClass = "bgfx"; - /// - inline void x11SetDisplayWindow(void* _display, uint32_t _window, void* _glx = NULL) - { - bgfx::PlatformData pd; - pd.ndt = _display; - pd.nwh = (void*)(uintptr_t)_window; - pd.context = _glx; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); - } - #define JS_EVENT_BUTTON 0x01 /* button pressed/released */ #define JS_EVENT_AXIS 0x02 /* joystick moved */ #define JS_EVENT_INIT 0x80 /* initial state of device */ @@ -208,7 +194,7 @@ namespace entry static void initTranslateKey(uint16_t _xk, Key::Enum _key) { _xk += 256; - BX_CHECK(_xk < BX_COUNTOF(s_translateKey), "Out of bounds %d.", _xk); + BX_ASSERT(_xk < BX_COUNTOF(s_translateKey), "Out of bounds %d.", _xk); s_translateKey[_xk&0x1ff] = (uint8_t)_key; } @@ -346,7 +332,13 @@ namespace entry int32_t run(int _argc, const char* const* _argv) { XInitThreads(); + m_display = XOpenDisplay(NULL); + if (NULL == m_display) + { + bx::printf("XOpenDisplay failed: DISPLAY environment variable must be set.\n\n"); + return bx::kExitFailure; + } int32_t screen = DefaultScreen(m_display); m_depth = DefaultDepth(m_display, screen); @@ -354,34 +346,30 @@ namespace entry m_root = RootWindow(m_display, screen); bx::memSet(&m_windowAttrs, 0, sizeof(m_windowAttrs) ); - m_windowAttrs.background_pixmap = 0; - m_windowAttrs.border_pixel = 0; - m_windowAttrs.event_mask = 0 - | ButtonPressMask - | ButtonReleaseMask - | ExposureMask - | KeyPressMask - | KeyReleaseMask - | PointerMotionMask - | StructureNotifyMask - ; + m_windowAttrs.background_pixel = 0; + m_windowAttrs.border_pixel = 0; + m_windowAttrs.bit_gravity = StaticGravity; + m_windowAttrs.event_mask = 0 + | ButtonPressMask + | ButtonReleaseMask + | ExposureMask + | KeyPressMask + | KeyReleaseMask + | PointerMotionMask + | StructureNotifyMask + ; m_windowAlloc.alloc(); - m_window[0] = XCreateWindow(m_display - , m_root - , 0, 0 - , 1, 1, 0 - , m_depth - , InputOutput - , m_visual - , CWBorderPixel|CWEventMask - , &m_windowAttrs - ); - - // Clear window to black. - XSetWindowAttributes attr; - bx::memSet(&attr, 0, sizeof(attr) ); - XChangeWindowAttributes(m_display, m_window[0], CWBackPixel, &attr); + m_window[0] = XCreateWindow( + m_display + , m_root + , 0, 0, 1, 1, 0 + , m_depth + , InputOutput + , m_visual + , CWBorderPixel|CWEventMask|CWBackPixel|CWBitGravity + , &m_windowAttrs + ); const char* wmDeleteWindowName = "WM_DELETE_WINDOW"; Atom wmDeleteWindow; @@ -401,18 +389,16 @@ namespace entry im = XOpenIM(m_display, NULL, NULL, NULL); XIC ic; - ic = XCreateIC(im - , XNInputStyle - , 0 - | XIMPreeditNothing - | XIMStatusNothing - , XNClientWindow - , m_window[0] - , NULL - ); - - // - x11SetDisplayWindow(m_display, m_window[0]); + ic = XCreateIC( + im + , XNInputStyle + , 0 + | XIMPreeditNothing + | XIMStatusNothing + , XNClientWindow + , m_window[0] + , NULL + ); MainThreadEntry mte; mte.m_argc = _argc; @@ -578,6 +564,9 @@ namespace entry XUnmapWindow(m_display, m_window[0]); XDestroyWindow(m_display, m_window[0]); + XCloseDisplay(m_display); + m_display = NULL; + return thread.getExitCode(); } @@ -589,26 +578,22 @@ namespace entry void createWindow(WindowHandle _handle, Msg* msg) { - Window window = XCreateWindow(m_display - , m_root - , msg->m_x - , msg->m_y - , msg->m_width - , msg->m_height - , 0 - , m_depth - , InputOutput - , m_visual - , CWBorderPixel|CWEventMask - , &m_windowAttrs - ); + Window window = XCreateWindow( + m_display + , m_root + , msg->m_x + , msg->m_y + , msg->m_width + , msg->m_height + , 0 + , m_depth + , InputOutput + , m_visual + , CWBorderPixel|CWEventMask|CWBackPixel|CWBitGravity + , &m_windowAttrs + ); m_window[_handle.idx] = window; - // Clear window to black. - XSetWindowAttributes attr; - bx::memSet(&attr, 0, sizeof(attr) ); - XChangeWindowAttributes(m_display, window, CWBackPixel, &attr); - const char* wmDeleteWindowName = "WM_DELETE_WINDOW"; Atom wmDeleteWindow; XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow); @@ -755,7 +740,10 @@ namespace entry { Display* display = s_ctx.m_display; Window window = s_ctx.m_window[_handle.idx]; - XStoreName(display, window, _title); + + XTextProperty tp; + Xutf8TextListToTextProperty(display, (char**)&_title, 1, XUTF8StringStyle, &tp); + XSetWMName(display, window, &tp); } void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled) @@ -773,6 +761,22 @@ namespace entry BX_UNUSED(_handle, _lock); } + void* getNativeWindowHandle(WindowHandle _handle) + { + return (void*)(uintptr_t)s_ctx.m_window[_handle.idx]; + } + + void* getNativeDisplayHandle() + { + return s_ctx.m_display; + } + + bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType(WindowHandle _handle) + { + BX_UNUSED(_handle); + return bgfx::NativeWindowHandleType::Default; + } + } // namespace entry int main(int _argc, const char* const* _argv) diff --git a/3rdparty/bgfx/examples/common/entry/input.cpp b/3rdparty/bgfx/examples/common/entry/input.cpp index 5fdad9c0bb6..770922d6fd4 100644 --- a/3rdparty/bgfx/examples/common/entry/input.cpp +++ b/3rdparty/bgfx/examples/common/entry/input.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include <memory.h> @@ -375,8 +375,8 @@ void inputSetMouseLock(bool _lock) if (s_input->m_mouse.m_lock != _lock) { s_input->m_mouse.m_lock = _lock; - entry::WindowHandle defaultWindow = { 0 }; - entry::setMouseLock(defaultWindow, _lock); + + entry::setMouseLock(entry::kDefaultWindowHandle, _lock); if (_lock) { s_input->m_mouse.m_norm[0] = 0.0f; diff --git a/3rdparty/bgfx/examples/common/entry/input.h b/3rdparty/bgfx/examples/common/entry/input.h index 6954f3daa19..d51a7f338f5 100644 --- a/3rdparty/bgfx/examples/common/entry/input.h +++ b/3rdparty/bgfx/examples/common/entry/input.h @@ -1,6 +1,6 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef INPUT_H_HEADER_GUARD |