]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/nonownedwnd.mm
Implement NSPanel support to get wxFRAME_TOOL_WINDOW and wxMiniFrame working.
[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 //
61 // wx native implementation classes
62 //
63
64 @interface wxNSWindow : NSWindow
65
66 {
67 wxNonOwnedWindowCocoaImpl* impl;
68 }
69
70 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation;
71 - (wxNonOwnedWindowCocoaImpl*) implementation;
72
73 @end
74
75 @implementation wxNSWindow
76
77 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation
78 {
79 impl = theImplementation;
80 }
81
82 - (wxNonOwnedWindowCocoaImpl*) implementation
83 {
84 return impl;
85 }
86
87
88 @end
89
90 @interface wxNSPanel : NSPanel
91
92 {
93 wxNonOwnedWindowCocoaImpl* impl;
94 }
95
96 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation;
97 - (wxNonOwnedWindowCocoaImpl*) implementation;
98
99 @end
100
101 @implementation wxNSPanel
102
103 - (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation
104 {
105 impl = theImplementation;
106 }
107
108 - (wxNonOwnedWindowCocoaImpl*) implementation
109 {
110 return impl;
111 }
112
113 @end
114
115
116 //
117 // controller
118 //
119
120 @interface wxNonOwnedWindowController : NSObject
121 {
122 }
123
124 - (void)windowDidResize:(NSNotification *)notification;
125 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
126 - (void)windowDidResignMain:(NSNotification *)notification;
127 - (void)windowDidBecomeMain:(NSNotification *)notification;
128 - (void)windowDidMove:(NSNotification *)notification;
129 - (BOOL)windowShouldClose:(id)window;
130
131 @end
132
133 @implementation wxNonOwnedWindowController
134
135 - (id) init
136 {
137 [super init];
138 return self;
139 }
140
141 - (BOOL)windowShouldClose:(id)nwindow
142 {
143 wxNSWindow* window = (wxNSWindow*) nwindow;
144 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
145 if ( windowimpl )
146 {
147 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
148 if ( wxpeer )
149 wxpeer->Close();
150 }
151 return NO;
152 }
153
154 - (NSSize)windowWillResize:(NSWindow *)win
155 toSize:(NSSize)proposedFrameSize
156 {
157 NSRect frame = [win frame];
158 wxRect wxframe = wxFromNSRect( NULL, frame );
159 wxframe.SetWidth( proposedFrameSize.width );
160 wxframe.SetHeight( proposedFrameSize.height );
161 wxNSWindow* window = (wxNSWindow*) win;
162 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
163 if ( windowimpl )
164 {
165 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
166 if ( wxpeer )
167 {
168 wxpeer->HandleResizing( 0, &wxframe );
169 NSSize newSize = NSMakeSize(wxframe.GetWidth(), wxframe.GetHeight());
170 return newSize;
171 }
172 }
173
174 return proposedFrameSize;
175 }
176
177 - (void)windowDidResize:(NSNotification *)notification
178 {
179 wxNSWindow* window = (wxNSWindow*) [notification object];
180 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
181 if ( windowimpl )
182 {
183 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
184 if ( wxpeer )
185 wxpeer->HandleResized(0);
186 }
187 }
188
189 - (void)windowDidMove:(NSNotification *)notification
190 {
191 wxNSWindow* window = (wxNSWindow*) [notification object];
192 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
193 if ( windowimpl )
194 {
195 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
196 if ( wxpeer )
197 wxpeer->HandleMoved(0);
198 }
199 }
200
201 - (void)windowDidBecomeMain:(NSNotification *)notification
202 {
203 wxNSWindow* window = (wxNSWindow*) [notification object];
204 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
205 if ( windowimpl )
206 {
207 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
208 if ( wxpeer )
209 wxpeer->HandleActivated(0, true);
210 }
211 }
212
213 - (void)windowDidResignMain:(NSNotification *)notification
214 {
215 wxNSWindow* window = (wxNSWindow*) [notification object];
216 wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation];
217 if ( windowimpl )
218 {
219 wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer();
220 if ( wxpeer )
221 wxpeer->HandleActivated(0, false);
222 }
223 }
224
225 @end
226
227 IMPLEMENT_DYNAMIC_CLASS( wxNonOwnedWindowCocoaImpl , wxNonOwnedWindowImpl )
228
229 wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl( wxNonOwnedWindow* nonownedwnd) :
230 wxNonOwnedWindowImpl(nonownedwnd)
231 {
232 m_macWindow = NULL;
233 m_macFullScreenData = NULL;
234 }
235
236 wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl()
237 {
238 m_macWindow = NULL;
239 m_macFullScreenData = NULL;
240 }
241
242 wxNonOwnedWindowCocoaImpl::~wxNonOwnedWindowCocoaImpl()
243 {
244 [m_macWindow setImplementation:nil];
245 [m_macWindow setDelegate:nil];
246 [m_macWindow release];
247 }
248
249 void wxNonOwnedWindowCocoaImpl::Destroy()
250 {
251 wxPendingDelete.Append( new wxDeferredObjectDeleter( this ) );
252 }
253
254 void wxNonOwnedWindowCocoaImpl::Create( wxWindow* parent, const wxPoint& pos, const wxSize& size,
255 long style, long extraStyle, const wxString& name )
256 {
257 static wxNonOwnedWindowController* controller = NULL;
258
259 if ( !controller )
260 controller =[[wxNonOwnedWindowController alloc] init];
261
262
263 int windowstyle = NSBorderlessWindowMask;
264
265 if ( style & wxFRAME_TOOL_WINDOW )
266 m_macWindow = [wxNSPanel alloc];
267 else
268 m_macWindow = [wxNSWindow alloc];
269
270 CGWindowLevel level = kCGNormalWindowLevel;
271
272 if ( style & wxFRAME_TOOL_WINDOW )
273 {
274 windowstyle |= NSTitledWindowMask | NSUtilityWindowMask;
275 }
276 else if ( ( style & wxPOPUP_WINDOW ) )
277 {
278 level = kCGPopUpMenuWindowLevel;
279 /*
280 if ( ( style & wxBORDER_NONE ) )
281 {
282 wclass = kHelpWindowClass ; // has no border
283 attr |= kWindowNoShadowAttribute;
284 }
285 else
286 {
287 wclass = kPlainWindowClass ; // has a single line border, it will have to do for now
288 }
289 */
290 }
291 else if ( ( style & wxCAPTION ) )
292 {
293 windowstyle |= NSTitledWindowMask ;
294 }
295 else if ( ( style & wxFRAME_DRAWER ) )
296 {
297 /*
298 wclass = kDrawerWindowClass;
299 */
300 }
301 else
302 {
303 // set these even if we have no title, otherwise the controls won't be visible
304 if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) ||
305 ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) )
306 {
307 windowstyle |= NSTitledWindowMask ;
308 }
309 /*
310 else if ( ( style & wxNO_BORDER ) )
311 {
312 wclass = kSimpleWindowClass ;
313 }
314 else
315 {
316 wclass = kPlainWindowClass ;
317 }
318 */
319 }
320
321 if ( windowstyle & NSTitledWindowMask )
322 {
323 if ( ( style & wxMINIMIZE_BOX ) )
324 windowstyle |= NSMiniaturizableWindowMask ;
325
326 if ( ( style & wxMAXIMIZE_BOX ) )
327 windowstyle |= NSResizableWindowMask ; // TODO showing ZOOM ?
328
329 if ( ( style & wxRESIZE_BORDER ) )
330 windowstyle |= NSResizableWindowMask ;
331
332 if ( ( style & wxCLOSE_BOX) )
333 windowstyle |= NSClosableWindowMask ;
334 }
335 if ( extraStyle & wxFRAME_EX_METAL)
336 windowstyle |= NSTexturedBackgroundWindowMask;
337
338 if ( ( style & wxFRAME_FLOAT_ON_PARENT ) || ( style & wxFRAME_TOOL_WINDOW ) )
339 level = kCGFloatingWindowLevel;
340
341 if ( ( style & wxSTAY_ON_TOP ) )
342 level = kCGUtilityWindowLevel;
343
344 NSRect r = wxToNSRect( NULL, wxRect( pos, size) );
345
346 [m_macWindow setImplementation:this];
347
348 [m_macWindow initWithContentRect:r
349 styleMask:windowstyle
350 backing:NSBackingStoreBuffered
351 defer:NO
352 ];
353
354 [m_macWindow setLevel:level];
355
356 [m_macWindow setDelegate:controller];
357
358 // [m_macWindow makeKeyAndOrderFront:nil];
359 }
360
361
362 WXWindow wxNonOwnedWindowCocoaImpl::GetWXWindow() const
363 {
364 return m_macWindow;
365 }
366
367 void wxNonOwnedWindowCocoaImpl::Raise()
368 {
369 [m_macWindow orderWindow:NSWindowAbove relativeTo:0];
370 }
371
372 void wxNonOwnedWindowCocoaImpl::Lower()
373 {
374 [m_macWindow orderWindow:NSWindowBelow relativeTo:0];
375 }
376
377 bool wxNonOwnedWindowCocoaImpl::Show(bool show)
378 {
379 if ( show )
380 {
381 [m_macWindow orderFront:nil];
382 [[m_macWindow contentView] setNeedsDisplay:YES];
383 }
384 else
385 [m_macWindow orderOut:nil];
386 return true;
387 }
388
389 bool wxNonOwnedWindowCocoaImpl::ShowWithEffect(bool show, wxShowEffect effect, unsigned timeout)
390 {
391 return Show(show);
392 }
393
394 void wxNonOwnedWindowCocoaImpl::Update()
395 {
396 [m_macWindow displayIfNeeded];
397 }
398
399 bool wxNonOwnedWindowCocoaImpl::SetTransparent(wxByte alpha)
400 {
401 [m_macWindow setAlphaValue:(CGFloat) alpha/255.0];
402 return true;
403 }
404
405 bool wxNonOwnedWindowCocoaImpl::SetBackgroundColour(const wxColour& col )
406 {
407 return true;
408 }
409
410 void wxNonOwnedWindowCocoaImpl::SetExtraStyle( long exStyle )
411 {
412 if ( m_macWindow )
413 {
414 bool metal = exStyle & wxFRAME_EX_METAL ;
415 int windowStyle = [ m_macWindow styleMask];
416 if ( metal && !(windowStyle & NSTexturedBackgroundWindowMask) )
417 {
418 wxFAIL_MSG( _T("Metal Style cannot be changed after creation") );
419 }
420 else if ( !metal && (windowStyle & NSTexturedBackgroundWindowMask ) )
421 {
422 wxFAIL_MSG( _T("Metal Style cannot be changed after creation") );
423 }
424 }
425 }
426
427 bool wxNonOwnedWindowCocoaImpl::SetBackgroundStyle(wxBackgroundStyle style)
428 {
429 return true;
430 }
431
432 bool wxNonOwnedWindowCocoaImpl::CanSetTransparent()
433 {
434 return true;
435 }
436
437 void wxNonOwnedWindowCocoaImpl::MoveWindow(int x, int y, int width, int height)
438 {
439 NSRect r = wxToNSRect( NULL, wxRect(x,y,width, height) );
440 // do not trigger refreshes upon invisible and possible partly created objects
441 [m_macWindow setFrame:r display:GetWXPeer()->IsShownOnScreen()];
442 }
443
444 void wxNonOwnedWindowCocoaImpl::GetPosition( int &x, int &y ) const
445 {
446 wxRect r = wxFromNSRect( NULL, [m_macWindow frame] );
447 x = r.GetLeft();
448 y = r.GetTop();
449 }
450
451 void wxNonOwnedWindowCocoaImpl::GetSize( int &width, int &height ) const
452 {
453 NSRect rect = [m_macWindow frame];
454 width = rect.size.width;
455 height = rect.size.height;
456 }
457
458 void wxNonOwnedWindowCocoaImpl::GetContentArea( int& left, int &right, int &width, int &height ) const
459 {
460 NSRect outer = NSMakeRect(100,100,100,100);
461 NSRect content = [NSWindow contentRectForFrameRect:outer styleMask:[m_macWindow styleMask] ];
462 NSRect rect = [[m_macWindow contentView] frame];
463 width = rect.size.width;
464 height = rect.size.height;
465 }
466
467 bool wxNonOwnedWindowCocoaImpl::SetShape(const wxRegion& region)
468 {
469 return false;
470 }
471
472 void wxNonOwnedWindowCocoaImpl::SetTitle( const wxString& title, wxFontEncoding encoding )
473 {
474 [m_macWindow setTitle:wxCFStringRef( title , encoding ).AsNSString()];
475 }
476
477 bool wxNonOwnedWindowCocoaImpl::IsMaximized() const
478 {
479 return [m_macWindow isZoomed];
480 }
481
482 bool wxNonOwnedWindowCocoaImpl::IsIconized() const
483 {
484 return [m_macWindow isMiniaturized];
485 }
486
487 void wxNonOwnedWindowCocoaImpl::Iconize( bool iconize )
488 {
489 if ( iconize )
490 [m_macWindow miniaturize:nil];
491 else
492 [m_macWindow deminiaturize:nil];
493 }
494
495 void wxNonOwnedWindowCocoaImpl::Maximize(bool maximize)
496 {
497 [m_macWindow zoom:nil];
498 }
499
500
501 // http://cocoadevcentral.com/articles/000028.php
502
503 typedef struct
504 {
505 int m_formerLevel;
506 NSRect m_formerFrame;
507 } FullScreenData ;
508
509 bool wxNonOwnedWindowCocoaImpl::IsFullScreen() const
510 {
511 return m_macFullScreenData != NULL ;
512 }
513
514 bool wxNonOwnedWindowCocoaImpl::ShowFullScreen(bool show, long style)
515 {
516 if ( show )
517 {
518 FullScreenData *data = (FullScreenData *)m_macFullScreenData ;
519 delete data ;
520 data = new FullScreenData();
521
522 m_macFullScreenData = data ;
523 data->m_formerLevel = [m_macWindow level];
524 data->m_formerFrame = [m_macWindow frame];
525 CGDisplayCapture( kCGDirectMainDisplay );
526 [m_macWindow setLevel:CGShieldingWindowLevel()];
527 [m_macWindow setFrame:[[NSScreen mainScreen] frame] display:YES];
528 }
529 else if ( m_macFullScreenData != NULL )
530 {
531 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
532 CGDisplayRelease( kCGDirectMainDisplay );
533 [m_macWindow setLevel:data->m_formerLevel];
534 [m_macWindow setFrame:data->m_formerFrame display:YES];
535 delete data ;
536 m_macFullScreenData = NULL ;
537 }
538
539 return true;
540 }
541
542 void wxNonOwnedWindowCocoaImpl::RequestUserAttention(int WXUNUSED(flags))
543 {
544 }
545
546 void wxNonOwnedWindowCocoaImpl::ScreenToWindow( int *x, int *y )
547 {
548 wxPoint p((x ? *x : 0), (y ? *y : 0) );
549 NSPoint nspt = wxToNSPoint( NULL, p );
550 nspt = [m_macWindow convertScreenToBase:nspt];
551 nspt = [[m_macWindow contentView] convertPoint:nspt fromView:nil];
552 p = wxFromNSPoint([m_macWindow contentView], nspt);
553 if ( x )
554 *x = p.x;
555 if ( y )
556 *y = p.y;
557 }
558
559 void wxNonOwnedWindowCocoaImpl::WindowToScreen( int *x, int *y )
560 {
561 wxPoint p((x ? *x : 0), (y ? *y : 0) );
562 NSPoint nspt = wxToNSPoint( [m_macWindow contentView], p );
563 nspt = [[m_macWindow contentView] convertPoint:nspt toView:nil];
564 nspt = [m_macWindow convertBaseToScreen:nspt];
565 p = wxFromNSPoint( NULL, nspt);
566 if ( x )
567 *x = p.x;
568 if ( y )
569 *y = p.y;
570 }
571
572 wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::CreateNonOwnedWindow( wxNonOwnedWindow* wxpeer, wxWindow* parent, const wxPoint& pos, const wxSize& size,
573 long style, long extraStyle, const wxString& name )
574 {
575 wxNonOwnedWindowImpl* now = new wxNonOwnedWindowCocoaImpl( wxpeer );
576 now->Create( parent, pos, size, style , extraStyle, name );
577 return now;
578 }