]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/nonownedwnd.mm
Disabling sheets codepath until we can resolve the nested loop issue.
[wxWidgets.git] / src / osx / cocoa / nonownedwnd.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/nonownedwnd.mm
3 // Purpose: non owned window for cocoa
4 // Author: DavidStefan Csomor
5 // Modified by:
6 // Created: 2008-06-20
7 // RCS-ID: $Id: nonownedwnd.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #ifndef WX_PRECOMP
14 #include "wx/nonownedwnd.h"
15 #include "wx/frame.h"
16 #endif
17
18 #include "wx/osx/private.h"
19
20 NSRect wxToNSRect( NSView* parent, const wxRect& r )
21 {
22 NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame];
23 int y = r.y;
24 int x = r.x ;
25 if ( parent == NULL || ![ parent isFlipped ] )
26 y = frame.size.height - ( r.y + r.height );
27 return NSMakeRect(x, y, r.width , r.height);
28 }
29
30 wxRect wxFromNSRect( NSView* parent, const NSRect& rect )
31 {
32 NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame];
33 int y = rect.origin.y;
34 int x = rect.origin.x;
35 if ( parent == NULL || ![ parent isFlipped ] )
36 y = frame.size.height - (rect.origin.y + rect.size.height);
37 return wxRect( x, y, rect.size.width, rect.size.height );
38 }
39
40 NSPoint wxToNSPoint( NSView* parent, const wxPoint& p )
41 {
42 NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame];
43 int x = p.x ;
44 int y = p.y;
45 if ( parent == NULL || ![ parent isFlipped ] )
46 y = frame.size.height - ( p.y );
47 return NSMakePoint(x, y);
48 }
49
50 wxPoint wxFromNSPoint( NSView* parent, const NSPoint& p )
51 {
52 NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame];
53 int x = p.x;
54 int y = p.y;
55 if ( parent == NULL || ![ parent isFlipped ] )
56 y = frame.size.height - ( p.y );
57 return wxPoint( x, y);
58 }
59
60 bool shouldHandleSelector(SEL selector)
61 {
62 if (selector == @selector(noop:)
63 || selector == @selector(complete:)
64 || selector == @selector(deleteBackward:)
65 || selector == @selector(deleteForward:)
66 || selector == @selector(insertNewline:)
67 || selector == @selector(insertTab:)
68 || selector == @selector(keyDown:)
69 || selector == @selector(keyUp:)
70 || selector == @selector(scrollPageUp:)
71 || selector == @selector(scrollPageDown:)
72 || selector == @selector(scrollToBeginningOfDocument:)
73 || selector == @selector(scrollToEndOfDocument:))
74 return false;
75
76 return true;
77
78 }
79
80 //
81 // wx native implementation classes
82 //
83
84 typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector);
85
86 @interface wxNSWindow : NSWindow
87 {
88 wxNonOwnedWindowCocoaImpl* impl;
89 }
90
91 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation;
92 - (wxNonOwnedWindowCocoaImpl*) implementation;
93 - (void)noResponderFor: (SEL) selector;
94 @end
95
96 @implementation wxNSWindow
97
98 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation
99 {
100 impl = theImplementation;
101 }
102
103 - (wxNonOwnedWindowCocoaImpl*) implementation
104 {
105 return impl;
106 }
107
108 - (void)doCommandBySelector:(SEL)selector
109 {
110 if (shouldHandleSelector(selector) &&
111 !(selector == @selector(cancel:) || selector == @selector(cancelOperation:)) )
112 [super doCommandBySelector:selector];
113 }
114
115
116 // NB: if we don't do this, all key downs that get handled lead to a NSBeep
117 - (void)noResponderFor: (SEL) selector
118 {
119 if (selector != @selector(keyDown:) && selector != @selector(keyUp:))
120 {
121 wxOSX_NoResponderHandlerPtr superimpl = (wxOSX_NoResponderHandlerPtr) [[self superclass] instanceMethodForSelector:@selector(noResponderFor:)];
122 superimpl(self, @selector(noResponderFor:), selector);
123 }
124 }
125
126 @end
127
128 @interface wxNSPanel : NSPanel
129
130 {
131 wxNonOwnedWindowCocoaImpl* impl;
132 }
133
134 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation;
135 - (wxNonOwnedWindowCocoaImpl*) implementation;
136 - (void)noResponderFor: (SEL) selector;
137 @end
138
139 @implementation wxNSPanel
140
141 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation
142 {
143 impl = theImplementation;
144 }
145
146 - (BOOL)canBecomeKeyWindow
147 {
148 return YES;
149 }
150
151 - (wxNonOwnedWindowCocoaImpl*) implementation
152 {
153 return impl;
154 }
155
156 - (void)doCommandBySelector:(SEL)selector
157 {
158 if (shouldHandleSelector(selector))
159 [super doCommandBySelector:selector];
160 }
161
162 // NB: if we don't do this, it seems that all events that end here lead to a NSBeep
163 - (void)noResponderFor: (SEL) selector
164 {
165 if (selector != @selector(keyDown:) && selector != @selector(keyUp:))
166 {
167 wxOSX_NoResponderHandlerPtr superimpl = (wxOSX_NoResponderHandlerPtr) [[self superclass] instanceMethodForSelector:@selector(noResponderFor:)];
168 superimpl(self, @selector(noResponderFor:), selector);
169 }
170 }
171
172 @end
173
174
175 //
176 // controller
177 //
178
179 @interface wxNonOwnedWindowController : NSObject
180 {
181 }
182
183 - (void)windowDidResize:(NSNotification *)notification;
184 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
185 - (void)windowDidResignKey:(NSNotification *)notification;
186 - (void)windowDidBecomeKey:(NSNotification *)notification;
187 - (void)windowDidMove:(NSNotification *)notification;
188 - (BOOL)windowShouldClose:(id)window;
189
190 @end
191
192 @implementation wxNonOwnedWindowController
193
194 - (id) init
195 {
196 [super init];
197 return self;
198 }
199
200 - (BOOL)windowShouldClose:(id)nwindow
201 {
202 wxNSWindow* window = (wxNSWindow*) nwindow;
203 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
204 if ( windowimpl )
205 {
206 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
207 if ( wxpeer )
208 wxpeer->Close();
209 }
210 return NO;
211 }
212
213 - (NSSize)windowWillResize:(NSWindow *)win
214 toSize:(NSSize)proposedFrameSize
215 {
216 NSRect frame = [win frame];
217 wxRect wxframe = wxFromNSRect( NULL, frame );
218 wxframe.SetWidth( proposedFrameSize.width );
219 wxframe.SetHeight( proposedFrameSize.height );
220 wxNSWindow* window = (wxNSWindow*) win;
221 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
222 if ( windowimpl )
223 {
224 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
225 if ( wxpeer )
226 {
227 wxpeer->HandleResizing( 0, &wxframe );
228 NSSize newSize = NSMakeSize(wxframe.GetWidth(), wxframe.GetHeight());
229 return newSize;
230 }
231 }
232
233 return proposedFrameSize;
234 }
235
236 - (void)windowDidResize:(NSNotification *)notification
237 {
238 wxNSWindow* window = (wxNSWindow*) [notification object];
239 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
240 if ( windowimpl )
241 {
242 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
243 if ( wxpeer )
244 wxpeer->HandleResized(0);
245 }
246 }
247
248 - (void)windowDidMove:(NSNotification *)notification
249 {
250 wxNSWindow* window = (wxNSWindow*) [notification object];
251 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
252 if ( windowimpl )
253 {
254 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
255 if ( wxpeer )
256 wxpeer->HandleMoved(0);
257 }
258 }
259
260 - (void)windowDidBecomeKey:(NSNotification *)notification
261 {
262 wxNSWindow* window = (wxNSWindow*) [notification object];
263 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
264 if ( windowimpl )
265 {
266 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
267 if ( wxpeer )
268 wxpeer->HandleActivated(0, true);
269 }
270 }
271
272 - (void)windowDidResignKey:(NSNotification *)notification
273 {
274 wxNSWindow* window = (wxNSWindow*) [notification object];
275 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
276 if ( windowimpl )
277 {
278 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
279 if ( wxpeer )
280 {
281 wxpeer->HandleActivated(0, false);
282 // Needed for popup window since the firstResponder
283 // (focus in wx) doesn't change when this
284 // TLW becomes inactive.
285 wxFocusEvent event( wxEVT_KILL_FOCUS, wxpeer->GetId());
286 event.SetEventObject(wxpeer);
287 wxpeer->HandleWindowEvent(event);
288 }
289 }
290 }
291
292 @end
293
294 IMPLEMENT_DYNAMIC_CLASS( wxNonOwnedWindowCocoaImpl , wxNonOwnedWindowImpl )
295
296 wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl( wxNonOwnedWindow* nonownedwnd) :
297 wxNonOwnedWindowImpl(nonownedwnd)
298 {
299 m_macWindow = NULL;
300 m_macFullScreenData = NULL;
301 }
302
303 wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl()
304 {
305 m_macWindow = NULL;
306 m_macFullScreenData = NULL;
307 }
308
309 wxNonOwnedWindowCocoaImpl::~wxNonOwnedWindowCocoaImpl()
310 {
311 [m_macWindow setImplementation:nil];
312 [m_macWindow setDelegate:nil];
313 [m_macWindow release];
314 }
315
316 void wxNonOwnedWindowCocoaImpl::Destroy()
317 {
318 wxPendingDelete.Append( new wxDeferredObjectDeleter( this ) );
319 }
320
321 void wxNonOwnedWindowCocoaImpl::Create( wxWindow* parent, const wxPoint& pos, const wxSize& size,
322 long style, long extraStyle, const wxString& name )
323 {
324 static wxNonOwnedWindowController* controller = NULL;
325
326 if ( !controller )
327 controller =[[wxNonOwnedWindowController alloc] init];
328
329
330 int windowstyle = NSBorderlessWindowMask;
331
332 if ( style & wxFRAME_TOOL_WINDOW || ( style & wxPOPUP_WINDOW ) ||
333 GetWXPeer()->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG )
334 {
335 m_macWindow = [wxNSPanel alloc];
336 }
337 else
338 m_macWindow = [wxNSWindow alloc];
339
340 CGWindowLevel level = kCGNormalWindowLevel;
341
342 if ( style & wxFRAME_TOOL_WINDOW )
343 {
344 windowstyle |= NSUtilityWindowMask;
345 if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) ||
346 ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) )
347 {
348 windowstyle |= NSTitledWindowMask ;
349 }
350 }
351 else if ( ( style & wxPOPUP_WINDOW ) )
352 {
353 level = kCGPopUpMenuWindowLevel;
354 /*
355 if ( ( style & wxBORDER_NONE ) )
356 {
357 wclass = kHelpWindowClass ; // has no border
358 attr |= kWindowNoShadowAttribute;
359 }
360 else
361 {
362 wclass = kPlainWindowClass ; // has a single line border, it will have to do for now
363 }
364 */
365 }
366 else if ( ( style & wxCAPTION ) )
367 {
368 windowstyle |= NSTitledWindowMask ;
369 }
370 else if ( ( style & wxFRAME_DRAWER ) )
371 {
372 /*
373 wclass = kDrawerWindowClass;
374 */
375 }
376 else
377 {
378 // set these even if we have no title, otherwise the controls won't be visible
379 if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) ||
380 ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) )
381 {
382 windowstyle |= NSTitledWindowMask ;
383 }
384 /*
385 else if ( ( style & wxNO_BORDER ) )
386 {
387 wclass = kSimpleWindowClass ;
388 }
389 else
390 {
391 wclass = kPlainWindowClass ;
392 }
393 */
394 }
395
396 if ( windowstyle & NSTitledWindowMask )
397 {
398 if ( ( style & wxMINIMIZE_BOX ) )
399 windowstyle |= NSMiniaturizableWindowMask ;
400
401 if ( ( style & wxMAXIMIZE_BOX ) )
402 windowstyle |= NSResizableWindowMask ; // TODO showing ZOOM ?
403
404 if ( ( style & wxRESIZE_BORDER ) )
405 windowstyle |= NSResizableWindowMask ;
406
407 if ( ( style & wxCLOSE_BOX) )
408 windowstyle |= NSClosableWindowMask ;
409 }
410 if ( extraStyle & wxFRAME_EX_METAL)
411 windowstyle |= NSTexturedBackgroundWindowMask;
412
413 if ( ( style & wxFRAME_FLOAT_ON_PARENT ) || ( style & wxFRAME_TOOL_WINDOW ) )
414 level = kCGFloatingWindowLevel;
415
416 if ( ( style & wxSTAY_ON_TOP ) )
417 level = kCGUtilityWindowLevel;
418
419 NSRect r = wxToNSRect( NULL, wxRect( pos, size) );
420
421 [m_macWindow setImplementation:this];
422
423 [m_macWindow initWithContentRect:r
424 styleMask:windowstyle
425 backing:NSBackingStoreBuffered
426 defer:NO
427 ];
428
429 [m_macWindow setLevel:level];
430
431 [m_macWindow setDelegate:controller];
432
433 [m_macWindow setAcceptsMouseMovedEvents: YES];
434 }
435
436
437 WXWindow wxNonOwnedWindowCocoaImpl::GetWXWindow() const
438 {
439 return m_macWindow;
440 }
441
442 void wxNonOwnedWindowCocoaImpl::Raise()
443 {
444 [m_macWindow orderWindow:NSWindowAbove relativeTo:0];
445 }
446
447 void wxNonOwnedWindowCocoaImpl::Lower()
448 {
449 [m_macWindow orderWindow:NSWindowBelow relativeTo:0];
450 }
451
452 bool wxNonOwnedWindowCocoaImpl::Show(bool show)
453 {
454 if ( show )
455 {
456 [m_macWindow makeKeyAndOrderFront:nil];
457 [[m_macWindow contentView] setNeedsDisplay:YES];
458 }
459 else
460 [m_macWindow orderOut:nil];
461 return true;
462 }
463
464 bool wxNonOwnedWindowCocoaImpl::ShowWithEffect(bool show, wxShowEffect effect, unsigned timeout)
465 {
466 return Show(show);
467 }
468
469 void wxNonOwnedWindowCocoaImpl::Update()
470 {
471 [m_macWindow displayIfNeeded];
472 }
473
474 bool wxNonOwnedWindowCocoaImpl::SetTransparent(wxByte alpha)
475 {
476 [m_macWindow setAlphaValue:(CGFloat) alpha/255.0];
477 return true;
478 }
479
480 bool wxNonOwnedWindowCocoaImpl::SetBackgroundColour(const wxColour& col )
481 {
482 return true;
483 }
484
485 void wxNonOwnedWindowCocoaImpl::SetExtraStyle( long exStyle )
486 {
487 if ( m_macWindow )
488 {
489 bool metal = exStyle & wxFRAME_EX_METAL ;
490 int windowStyle = [ m_macWindow styleMask];
491 if ( metal && !(windowStyle & NSTexturedBackgroundWindowMask) )
492 {
493 wxFAIL_MSG( _T("Metal Style cannot be changed after creation") );
494 }
495 else if ( !metal && (windowStyle & NSTexturedBackgroundWindowMask ) )
496 {
497 wxFAIL_MSG( _T("Metal Style cannot be changed after creation") );
498 }
499 }
500 }
501
502 bool wxNonOwnedWindowCocoaImpl::SetBackgroundStyle(wxBackgroundStyle style)
503 {
504 return true;
505 }
506
507 bool wxNonOwnedWindowCocoaImpl::CanSetTransparent()
508 {
509 return true;
510 }
511
512 void wxNonOwnedWindowCocoaImpl::MoveWindow(int x, int y, int width, int height)
513 {
514 NSRect r = wxToNSRect( NULL, wxRect(x,y,width, height) );
515 // do not trigger refreshes upon invisible and possible partly created objects
516 [m_macWindow setFrame:r display:GetWXPeer()->IsShownOnScreen()];
517 }
518
519 void wxNonOwnedWindowCocoaImpl::GetPosition( int &x, int &y ) const
520 {
521 wxRect r = wxFromNSRect( NULL, [m_macWindow frame] );
522 x = r.GetLeft();
523 y = r.GetTop();
524 }
525
526 void wxNonOwnedWindowCocoaImpl::GetSize( int &width, int &height ) const
527 {
528 NSRect rect = [m_macWindow frame];
529 width = rect.size.width;
530 height = rect.size.height;
531 }
532
533 void wxNonOwnedWindowCocoaImpl::GetContentArea( int& left, int &top, int &width, int &height ) const
534 {
535 NSRect outer = NSMakeRect(100,100,100,100);
536 NSRect content = [NSWindow contentRectForFrameRect:outer styleMask:[m_macWindow styleMask] ];
537 NSRect rect = [[m_macWindow contentView] frame];
538 left = rect.origin.x;
539 top = rect.origin.y;
540 width = rect.size.width;
541 height = rect.size.height;
542 }
543
544 bool wxNonOwnedWindowCocoaImpl::SetShape(const wxRegion& region)
545 {
546 return false;
547 }
548
549 void wxNonOwnedWindowCocoaImpl::SetTitle( const wxString& title, wxFontEncoding encoding )
550 {
551 [m_macWindow setTitle:wxCFStringRef( title , encoding ).AsNSString()];
552 }
553
554 bool wxNonOwnedWindowCocoaImpl::IsMaximized() const
555 {
556 return [m_macWindow isZoomed];
557 }
558
559 bool wxNonOwnedWindowCocoaImpl::IsIconized() const
560 {
561 return [m_macWindow isMiniaturized];
562 }
563
564 void wxNonOwnedWindowCocoaImpl::Iconize( bool iconize )
565 {
566 if ( iconize )
567 [m_macWindow miniaturize:nil];
568 else
569 [m_macWindow deminiaturize:nil];
570 }
571
572 void wxNonOwnedWindowCocoaImpl::Maximize(bool maximize)
573 {
574 [m_macWindow zoom:nil];
575 }
576
577
578 // http://cocoadevcentral.com/articles/000028.php
579
580 typedef struct
581 {
582 int m_formerLevel;
583 NSRect m_formerFrame;
584 } FullScreenData ;
585
586 bool wxNonOwnedWindowCocoaImpl::IsFullScreen() const
587 {
588 return m_macFullScreenData != NULL ;
589 }
590
591 bool wxNonOwnedWindowCocoaImpl::ShowFullScreen(bool show, long style)
592 {
593 if ( show )
594 {
595 FullScreenData *data = (FullScreenData *)m_macFullScreenData ;
596 delete data ;
597 data = new FullScreenData();
598
599 m_macFullScreenData = data ;
600 data->m_formerLevel = [m_macWindow level];
601 data->m_formerFrame = [m_macWindow frame];
602 CGDisplayCapture( kCGDirectMainDisplay );
603 [m_macWindow setLevel:CGShieldingWindowLevel()];
604 [m_macWindow setFrame:[[NSScreen mainScreen] frame] display:YES];
605 }
606 else if ( m_macFullScreenData != NULL )
607 {
608 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
609 CGDisplayRelease( kCGDirectMainDisplay );
610 [m_macWindow setLevel:data->m_formerLevel];
611 [m_macWindow setFrame:data->m_formerFrame display:YES];
612 delete data ;
613 m_macFullScreenData = NULL ;
614 }
615
616 return true;
617 }
618
619 void wxNonOwnedWindowCocoaImpl::RequestUserAttention(int WXUNUSED(flags))
620 {
621 }
622
623 void wxNonOwnedWindowCocoaImpl::ScreenToWindow( int *x, int *y )
624 {
625 wxPoint p((x ? *x : 0), (y ? *y : 0) );
626 NSPoint nspt = wxToNSPoint( NULL, p );
627 nspt = [m_macWindow convertScreenToBase:nspt];
628 nspt = [[m_macWindow contentView] convertPoint:nspt fromView:nil];
629 p = wxFromNSPoint([m_macWindow contentView], nspt);
630 if ( x )
631 *x = p.x;
632 if ( y )
633 *y = p.y;
634 }
635
636 void wxNonOwnedWindowCocoaImpl::WindowToScreen( int *x, int *y )
637 {
638 wxPoint p((x ? *x : 0), (y ? *y : 0) );
639 NSPoint nspt = wxToNSPoint( [m_macWindow contentView], p );
640 nspt = [[m_macWindow contentView] convertPoint:nspt toView:nil];
641 nspt = [m_macWindow convertBaseToScreen:nspt];
642 p = wxFromNSPoint( NULL, nspt);
643 if ( x )
644 *x = p.x;
645 if ( y )
646 *y = p.y;
647 }
648
649 wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::CreateNonOwnedWindow( wxNonOwnedWindow* wxpeer, wxWindow* parent, const wxPoint& pos, const wxSize& size,
650 long style, long extraStyle, const wxString& name )
651 {
652 wxNonOwnedWindowImpl* now = new wxNonOwnedWindowCocoaImpl( wxpeer );
653 now->Create( parent, pos, size, style , extraStyle, name );
654 return now;
655 }