* Use a subclass of NSView for the dummy view which overrides hitTest: to
[wxWidgets.git] / src / cocoa / window.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/window.mm
3 // Purpose:     wxWindowCocoa
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2002/12/26
7 // RCS-ID:      $Id:
8 // Copyright:   (c) 2002 David Elliott
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/window.h"
13 #include "wx/log.h"
14
15 #include "wx/cocoa/autorelease.h"
16
17 #import <Appkit/NSView.h>
18 #import <AppKit/NSEvent.h>
19 #import <AppKit/NSScrollView.h>
20 #import <AppKit/NSColor.h>
21 #import <AppKit/NSClipView.h>
22
23 // Turn this on to paint green over the dummy views for debugging
24 #undef WXCOCOA_FILL_DUMMY_VIEW
25
26 #ifdef WXCOCOA_FILL_DUMMY_VIEW
27 #import <AppKit/NSBezierPath.h>
28 #endif //def WXCOCOA_FILL_DUMMY_VIEW
29
30 // ========================================================================
31 // wxWindowCocoaHider
32 // ========================================================================
33 class wxWindowCocoaHider: protected wxCocoaNSView
34 {
35     DECLARE_NO_COPY_CLASS(wxWindowCocoaHider)
36 public:
37     wxWindowCocoaHider(wxWindow *owner);
38     virtual ~wxWindowCocoaHider();
39     inline WX_NSView GetNSView() { return m_dummyNSView; }
40 protected:
41     wxWindowCocoa *m_owner;
42     WX_NSView m_dummyNSView;
43     virtual void Cocoa_FrameChanged(void);
44 #ifdef WXCOCOA_FILL_DUMMY_VIEW
45     virtual bool Cocoa_drawRect(const NSRect& rect);
46 #endif //def WXCOCOA_FILL_DUMMY_VIEW
47 private:
48     wxWindowCocoaHider();
49 };
50
51 // ========================================================================
52 // wxWindowCocoaScroller
53 // ========================================================================
54 class wxWindowCocoaScroller: protected wxCocoaNSView
55 {
56     DECLARE_NO_COPY_CLASS(wxWindowCocoaScroller)
57 public:
58     wxWindowCocoaScroller(wxWindow *owner);
59     virtual ~wxWindowCocoaScroller();
60     inline WX_NSScrollView GetNSScrollView() { return m_cocoaNSScrollView; }
61     void ClientSizeToSize(int &width, int &height);
62     void DoGetClientSize(int *x, int *y) const;
63     void Encapsulate();
64     void Unencapsulate();
65 protected:
66     wxWindowCocoa *m_owner;
67     WX_NSScrollView m_cocoaNSScrollView;
68     virtual void Cocoa_FrameChanged(void);
69 private:
70     wxWindowCocoaScroller();
71 };
72
73 // ========================================================================
74 // wxDummyNSView
75 // ========================================================================
76 @interface wxDummyNSView : NSView
77 - (NSView *)hitTest:(NSPoint)aPoint;
78 @end
79
80 @implementation wxDummyNSView : NSView
81 - (NSView *)hitTest:(NSPoint)aPoint
82 {
83     return nil;
84 }
85
86 @end
87
88 // ========================================================================
89 // wxWindowCocoaHider
90 // ========================================================================
91 wxWindowCocoaHider::wxWindowCocoaHider(wxWindow *owner)
92 :   m_owner(owner)
93 {
94     wxASSERT(owner);
95     wxASSERT(owner->GetNSViewForHiding());
96     m_dummyNSView = [[wxDummyNSView alloc]
97         initWithFrame:[owner->GetNSViewForHiding() frame]];
98     [m_dummyNSView setAutoresizingMask: [owner->GetNSViewForHiding() autoresizingMask]];
99     AssociateNSView(m_dummyNSView);
100 }
101
102 wxWindowCocoaHider::~wxWindowCocoaHider()
103 {
104     DisassociateNSView(m_dummyNSView);
105     [m_dummyNSView release];
106 }
107
108 void wxWindowCocoaHider::Cocoa_FrameChanged(void)
109 {
110     // Keep the real window in synch with the dummy
111     wxASSERT(m_dummyNSView);
112     [m_owner->GetNSViewForHiding() setFrame:[m_dummyNSView frame]];
113 }
114
115 #ifdef WXCOCOA_FILL_DUMMY_VIEW
116 bool wxWindowCocoaHider::Cocoa_drawRect(const NSRect& rect)
117 {
118     NSBezierPath *bezpath = [NSBezierPath bezierPathWithRect:rect];
119     [[NSColor greenColor] set];
120     [bezpath stroke];
121     [bezpath fill];
122     return true;
123 }
124 #endif //def WXCOCOA_FILL_DUMMY_VIEW
125
126 // ========================================================================
127 // wxFlippedNSClipView
128 // ========================================================================
129 @interface wxFlippedNSClipView : NSClipView
130 - (BOOL)isFlipped;
131 @end
132
133 @implementation wxFlippedNSClipView : NSClipView
134 - (BOOL)isFlipped
135 {
136     return YES;
137 }
138
139 @end
140
141 // ========================================================================
142 // wxWindowCocoaScroller
143 // ========================================================================
144 wxWindowCocoaScroller::wxWindowCocoaScroller(wxWindow *owner)
145 :   m_owner(owner)
146 {
147     wxASSERT(owner);
148     wxASSERT(owner->GetNSView());
149     m_cocoaNSScrollView = [[NSScrollView alloc]
150         initWithFrame:[owner->GetNSView() frame]];
151     AssociateNSView(m_cocoaNSScrollView);
152
153     /* Replace the default NSClipView with a flipped one.  This ensures
154        scrolling is "pinned" to the top-left instead of bottom-right. */
155     NSClipView *flippedClip = [[wxFlippedNSClipView alloc]
156         initWithFrame: [[m_cocoaNSScrollView contentView] frame]];
157     [m_cocoaNSScrollView setContentView:flippedClip];
158     [flippedClip release];
159
160     [m_cocoaNSScrollView setBackgroundColor: [NSColor windowBackgroundColor]];
161     [m_cocoaNSScrollView setHasHorizontalScroller: YES];
162     [m_cocoaNSScrollView setHasVerticalScroller: YES];
163     Encapsulate();
164 }
165
166 void wxWindowCocoaScroller::Encapsulate()
167 {
168     // NOTE: replaceSubView will cause m_cocaNSView to be released
169     // except when it hasn't been added into an NSView hierarchy in which
170     // case it doesn't need to be and this should work out to a no-op
171     m_owner->CocoaReplaceView(m_owner->GetNSView(), m_cocoaNSScrollView);
172     // The NSView is still retained by owner
173     [m_cocoaNSScrollView setDocumentView: m_owner->GetNSView()];
174     // Now it's also retained by the NSScrollView
175 }
176
177 void wxWindowCocoaScroller::Unencapsulate()
178 {
179     [m_cocoaNSScrollView setDocumentView: nil];
180     m_owner->CocoaReplaceView(m_cocoaNSScrollView, m_owner->GetNSView());
181 }
182
183 wxWindowCocoaScroller::~wxWindowCocoaScroller()
184 {
185     DisassociateNSView(m_cocoaNSScrollView);
186     [m_cocoaNSScrollView release];
187 }
188
189 void wxWindowCocoaScroller::ClientSizeToSize(int &width, int &height)
190 {
191     NSSize frameSize = [NSScrollView
192         frameSizeForContentSize: NSMakeSize(width,height)
193         hasHorizontalScroller: [m_cocoaNSScrollView hasHorizontalScroller]
194         hasVerticalScroller: [m_cocoaNSScrollView hasVerticalScroller]
195         borderType: [m_cocoaNSScrollView borderType]];
196     width = frameSize.width;
197     height = frameSize.height;
198 }
199
200 void wxWindowCocoaScroller::DoGetClientSize(int *x, int *y) const
201 {
202     NSSize nssize = [m_cocoaNSScrollView contentSize];
203     if(x)
204         *x = nssize.width;
205     if(y)
206         *y = nssize.height;
207 }
208
209 void wxWindowCocoaScroller::Cocoa_FrameChanged(void)
210 {
211     wxLogDebug("Cocoa_FrameChanged");
212     wxSizeEvent event(m_owner->GetSize(), m_owner->GetId());
213     event.SetEventObject(m_owner);
214     m_owner->GetEventHandler()->ProcessEvent(event);
215 }
216
217 // ========================================================================
218 // wxWindowCocoa
219 // ========================================================================
220 // normally the base classes aren't included, but wxWindow is special
221 #ifdef __WXUNIVERSAL__
222 IMPLEMENT_ABSTRACT_CLASS(wxWindowCocoa, wxWindowBase)
223 #else
224 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
225 #endif
226
227 BEGIN_EVENT_TABLE(wxWindowCocoa, wxWindowBase)
228 END_EVENT_TABLE()
229
230 wxWindow *wxWindowCocoa::sm_capturedWindow = NULL;
231
232 // Constructor
233 void wxWindowCocoa::Init()
234 {
235     InitBase();
236
237     m_cocoaNSView = NULL;
238     m_cocoaHider = NULL;
239     m_cocoaScroller = NULL;
240     m_isBeingDeleted = FALSE;
241     m_isInPaint = FALSE;
242     m_shouldBeEnabled = true;
243 }
244
245 // Constructor
246 bool wxWindow::Create(wxWindow *parent, wxWindowID winid,
247            const wxPoint& pos,
248            const wxSize& size,
249            long style,
250            const wxString& name)
251 {
252     if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
253         return false;
254
255     // TODO: create the window
256     m_cocoaNSView = NULL;
257     SetNSView([[NSView alloc] initWithFrame: MakeDefaultNSRect(size)]);
258     [m_cocoaNSView release];
259
260     if (m_parent)
261     {
262         m_parent->AddChild(this);
263         m_parent->CocoaAddChild(this);
264     }
265     SetInitialFrameRect(pos,size);
266
267     return TRUE;
268 }
269
270 // Destructor
271 wxWindow::~wxWindow()
272 {
273     wxAutoNSAutoreleasePool pool;
274     DestroyChildren();
275
276     if(m_parent)
277         m_parent->RemoveChild(this);
278
279     CocoaRemoveFromParent();
280     delete m_cocoaHider;
281     delete m_cocoaScroller;
282     SetNSView(NULL);
283 }
284
285 void wxWindowCocoa::CocoaAddChild(wxWindowCocoa *child)
286 {
287     NSView *childView = child->GetNSViewForSuperview();
288
289     wxASSERT(childView);
290     [m_cocoaNSView addSubview: childView];
291     child->m_isShown = !m_cocoaHider;
292 }
293
294 void wxWindowCocoa::CocoaRemoveFromParent(void)
295 {
296     [GetNSViewForSuperview() removeFromSuperview];
297 }
298
299 void wxWindowCocoa::SetNSView(WX_NSView cocoaNSView)
300 {
301     bool need_debug = cocoaNSView || m_cocoaNSView;
302     if(need_debug) wxLogDebug("wxWindowCocoa=%p::SetNSView [m_cocoaNSView=%p retainCount]=%d",this,m_cocoaNSView,[m_cocoaNSView retainCount]);
303     DisassociateNSView(m_cocoaNSView);
304     [cocoaNSView retain];
305     [m_cocoaNSView release];
306     m_cocoaNSView = cocoaNSView;
307     AssociateNSView(m_cocoaNSView);
308     if(need_debug) wxLogDebug("wxWindowCocoa=%p::SetNSView [cocoaNSView=%p retainCount]=%d",this,cocoaNSView,[cocoaNSView retainCount]);
309 }
310
311 WX_NSView wxWindowCocoa::GetNSViewForSuperview() const
312 {
313     return m_cocoaHider
314         ?   m_cocoaHider->GetNSView()
315         :   m_cocoaScroller
316             ?   m_cocoaScroller->GetNSScrollView()
317             :   m_cocoaNSView;
318 }
319
320 WX_NSView wxWindowCocoa::GetNSViewForHiding() const
321 {
322     return m_cocoaScroller
323         ?   m_cocoaScroller->GetNSScrollView()
324         :   m_cocoaNSView;
325 }
326
327 bool wxWindowCocoa::Cocoa_drawRect(const NSRect &rect)
328 {
329     wxLogDebug("Cocoa_drawRect");
330     // Recursion can happen if the event loop runs from within the paint
331     // handler.  For instance, if an assertion dialog is shown.
332     // FIXME: This seems less than ideal.
333     if(m_isInPaint)
334     {
335         wxLogDebug("Paint event recursion!");
336         return false;
337     }
338     //FIXME: should probably turn that rect into the update region
339     m_isInPaint = TRUE;
340     wxPaintEvent event(m_windowId);
341     event.SetEventObject(this);
342     bool ret = GetEventHandler()->ProcessEvent(event);
343     m_isInPaint = FALSE;
344     return ret;
345 }
346
347 void wxWindowCocoa::InitMouseEvent(wxMouseEvent& event, WX_NSEvent cocoaEvent)
348 {
349     wxASSERT_MSG([m_cocoaNSView window]==[cocoaEvent window],"Mouse event for different NSWindow");
350     NSPoint cocoaPoint = [m_cocoaNSView convertPoint:[(NSEvent*)cocoaEvent locationInWindow] fromView:nil];
351     NSRect cocoaRect = [m_cocoaNSView frame];
352     const wxPoint &clientorigin = GetClientAreaOrigin();
353     event.m_x = (wxCoord)cocoaPoint.x - clientorigin.x;
354     event.m_y = (wxCoord)(cocoaRect.size.height - cocoaPoint.y) - clientorigin.y;
355
356     event.m_shiftDown = [cocoaEvent modifierFlags] & NSShiftKeyMask;
357     event.m_controlDown = [cocoaEvent modifierFlags] & NSControlKeyMask;
358     event.m_altDown = [cocoaEvent modifierFlags] & NSAlternateKeyMask;
359     event.m_metaDown = [cocoaEvent modifierFlags] & NSCommandKeyMask;
360
361     // TODO: set timestamp?
362     event.SetEventObject(this);
363     event.SetId(GetId());
364 }
365
366 bool wxWindowCocoa::Cocoa_mouseMoved(WX_NSEvent theEvent)
367 {
368     wxMouseEvent event(wxEVT_MOTION);
369     InitMouseEvent(event,theEvent);
370     wxLogDebug("Mouse Drag @%d,%d",event.m_x,event.m_y);
371     return GetEventHandler()->ProcessEvent(event);
372 }
373
374 bool wxWindowCocoa::Cocoa_mouseEntered(WX_NSEvent theEvent)
375 {
376     return false;
377 }
378
379 bool wxWindowCocoa::Cocoa_mouseExited(WX_NSEvent theEvent)
380 {
381     return false;
382 }
383
384 bool wxWindowCocoa::Cocoa_mouseDown(WX_NSEvent theEvent)
385 {
386     wxMouseEvent event([theEvent clickCount]<2?wxEVT_LEFT_DOWN:wxEVT_LEFT_DCLICK);
387     InitMouseEvent(event,theEvent);
388     wxLogDebug("Mouse Down @%d,%d num clicks=%d",event.m_x,event.m_y,[theEvent clickCount]);
389     return GetEventHandler()->ProcessEvent(event);
390 }
391
392 bool wxWindowCocoa::Cocoa_mouseDragged(WX_NSEvent theEvent)
393 {
394     wxMouseEvent event(wxEVT_MOTION);
395     InitMouseEvent(event,theEvent);
396     event.m_leftDown = true;
397     wxLogDebug("Mouse Drag @%d,%d",event.m_x,event.m_y);
398     return GetEventHandler()->ProcessEvent(event);
399 }
400
401 bool wxWindowCocoa::Cocoa_mouseUp(WX_NSEvent theEvent)
402 {
403     wxMouseEvent event(wxEVT_LEFT_UP);
404     InitMouseEvent(event,theEvent);
405     wxLogDebug("Mouse Up @%d,%d",event.m_x,event.m_y);
406     return GetEventHandler()->ProcessEvent(event);
407 }
408
409 bool wxWindowCocoa::Cocoa_rightMouseDown(WX_NSEvent theEvent)
410 {
411     return false;
412 }
413
414 bool wxWindowCocoa::Cocoa_rightMouseDragged(WX_NSEvent theEvent)
415 {
416     return false;
417 }
418
419 bool wxWindowCocoa::Cocoa_rightMouseUp(WX_NSEvent theEvent)
420 {
421     return false;
422 }
423
424 bool wxWindowCocoa::Cocoa_otherMouseDown(WX_NSEvent theEvent)
425 {
426     return false;
427 }
428
429 bool wxWindowCocoa::Cocoa_otherMouseDragged(WX_NSEvent theEvent)
430 {
431     return false;
432 }
433
434 bool wxWindowCocoa::Cocoa_otherMouseUp(WX_NSEvent theEvent)
435 {
436     return false;
437 }
438
439 void wxWindowCocoa::Cocoa_FrameChanged(void)
440 {
441     wxLogDebug("Cocoa_FrameChanged");
442     wxSizeEvent event(GetSize(), m_windowId);
443     event.SetEventObject(this);
444     GetEventHandler()->ProcessEvent(event);
445 }
446
447 bool wxWindow::Close(bool force)
448 {
449     // The only reason this function exists is that it is virtual and
450     // wxTopLevelWindowCocoa will override it.
451     return wxWindowBase::Close(force);
452 }
453
454 void wxWindow::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
455 {
456     [[oldView superview] replaceSubview:oldView with:newView];
457 }
458
459 bool wxWindow::EnableSelfAndChildren(bool enable)
460 {
461     // If the state isn't changing, don't do anything
462     if(!wxWindowBase::Enable(enable && m_shouldBeEnabled))
463         return false;
464     // Set the state of the Cocoa window
465     CocoaSetEnabled(m_isEnabled);
466     // Disable all children or (if enabling) return them to their proper state
467     for(wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
468         node; node = node->GetNext())
469     {
470         node->GetData()->EnableSelfAndChildren(enable);
471     }
472     return true;
473 }
474
475 bool wxWindow::Enable(bool enable)
476 {
477     // Keep track of what the window SHOULD be doing
478     m_shouldBeEnabled = enable;
479     // If the parent is disabled for any reason, then this window will be too.
480     if(!IsTopLevel() && GetParent())
481     {
482         enable = enable && GetParent()->IsEnabled();
483     }
484     return EnableSelfAndChildren(enable);
485 }
486
487 bool wxWindow::Show(bool show)
488 {
489     wxAutoNSAutoreleasePool pool;
490     // If the window is marked as visible, then it shouldn't have a dummy view
491     // If the window is marked hidden, then it should have a dummy view
492     // wxSpinCtrl (generic) abuses m_isShown, don't use it for any logic
493 //    wxASSERT_MSG( (m_isShown && !m_dummyNSView) || (!m_isShown && m_dummyNSView),"wxWindow: m_isShown does not agree with m_dummyNSView");
494     // Return false if there isn't a window to show or hide
495     NSView *cocoaView = GetNSViewForHiding();
496     if(!cocoaView)
497         return false;
498     if(show)
499     {
500         // If state isn't changing, return false
501         if(!m_cocoaHider)
502             return false;
503         CocoaReplaceView(m_cocoaHider->GetNSView(), cocoaView);
504         wxASSERT(![m_cocoaHider->GetNSView() superview]);
505         delete m_cocoaHider;
506         m_cocoaHider = NULL;
507         wxASSERT([cocoaView superview]);
508     }
509     else
510     {
511         // If state isn't changing, return false
512         if(m_cocoaHider)
513             return false;
514         m_cocoaHider = new wxWindowCocoaHider(this);
515         // NOTE: replaceSubview:with will cause m_cocaNSView to be
516         // (auto)released which balances out addSubview
517         CocoaReplaceView(cocoaView, m_cocoaHider->GetNSView());
518         // m_coocaNSView is now only retained by us
519         wxASSERT([m_cocoaHider->GetNSView() superview]);
520         wxASSERT(![cocoaView superview]);
521     }
522     m_isShown = show;
523     return true;
524 }
525
526 void wxWindowCocoa::DoSetSize(int x, int y, int width, int height, int sizeFlags)
527 {
528 //    wxLogDebug("wxWindow=%p::DoSetSizeWindow(%d,%d,%d,%d,Auto: %s%s)",this,x,y,width,height,(sizeFlags&wxSIZE_AUTO_WIDTH)?"W":".",sizeFlags&wxSIZE_AUTO_HEIGHT?"H":".");
529     int currentX, currentY;
530     int currentW, currentH;
531     DoGetPosition(&currentX, &currentY);
532     DoGetSize(&currentW, &currentH);
533     if((x==-1) && !(sizeFlags&wxSIZE_ALLOW_MINUS_ONE))
534         x=currentX;
535     if((y==-1) && !(sizeFlags&wxSIZE_ALLOW_MINUS_ONE))
536         y=currentY;
537
538     AdjustForParentClientOrigin(x,y,sizeFlags);
539
540     wxSize size(-1,-1);
541
542     if((width==-1)&&!(sizeFlags&wxSIZE_ALLOW_MINUS_ONE))
543     {
544         if(sizeFlags&wxSIZE_AUTO_WIDTH)
545         {
546             size=DoGetBestSize();
547             width=size.x;
548         }
549         else
550             width=currentW;
551     }
552     if((height==-1)&&!(sizeFlags&wxSIZE_ALLOW_MINUS_ONE))
553     {
554         if(sizeFlags&wxSIZE_AUTO_HEIGHT)
555         {
556             if(size.x==-1)
557                 size=DoGetBestSize();
558             height=size.y;
559         }
560         else
561             height=currentH;
562     }
563     DoMoveWindow(x,y,width,height);
564 }
565
566 void wxWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
567 {
568 //    wxLogDebug("wxWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
569
570     NSView *nsview = GetNSViewForSuperview();
571     NSView *superview = [nsview superview];
572     wxCHECK_RET(superview,"NSView does not have a superview");
573     NSRect parentRect = [superview bounds];
574
575     NSRect cocoaRect = NSMakeRect(x,parentRect.size.height-(y+height),width,height);
576     [nsview setFrame: cocoaRect];
577     // Be sure to redraw the parent to reflect the changed position
578     [superview setNeedsDisplay:YES];
579 }
580
581 void wxWindowCocoa::SetInitialFrameRect(const wxPoint& pos, const wxSize& size)
582 {
583     NSView *nsview = GetNSViewForSuperview();
584     NSView *superview = [nsview superview];
585     wxCHECK_RET(superview,"NSView does not have a superview");
586     NSRect parentRect = [superview bounds];
587     NSRect frameRect = [nsview frame];
588     if(size.x!=-1)
589         frameRect.size.width = size.x;
590     if(size.y!=-1)
591         frameRect.size.height = size.y;
592     frameRect.origin.x = pos.x;
593     frameRect.origin.y = parentRect.size.height-(pos.y+frameRect.size.height);
594     [nsview setFrame: frameRect];
595     // Tell Cocoa to change the margin between the bottom of the superview
596     // and the bottom of the control.  Keeps the control pinned to the top
597     // of its superview so that its position in the wxWindows coordinate
598     // system doesn't change.
599     if(![superview isFlipped])
600         [nsview setAutoresizingMask: NSViewMinYMargin];
601 }
602
603 // Get total size
604 void wxWindow::DoGetSize(int *w, int *h) const
605 {
606     NSRect cocoaRect = [GetNSViewForSuperview() frame];
607     if(w)
608         *w=(int)cocoaRect.size.width;
609     if(h)
610         *h=(int)cocoaRect.size.height;
611 //    wxLogDebug("wxWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
612 }
613
614 void wxWindow::DoGetPosition(int *x, int *y) const
615 {
616     NSView *nsview = GetNSViewForSuperview();
617     NSView *superview = [nsview superview];
618     wxCHECK_RET(superview,"NSView does not have a superview");
619     NSRect parentRect = [superview bounds];
620
621     NSRect cocoaRect = [nsview frame];
622     if(x)
623         *x=(int)cocoaRect.origin.x;
624     if(y)
625         *y=(int)(parentRect.size.height-(cocoaRect.origin.y+cocoaRect.size.height));
626 //    wxLogDebug("wxWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
627 }
628
629 WXWidget wxWindow::GetHandle() const
630 {
631     return m_cocoaNSView;
632 }
633
634 void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
635 {
636     [m_cocoaNSView setNeedsDisplay:YES];
637 }
638
639 void wxWindow::SetFocus()
640 {
641     // TODO
642 }
643
644 void wxWindow::DoCaptureMouse()
645 {
646     // TODO
647     sm_capturedWindow = this;
648 }
649
650 void wxWindow::DoReleaseMouse()
651 {
652     // TODO
653     sm_capturedWindow = NULL;
654 }
655
656 void wxWindow::DoScreenToClient(int *x, int *y) const
657 {
658     // TODO
659 }
660
661 void wxWindow::DoClientToScreen(int *x, int *y) const
662 {
663     // TODO
664 }
665
666 // Get size *available for subwindows* i.e. excluding menu bar etc.
667 void wxWindow::DoGetClientSize(int *x, int *y) const
668 {
669     wxLogDebug("DoGetClientSize:");
670     if(m_cocoaScroller)
671         m_cocoaScroller->DoGetClientSize(x,y);
672     else
673         wxWindowCocoa::DoGetSize(x,y);
674 }
675
676 void wxWindow::DoSetClientSize(int width, int height)
677 {
678     wxLogDebug("DoSetClientSize=(%d,%d)",width,height);
679     if(m_cocoaScroller)
680         m_cocoaScroller->ClientSizeToSize(width,height);
681     CocoaSetWxWindowSize(width,height);
682 }
683
684 void wxWindow::CocoaSetWxWindowSize(int width, int height)
685 {
686     wxWindowCocoa::DoSetSize(-1,-1,width,height,wxSIZE_USE_EXISTING);
687 }
688
689 int wxWindow::GetCharHeight() const
690 {
691     // TODO
692     return 0;
693 }
694
695 int wxWindow::GetCharWidth() const
696 {
697     // TODO
698     return 0;
699 }
700
701 void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
702         int *descent, int *externalLeading, const wxFont *theFont) const
703 {
704     // TODO
705 }
706
707 // Coordinates relative to the window
708 void wxWindow::WarpPointer (int x_pos, int y_pos)
709 {
710     // TODO
711 }
712
713 int wxWindow::GetScrollPos(int orient) const
714 {
715     // TODO
716     return 0;
717 }
718
719 // This now returns the whole range, not just the number
720 // of positions that we can scroll.
721 int wxWindow::GetScrollRange(int orient) const
722 {
723     // TODO
724     return 0;
725 }
726
727 int wxWindow::GetScrollThumb(int orient) const
728 {
729     // TODO
730     return 0;
731 }
732
733 void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
734 {
735     // TODO
736 }
737
738 void wxWindow::CocoaCreateNSScrollView()
739 {
740     if(!m_cocoaScroller)
741     {
742         m_cocoaScroller = new wxWindowCocoaScroller(this);
743     }
744 }
745
746 // New function that will replace some of the above.
747 void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
748     int range, bool refresh)
749 {
750     CocoaCreateNSScrollView();
751     // TODO
752 }
753
754 // Does a physical scroll
755 void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
756 {
757     // TODO
758 }
759
760 void wxWindow::DoSetVirtualSize( int x, int y )
761 {
762     wxWindowBase::DoSetVirtualSize(x,y);
763     CocoaCreateNSScrollView();
764     [m_cocoaNSView setFrameSize:NSMakeSize(m_virtualSize.x,m_virtualSize.y)];
765 }
766
767 bool wxWindow::SetFont(const wxFont& font)
768 {
769     // TODO
770     return TRUE;
771 }
772
773 static int CocoaRaiseWindowCompareFunction(id first, id second, void *target)
774 {
775     // first should be ordered higher
776     if(first==target)
777         return NSOrderedDescending;
778     // second should be ordered higher
779     if(second==target)
780         return NSOrderedAscending;
781     return NSOrderedSame;
782 }
783
784 // Raise the window to the top of the Z order
785 void wxWindow::Raise()
786 {
787 //    wxAutoNSAutoreleasePool pool;
788     NSView *nsview = GetNSViewForSuperview();
789     [[nsview superview] sortSubviewsUsingFunction:
790             CocoaRaiseWindowCompareFunction
791         context: nsview];
792 }
793
794 static int CocoaLowerWindowCompareFunction(id first, id second, void *target)
795 {
796     // first should be ordered lower
797     if(first==target)
798         return NSOrderedAscending;
799     // second should be ordered lower
800     if(second==target)
801         return NSOrderedDescending;
802     return NSOrderedSame;
803 }
804
805 // Lower the window to the bottom of the Z order
806 void wxWindow::Lower()
807 {
808     NSView *nsview = GetNSViewForSuperview();
809     [[nsview superview] sortSubviewsUsingFunction:
810             CocoaLowerWindowCompareFunction
811         context: nsview];
812 }
813
814 bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
815 {
816     return FALSE;
817 }
818
819 // Get the window with the focus
820 wxWindow *wxWindowBase::FindFocus()
821 {
822     // TODO
823     return NULL;
824 }
825
826 /* static */ wxWindow *wxWindowBase::GetCapture()
827 {
828     // TODO
829     return wxWindowCocoa::sm_capturedWindow;
830 }
831
832 wxWindow *wxGetActiveWindow()
833 {
834     // TODO
835     return NULL;
836 }
837
838 wxPoint wxGetMousePosition()
839 {
840     // TODO
841     return wxDefaultPosition;
842 }
843
844 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
845 {
846     pt = wxGetMousePosition();
847     return NULL;
848 }
849