diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/immediate-renderer-base.cpp | 36 | ||||
| -rw-r--r-- | tools/gfx/render.cpp | 6 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 51 | ||||
| -rw-r--r-- | tools/platform/gui.cpp | 3 | ||||
| -rw-r--r-- | tools/platform/linux/x11-key-code.cpp | 247 | ||||
| -rw-r--r-- | tools/platform/linux/x11-window.cpp | 474 | ||||
| -rw-r--r-- | tools/platform/placeholder/placeholder-window.cpp | 33 | ||||
| -rw-r--r-- | tools/platform/window.h | 60 | ||||
| -rw-r--r-- | tools/platform/windows/win-window.cpp | 2 |
9 files changed, 855 insertions, 57 deletions
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp index 36d98f957..14c6cf217 100644 --- a/tools/gfx/immediate-renderer-base.cpp +++ b/tools/gfx/immediate-renderer-base.cpp @@ -57,8 +57,8 @@ public: *outObject = nullptr; return SLANG_E_NO_INTERFACE; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: CommandWriter* m_writer; @@ -99,13 +99,13 @@ public: m_writer->clearFrame(clearMask, clearDepth, clearStencil); } - virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state) + virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state) override { m_writer->setPipelineState(state); } virtual SLANG_NO_THROW void SLANG_MCALL - bindRootShaderObject(IShaderObject* object) + bindRootShaderObject(IShaderObject* object) override { m_writer->bindRootShaderObject(PipelineType::Graphics, object); } @@ -113,22 +113,22 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL setDescriptorSet( IPipelineLayout* layout, UInt index, - IDescriptorSet* descriptorSet) + IDescriptorSet* descriptorSet) override { m_writer->setDescriptorSet(PipelineType::Graphics, layout, index, descriptorSet); } virtual SLANG_NO_THROW void SLANG_MCALL - setViewports(uint32_t count, const Viewport* viewports) + setViewports(uint32_t count, const Viewport* viewports) override { m_writer->setViewports(count, viewports); } virtual SLANG_NO_THROW void SLANG_MCALL - setScissorRects(uint32_t count, const ScissorRect* scissors) + setScissorRects(uint32_t count, const ScissorRect* scissors) override { m_writer->setScissorRects(count, scissors); } - virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) + virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) override { m_writer->setPrimitiveTopology(topology); } @@ -137,29 +137,29 @@ public: UInt slotCount, IBufferResource* const* buffers, const UInt* strides, - const UInt* offsets) + const UInt* offsets) override { m_writer->setVertexBuffers(startSlot, slotCount, buffers, strides, offsets); } virtual SLANG_NO_THROW void SLANG_MCALL - setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) + setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override { m_writer->setIndexBuffer(buffer, indexFormat, offset); } - virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex) + virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex) override { m_writer->draw(vertexCount, startVertex); } virtual SLANG_NO_THROW void SLANG_MCALL - drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex) + drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex) override { m_writer->drawIndexed(indexCount, startIndex, baseVertex); } - virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) + virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override { m_writer->setStencilReference(referenceValue); } @@ -193,8 +193,8 @@ public: *outObject = nullptr; return SLANG_E_NO_INTERFACE; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: CommandWriter* m_writer; @@ -255,8 +255,8 @@ public: *outObject = nullptr; return SLANG_E_NO_INTERFACE; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: CommandWriter* m_writer; @@ -278,7 +278,7 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) + uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override { m_writer->uploadBufferData(dst, offset, size, data); } diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp index 5ef2a454e..4ecb52287 100644 --- a/tools/gfx/render.cpp +++ b/tools/gfx/render.cpp @@ -90,6 +90,12 @@ extern "C" return SLANG_FAIL; } break; +#elif SLANG_LINUX_FAMILY + case DeviceType::Default: + case DeviceType::Vulkan: + { + return createVKDevice(desc, outDevice); + } #endif default: diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index c0ece3e2f..ee494d4c8 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -30,6 +30,11 @@ # endif #endif +// Undef xlib macros +#ifdef Always +#undef Always +#endif + namespace gfx { using namespace Slang; @@ -1552,7 +1557,7 @@ public: size_t dstOffset, IBufferResource* src, size_t srcOffset, - size_t size) + size_t size) override { SLANG_UNUSED(dst); SLANG_UNUSED(srcOffset); @@ -1561,7 +1566,7 @@ public: SLANG_UNUSED(size); } virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data) + uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data) override { _uploadBufferData( m_commandBuffer->m_commandBuffer, @@ -1850,9 +1855,7 @@ public: ::GetClientRect((HWND)m_windowHandle.handleValues[0], &rc); *widthOut = rc.right - rc.left; *heightOut = rc.bottom - rc.top; -#else - auto platformDesc = _getPlatformDesc<XPlatformDesc>(); - +#elif defined(SLANG_ENABLE_XLIB) XWindowAttributes winAttr = {}; XGetWindowAttributes( (Display*)m_windowHandle.handleValues[0], @@ -1861,6 +1864,9 @@ public: *widthOut = winAttr.width; *heightOut = winAttr.height; +#else + *widthOut = 0; + *heightOut = 0; #endif } @@ -2088,9 +2094,9 @@ public: return SLANG_OK; } - virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() { return m_desc; } + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; } virtual SLANG_NO_THROW Result - SLANG_MCALL getImage(uint32_t index, ITextureResource** outResource) + SLANG_MCALL getImage(uint32_t index, ITextureResource** outResource) override { if (m_images.getCount() <= (Index)index) return SLANG_FAIL; @@ -2098,14 +2104,14 @@ public: m_images[index]->addRef(); return SLANG_OK; } - virtual SLANG_NO_THROW Result SLANG_MCALL resize(uint32_t width, uint32_t height) + virtual SLANG_NO_THROW Result SLANG_MCALL resize(uint32_t width, uint32_t height) override { SLANG_UNUSED(width); SLANG_UNUSED(height); destroySwapchainAndImages(); return createSwapchainAndImages(); } - virtual SLANG_NO_THROW Result SLANG_MCALL present() + virtual SLANG_NO_THROW Result SLANG_MCALL present() override { uint32_t swapChainIndices[] = {uint32_t(m_currentImageIndex)}; @@ -2123,7 +2129,7 @@ public: m_queue->m_pendingWaitSemaphore = VK_NULL_HANDLE; return SLANG_OK; } - virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() + virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() override { if (!m_images.getCount()) return -1; @@ -2283,9 +2289,9 @@ VkBool32 VKDevice::handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReport fprintf(stderr, "%s", buffer); fflush(stderr); - +#ifdef _WIN32 OutputDebugStringA(buffer); - +#endif return VK_FALSE; } @@ -2339,8 +2345,9 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer) applicationInfo.pApplicationName = "slang-render-test"; applicationInfo.pEngineName = "slang-render-test"; applicationInfo.apiVersion = VK_API_VERSION_1_0; - - char const* instanceExtensions[] = + applicationInfo.engineVersion = 1; + applicationInfo.applicationVersion = 1; + const char* instanceExtensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, @@ -2348,8 +2355,8 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer) #if SLANG_WINDOWS_FAMILY VK_KHR_WIN32_SURFACE_EXTENSION_NAME, -#else - VK_KHR_XLIB_SURFACE_EXTENSION_NAME +#elif defined(SLANG_ENABLE_XLIB) + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, #endif #if ENABLE_VALIDATION_LAYER @@ -2361,7 +2368,6 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer) VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; instanceCreateInfo.pApplicationInfo = &applicationInfo; - instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions); instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0]; @@ -2414,9 +2420,7 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer) instanceCreateInfo.ppEnabledLayerNames = layerNames; } } - - if (m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS) - return SLANG_FAIL; + SLANG_RETURN_ON_FAIL(m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance)); SLANG_RETURN_ON_FAIL(m_api.initInstanceProcs(instance)); if (useValidationLayer) @@ -2673,6 +2677,13 @@ Result VKDevice::createCommandQueue(const ICommandQueue::Desc& desc, ICommandQue Result VKDevice::createSwapchain( const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) { +#if !defined(SLANG_ENABLE_XLIB) + if (window.type == WindowHandle::Type::XLibHandle) + { + return SLANG_FAIL; + } +#endif + RefPtr<SwapchainImpl> sc = new SwapchainImpl(); SLANG_RETURN_ON_FAIL(sc->init(this, desc, window)); *outSwapchain = sc.detach(); diff --git a/tools/platform/gui.cpp b/tools/platform/gui.cpp index 5c210f460..f2f9561d5 100644 --- a/tools/platform/gui.cpp +++ b/tools/platform/gui.cpp @@ -34,7 +34,6 @@ LRESULT CALLBACK guiWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam return handled; } -void setNativeWindowHook(Window* window, WNDPROC proc); #endif @@ -51,8 +50,6 @@ GUI::GUI( #ifdef _WIN32 ImGui_ImplWin32_Init((HWND)window->getNativeHandle().handleValues[0]); - - setNativeWindowHook(window, &guiWindowProc); #endif // Let's do the initialization work required for our graphics API diff --git a/tools/platform/linux/x11-key-code.cpp b/tools/platform/linux/x11-key-code.cpp new file mode 100644 index 000000000..ce4e8945c --- /dev/null +++ b/tools/platform/linux/x11-key-code.cpp @@ -0,0 +1,247 @@ +#if defined(SLANG_ENABLE_XLIB) + +#include "core/slang-basic.h" +#include "../window.h" +#include <X11/keysym.h> +#include <X11/Xlib.h> + +#ifdef None +#undef None +#endif + +// Translates X11 key code values to Win32 Virtual Key values + +using namespace Slang; + +namespace platform +{ + Dictionary<int, KeyCode> keyCodeMap; + + struct Win32KeyCode + { + KeyCode vKeyCode; + int keySym; + }; + + Win32KeyCode keys[] = + { + {KeyCode::Left, XK_Left}, + {KeyCode::Up, XK_Up}, + {KeyCode::Down, XK_Down}, + {KeyCode::Right, XK_Right}, + {KeyCode::Escape, XK_Escape}, + {KeyCode::Return, XK_Return}, + {KeyCode::Space, XK_space}, + {KeyCode::Shift, XK_Shift_L}, + {KeyCode::Shift, XK_Shift_R}, + {KeyCode::Ctrl, XK_Control_L}, + {KeyCode::Ctrl, XK_Control_R}, + {KeyCode::Alt, XK_Alt_L}, + {KeyCode::Alt, XK_Alt_R}, + {KeyCode::Backspace, XK_BackSpace}, + {KeyCode::Delete, XK_Delete}, + {KeyCode::Home, XK_Home}, + {KeyCode::End, XK_End}, + {KeyCode::PageUp, XK_Page_Up}, + {KeyCode::PageDown, XK_Page_Down}, + {KeyCode::Insert, XK_Insert}, + {KeyCode::Tab, XK_Tab}, + {KeyCode::A, 0x41}, + {KeyCode::B, 0x42}, + {KeyCode::C, 0x43}, + {KeyCode::D, 0x44}, + {KeyCode::E, 0x45}, + {KeyCode::F, 0x46}, + {KeyCode::G, 0x47}, + {KeyCode::H, 0x48}, + {KeyCode::I, 0x49}, + {KeyCode::J, 0x4A}, + {KeyCode::K, 0x4B}, + {KeyCode::L, 0x4C}, + {KeyCode::M, 0x4D}, + {KeyCode::N, 0x4E}, + {KeyCode::O, 0x4F}, + {KeyCode::P, 0x50}, + {KeyCode::Q, 0x51}, + {KeyCode::R, 0x52}, + {KeyCode::S, 0x53}, + {KeyCode::T, 0x54}, + {KeyCode::U, 0x55}, + {KeyCode::V, 0x56}, + {KeyCode::W, 0x57}, + {KeyCode::X, 0x58}, + {KeyCode::Y, 0x59}, + {KeyCode::Z, 0x5A}, + {KeyCode::Semicolon, XK_semicolon}, + {KeyCode::Comma, XK_comma}, + {KeyCode::Dot, XK_period}, + {KeyCode::Slash, XK_slash}, + {KeyCode::Quote, XK_apostrophe}, + {KeyCode::LBracket, XK_bracketleft}, + {KeyCode::RBracket, XK_bracketright}, + {KeyCode::Backslash, XK_backslash}, + {KeyCode::Minus, XK_minus}, + {KeyCode::Plus, XK_equal}, + {KeyCode::Tilde, XK_asciitilde}, + {KeyCode::Key0, 0x30}, + {KeyCode::Key1, 0x31}, + {KeyCode::Key2, 0x32}, + {KeyCode::Key3, 0x33}, + {KeyCode::Key4, 0x34}, + {KeyCode::Key5, 0x35}, + {KeyCode::Key6, 0x36}, + {KeyCode::Key7, 0x37}, + {KeyCode::Key8, 0x38}, + {KeyCode::Key9, 0x39}, + {KeyCode::F1, XK_F1}, + {KeyCode::F2, XK_F2}, + {KeyCode::F3, XK_F3}, + {KeyCode::F4, XK_F4}, + {KeyCode::F5, XK_F5}, + {KeyCode::F6, XK_F6}, + {KeyCode::F7, XK_F7}, + {KeyCode::F8, XK_F8}, + {KeyCode::F9, XK_F9}, + {KeyCode::F10, XK_F10}, + {KeyCode::F11, XK_F11}, + {KeyCode::F12, XK_F12} + }; + + void initKeyCodeTranslationTable(Display* display) + { + for (auto entry : keys) + { + auto systemKeyCode = XKeysymToKeycode(display, entry.keySym); + keyCodeMap[systemKeyCode] = entry.vKeyCode; + } + } + + void freeKeyCodeTranslationTable() + { + keyCodeMap = decltype(keyCodeMap)(); + } + + KeyCode translateKeyCode(int keyCode) + { + KeyCode result = KeyCode::None; + keyCodeMap.TryGetValue(keyCode, result); + return result; + } + + int getKeyChar(KeyCode keyCode, int keyState) + { + bool shift = (keyState & ShiftMask) != 0; + if (keyCode >= KeyCode::A && keyCode <= KeyCode::Z ) + { + bool capslock = (keyState & LockMask) != 0; + bool isCapital = capslock ^ shift; + if (isCapital) + return (int)keyCode; + else + return (int)keyCode + ('a'-'A'); + } + else if (keyCode == KeyCode::Space) + { + return ' '; + } + else if (keyCode == KeyCode::Return) + { + return (int)keyCode; + } + else if (keyCode >= KeyCode::Key0 && keyCode <= KeyCode::Key9) + { + if (!shift) + return (int)keyCode; + else + { + switch (keyCode) + { + case KeyCode::Key0: + return ')'; + case KeyCode::Key1: + return '!'; + case KeyCode::Key2: + return '@'; + case KeyCode::Key3: + return '#'; + case KeyCode::Key4: + return '$'; + case KeyCode::Key5: + return '%'; + case KeyCode::Key6: + return '^'; + case KeyCode::Key7: + return '&'; + case KeyCode::Key8: + return '*'; + case KeyCode::Key9: + return '('; + default: + return 0; + } + } + } + if (shift) + { + switch (keyCode) + { + case KeyCode::Semicolon: + return ':'; + case KeyCode::Comma: + return '<'; + case KeyCode::Dot: + return '>'; + case KeyCode::Slash: + return '?'; + case KeyCode::Quote: + return '\"'; + case KeyCode::LBracket: + return '{'; + case KeyCode::RBracket: + return '}'; + case KeyCode::Backslash: + return '|'; + case KeyCode::Minus: + return '_'; + case KeyCode::Plus: + return '+'; + case KeyCode::Tilde: + return '~'; + default: + return 0; + } + } + else + { + switch (keyCode) + { + case KeyCode::Semicolon: + return ';'; + case KeyCode::Comma: + return ','; + case KeyCode::Dot: + return '.'; + case KeyCode::Slash: + return '/'; + case KeyCode::Quote: + return '\''; + case KeyCode::LBracket: + return '['; + case KeyCode::RBracket: + return ']'; + case KeyCode::Backslash: + return '\\'; + case KeyCode::Minus: + return '-'; + case KeyCode::Plus: + return '='; + case KeyCode::Tilde: + return '`'; + default: + return 0; + } + } + } +} // namespace platform + +#endif diff --git a/tools/platform/linux/x11-window.cpp b/tools/platform/linux/x11-window.cpp new file mode 100644 index 000000000..2721c00f3 --- /dev/null +++ b/tools/platform/linux/x11-window.cpp @@ -0,0 +1,474 @@ +#ifdef SLANG_ENABLE_XLIB + +#include "../window.h" +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xresource.h> + +#ifdef None +#undef None +#endif + +#include "core/slang-basic.h" + +using namespace Slang; + +namespace platform +{ +typedef ::Window X11WindowHandle; +class X11PlatformWindow; + +void initKeyCodeTranslationTable(Display *display); +void freeKeyCodeTranslationTable(); +KeyCode translateKeyCode(int keyCode); +int getKeyChar(KeyCode keyCode, int keyState); + +const int kKeyStateTableSize = 256; + +enum class KeyState +{ + Released, + Pressed, + Hold +}; + +enum class KeyEvent +{ + Press, Release +}; + +enum class MouseEvent +{ + Move, Down, Up, Scroll +}; + +class X11AppContext +{ +public: + static bool isTerminated; + static RefPtr<Window> mainWindow; + static OrderedDictionary<X11WindowHandle, X11PlatformWindow*> windows; + static X11WindowHandle mainWindowHandle; + static Display* xdisplay; + static KeyState keyStates[kKeyStateTableSize]; + static X11PlatformWindow *currentMouseEventWindow; +}; + +bool X11AppContext::isTerminated = false; +RefPtr<Window> X11AppContext::mainWindow; +OrderedDictionary<X11WindowHandle, X11PlatformWindow*> X11AppContext::windows; +X11WindowHandle X11AppContext::mainWindowHandle; +Display* X11AppContext::xdisplay = nullptr; +KeyState X11AppContext::keyStates[kKeyStateTableSize] = {}; +X11PlatformWindow* X11AppContext::currentMouseEventWindow = nullptr; + +void Application::init() +{ + +} + +static void doEventsImpl(bool waitForEvents); + +void Application::doEvents() { doEventsImpl(false); } + +void Application::quit() { X11AppContext::isTerminated = true; } + +void Application::dispose() +{ + X11AppContext::mainWindow = nullptr; + X11AppContext::windows = decltype(X11AppContext::windows)(); + freeKeyCodeTranslationTable(); +} + +void Application::run(Window* mainWindow, bool waitForEvents) +{ + if (mainWindow) + { + X11AppContext::mainWindow = mainWindow; + X11AppContext::mainWindowHandle = (X11WindowHandle)mainWindow->getNativeHandle().handleValues[1]; + mainWindow->show(); + while (!X11AppContext::isTerminated) + { + doEventsImpl(waitForEvents); + if (!X11AppContext::isTerminated) + mainWindow->events.mainLoop(); + } + } +} + +class X11PlatformWindow : public Window +{ +public: + X11WindowHandle handle; + bool visible = false; + int currentWidth = 0; + int currentHeight = 0; + bool fixedSized = false; + X11PlatformWindow(const WindowDesc &desc) + { + currentWidth = desc.width; + currentHeight = desc.height; + + int blackColor = BlackPixel(X11AppContext::xdisplay, DefaultScreen(X11AppContext::xdisplay)); + int whiteColor = WhitePixel(X11AppContext::xdisplay, DefaultScreen(X11AppContext::xdisplay)); + handle = XCreateSimpleWindow(X11AppContext::xdisplay, DefaultRootWindow(X11AppContext::xdisplay), 0, 0, + desc.width, desc.height, 0, blackColor, blackColor); + X11AppContext::windows[handle] = this; + Atom wmDelete = XInternAtom(X11AppContext::xdisplay, "WM_DELETE_WINDOW", True); + XSetWMProtocols(X11AppContext::xdisplay, handle, &wmDelete, 1); + XSelectInput(X11AppContext::xdisplay, handle, StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | + ButtonPressMask | ButtonReleaseMask | ExposureMask | FocusChangeMask); + + if (desc.style == WindowStyle::FixedSize) + { + fixedSized = true; + setFixedSizeHint(desc.width, desc.height); + } + setText(desc.title); + } + + ~X11PlatformWindow() + { + close(); + } + + void setFixedSizeHint(int w, int h) + { + auto sizeHints = XAllocSizeHints(); + sizeHints->flags = PMinSize | PMaxSize; + sizeHints->min_width = sizeHints->max_width = w; + sizeHints->min_height = sizeHints->max_height = h; + XSetWMNormalHints(X11AppContext::xdisplay, handle, sizeHints); + XFree(sizeHints); + } + + virtual void setClientSize(uint32_t width, uint32_t height) override + { + if (fixedSized) + setFixedSizeHint(width, height); + XResizeWindow(X11AppContext::xdisplay, handle, width, height); + handleResizeEvent(width, height); + } + + virtual Rect getClientRect() override + { + Rect rect = {}; + if (!handle) + return rect; + X11WindowHandle winRoot = 0, winParent = 0; + X11WindowHandle* winChildren = nullptr; + unsigned int numChilren = 0; + XQueryTree(X11AppContext::xdisplay, handle, &winRoot, &winParent, &winChildren, &numChilren); + unsigned borderWidth, depth; + XGetGeometry(X11AppContext::xdisplay, handle, &winRoot, &rect.x, &rect.y, (uint32_t*)&rect.width, (uint32_t*)&rect.height, &borderWidth, &depth); + return rect; + } + + virtual void centerScreen() override + { + auto currentRect = getClientRect(); + XWindowAttributes attributes; + XGetWindowAttributes(X11AppContext::xdisplay, handle, &attributes); + int screenWidth = WidthOfScreen(attributes.screen); + int screenHeight = HeightOfScreen(attributes.screen); + int x = (screenWidth - currentRect.width) / 2; + int y = (screenHeight - currentRect.height) / 2; + XMoveWindow(X11AppContext::xdisplay, handle, x, y); + } + virtual void close() override + { + if (handle) + { + X11AppContext::windows.Remove(handle); + XDestroyWindow(X11AppContext::xdisplay, handle); + handle = 0; + } + } + virtual bool getFocused() override + { + if (!handle) return false; + int revertTo; + X11WindowHandle focusedWindow; + XGetInputFocus(X11AppContext::xdisplay, &focusedWindow, &revertTo); + return focusedWindow == handle; + } + virtual WindowHandle getNativeHandle() override + { + WindowHandle rs; + rs.type = WindowHandle::Type::XLibHandle; + rs.handleValues[0] = (intptr_t)X11AppContext::xdisplay; + rs.handleValues[1] = (intptr_t)handle; + return rs; + } + virtual void setText(String text) override + { + if (!handle) return; + XStoreName(X11AppContext::xdisplay, handle, text.getBuffer()); + XClassHint* hint = XAllocClassHint(); + hint->res_class = (char *)"Slang platform window"; + hint->res_name = (char *)"Slang platform window"; + XSetClassHint(X11AppContext::xdisplay, handle, hint); + XFree(hint); + } + virtual bool getVisible() override + { + return visible; + } + virtual void show() override + { + XMapWindow(X11AppContext::xdisplay, handle); + visible = true; + } + virtual void hide() override + { + if (!handle) return; + XUnmapWindow(X11AppContext::xdisplay, handle); + visible = false; + } + virtual int getCurrentDpi() override + { + char *resourceString = XResourceManagerString(X11AppContext::xdisplay); + XrmDatabase db; + XrmValue value; + char *type = NULL; + double dpi = 96.0; + db = XrmGetStringDatabase(resourceString); + if (resourceString) + { + if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) + { + if (value.addr) + { + dpi = atof(value.addr); + } + } + } + return (int)dpi; + } + void handleResizeEvent(int w, int h) + { + if (w != currentWidth || h != currentHeight) + { + currentWidth = w; + currentHeight = h; + events.sizeChanged(); + } + } + + static void addButtonState(ButtonState::Enum& state, ButtonState::Enum newState) + { + state = ButtonState::Enum((int)state | (int)newState); + } + + ButtonState::Enum getButtonState(int state) + { + ButtonState::Enum buttonState = ButtonState::Enum::None; + if (state & ShiftMask) addButtonState(buttonState, ButtonState::Enum::Shift); + if (state & ControlMask) addButtonState(buttonState, ButtonState::Enum::Control); + if (state & Mod1Mask) addButtonState(buttonState, ButtonState::Enum::Alt); + if (state & Button1Mask) addButtonState(buttonState, ButtonState::Enum::LeftButton); + if (state & Button2Mask) addButtonState(buttonState, ButtonState::Enum::MiddleButton); + if (state & Button3Mask) addButtonState(buttonState, ButtonState::Enum::RightButton); + return buttonState; + } + + void handleKeyEvent(KeyEvent eventType, KeyCode keyCode, int keyChar, int state) + { + KeyEventArgs e; + e.buttons = getButtonState(state); + e.cancelEvent = false; + e.key = keyCode; + e.keyChar = keyChar; + if (eventType == KeyEvent::Press) + { + events.keyDown(e); + if (keyChar) + events.keyPress(e); + } + else + { + events.keyUp(e); + } + } + + void handleMouseEvent(MouseEvent eventType, int x, int y, int delta, int button, int state, unsigned long time) + { + auto buttonState = getButtonState(state); + if (button == Button1) + addButtonState(buttonState, ButtonState::Enum::LeftButton); + else if (button == Button2) + addButtonState(buttonState, ButtonState::Enum::MiddleButton); + else if (button == Button3) + addButtonState(buttonState, ButtonState::Enum::RightButton); + MouseEventArgs e; + e.buttons = buttonState; + e.delta = delta; + e.x = x; + e.y = y; + + switch (eventType) + { + case MouseEvent::Down: + events.mouseDown(e); + break; + case MouseEvent::Up: + events.mouseUp(e); + break; + case MouseEvent::Move: + events.mouseMove(e); + break; + case MouseEvent::Scroll: + events.mouseWheel(e); + break; + default: + break; + } + } + + void handleCloseEvent() + { + hide(); + if (X11AppContext::mainWindowHandle == handle) + Application::quit(); + } + + void handleExposeEvent() + { + } + + void handleFocus(bool focus) + { + } + +}; + +Window* Application::createWindow(const WindowDesc& desc) +{ + if (!X11AppContext::xdisplay) + { + XInitThreads(); + XrmInitialize(); + X11AppContext::xdisplay = XOpenDisplay(nullptr); + initKeyCodeTranslationTable(X11AppContext::xdisplay); + if (!X11AppContext::xdisplay) + printf("Failed to open XDisplay.\n"); + } + return new X11PlatformWindow(desc); +} + +void doEventsImpl(bool waitForEvents) +{ + auto xdisplay = X11AppContext::xdisplay; + if (!X11AppContext::xdisplay) + return; + + static bool supressInvokeTasks = false; + X11PlatformWindow* sysWindow = nullptr; + KeyCode vKeyCode = KeyCode::None; + int iKeyCode = 0; + while (XPending(xdisplay)) + { + XEvent nextEvent; + XNextEvent(xdisplay, &nextEvent); + switch (nextEvent.type) + { + case KeyPress: + vKeyCode = translateKeyCode(nextEvent.xkey.keycode); + iKeyCode = (int)vKeyCode; + if (iKeyCode < kKeyStateTableSize) + { + if (X11AppContext::keyStates[iKeyCode] == KeyState::Released) + X11AppContext::keyStates[iKeyCode] = KeyState::Pressed; + else if (X11AppContext::keyStates[iKeyCode] == KeyState::Pressed) + X11AppContext::keyStates[iKeyCode] = KeyState::Hold; + } + if (X11AppContext::windows.TryGetValue(nextEvent.xkey.window, sysWindow)) + { + wchar_t keyChar = getKeyChar(vKeyCode, nextEvent.xkey.state); + sysWindow->handleKeyEvent(KeyEvent::Press, vKeyCode, keyChar, nextEvent.xkey.state); + } + break; + case KeyRelease: + vKeyCode = translateKeyCode(nextEvent.xkey.keycode); + iKeyCode = (int)vKeyCode; + if (iKeyCode < kKeyStateTableSize) + { + X11AppContext::keyStates[iKeyCode] = KeyState::Released; + } + if (X11AppContext::windows.TryGetValue(nextEvent.xkey.window, sysWindow)) + { + sysWindow->handleKeyEvent(KeyEvent::Release, vKeyCode, 0, nextEvent.xkey.state); + } + break; + case MotionNotify: + if (X11AppContext::windows.TryGetValue(nextEvent.xmotion.window, sysWindow)) + { + X11AppContext::currentMouseEventWindow = sysWindow; + sysWindow->handleMouseEvent(MouseEvent::Move, nextEvent.xmotion.x, nextEvent.xmotion.y, 0, + 0, nextEvent.xmotion.state, nextEvent.xmotion.time); + } + break; + case ButtonPress: + if (X11AppContext::windows.TryGetValue(nextEvent.xbutton.window, sysWindow)) + { + X11AppContext::currentMouseEventWindow = sysWindow; + if (nextEvent.xbutton.button <= Button3) + sysWindow->handleMouseEvent(MouseEvent::Down, nextEvent.xbutton.x, nextEvent.xbutton.y, 0, + nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time); + else if (nextEvent.xbutton.button == Button4) + sysWindow->handleMouseEvent(MouseEvent::Scroll, nextEvent.xbutton.x, nextEvent.xbutton.y, 120, + nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time); + else if (nextEvent.xbutton.button == Button5) + sysWindow->handleMouseEvent(MouseEvent::Scroll, nextEvent.xbutton.x, nextEvent.xbutton.y, -120, + nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time); + } + break; + case ButtonRelease: + if (X11AppContext::windows.TryGetValue(nextEvent.xbutton.window, sysWindow)) + { + X11AppContext::currentMouseEventWindow = sysWindow; + sysWindow->handleMouseEvent(MouseEvent::Up, nextEvent.xbutton.x, nextEvent.xbutton.y, 0, + nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time); + } + break; + case ConfigureNotify: + if (X11AppContext::windows.TryGetValue(nextEvent.xconfigure.window, sysWindow)) + { + sysWindow->handleResizeEvent(nextEvent.xconfigure.width, nextEvent.xconfigure.height); + } + break; + case Expose: + if (X11AppContext::windows.TryGetValue(nextEvent.xexpose.window, sysWindow)) + { + sysWindow->handleExposeEvent(); + } + break; + case ClientMessage: + if (X11AppContext::windows.TryGetValue(nextEvent.xclient.window, sysWindow)) + { + Atom wmDelete = XInternAtom(X11AppContext::xdisplay, "WM_DELETE_WINDOW", True); + if (nextEvent.xclient.data.l[0] == wmDelete) + { + sysWindow->handleCloseEvent(); + } + } + break; + case FocusIn: + if (X11AppContext::windows.TryGetValue(nextEvent.xfocus.window, sysWindow)) + { + sysWindow->handleFocus(true); + } + break; + case FocusOut: + if (X11AppContext::windows.TryGetValue(nextEvent.xfocus.window, sysWindow)) + { + sysWindow->handleFocus(false); + } + break; + } + } +} + +} + +#endif diff --git a/tools/platform/placeholder/placeholder-window.cpp b/tools/platform/placeholder/placeholder-window.cpp new file mode 100644 index 000000000..a94287d55 --- /dev/null +++ b/tools/platform/placeholder/placeholder-window.cpp @@ -0,0 +1,33 @@ +#if !defined(_WIN32) && !defined(SLANG_ENABLE_XLIB) + +#include "../window.h" + +using namespace Slang; + +namespace platform +{ + +void Application::init() +{ +} + +void Application::doEvents() { } + +void Application::quit() { } + +void Application::dispose() +{ +} + +void Application::run(Window* mainWindow, bool waitForEvents) +{ + SLANG_UNUSED(mainWindow); + SLANG_UNUSED(waitForEvents); +} + +Window* Application::createWindow(const WindowDesc& desc) { return nullptr; } + + +} // namespace platform + +#endif diff --git a/tools/platform/window.h b/tools/platform/window.h index e4a867f0b..884f28b0d 100644 --- a/tools/platform/window.h +++ b/tools/platform/window.h @@ -5,6 +5,25 @@ #include "source/core/slang-basic.h" #include "source/core/slang-func-ptr.h" +#if defined(SLANG_PLATFORM_DYNAMIC) +# if defined(_MSC_VER) +# ifdef SLANG_PLATFORM_DYNAMIC_EXPORT +# define SLANG_PLATFORM_API SLANG_DLL_EXPORT +# else +# define SLANG_PLATFORM_API __declspec(dllimport) +# endif +# else +// TODO: need to consider compiler capabilities +//# ifdef SLANG_DYNAMIC_EXPORT +# define SLANG_PLATFORM_API SLANG_DLL_EXPORT +//# endif +# endif +#endif + +#ifndef SLANG_PLATFORM_API +# define SLANG_PLATFORM_API +#endif + namespace platform { enum class KeyCode : uint32_t @@ -99,14 +118,14 @@ struct WindowHandle }; Type type; intptr_t handleValues[2]; - static WindowHandle FromHwnd(void* hwnd) + static WindowHandle fromHwnd(void* hwnd) { WindowHandle handle = {}; handle.type = WindowHandle::Type::Win32Handle; handle.handleValues[0] = (intptr_t)(hwnd); return handle; } - static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow) + static WindowHandle fromXWindow(void* xdisplay, uint32_t xwindow) { WindowHandle handle = {}; handle.type = WindowHandle::Type::XLibHandle; @@ -114,6 +133,15 @@ struct WindowHandle handle.handleValues[1] = xwindow; return handle; } + template<typename T> + T convert() + { + T result; + result.type = (decltype(result.type))type; + result.handleValues[0] = handleValues[0]; + result.handleValues[1] = handleValues[1]; + return result; + } }; struct ButtonState @@ -174,6 +202,7 @@ public: Slang::Action<MouseEventArgs> mouseMove; Slang::Action<MouseEventArgs> mouseUp; Slang::Action<MouseEventArgs> mouseDown; + Slang::Action<MouseEventArgs> mouseWheel; }; Events events; @@ -194,12 +223,12 @@ public: class Application { public: - static Window* createWindow(const WindowDesc& desc); - static void init(); - static void run(Window* mainWindow, bool waitForEvents = false); - static void quit(); - static void doEvents(); - static void dispose(); + static SLANG_PLATFORM_API Window* createWindow(const WindowDesc& desc); + static SLANG_PLATFORM_API void init(); + static SLANG_PLATFORM_API void run(Window* mainWindow, bool waitForEvents = false); + static SLANG_PLATFORM_API void quit(); + static SLANG_PLATFORM_API void doEvents(); + static SLANG_PLATFORM_API void dispose(); }; } // namespace platform @@ -230,12 +259,13 @@ public: #else -# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \ - int main() \ - { \ - platform::Application::init(); \ - auto rs - APPLICATION_ENTRY(); \ - platform::Application::dispose(); \ - } +#define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \ + int main() \ + { \ + platform::Application::init(); \ + auto rs = APPLICATION_ENTRY(); \ + platform::Application::dispose(); \ + return rs; \ + } #endif diff --git a/tools/platform/windows/win-window.cpp b/tools/platform/windows/win-window.cpp index 8822a6393..0d80eda7b 100644 --- a/tools/platform/windows/win-window.cpp +++ b/tools/platform/windows/win-window.cpp @@ -406,7 +406,7 @@ public: virtual bool getVisible() override { return visible; } virtual WindowHandle getNativeHandle() override { - return WindowHandle::FromHwnd(handle); + return WindowHandle::fromHwnd(handle); } virtual void setText(Slang::String text) override { |
