summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-11 09:14:30 -0800
committerGitHub <noreply@github.com>2021-03-11 09:14:30 -0800
commita07455c175db33d8d95bc5cd83738808d74cd105 (patch)
tree02660537db912b7d48f34c751dc5731b88daa0db /tools
parent6cbd9d68a03f0a22305d4e224a3da7633b23de38 (diff)
Add Linux support to `platform` and `gfx`. (#1744)
Diffstat (limited to 'tools')
-rw-r--r--tools/gfx/immediate-renderer-base.cpp36
-rw-r--r--tools/gfx/render.cpp6
-rw-r--r--tools/gfx/vulkan/render-vk.cpp51
-rw-r--r--tools/platform/gui.cpp3
-rw-r--r--tools/platform/linux/x11-key-code.cpp247
-rw-r--r--tools/platform/linux/x11-window.cpp474
-rw-r--r--tools/platform/placeholder/placeholder-window.cpp33
-rw-r--r--tools/platform/window.h60
-rw-r--r--tools/platform/windows/win-window.cpp2
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
{