yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
4f03eb9d6
master
1#ifdef __APPLE__ 2 3#include "../window.h" 4 5#import <Cocoa/Cocoa.h> 6#import <QuartzCore/CAMetalLayer.h> 7 8using namespace Slang ; 9using namespace platform ; 10 11namespace platform { 12class CocoaPlatformWindow ; 13static KeyCode keyCodes [256 ]; 14 15class CocoaAppContext 16{ 17public : 18static Window * mainWindow ; 19static bool isTerminated ; 20}; 21 22Window * CocoaAppContext ::mainWindow ; 23bool CocoaAppContext ::isTerminated = false; 24} 25 26@interface WindowDelegate :NSObject < NSWindowDelegate > 27{ 28CocoaPlatformWindow * window ; 29} 30 31- (instancetype )initWithPlatformWindow : (CocoaPlatformWindow * )platformWindow ; 32 33@end 34 35@interface ContentView :NSView 36{ 37CocoaPlatformWindow * window ; 38NSTrackingArea * trackingArea ; 39int mouseX ,mouseY ; 40} 41 42- (instancetype )initWithPlatformWindow : (CocoaPlatformWindow * )platformWindow ; 43 44@end 45 46namespace platform { 47 48class CocoaPlatformWindow :public Window 49{ 50public : 51NSWindow * window ; 52WindowDelegate * delegate ; 53bool shouldClose = false; 54 55CocoaPlatformWindow (const WindowDesc & desc ); 56 ~CocoaPlatformWindow (); 57 58virtual void setClientSize (uint32_t width ,uint32_t height )override ; 59virtual Rect getClientRect ()override ; 60virtual void centerScreen() override; 61virtual void close() override; 62virtual bool getFocused() override; 63virtual bool getVisible() override; 64virtual WindowHandle getNativeHandle() override; 65virtual void setText( Slang ::String text) override; 66virtual void show() override; 67virtual void hide() override; 68virtual int getCurrentDpi() override; 69}; 70 71void getMousePosition( NSEvent * event, NSView * view, int & x, int & y) 72{ 73const NSRect contentRect = [view frame]; 74const NSPoint pos = [event locationInWindow]; 75x = ( int )pos.x; 76y = ( int )(contentRect.size.height - pos.y); 77} 78 79ButtonState :: Enum _addButtonState( ButtonState ::Enum val, ButtonState ::Enum newState) 80{ 81return (ButtonState::Enum)(( int )val | ( int )newState); 82} 83 84static ButtonState ::Enum getModifierState( NSUInteger flags) 85{ 86ButtonState :: Enum result = ButtonState::None; 87 88if (flags & NSEventModifierFlagShift) 89result = _addButtonState(result, ButtonState::Shift); 90if (flags & NSEventModifierFlagControl) 91result = _addButtonState(result, ButtonState::Control); 92if (flags & NSEventModifierFlagOption) 93result = _addButtonState(result, ButtonState::Alt); 94return result; 95} 96 97static KeyCode getKeyCode( NSUInteger keyCode) 98{ 99return keyCode < 256 ? keyCodes[keyCode] : KeyCode::None; 100} 101 102} 103 104 105@implementation WindowDelegate 106 107- ( instancetype )initWithPlatformWindow : ( CocoaPlatformWindow * ) platformWindow 108{ 109self = [super init]; 110if (self) 111{ 112window = platformWindow; 113} 114return self; 115} 116 117- ( BOOL )applicationShouldTerminateAfterLastWindowClosed : ( NSApplication * ) sender 118{ 119return YES; 120} 121 122- ( BOOL )windowShouldClose : ( id ) window_ 123{ 124window -> shouldClose = true; 125if (CocoaAppContext::mainWindow == window) 126CocoaAppContext ::isTerminated = true; 127return YES; 128} 129 130- ( NSApplicationTerminateReply )applicationShouldTerminate : ( NSApplication * ) sender 131{ 132printf( "applicationShouldTerminate\n" ); 133return NSTerminateCancel; 134} 135 136- ( void )windowDidResize : ( NSNotification * ) notification 137{ 138window -> events. sizeChanged (); 139} 140 141- ( void )windowDidBecomeKey : ( NSNotification * ) notification 142{ 143window -> events. focus (); 144} 145 146- ( void )windowDidResignKey : ( NSNotification * ) notification 147{ 148window -> events. lostFocus (); 149} 150 151@end 152 153@implementation ContentView 154 155- ( instancetype )initWithPlatformWindow : ( CocoaPlatformWindow * ) platformWindow 156{ 157self = [super init]; 158if (self) 159{ 160window = platformWindow; 161mouseX = 0 ; 162mouseY = 0 ; 163[self updateTrackingAreas]; 164} 165return self; 166} 167 168- ( void )updateTrackingAreas 169{ 170if (trackingArea != nil) 171{ 172[self removeTrackingArea:trackingArea]; 173[trackingArea release]; 174} 175 176const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | 177NSTrackingMouseMoved | 178NSTrackingActiveInKeyWindow | 179NSTrackingEnabledDuringMouseDrag | 180NSTrackingCursorUpdate | 181NSTrackingInVisibleRect | 182NSTrackingAssumeInside; 183 184trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] 185options:options 186owner:self 187userInfo:nil]; 188 189[self addTrackingArea:trackingArea]; 190[super updateTrackingAreas]; 191} 192 193- ( BOOL )isOpaque 194{ 195return YES; 196} 197 198- ( BOOL )canBecomeKeyView 199{ 200return YES; 201} 202 203- ( BOOL )acceptsFirstResponder 204{ 205return YES; 206} 207 208- ( BOOL )acceptsFirstMouse : ( NSEvent * ) event 209{ 210return YES; 211} 212 213- ( BOOL )wantsUpdateLayer 214{ 215return YES; 216} 217 218- ( void )mouseDown : ( NSEvent * ) event 219{ 220getMousePosition(event, self, mouseX, mouseY); 221ButtonState :: Enum buttons = ButtonState::LeftButton; 222buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 223window -> events. mouseDown (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 224} 225 226- ( void )mouseUp : ( NSEvent * ) event 227{ 228getMousePosition(event, self, mouseX, mouseY); 229ButtonState :: Enum buttons = ButtonState::LeftButton; 230buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 231window -> events. mouseUp (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 232} 233 234- ( void )rightMouseDown : ( NSEvent * ) event 235{ 236getMousePosition(event, self, mouseX, mouseY); 237ButtonState :: Enum buttons = ButtonState::RightButton; 238buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 239window -> events. mouseDown (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 240} 241 242- ( void )rightMouseUp : ( NSEvent * ) event 243{ 244getMousePosition(event, self, mouseX, mouseY); 245ButtonState :: Enum buttons = ButtonState::RightButton; 246buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 247window -> events. mouseUp (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 248} 249 250- ( void )otherMouseDown : ( NSEvent * ) event 251{ 252if ([event buttonNumber] == 2 ) 253{ 254getMousePosition(event, self, mouseX, mouseY); 255ButtonState :: Enum buttons = ButtonState::MiddleButton; 256buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 257window -> events. mouseDown (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 258} 259} 260 261- ( void )otherMouseUp : ( NSEvent * ) event 262{ 263if ([event buttonNumber] == 2 ) 264{ 265getMousePosition(event, self, mouseX, mouseY); 266ButtonState :: Enum buttons = ButtonState::MiddleButton; 267buttons = _addButtonState(buttons, getModifierState([event modifierFlags])); 268window -> events. mouseUp (MouseEventArgs{mouseX, mouseY, 0 , buttons}); 269} 270} 271 272- ( void )mouseDragged : ( NSEvent * ) event 273{ 274[self mouseMoved:event]; 275} 276 277- ( void )rightMouseDragged : ( NSEvent * ) event 278{ 279[self mouseMoved:event]; 280} 281 282- ( void )otherMouseDragged : ( NSEvent * ) event 283{ 284[self mouseMoved:event]; 285} 286 287- ( void )mouseMoved : ( NSEvent * ) event 288{ 289getMousePosition(event, self, mouseX, mouseY); 290window -> events. mouseMove (MouseEventArgs{mouseX, mouseY, 0 , getModifierState([event modifierFlags])}); 291} 292 293- ( void )scrollWheel : ( NSEvent * ) event 294{ 295double deltaX = [event scrollingDeltaX]; 296double deltaY = [event scrollingDeltaY]; 297if ([event hasPreciseScrollingDeltas]) 298{ 299deltaX *= 0.1 ; 300deltaY *= 0.1 ; 301} 302 303int delta = ( int )deltaY; 304 305window -> events. mouseWheel (MouseEventArgs{ 0 , 0 , delta, getModifierState([event modifierFlags])}); 306} 307 308- ( void )keyDown : ( NSEvent * ) event 309{ 310KeyCode key = getKeyCode([event keyCode]); 311if (key == KeyCode::None) 312return ; 313KeyEventArgs keyEventArgs = {key, 0 , getModifierState([event modifierFlags]), false}; 314window -> events. keyDown (keyEventArgs); 315// if (!keyEventArgs.cancelEvent) 316// [self interpretKeyEvents:@[event]]; 317} 318 319- ( void )keyUp : ( NSEvent * ) event 320{ 321KeyCode key = getKeyCode([event keyCode]); 322if (key == KeyCode::None) 323return ; 324KeyEventArgs keyEventArgs = {key, 0 , getModifierState([event modifierFlags]), false}; 325window -> events. keyUp (keyEventArgs); 326// if (!keyEventArgs.cancelEvent) 327// [self interpretKeyEvents:@[event]]; 328} 329 330- ( void )flagsChanged : ( NSEvent * ) event 331{ 332KeyCode key = getKeyCode([event keyCode]); 333ButtonState :: Enum buttons = getModifierState([event modifierFlags]); 334ButtonState :: Enum button = ButtonState::None; 335if (key == KeyCode::Shift) 336button = ButtonState::Shift; 337else if (key == KeyCode::Ctrl) 338button = ButtonState::Control; 339else if (key == KeyCode::Alt) 340button = ButtonState::Alt; 341342 KeyEventArgs keyEventArgs = {key, 0 , buttons, false}; 343if (button & buttons) { 344window -> events. keyDown (keyEventArgs); 345} else { 346window -> events. keyUp (keyEventArgs); 347} 348} 349 350@end 351 352 353static NSApplication * _application; 354 355 356namespace platform { 357 358void Application::init() 359{ 360_application = [NSApplication sharedApplication]; 361[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; 362[NSApp activateIgnoringOtherApps:YES]; 363 364// Setup key translation table. 365::memset(keyCodes, ( int )KeyCode::None, sizeof (keyCodes)); 366 367keyCodes[ 0x1D ] = KeyCode::Key0; 368keyCodes[ 0x12 ] = KeyCode::Key1; 369keyCodes[ 0x13 ] = KeyCode::Key2; 370keyCodes[ 0x14 ] = KeyCode::Key3; 371keyCodes[ 0x15 ] = KeyCode::Key4; 372keyCodes[ 0x17 ] = KeyCode::Key5; 373keyCodes[ 0x16 ] = KeyCode::Key6; 374keyCodes[ 0x1A ] = KeyCode::Key7; 375keyCodes[ 0x1C ] = KeyCode::Key8; 376keyCodes[ 0x19 ] = KeyCode::Key9; 377keyCodes[ 0x00 ] = KeyCode::A; 378keyCodes[ 0x0B ] = KeyCode::B; 379keyCodes[ 0x08 ] = KeyCode::C; 380keyCodes[ 0x02 ] = KeyCode::D; 381keyCodes[ 0x0E ] = KeyCode::E; 382keyCodes[ 0x03 ] = KeyCode::F; 383keyCodes[ 0x05 ] = KeyCode::G; 384keyCodes[ 0x04 ] = KeyCode::H; 385keyCodes[ 0x22 ] = KeyCode::I; 386keyCodes[ 0x26 ] = KeyCode::J; 387keyCodes[ 0x28 ] = KeyCode::K; 388keyCodes[ 0x25 ] = KeyCode::L; 389keyCodes[ 0x2E ] = KeyCode::M; 390keyCodes[ 0x2D ] = KeyCode::N; 391keyCodes[ 0x1F ] = KeyCode::O; 392keyCodes[ 0x23 ] = KeyCode::P; 393keyCodes[ 0x0C ] = KeyCode::Q; 394keyCodes[ 0x0F ] = KeyCode::R; 395keyCodes[ 0x01 ] = KeyCode::S; 396keyCodes[ 0x11 ] = KeyCode::T; 397keyCodes[ 0x20 ] = KeyCode::U; 398keyCodes[ 0x09 ] = KeyCode::V; 399keyCodes[ 0x0D ] = KeyCode::W; 400keyCodes[ 0x07 ] = KeyCode::X; 401keyCodes[ 0x10 ] = KeyCode::Y; 402keyCodes[ 0x06 ] = KeyCode::Z; 403 404keyCodes[ 0x27 ] = KeyCode::Quote; 405keyCodes[ 0x2A ] = KeyCode::Backslash; 406keyCodes[ 0x2B ] = KeyCode::Comma; 407keyCodes[ 0x18 ] = KeyCode::Plus; 408keyCodes[ 0x32 ] = KeyCode::Tilde; 409keyCodes[ 0x21 ] = KeyCode::LBracket; 410keyCodes[ 0x1B ] = KeyCode::Minus; 411keyCodes[ 0x2F ] = KeyCode::Dot; 412keyCodes[ 0x1E ] = KeyCode::RBracket; 413keyCodes[ 0x29 ] = KeyCode::Semicolon; 414keyCodes[ 0x2C ] = KeyCode::Slash; 415 416keyCodes[ 0x33 ] = KeyCode::Backspace; 417keyCodes[ 0x75 ] = KeyCode::Delete; 418keyCodes[ 0x7D ] = KeyCode::Down; 419keyCodes[ 0x77 ] = KeyCode::End; 420keyCodes[ 0x24 ] = KeyCode::Return; 421keyCodes[ 0x35 ] = KeyCode::Escape; 422keyCodes[ 0x7A ] = KeyCode::F1; 423keyCodes[ 0x78 ] = KeyCode::F2; 424keyCodes[ 0x63 ] = KeyCode::F3; 425keyCodes[ 0x76 ] = KeyCode::F4; 426keyCodes[ 0x60 ] = KeyCode::F5; 427keyCodes[ 0x61 ] = KeyCode::F6; 428keyCodes[ 0x62 ] = KeyCode::F7; 429keyCodes[ 0x64 ] = KeyCode::F8; 430keyCodes[ 0x65 ] = KeyCode::F9; 431keyCodes[ 0x6D ] = KeyCode::F10; 432keyCodes[ 0x67 ] = KeyCode::F11; 433keyCodes[ 0x6F ] = KeyCode::F12; 434keyCodes[ 0x73 ] = KeyCode::Home; 435keyCodes[ 0x72 ] = KeyCode::Insert; 436keyCodes[ 0x7B ] = KeyCode::Left; 437keyCodes[ 0x79 ] = KeyCode::PageDown; 438keyCodes[ 0x74 ] = KeyCode::PageUp; 439keyCodes[ 0x7C ] = KeyCode::Right; 440keyCodes[ 0x31 ] = KeyCode::Space; 441keyCodes[ 0x30 ] = KeyCode::Tab; 442keyCodes[ 0x7E ] = KeyCode::Up; 443 444keyCodes[ 0x38 ] = KeyCode::Shift; 445keyCodes[ 0x3B ] = KeyCode::Ctrl; 446keyCodes[ 0x3A ] = KeyCode::Alt; 447} 448 449void doEventsImpl( bool waitForEvents) 450{ 451NSEvent * event; 452do { 453event = [NSApp nextEventMatchingMask:NSEventMaskAny 454untilDate:waitForEvents ? [NSDate distantFuture] : [NSDate distantPast] 455inMode:NSDefaultRunLoopMode 456dequeue:YES]; 457if (event) { 458[NSApp sendEvent:event]; 459} 460} while (!CocoaAppContext::isTerminated && event); 461} 462 463void Application::doEvents() 464{ 465doEventsImpl(false); 466} 467 468void Application::quit() 469{ 470CocoaAppContext ::isTerminated = true; 471} 472 473void Application::dispose() 474{ 475CocoaAppContext ::mainWindow = nullptr ; 476} 477 478void Application::run( Window * mainWindow, bool waitForEvents) 479{ 480if (mainWindow) 481{ 482CocoaAppContext ::mainWindow = mainWindow; 483mainWindow -> show (); 484} 485while (!CocoaAppContext::isTerminated) 486{ 487doEventsImpl(waitForEvents); 488if (CocoaAppContext::isTerminated) 489break ; 490if (mainWindow) 491{ 492mainWindow -> events. mainLoop (); 493} 494} 495} 496 497CocoaPlatformWindow ::CocoaPlatformWindow( const WindowDesc & desc) 498{ 499// Create a reference rectangle 500NSRect rect = NSMakeRect( 0.0f , 0.0f , desc.width, desc.height); 501 502// Allocate window 503window = [[NSWindow alloc] initWithContentRect:rect 504styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable 505backing:NSBackingStoreBuffered 506defer:NO]; 507 508const NSWindowCollectionBehavior behavior 509= NSWindowCollectionBehaviorFullScreenPrimary | NSWindowCollectionBehaviorManaged; 510[window setCollectionBehavior:behavior]; 511 512if (desc.style == WindowStyle::Default) 513[window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; 514else if (desc.style == WindowStyle::FixedSize) 515[window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable]; 516 517delegate = [[WindowDelegate alloc] initWithPlatformWindow:this]; 518[window setDelegate:delegate]; 519 520NSString * title = [NSString stringWithUTF8String:desc.title]; 521[window setTitle:title]; 522 523[window center]; 524[window makeKeyAndOrderFront:nil]; 525} 526 527CocoaPlatformWindow ::~CocoaPlatformWindow() 528{ 529close(); 530} 531 532void CocoaPlatformWindow::setClientSize( uint32_t width, uint32_t height) 533{ 534NSSize size = NSMakeSize(width, height); 535[window setContentSize:size]; 536} 537 538Rect CocoaPlatformWindow::getClientRect() 539{ 540NSRect rect = [window contentRectForFrameRect:[window frame]]; 541return { ( int )rect.origin.x, ( int )rect.origin.y, ( int )rect.size.width, ( int )rect.size.height }; 542} 543 544void CocoaPlatformWindow::centerScreen() 545{ 546[window center]; 547} 548 549void CocoaPlatformWindow::close() 550{ 551[window release]; 552[delegate release]; 553 554window = nil; 555delegate = nil; 556} 557 558bool CocoaPlatformWindow::getFocused() 559{ 560return [window isKeyWindow]; 561} 562 563bool CocoaPlatformWindow::getVisible() 564{ 565return [window isVisible]; 566} 567 568WindowHandle CocoaPlatformWindow::getNativeHandle() 569{ 570return WindowHandle::fromNSWindow(window); 571} 572 573void CocoaPlatformWindow::setText( Slang ::String text) 574{ 575NSString * title = [NSString stringWithUTF8String:text. begin ()]; 576[window setTitle:title]; 577} 578 579void CocoaPlatformWindow::show() 580{ 581[window setIsVisible:YES]; 582} 583 584void CocoaPlatformWindow::hide() 585{ 586[window setIsVisible:NO]; 587} 588 589int CocoaPlatformWindow::getCurrentDpi() 590{ 591// There seems to be no API to get the actual DPI of the screen. 592return 0 ; 593} 594 595Window * Application::createWindow( const WindowDesc & desc) { return new CocoaPlatformWindow(desc); } 596 597 598} // namespace platform 599 600#endif // __APPLE__