1 module cocoatest; 2 version(OSX): 3 4 import derelict.cocoa; 5 6 import dlangui.core.logger; 7 import dlangui.core.types; 8 import dlangui.core.events; 9 import dlangui.graphics.drawbuf; 10 import std.uuid; 11 import core.stdc.stdlib; 12 import std.string; 13 14 void main(string[] args) 15 { 16 Log.setStderrLogger(); 17 Log.setLogLevel(LogLevel.Trace); 18 DerelictCocoa.load(); 19 20 21 22 static if (true) { 23 auto pool = new NSAutoreleasePool; 24 NSString appName = NSProcessInfo.processInfo().processName(); 25 Log.i("appName = %s", appName); 26 27 CocoaWindow window = new CocoaWindow(cast(void*)null, new IWindowListenerLogger(), 300, 300); 28 Log.d(""); 29 } else { 30 31 32 NSString appName = NSProcessInfo.processInfo().processName(); 33 Log.i("appName = %s", appName); 34 //writefln("appName = %s", appName); 35 36 auto pool = new NSAutoreleasePool; 37 38 auto NSApp = NSApplication.sharedApplication; 39 40 NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular); 41 42 NSMenu menubar = NSMenu.alloc; 43 menubar.init_(); 44 NSMenuItem appMenuItem = NSMenuItem.alloc(); 45 appMenuItem.init_(); 46 menubar.addItem(appMenuItem); 47 NSApp.setMainMenu(menubar); 48 49 NSWindow window = NSWindow.alloc(); 50 window.initWithContentRect(NSMakeRect(10, 10, 200, 200), 51 NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask, //NSBorderlessWindowMask, 52 NSBackingStoreBuffered, NO); 53 window.makeKeyAndOrderFront(); 54 55 NSView parentView; 56 parentView = window.contentView(); 57 58 Log.i("parentView=", parentView); 59 60 NSApp.activateIgnoringOtherApps(YES); 61 62 // string uuid = randomUUID().toString(); 63 // DlanguiCocoaView.customClassName = "DlanguiCocoaView_" ~ uuid; 64 // DlanguiCocoaView.registerSubclass(); 65 // 66 // _view = DlanguiCocoaView.alloc(); 67 // _view.initialize(this, width, height); 68 // 69 // parentView.addSubview(_view); 70 71 72 NSApp.run(); 73 } 74 75 DerelictCocoa.unload(); 76 } 77 78 interface IWindowListener { 79 void onMouseWheel(int x, int y, int deltaX, int deltaY, MouseState state); 80 void onKeyDown(uint key); 81 void onKeyUp(uint key); 82 void onMouseMove(int x, int y, int deltaX, int deltaY, 83 MouseState mouseState); 84 void onMouseRelease(int x, int y, MouseButton mb, MouseState mouseState); 85 void onMouseClick(int x, int y, MouseButton mb, bool isDoubleClick, MouseState mouseState); 86 void recomputeDirtyAreas(); 87 void onResized(int width, int height); 88 void onAnimate(double dt, double time); 89 Rect getDirtyRectangle(); 90 } 91 92 class IWindowListenerLogger : IWindowListener { 93 override void onMouseWheel(int x, int y, int deltaX, int deltaY, MouseState state) { 94 Log.d("onMouseWheel"); 95 } 96 override void onKeyDown(uint key) { 97 Log.d("onKeyDown"); 98 } 99 override void onKeyUp(uint key) { 100 Log.d("onKeyUp"); 101 } 102 override void onMouseMove(int x, int y, int deltaX, int deltaY, 103 MouseState mouseState) { 104 Log.d("onMouseMove ", x, ", ", y); 105 } 106 override void onMouseRelease(int x, int y, MouseButton mb, MouseState mouseState) { 107 Log.d("onMouseRelease"); 108 } 109 override void onMouseClick(int x, int y, MouseButton mb, bool isDoubleClick, MouseState mouseState) { 110 Log.d("onMouseClick"); 111 } 112 override void recomputeDirtyAreas() { 113 //Log.d("recomputeDirtyAreas"); 114 } 115 override void onResized(int width, int height) { 116 Log.d("onResized ", width, ", ", height); 117 _width = width; 118 _height = height; 119 } 120 override void onAnimate(double dt, double time) { 121 //Log.d("onAnimate"); 122 } 123 override Rect getDirtyRectangle() { 124 return Rect(0, 0, _width, _height); 125 } 126 int _width = 100; 127 int _height = 100; 128 } 129 130 struct MouseState { 131 bool leftButtonDown; 132 bool rightButtonDown; 133 bool middleButtonDown; 134 bool ctrlPressed; 135 bool shiftPressed; 136 bool altPressed; 137 } 138 139 enum MouseButton : int { 140 left, 141 right, 142 middle 143 } 144 145 final class CocoaWindow 146 { 147 private: 148 IWindowListener _listener; 149 150 // Stays null in the case of a plugin, but exists for a stand-alone program 151 // For testing purpose. 152 NSWindow _cocoaWindow = null; 153 NSApplication _cocoaApplication; 154 155 NSColorSpace _nsColorSpace; 156 CGColorSpaceRef _cgColorSpaceRef; 157 NSData _imageData; 158 NSString _logFormatStr; 159 160 ColorDrawBuf _drawBuf; 161 162 DPlugCustomView _view = null; 163 164 bool _terminated = false; 165 166 int _lastMouseX, _lastMouseY; 167 bool _firstMouseMove = true; 168 169 int _width; 170 int _height; 171 172 ubyte* _buffer = null; 173 174 uint _timeAtCreationInMs; 175 uint _lastMeasturedTimeInMs; 176 bool _dirtyAreasAreNotYetComputed; 177 178 public: 179 180 this(void* parentWindow, IWindowListener listener, int width, int height) 181 { 182 _listener = listener; 183 184 DerelictCocoa.load(); 185 NSApplicationLoad(); // to use Cocoa in Carbon applications 186 bool parentViewExists = parentWindow !is null; 187 NSView parentView; 188 if (!parentViewExists) 189 { 190 // create a NSWindow to hold our NSView 191 _cocoaApplication = NSApplication.sharedApplication; 192 _cocoaApplication.setActivationPolicy(NSApplicationActivationPolicyRegular); 193 194 NSWindow window = NSWindow.alloc(); 195 window.initWithContentRect(NSMakeRect(100, 100, width, height), 196 NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask, 197 NSBackingStoreBuffered, 198 NO); 199 window.makeKeyAndOrderFront(); 200 201 parentView = window.contentView(); 202 //parentView. 203 204 _cocoaApplication.activateIgnoringOtherApps(YES); 205 } 206 else 207 parentView = NSView(cast(id)parentWindow); 208 209 210 211 _width = 0; 212 _height = 0; 213 214 _nsColorSpace = NSColorSpace.sRGBColorSpace(); 215 // hopefully not null else the colors will be brighter 216 _cgColorSpaceRef = _nsColorSpace.CGColorSpace(); 217 218 _logFormatStr = NSString.stringWith("%@"); 219 220 _timeAtCreationInMs = getTimeMs(); 221 _lastMeasturedTimeInMs = _timeAtCreationInMs; 222 223 _dirtyAreasAreNotYetComputed = true; 224 225 string uuid = randomUUID().toString(); 226 DPlugCustomView.customClassName = "DPlugCustomView_" ~ uuid; 227 DPlugCustomView.registerSubclass(); 228 229 _view = DPlugCustomView.alloc(); 230 _view.initialize(this, width, height); 231 232 parentView.addSubview(_view); 233 234 if (_cocoaApplication) 235 _cocoaApplication.run(); 236 237 238 } 239 240 ~this() 241 { 242 if (_view) 243 { 244 //debug ensureNotInGC("CocoaWindow"); 245 _terminated = true; 246 247 { 248 _view.killTimer(); 249 } 250 251 _view.removeFromSuperview(); 252 _view.release(); 253 _view = DPlugCustomView(null); 254 255 DPlugCustomView.unregisterSubclass(); 256 257 if (_buffer != null) 258 { 259 free(_buffer); 260 _buffer = null; 261 } 262 263 DerelictCocoa.unload(); 264 } 265 } 266 267 // Implements IWindow 268 void waitEventAndDispatch() 269 { 270 assert(false); // not implemented in Cocoa, since we don't have a NSWindow 271 } 272 273 bool terminated() 274 { 275 return _terminated; 276 } 277 278 void debugOutput(string s) 279 { 280 import core.stdc.stdio; 281 fprintf(stderr, toStringz(s)); 282 } 283 284 uint getTimeMs() 285 { 286 return cast(uint)(NSDate.timeIntervalSinceReferenceDate() * 1000.0); 287 } 288 289 private: 290 291 MouseState getMouseState(NSEvent event) 292 { 293 // not working 294 MouseState state; 295 uint pressedMouseButtons = event.pressedMouseButtons(); 296 if (pressedMouseButtons & 1) 297 state.leftButtonDown = true; 298 if (pressedMouseButtons & 2) 299 state.rightButtonDown = true; 300 if (pressedMouseButtons & 4) 301 state.middleButtonDown = true; 302 303 NSEventModifierFlags mod = event.modifierFlags(); 304 if (mod & NSControlKeyMask) 305 state.ctrlPressed = true; 306 if (mod & NSShiftKeyMask) 307 state.shiftPressed = true; 308 if (mod & NSAlternateKeyMask) 309 state.altPressed = true; 310 311 return state; 312 } 313 314 void handleMouseWheel(NSEvent event) 315 { 316 int deltaX = cast(int)(0.5 + 10 * event.deltaX); 317 int deltaY = cast(int)(0.5 + 10 * event.deltaY); 318 Point mousePos = getMouseXY(_view, event, _height); 319 _listener.onMouseWheel(mousePos.x, mousePos.y, deltaX, deltaY, getMouseState(event)); 320 } 321 322 void handleKeyEvent(NSEvent event, bool released) 323 { 324 uint keyCode = event.keyCode(); 325 uint key; 326 switch (keyCode) 327 { 328 case kVK_ANSI_Keypad0: key = KeyCode.KEY_0; break; 329 case kVK_ANSI_Keypad1: key = KeyCode.KEY_1; break; 330 case kVK_ANSI_Keypad2: key = KeyCode.KEY_2; break; 331 case kVK_ANSI_Keypad3: key = KeyCode.KEY_3; break; 332 case kVK_ANSI_Keypad4: key = KeyCode.KEY_4; break; 333 case kVK_ANSI_Keypad5: key = KeyCode.KEY_5; break; 334 case kVK_ANSI_Keypad6: key = KeyCode.KEY_6; break; 335 case kVK_ANSI_Keypad7: key = KeyCode.KEY_7; break; 336 case kVK_ANSI_Keypad8: key = KeyCode.KEY_8; break; 337 case kVK_ANSI_Keypad9: key = KeyCode.KEY_9; break; 338 case kVK_Return: key = KeyCode.RETURN; break; 339 case kVK_Escape: key = KeyCode.ESCAPE; break; 340 case kVK_LeftArrow: key = KeyCode.LEFT; break; 341 case kVK_RightArrow: key = KeyCode.RIGHT; break; 342 case kVK_DownArrow: key = KeyCode.DOWN; break; 343 case kVK_UpArrow: key = KeyCode.UP; break; 344 default: key = 0; 345 } 346 347 if (released) 348 _listener.onKeyDown(key); 349 else 350 _listener.onKeyUp(key); 351 } 352 353 void handleMouseMove(NSEvent event) 354 { 355 Point mousePos = getMouseXY(_view, event, _height); 356 357 if (_firstMouseMove) 358 { 359 _firstMouseMove = false; 360 _lastMouseX = mousePos.x; 361 _lastMouseY = mousePos.y; 362 } 363 364 _listener.onMouseMove(mousePos.x, mousePos.y, mousePos.x - _lastMouseX, mousePos.y - _lastMouseY, 365 getMouseState(event)); 366 367 _lastMouseX = mousePos.x; 368 _lastMouseY = mousePos.y; 369 } 370 371 void handleMouseClicks(NSEvent event, MouseButton mb, bool released) 372 { 373 Point mousePos = getMouseXY(_view, event, _height); 374 375 if (released) 376 _listener.onMouseRelease(mousePos.x, mousePos.y, mb, getMouseState(event)); 377 else 378 { 379 int clickCount = event.clickCount(); 380 bool isDoubleClick = clickCount >= 2; 381 _listener.onMouseClick(mousePos.x, mousePos.y, mb, isDoubleClick, getMouseState(event)); 382 } 383 } 384 385 enum scanLineAlignment = 4; // could be anything 386 387 // given a width, how long in bytes should scanlines be 388 int byteStride(int width) 389 { 390 int widthInBytes = width * 4; 391 return (widthInBytes + (scanLineAlignment - 1)) & ~(scanLineAlignment-1); 392 } 393 394 void drawRect(NSRect rect) 395 { 396 NSGraphicsContext nsContext = NSGraphicsContext.currentContext(); 397 398 CIContext ciContext = nsContext.getCIContext(); 399 400 // update internal buffers in case of startup/resize 401 { 402 NSRect boundsRect = _view.bounds(); 403 int width = cast(int)(boundsRect.size.width); // truncating down the dimensions of bounds 404 int height = cast(int)(boundsRect.size.height); 405 updateSizeIfNeeded(width, height); 406 _drawBuf.resize(width, height); 407 } 408 409 // The first drawRect callback occurs before the timer triggers. 410 // But because recomputeDirtyAreas() wasn't called before there is nothing to draw. 411 // Hence, do it. 412 if (_dirtyAreasAreNotYetComputed) 413 { 414 _dirtyAreasAreNotYetComputed = false; 415 _listener.recomputeDirtyAreas(); 416 } 417 418 // draw buffers 419 // ImageRef!RGBA wfb; 420 // wfb.w = _width; 421 // wfb.h = _height; 422 // wfb.pitch = byteStride(_width); 423 // wfb.pixels = cast(RGBA*)_buffer; 424 // _listener.onDraw(wfb, WindowPixelFormat.ARGB8); 425 _drawBuf.fill(0x8090B0); 426 _drawBuf.fillRect(Rect(20, 20, 120, 120), 0xFFBBBB); 427 428 size_t sizeNeeded = byteStride(_width) * _height; 429 //_imageData = NSData.dataWithBytesNoCopy(cast(ubyte*)_drawBuf.scanLine(0), sizeNeeded, false); 430 _imageData = NSData.dataWithBytesNoCopy(cast(ubyte*)_drawBuf.scanLine(0), sizeNeeded, false); 431 432 CIImage image = CIImage.imageWithBitmapData(_imageData, 433 byteStride(_drawBuf.width), 434 CGSize(_drawBuf.width, _drawBuf.height), 435 kCIFormatARGB8, 436 _cgColorSpaceRef); 437 // NSRect rc; 438 // rc.origin.x = 0; 439 // rc.origin.y = 0; 440 // rc.size.width = _drawBuf.width; 441 // rc.size.height = _drawBuf.height; 442 ciContext.drawImage(image, rect, rect); 443 } 444 445 /// Returns: true if window size changed. 446 bool updateSizeIfNeeded(int newWidth, int newHeight) 447 { 448 // only do something if the client size has changed 449 if ( (newWidth != _width) || (newHeight != _height) ) 450 { 451 // Extends buffer 452 if (_buffer != null) 453 { 454 free(_buffer); 455 _buffer = null; 456 } 457 458 size_t sizeNeeded = byteStride(newWidth) * newHeight; 459 _buffer = cast(ubyte*) malloc(sizeNeeded); 460 _width = newWidth; 461 _height = newHeight; 462 if (_drawBuf is null) 463 _drawBuf = new ColorDrawBuf(_width, _height); 464 else if (_drawBuf.width != _width || _drawBuf.height != _height) 465 _drawBuf.resize(_width, _height); 466 _listener.onResized(_width, _height); 467 return true; 468 } 469 else 470 return false; 471 } 472 473 void doAnimation() 474 { 475 uint now = getTimeMs(); 476 double dt = (now - _lastMeasturedTimeInMs) * 0.001; 477 double time = (now - _timeAtCreationInMs) * 0.001; // hopefully no plug-in will be open more than 49 days 478 _lastMeasturedTimeInMs = now; 479 _listener.onAnimate(dt, time); 480 } 481 482 void onTimer() 483 { 484 // Deal with animation 485 doAnimation(); 486 487 _listener.recomputeDirtyAreas(); 488 _dirtyAreasAreNotYetComputed = false; 489 Rect dirtyRect = _listener.getDirtyRectangle(); 490 if (!dirtyRect.empty()) 491 { 492 493 NSRect boundsRect = _view.bounds(); 494 int height = cast(int)(boundsRect.size.height); 495 NSRect r = NSMakeRect(dirtyRect.left, 496 height - dirtyRect.top - dirtyRect.height, 497 dirtyRect.width, 498 dirtyRect.height); 499 _view.setNeedsDisplayInRect(r); 500 } 501 } 502 } 503 504 struct DPlugCustomView 505 { 506 // This class uses a unique class name for each plugin instance 507 static string customClassName = null; 508 509 NSView parent; 510 alias parent this; 511 512 // create from an id 513 this (id id_) 514 { 515 this._id = id_; 516 } 517 518 /// Allocates, but do not init 519 static DPlugCustomView alloc() 520 { 521 alias fun_t = extern(C) id function (id obj, SEL sel); 522 return DPlugCustomView( (cast(fun_t)objc_msgSend)(getClassID(), sel!"alloc") ); 523 } 524 525 static Class getClass() 526 { 527 return cast(Class)( getClassID() ); 528 } 529 530 static id getClassID() 531 { 532 assert(customClassName !is null); 533 return objc_getClass(customClassName); 534 } 535 536 private: 537 538 CocoaWindow _window; 539 NSTimer _timer = null; 540 541 void initialize(CocoaWindow window, int width, int height) 542 { 543 // Warning: taking this address is fishy since DPlugCustomView is a struct and thus could be copied 544 // we rely on the fact it won't :| 545 void* thisPointer = cast(void*)(&this); 546 object_setInstanceVariable(_id, "this", thisPointer); 547 548 this._window = window; 549 550 NSRect r = NSRect(NSPoint(0, 0), NSSize(width, height)); 551 initWithFrame(r); 552 553 _timer = NSTimer.timerWithTimeInterval(1 / 60.0, this, sel!"onTimer:", null, true); 554 NSRunLoop.currentRunLoop().addTimer(_timer, NSRunLoopCommonModes); 555 } 556 557 static Class clazz; 558 559 static void registerSubclass() 560 { 561 clazz = objc_allocateClassPair(cast(Class) lazyClass!"NSView", toStringz(customClassName), 0); 562 563 class_addMethod(clazz, sel!"keyDown:", cast(IMP) &keyDown, "v@:@"); 564 class_addMethod(clazz, sel!"keyUp:", cast(IMP) &keyUp, "v@:@"); 565 class_addMethod(clazz, sel!"mouseDown:", cast(IMP) &mouseDown, "v@:@"); 566 class_addMethod(clazz, sel!"mouseUp:", cast(IMP) &mouseUp, "v@:@"); 567 class_addMethod(clazz, sel!"rightMouseDown:", cast(IMP) &rightMouseDown, "v@:@"); 568 class_addMethod(clazz, sel!"rightMouseUp:", cast(IMP) &rightMouseUp, "v@:@"); 569 class_addMethod(clazz, sel!"otherMouseDown:", cast(IMP) &otherMouseDown, "v@:@"); 570 class_addMethod(clazz, sel!"otherMouseUp:", cast(IMP) &otherMouseUp, "v@:@"); 571 class_addMethod(clazz, sel!"mouseMoved:", cast(IMP) &mouseMoved, "v@:@"); 572 class_addMethod(clazz, sel!"mouseDragged:", cast(IMP) &mouseMoved, "v@:@"); 573 class_addMethod(clazz, sel!"rightMouseDragged:", cast(IMP) &mouseMoved, "v@:@"); 574 class_addMethod(clazz, sel!"otherMouseDragged:", cast(IMP) &mouseMoved, "v@:@"); 575 class_addMethod(clazz, sel!"acceptsFirstResponder", cast(IMP) &acceptsFirstResponder, "b@:"); 576 class_addMethod(clazz, sel!"isOpaque", cast(IMP) &isOpaque, "b@:"); 577 class_addMethod(clazz, sel!"acceptsFirstMouse:", cast(IMP) &acceptsFirstMouse, "b@:@"); 578 class_addMethod(clazz, sel!"viewDidMoveToWindow", cast(IMP) &viewDidMoveToWindow, "v@:"); 579 class_addMethod(clazz, sel!"drawRect:", cast(IMP) &drawRect, "v@:" ~ encode!NSRect); 580 class_addMethod(clazz, sel!"onTimer:", cast(IMP) &onTimer, "v@:@"); 581 582 // This ~ is to avoid a strange DMD ICE. Didn't succeed in isolating it. 583 class_addMethod(clazz, sel!("scroll" ~ "Wheel:") , cast(IMP) &scrollWheel, "v@:@"); 584 585 // very important: add an instance variable for the this pointer so that the D object can be 586 // retrieved from an id 587 class_addIvar(clazz, "this", (void*).sizeof, (void*).sizeof == 4 ? 2 : 3, "^v"); 588 589 objc_registerClassPair(clazz); 590 } 591 592 static void unregisterSubclass() 593 { 594 // For some reason the class need to continue to exist, so we leak it 595 // objc_disposeClassPair(clazz); 596 // TODO: remove this crap 597 } 598 599 void killTimer() 600 { 601 if (_timer) 602 { 603 _timer.invalidate(); 604 _timer = NSTimer(null); 605 } 606 } 607 } 608 609 DPlugCustomView getInstance(id anId) 610 { 611 // strange thing: object_getInstanceVariable definition is odd (void**) 612 // and only works for pointer-sized values says SO 613 void* thisPointer = null; 614 Ivar var = object_getInstanceVariable(anId, "this", &thisPointer); 615 assert(var !is null); 616 assert(thisPointer !is null); 617 return *cast(DPlugCustomView*)thisPointer; 618 } 619 620 Point getMouseXY(NSView view, NSEvent event, int windowHeight) 621 { 622 NSPoint mouseLocation = event.locationInWindow(); 623 mouseLocation = view.convertPoint(mouseLocation, NSView(null)); 624 int px = cast(int)(mouseLocation.x) - 2; 625 int py = windowHeight - cast(int)(mouseLocation.y) - 3; 626 return Point(px, py); 627 } 628 629 // Overridden function gets called with an id, instead of the self pointer. 630 // So we have to get back the D class object address. 631 // Big thanks to Mike Ash (@macdev) 632 extern(C) 633 { 634 void keyDown(id self, SEL selector, id event) 635 { 636 //FPControl fpctrl; 637 //fpctrl.initialize(); 638 DPlugCustomView view = getInstance(self); 639 view._window.handleKeyEvent(NSEvent(event), false); 640 } 641 642 void keyUp(id self, SEL selector, id event) 643 { 644 //FPControl fpctrl; 645 //fpctrl.initialize(); 646 DPlugCustomView view = getInstance(self); 647 view._window.handleKeyEvent(NSEvent(event), true); 648 } 649 650 void mouseDown(id self, SEL selector, id event) 651 { 652 //FPControl fpctrl; 653 //fpctrl.initialize(); 654 DPlugCustomView view = getInstance(self); 655 view._window.handleMouseClicks(NSEvent(event), MouseButton.left, false); 656 } 657 658 void mouseUp(id self, SEL selector, id event) 659 { 660 //FPControl fpctrl; 661 //fpctrl.initialize(); 662 DPlugCustomView view = getInstance(self); 663 view._window.handleMouseClicks(NSEvent(event), MouseButton.left, true); 664 } 665 666 void rightMouseDown(id self, SEL selector, id event) 667 { 668 //FPControl fpctrl; 669 //fpctrl.initialize(); 670 DPlugCustomView view = getInstance(self); 671 view._window.handleMouseClicks(NSEvent(event), MouseButton.right, false); 672 } 673 674 void rightMouseUp(id self, SEL selector, id event) 675 { 676 //FPControl fpctrl; 677 //fpctrl.initialize(); 678 DPlugCustomView view = getInstance(self); 679 view._window.handleMouseClicks(NSEvent(event), MouseButton.right, true); 680 } 681 682 void otherMouseDown(id self, SEL selector, id event) 683 { 684 //FPControl fpctrl; 685 //fpctrl.initialize(); 686 DPlugCustomView view = getInstance(self); 687 auto nsEvent = NSEvent(event); 688 if (nsEvent.buttonNumber == 2) 689 view._window.handleMouseClicks(nsEvent, MouseButton.middle, false); 690 } 691 692 void otherMouseUp(id self, SEL selector, id event) 693 { 694 //FPControl fpctrl; 695 //fpctrl.initialize(); 696 DPlugCustomView view = getInstance(self); 697 auto nsEvent = NSEvent(event); 698 if (nsEvent.buttonNumber == 2) 699 view._window.handleMouseClicks(nsEvent, MouseButton.middle, true); 700 } 701 702 void mouseMoved(id self, SEL selector, id event) 703 { 704 //FPControl fpctrl; 705 //fpctrl.initialize(); 706 DPlugCustomView view = getInstance(self); 707 view._window.handleMouseMove(NSEvent(event)); 708 } 709 710 void scrollWheel(id self, SEL selector, id event) 711 { 712 //FPControl fpctrl; 713 //fpctrl.initialize(); 714 DPlugCustomView view = getInstance(self); 715 view._window.handleMouseWheel(NSEvent(event)); 716 } 717 718 bool acceptsFirstResponder(id self, SEL selector) 719 { 720 return YES; 721 } 722 723 bool acceptsFirstMouse(id self, SEL selector, id pEvent) 724 { 725 return YES; 726 } 727 728 bool isOpaque(id self, SEL selector) 729 { 730 return YES; 731 } 732 733 void viewDidMoveToWindow(id self, SEL selector) 734 { 735 DPlugCustomView view = getInstance(self); 736 NSWindow parentWindow = view.window(); 737 if (parentWindow) 738 { 739 parentWindow.makeFirstResponder(view); 740 parentWindow.setAcceptsMouseMovedEvents(true); 741 } 742 } 743 744 void drawRect(id self, SEL selector, NSRect rect) 745 { 746 //FPControl fpctrl; 747 //fpctrl.initialize(); 748 DPlugCustomView view = getInstance(self); 749 view._window.drawRect(rect); 750 } 751 752 void onTimer(id self, SEL selector, id timer) 753 { 754 //FPControl fpctrl; 755 //fpctrl.initialize(); 756 DPlugCustomView view = getInstance(self); 757 view._window.onTimer(); 758 } 759 }