diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/apple/cocoa-util.h | 12 | ||||
| -rw-r--r-- | tools/gfx/apple/cocoa-util.mm | 15 | ||||
| -rw-r--r-- | tools/gfx/render.cpp | 2 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-api.h | 4 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-device.cpp | 13 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-module.cpp | 3 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-module.h | 2 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-swap-chain.cpp | 16 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-swap-chain.h | 17 | ||||
| -rw-r--r-- | tools/platform/apple/cocoa-window.mm | 618 | ||||
| -rw-r--r-- | tools/platform/placeholder/placeholder-window.cpp | 2 | ||||
| -rw-r--r-- | tools/platform/window.h | 8 |
12 files changed, 691 insertions, 21 deletions
diff --git a/tools/gfx/apple/cocoa-util.h b/tools/gfx/apple/cocoa-util.h new file mode 100644 index 000000000..80467d8a4 --- /dev/null +++ b/tools/gfx/apple/cocoa-util.h @@ -0,0 +1,12 @@ +#pragma once + +namespace gfx { + +// Utility functions for Cocoa +struct CocoaUtil { + + static void getNSViewRectSize(void* nsview, int* widthOut, int* heightOut); + +}; + +} diff --git a/tools/gfx/apple/cocoa-util.mm b/tools/gfx/apple/cocoa-util.mm new file mode 100644 index 000000000..45b1c3df0 --- /dev/null +++ b/tools/gfx/apple/cocoa-util.mm @@ -0,0 +1,15 @@ +#include "cocoa-util.h" + +#import <Cocoa/Cocoa.h> + +namespace gfx { + +void CocoaUtil::getNSViewRectSize(void* nsview, int* widthOut, int* heightOut) +{ + NSView* view = (NSView*)nsview; + NSRect rect = [view frame]; + *widthOut = rect.size.width; + *heightOut = rect.size.height; +} + +}
\ No newline at end of file diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp index aad544eb4..6dd0c90dd 100644 --- a/tools/gfx/render.cpp +++ b/tools/gfx/render.cpp @@ -324,7 +324,7 @@ extern "C" return SLANG_FAIL; } break; -#elif SLANG_LINUX_FAMILY && !defined(__CYGWIN__) +#elif (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) && !defined(__CYGWIN__) case DeviceType::Default: case DeviceType::Vulkan: { diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h index b7cbf13de..213921406 100644 --- a/tools/gfx/vulkan/vk-api.h +++ b/tools/gfx/vulkan/vk-api.h @@ -141,6 +141,10 @@ namespace gfx { # define VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \ x(vkCreateWin32SurfaceKHR) \ /* */ +#elif SLANG_APPLE_FAMILY +# define VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \ + x(vkCreateMacOSSurfaceMVK) \ + /* */ #elif SLANG_ENABLE_XLIB # define VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \ x(vkCreateXlibSurfaceKHR) \ diff --git a/tools/gfx/vulkan/vk-device.cpp b/tools/gfx/vulkan/vk-device.cpp index fe3680eda..66c2c811b 100644 --- a/tools/gfx/vulkan/vk-device.cpp +++ b/tools/gfx/vulkan/vk-device.cpp @@ -171,8 +171,11 @@ Result DeviceImpl::initVulkanInstanceAndDevice( applicationInfo.engineVersion = 1; applicationInfo.applicationVersion = 1; - Array<const char*, 6> instanceExtensions; + Array<const char*, 7> instanceExtensions; +#if SLANG_APPLE_FAMILY + instanceExtensions.add(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); +#endif instanceExtensions.add(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); instanceExtensions.add(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); @@ -185,6 +188,8 @@ Result DeviceImpl::initVulkanInstanceAndDevice( // instanceExtensions.add("VK_GOOGLE_surfaceless_query"); #if SLANG_WINDOWS_FAMILY instanceExtensions.add(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); +#elif SLANG_APPLE_FAMILY + instanceExtensions.add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); #elif defined(SLANG_ENABLE_XLIB) instanceExtensions.add(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); @@ -195,6 +200,9 @@ Result DeviceImpl::initVulkanInstanceAndDevice( instanceExtensions.add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; +#if SLANG_APPLE_FAMILY + instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; +#endif instanceCreateInfo.pApplicationInfo = &applicationInfo; instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.getCount(); instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0]; @@ -352,6 +360,9 @@ Result DeviceImpl::initVulkanInstanceAndDevice( List<const char*> deviceExtensions; deviceExtensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME); +#if SLANG_APPLE_FAMILY + deviceExtensions.add("VK_KHR_portability_subset"); +#endif VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; deviceCreateInfo.queueCreateInfoCount = 1; diff --git a/tools/gfx/vulkan/vk-module.cpp b/tools/gfx/vulkan/vk-module.cpp index cff75569e..0e4df8e7f 100644 --- a/tools/gfx/vulkan/vk-module.cpp +++ b/tools/gfx/vulkan/vk-module.cpp @@ -32,6 +32,9 @@ Slang::Result VulkanModule::init(bool useSoftwareImpl) dynamicLibraryName = useSoftwareImpl ? "vk_swiftshader.dll" : "vulkan-1.dll"; HMODULE module = ::LoadLibraryA(dynamicLibraryName); m_module = (void*)module; +#elif SLANG_APPLE_FAMILY + dynamicLibraryName = useSoftwareImpl ? "libvk_swiftshader.dylib" : "libvulkan.1.dylib"; + m_module = dlopen(dynamicLibraryName, RTLD_NOW | RTLD_GLOBAL); #else dynamicLibraryName = useSoftwareImpl ? "libvk_swiftshader.so" : "libvulkan.so.1"; if (useSoftwareImpl) diff --git a/tools/gfx/vulkan/vk-module.h b/tools/gfx/vulkan/vk-module.h index 97a0c8aba..9b8fe0ed3 100644 --- a/tools/gfx/vulkan/vk-module.h +++ b/tools/gfx/vulkan/vk-module.h @@ -7,6 +7,8 @@ #if SLANG_WINDOWS_FAMILY # define VK_USE_PLATFORM_WIN32_KHR 1 +#elif SLANG_APPLE_FAMILY +# define VK_USE_PLATFORM_MACOS_MVK 1 #else # define VK_USE_PLATFORM_XLIB_KHR 1 #endif diff --git a/tools/gfx/vulkan/vk-swap-chain.cpp b/tools/gfx/vulkan/vk-swap-chain.cpp index 384ca86ed..856fa2489 100644 --- a/tools/gfx/vulkan/vk-swap-chain.cpp +++ b/tools/gfx/vulkan/vk-swap-chain.cpp @@ -2,6 +2,7 @@ #include "vk-swap-chain.h" #include "vk-util.h" +#include "../apple/cocoa-util.h" namespace gfx { @@ -38,6 +39,8 @@ void SwapchainImpl::getWindowSize(int* widthOut, int* heightOut) const ::GetClientRect((HWND)m_windowHandle.handleValues[0], &rc); *widthOut = rc.right - rc.left; *heightOut = rc.bottom - rc.top; +#elif SLANG_APPLE_FAMILY + CocoaUtil::getNSViewRectSize((void*)m_windowHandle.handleValues[0], widthOut, heightOut); #elif defined(SLANG_ENABLE_XLIB) XWindowAttributes winAttr = {}; XGetWindowAttributes( @@ -221,6 +224,12 @@ Result SwapchainImpl::init(DeviceImpl* renderer, const ISwapchain::Desc& desc, W surfaceCreateInfo.hwnd = (HWND)window.handleValues[0]; SLANG_VK_RETURN_ON_FAIL( m_api->vkCreateWin32SurfaceKHR(m_api->m_instance, &surfaceCreateInfo, nullptr, &m_surface)); +#elif SLANG_APPLE_FAMILY + VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; + surfaceCreateInfo.pView = (void*)window.handleValues[0]; + SLANG_VK_RETURN_ON_FAIL( + m_api->vkCreateMacOSSurfaceMVK(m_api->m_instance, &surfaceCreateInfo, nullptr, &m_surface)); #elif SLANG_ENABLE_XLIB VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = {}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; @@ -347,7 +356,12 @@ int SwapchainImpl::acquireNextImage() VK_NULL_HANDLE, (uint32_t*)&m_currentImageIndex); - if (result != VK_SUCCESS) + if ( + result != VK_SUCCESS +#if SLANG_APPLE_FAMILY + && result != VK_SUBOPTIMAL_KHR +#endif + ) { m_currentImageIndex = -1; destroySwapchainAndImages(); diff --git a/tools/gfx/vulkan/vk-swap-chain.h b/tools/gfx/vulkan/vk-swap-chain.h index 6a39e2afa..2c0fe62ed 100644 --- a/tools/gfx/vulkan/vk-swap-chain.h +++ b/tools/gfx/vulkan/vk-swap-chain.h @@ -23,23 +23,6 @@ public: ISwapchain* getInterface(const Guid& guid); public: - struct PlatformDesc - {}; - -#if SLANG_WINDOWS_FAMILY - struct WinPlatformDesc : public PlatformDesc - { - HINSTANCE m_hinstance; - HWND m_hwnd; - }; -#else - struct XPlatformDesc : public PlatformDesc - { - Display* m_display; - Window m_window; - }; -#endif -public: VkSwapchainKHR m_swapChain; VkSurfaceKHR m_surface; VkSemaphore m_nextImageSemaphore; // Semaphore to signal after `acquireNextImage`. diff --git a/tools/platform/apple/cocoa-window.mm b/tools/platform/apple/cocoa-window.mm new file mode 100644 index 000000000..450087dd2 --- /dev/null +++ b/tools/platform/apple/cocoa-window.mm @@ -0,0 +1,618 @@ +#ifdef __APPLE__ + +#include "../window.h" + +#import <Cocoa/Cocoa.h> +#import <QuartzCore/CAMetalLayer.h> + +using namespace Slang; +using namespace platform; + +namespace platform { +class CocoaPlatformWindow; +static KeyCode keyCodes[256]; + +class CocoaAppContext +{ +public: + static Window* mainWindow; + static bool isTerminated; +}; + +Window* CocoaAppContext::mainWindow; +bool CocoaAppContext::isTerminated = false; +} + +@interface WindowDelegate : NSObject <NSWindowDelegate> +{ + CocoaPlatformWindow* window; +} + +- (instancetype)initWithPlatformWindow:(CocoaPlatformWindow*)platformWindow; + +@end + +@interface ContentView : NSView +{ + CocoaPlatformWindow* window; + NSTrackingArea* trackingArea; + int mouseX, mouseY; +} + +- (instancetype)initWithPlatformWindow:(CocoaPlatformWindow*)platformWindow; + +@end + +namespace platform { + +class CocoaPlatformWindow : public Window +{ +public: + NSWindow* window; + WindowDelegate* delegate; + ContentView* view; + CAMetalLayer* layer; + bool shouldClose = false; + + CocoaPlatformWindow(const WindowDesc& desc); + ~CocoaPlatformWindow(); + + virtual void setClientSize(uint32_t width, uint32_t height) override; + virtual Rect getClientRect() override; + virtual void centerScreen() override; + virtual void close() override; + virtual bool getFocused() override; + virtual bool getVisible() override; + virtual WindowHandle getNativeHandle() override; + virtual void setText(Slang::String text) override; + virtual void show() override; + virtual void hide() override; + virtual int getCurrentDpi() override; +}; + +void getMousePosition(NSEvent* event, NSView* view, int& x, int& y) +{ + const NSRect contentRect = [view frame]; + const NSPoint pos = [event locationInWindow]; + x = (int)pos.x; + y = (int)(contentRect.size.height - pos.y); +} + +ButtonState::Enum _addButtonState(ButtonState::Enum val, ButtonState::Enum newState) +{ + return (ButtonState::Enum)((int)val | (int)newState); +} + +static ButtonState::Enum getModifierState(NSUInteger flags) +{ + ButtonState::Enum result = ButtonState::None; + + if (flags & NSEventModifierFlagShift) + result = _addButtonState(result, ButtonState::Shift); + if (flags & NSEventModifierFlagControl) + result = _addButtonState(result, ButtonState::Control); + if (flags & NSEventModifierFlagOption) + result = _addButtonState(result, ButtonState::Alt); + return result; +} + +static KeyCode getKeyCode(NSUInteger keyCode) +{ + return keyCode < 256 ? keyCodes[keyCode] : KeyCode::None; +} + +} + + +@implementation WindowDelegate + +- (instancetype)initWithPlatformWindow:(CocoaPlatformWindow*)platformWindow +{ + self = [super init]; + if (self) + { + window = platformWindow; + } + return self; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender +{ + return YES; +} + +- (BOOL)windowShouldClose:(id)window_ +{ + window->shouldClose = true; + if (CocoaAppContext::mainWindow == window) + CocoaAppContext::isTerminated = true; + return YES; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + printf("applicationShouldTerminate\n"); + return NSTerminateCancel; +} + +- (void)windowDidResize:(NSNotification*)notification +{ + window->events.sizeChanged(); +} + +- (void)windowDidBecomeKey:(NSNotification*)notification +{ + window->events.focus(); +} + +- (void)windowDidResignKey:(NSNotification*)notification +{ + window->events.lostFocus(); +} + +@end + +@implementation ContentView + +- (instancetype)initWithPlatformWindow:(CocoaPlatformWindow*)platformWindow +{ + self = [super init]; + if (self) + { + window = platformWindow; + mouseX = 0; + mouseY = 0; + [self updateTrackingAreas]; + } + return self; +} + +- (void)updateTrackingAreas +{ + if (trackingArea != nil) + { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingActiveInKeyWindow | + NSTrackingEnabledDuringMouseDrag | + NSTrackingCursorUpdate | + NSTrackingInVisibleRect | + NSTrackingAssumeInside; + + trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; + [super updateTrackingAreas]; +} + +- (BOOL)isOpaque +{ + return YES; +} + +- (BOOL)canBecomeKeyView +{ + return YES; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)acceptsFirstMouse:(NSEvent*)event +{ + return YES; +} + +- (BOOL)wantsUpdateLayer +{ + return YES; +} + +- (void)mouseDown:(NSEvent*)event +{ + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::LeftButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseDown(MouseEventArgs{mouseX, mouseY, 0, buttons}); +} + +- (void)mouseUp:(NSEvent*)event +{ + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::LeftButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseUp(MouseEventArgs{mouseX, mouseY, 0, buttons}); +} + +- (void)rightMouseDown:(NSEvent*)event +{ + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::RightButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseDown(MouseEventArgs{mouseX, mouseY, 0, buttons}); +} + +- (void)rightMouseUp:(NSEvent*)event +{ + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::RightButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseUp(MouseEventArgs{mouseX, mouseY, 0, buttons}); +} + +- (void)otherMouseDown:(NSEvent *)event +{ + if ([event buttonNumber] == 2) + { + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::MiddleButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseDown(MouseEventArgs{mouseX, mouseY, 0, buttons}); + } +} + +- (void)otherMouseUp:(NSEvent *)event +{ + if ([event buttonNumber] == 2) + { + getMousePosition(event, self, mouseX, mouseY); + ButtonState::Enum buttons = ButtonState::MiddleButton; + buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); + window->events.mouseUp(MouseEventArgs{mouseX, mouseY, 0, buttons}); + } +} + +- (void)mouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)rightMouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)otherMouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)mouseMoved:(NSEvent*)event +{ + getMousePosition(event, self, mouseX, mouseY); + window->events.mouseMove(MouseEventArgs{mouseX, mouseY, 0, getModifierState([event modifierFlags])}); +} + +- (void)scrollWheel:(NSEvent *)event +{ + double deltaX = [event scrollingDeltaX]; + double deltaY = [event scrollingDeltaY]; + if ([event hasPreciseScrollingDeltas]) + { + deltaX *= 0.1; + deltaY *= 0.1; + } + + int delta = (int)deltaY; + + window->events.mouseWheel(MouseEventArgs{0, 0, delta, getModifierState([event modifierFlags])}); +} + +- (void)keyDown:(NSEvent *)event +{ + KeyCode key = getKeyCode([event keyCode]); + if (key == KeyCode::None) + return; + KeyEventArgs keyEventArgs = {key, 0, getModifierState([event modifierFlags]), false}; + window->events.keyDown(keyEventArgs); + // if (!keyEventArgs.cancelEvent) + // [self interpretKeyEvents:@[event]]; +} + +- (void)keyUp:(NSEvent *)event +{ + KeyCode key = getKeyCode([event keyCode]); + if (key == KeyCode::None) + return; + KeyEventArgs keyEventArgs = {key, 0, getModifierState([event modifierFlags]), false}; + window->events.keyUp(keyEventArgs); + // if (!keyEventArgs.cancelEvent) + // [self interpretKeyEvents:@[event]]; +} + +- (void)flagsChanged:(NSEvent *)event +{ + KeyCode key = getKeyCode([event keyCode]); + ButtonState::Enum buttons = getModifierState([event modifierFlags]); + ButtonState::Enum button = ButtonState::None; + if (key == KeyCode::Shift) + button = ButtonState::Shift; + else if (key == KeyCode::Ctrl) + button = ButtonState::Control; + else if (key == KeyCode::Alt) + button = ButtonState::Alt; + + KeyEventArgs keyEventArgs = {key, 0, buttons, false}; + if (button & buttons) { + window->events.keyDown(keyEventArgs); + } else { + window->events.keyUp(keyEventArgs); + } +} + +@end + + +static NSApplication *_application; + + +namespace platform { + +void Application::init() +{ + _application = [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + [NSApp activateIgnoringOtherApps:YES]; + + // Setup key translation table. + ::memset(keyCodes, (int)KeyCode::None, sizeof(keyCodes)); + + keyCodes[0x1D] = KeyCode::Key0; + keyCodes[0x12] = KeyCode::Key1; + keyCodes[0x13] = KeyCode::Key2; + keyCodes[0x14] = KeyCode::Key3; + keyCodes[0x15] = KeyCode::Key4; + keyCodes[0x17] = KeyCode::Key5; + keyCodes[0x16] = KeyCode::Key6; + keyCodes[0x1A] = KeyCode::Key7; + keyCodes[0x1C] = KeyCode::Key8; + keyCodes[0x19] = KeyCode::Key9; + keyCodes[0x00] = KeyCode::A; + keyCodes[0x0B] = KeyCode::B; + keyCodes[0x08] = KeyCode::C; + keyCodes[0x02] = KeyCode::D; + keyCodes[0x0E] = KeyCode::E; + keyCodes[0x03] = KeyCode::F; + keyCodes[0x05] = KeyCode::G; + keyCodes[0x04] = KeyCode::H; + keyCodes[0x22] = KeyCode::I; + keyCodes[0x26] = KeyCode::J; + keyCodes[0x28] = KeyCode::K; + keyCodes[0x25] = KeyCode::L; + keyCodes[0x2E] = KeyCode::M; + keyCodes[0x2D] = KeyCode::N; + keyCodes[0x1F] = KeyCode::O; + keyCodes[0x23] = KeyCode::P; + keyCodes[0x0C] = KeyCode::Q; + keyCodes[0x0F] = KeyCode::R; + keyCodes[0x01] = KeyCode::S; + keyCodes[0x11] = KeyCode::T; + keyCodes[0x20] = KeyCode::U; + keyCodes[0x09] = KeyCode::V; + keyCodes[0x0D] = KeyCode::W; + keyCodes[0x07] = KeyCode::X; + keyCodes[0x10] = KeyCode::Y; + keyCodes[0x06] = KeyCode::Z; + + keyCodes[0x27] = KeyCode::Quote; + keyCodes[0x2A] = KeyCode::Backslash; + keyCodes[0x2B] = KeyCode::Comma; + keyCodes[0x18] = KeyCode::Plus; + keyCodes[0x32] = KeyCode::Tilde; + keyCodes[0x21] = KeyCode::LBracket; + keyCodes[0x1B] = KeyCode::Minus; + keyCodes[0x2F] = KeyCode::Dot; + keyCodes[0x1E] = KeyCode::RBracket; + keyCodes[0x29] = KeyCode::Semicolon; + keyCodes[0x2C] = KeyCode::Slash; + + keyCodes[0x33] = KeyCode::Backspace; + keyCodes[0x75] = KeyCode::Delete; + keyCodes[0x7D] = KeyCode::Down; + keyCodes[0x77] = KeyCode::End; + keyCodes[0x24] = KeyCode::Return; + keyCodes[0x35] = KeyCode::Escape; + keyCodes[0x7A] = KeyCode::F1; + keyCodes[0x78] = KeyCode::F2; + keyCodes[0x63] = KeyCode::F3; + keyCodes[0x76] = KeyCode::F4; + keyCodes[0x60] = KeyCode::F5; + keyCodes[0x61] = KeyCode::F6; + keyCodes[0x62] = KeyCode::F7; + keyCodes[0x64] = KeyCode::F8; + keyCodes[0x65] = KeyCode::F9; + keyCodes[0x6D] = KeyCode::F10; + keyCodes[0x67] = KeyCode::F11; + keyCodes[0x6F] = KeyCode::F12; + keyCodes[0x73] = KeyCode::Home; + keyCodes[0x72] = KeyCode::Insert; + keyCodes[0x7B] = KeyCode::Left; + keyCodes[0x79] = KeyCode::PageDown; + keyCodes[0x74] = KeyCode::PageUp; + keyCodes[0x7C] = KeyCode::Right; + keyCodes[0x31] = KeyCode::Space; + keyCodes[0x30] = KeyCode::Tab; + keyCodes[0x7E] = KeyCode::Up; + + keyCodes[0x38] = KeyCode::Shift; + keyCodes[0x3B] = KeyCode::Ctrl; + keyCodes[0x3A] = KeyCode::Alt; +} + +void doEventsImpl(bool waitForEvents) +{ + NSEvent *event; + do { + event = [NSApp nextEventMatchingMask:NSEventMaskAny + untilDate:waitForEvents ? [NSDate distantFuture] : [NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if (event) { + [NSApp sendEvent:event]; + } + } while (!CocoaAppContext::isTerminated && event); +} + +void Application::doEvents() +{ + doEventsImpl(false); +} + +void Application::quit() +{ + CocoaAppContext::isTerminated = true; +} + +void Application::dispose() +{ + CocoaAppContext::mainWindow = nullptr; +} + +void Application::run(Window* mainWindow, bool waitForEvents) +{ + if (mainWindow) + { + CocoaAppContext::mainWindow = mainWindow; + mainWindow->show(); + } + while (!CocoaAppContext::isTerminated) + { + doEventsImpl(waitForEvents); + if (CocoaAppContext::isTerminated) + break; + if (mainWindow) + { + mainWindow->events.mainLoop(); + } + } +} + +CocoaPlatformWindow::CocoaPlatformWindow(const WindowDesc& desc) +{ + // Create a reference rectangle + NSRect rect = NSMakeRect(0.0f, 0.0f, desc.width, desc.height); + + // Allocate window + window = [[NSWindow alloc] initWithContentRect:rect + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable + backing:NSBackingStoreBuffered + defer:NO]; + + const NSWindowCollectionBehavior behavior + = NSWindowCollectionBehaviorFullScreenPrimary | NSWindowCollectionBehaviorManaged; + [window setCollectionBehavior:behavior]; + + if (desc.style == WindowStyle::Default) + [window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; + else if (desc.style == WindowStyle::FixedSize) + [window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable]; + + // Allocate view + rect = [window backingAlignedRect:rect options:NSAlignAllEdgesOutward]; + view = [[ContentView alloc] initWithPlatformWindow:this]; + [view setHidden:NO]; + [view setNeedsDisplay:YES]; + [view setWantsLayer:YES]; + + delegate = [[WindowDelegate alloc] initWithPlatformWindow:this]; + [window setDelegate:delegate]; + [window setContentView:view]; + + NSString* title = [NSString stringWithUTF8String:desc.title]; + [window setTitle:title]; + + [window center]; + [window makeKeyAndOrderFront:nil]; + + // Setup layer + layer = [[CAMetalLayer alloc] init]; + [view setLayer:layer]; +} + +CocoaPlatformWindow::~CocoaPlatformWindow() +{ + close(); +} + +void CocoaPlatformWindow::setClientSize(uint32_t width, uint32_t height) +{ + NSSize size = NSMakeSize(width, height); + [window setContentSize:size]; +} + +Rect CocoaPlatformWindow::getClientRect() +{ + NSRect rect = [window contentRectForFrameRect:[window frame]]; + return { (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height }; +} + +void CocoaPlatformWindow::centerScreen() +{ + [window center]; +} + +void CocoaPlatformWindow::close() +{ + [window release]; + [delegate release]; + [view release]; + [layer release]; + + window = nil; + delegate = nil; + view = nil; + layer = nil; +} + +bool CocoaPlatformWindow::getFocused() +{ + return [window isKeyWindow]; +} + +bool CocoaPlatformWindow::getVisible() +{ + return [window isVisible]; +} + +WindowHandle CocoaPlatformWindow::getNativeHandle() +{ + return WindowHandle::fromNSView(view); +} + +void CocoaPlatformWindow::setText(Slang::String text) +{ + NSString* title = [NSString stringWithUTF8String:text.begin()]; + [window setTitle:title]; +} + +void CocoaPlatformWindow::show() +{ + [window setIsVisible:YES]; +} + +void CocoaPlatformWindow::hide() +{ + [window setIsVisible:NO]; +} + +int CocoaPlatformWindow::getCurrentDpi() +{ + // There seems to be no API to get the actual DPI of the screen. + return 0; +} + +Window* Application::createWindow(const WindowDesc& desc) { return new CocoaPlatformWindow(desc); } + + +} // namespace platform + +#endif // __APPLE__ diff --git a/tools/platform/placeholder/placeholder-window.cpp b/tools/platform/placeholder/placeholder-window.cpp index a94287d55..ae4f413f8 100644 --- a/tools/platform/placeholder/placeholder-window.cpp +++ b/tools/platform/placeholder/placeholder-window.cpp @@ -1,4 +1,4 @@ -#if !defined(_WIN32) && !defined(SLANG_ENABLE_XLIB) +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(SLANG_ENABLE_XLIB) #include "../window.h" diff --git a/tools/platform/window.h b/tools/platform/window.h index f80e21302..7f78b8af9 100644 --- a/tools/platform/window.h +++ b/tools/platform/window.h @@ -97,6 +97,7 @@ struct WindowHandle { Unknown, Win32Handle, + NSViewHandle, XLibHandle, }; Type type; @@ -108,6 +109,13 @@ struct WindowHandle handle.handleValues[0] = (intptr_t)(hwnd); return handle; } + static WindowHandle fromNSView(void* nsview) + { + WindowHandle handle = {}; + handle.type = WindowHandle::Type::NSViewHandle; + handle.handleValues[0] = (intptr_t)(nsview); + return handle; + } static WindowHandle fromXWindow(void* xdisplay, uint32_t xwindow) { WindowHandle handle = {}; |
