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 }