1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/toplevel.mm
3 // Purpose: implements wxTopLevelWindow for Cocoa
4 // Author: David Elliott
8 // Copyright: (c) 2002 David Elliott
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #include "wx/window.h"
24 #include "wx/toplevel.h"
25 #include "wx/menuitem.h"
31 #include "wx/cocoa/autorelease.h"
32 #include "wx/cocoa/string.h"
34 #import <AppKit/NSView.h>
35 #import <AppKit/NSWindow.h>
36 #import <AppKit/NSPanel.h>
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 // list of all frames and modeless dialogs
42 wxWindowList wxModelessWindows;
44 // ============================================================================
45 // wxTopLevelWindowCocoa implementation
46 // ============================================================================
48 wxTopLevelWindowCocoa *wxTopLevelWindowCocoa::sm_cocoaDeactivateWindow = NULL;
50 // ----------------------------------------------------------------------------
51 // wxTopLevelWindowCocoa creation
52 // ----------------------------------------------------------------------------
53 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
54 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
57 void wxTopLevelWindowCocoa::Init()
64 unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
66 unsigned int styleMask = 0;
68 styleMask |= NSTitledWindowMask;
69 if(style & wxMINIMIZE_BOX)
70 styleMask |= NSMiniaturizableWindowMask;
72 if(style & wxMAXIMIZE_BOX)
73 styleMask |= NSWindowMask;
75 if(style & wxCLOSE_BOX)
76 styleMask |= NSClosableWindowMask;
77 if(style & wxRESIZE_BORDER)
78 styleMask |= NSResizableWindowMask;
79 if(style & wxSIMPLE_BORDER)
80 styleMask |= NSBorderlessWindowMask;
84 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
86 const wxString& title,
92 wxAutoNSAutoreleasePool pool;
93 wxTopLevelWindows.Append(this);
95 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
99 parent->AddChild(this);
101 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
102 if(style & wxFRAME_TOOL_WINDOW)
103 cocoaStyle |= NSUtilityWindowMask;
105 wxPoint realpos = pos;
106 wxSize realsize = size;
107 // FIXME: this is lame
116 // NOTE: y-origin needs to be flipped.
117 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(realpos.x,realpos.y,realsize.x,realsize.y) styleMask:cocoaStyle];
119 m_cocoaNSWindow = NULL;
120 m_cocoaNSView = NULL;
121 if(style & wxFRAME_TOOL_WINDOW)
122 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
124 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
125 // NOTE: SetNSWindow has retained the Cocoa object for this object.
126 // Because we do not release on close, the following release matches the
127 // above alloc and thus the retain count will be 1.
128 [m_cocoaNSWindow release];
130 if(style & wxFRAME_NO_TASKBAR)
131 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
132 if(style & wxSTAY_ON_TOP)
133 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
134 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
138 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
140 wxASSERT(sm_cocoaDeactivateWindow!=this);
141 wxAutoNSAutoreleasePool pool;
146 bool wxTopLevelWindowCocoa::Destroy()
148 if(sm_cocoaDeactivateWindow==this)
150 sm_cocoaDeactivateWindow = NULL;
151 wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey();
153 return wxTopLevelWindowBase::Destroy();
156 // ----------------------------------------------------------------------------
157 // wxTopLevelWindowCocoa Cocoa Specifics
158 // ----------------------------------------------------------------------------
160 wxMenuBar* wxTopLevelWindowCocoa::GetAppMenuBar(wxCocoaNSWindow *win)
162 wxTopLevelWindowCocoa *parent = wxDynamicCast(GetParent(),wxTopLevelWindow);
164 return parent->GetAppMenuBar(win);
168 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
170 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
171 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
172 DisassociateNSWindow(m_cocoaNSWindow);
173 [cocoaNSWindow retain];
174 [m_cocoaNSWindow release];
175 m_cocoaNSWindow = cocoaNSWindow;
177 SetNSView([m_cocoaNSWindow contentView]);
180 AssociateNSWindow(m_cocoaNSWindow);
181 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
184 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
186 if([m_cocoaNSWindow contentView] == (id)oldView)
187 [m_cocoaNSWindow setContentView:newView];
190 /*static*/ void wxTopLevelWindowCocoa::DeactivatePendingWindow()
192 if(sm_cocoaDeactivateWindow)
193 sm_cocoaDeactivateWindow->wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey();
194 sm_cocoaDeactivateWindow = NULL;
197 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
199 DeactivatePendingWindow();
200 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
201 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
202 event.SetEventObject(this);
203 GetEventHandler()->ProcessEvent(event);
206 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
208 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
209 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
210 event.SetEventObject(this);
211 GetEventHandler()->ProcessEvent(event);
214 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
216 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
219 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
221 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
224 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
228 /* Be SURE that idle events get ran. If the window was not active when
229 it was closed, then there will be no more events to trigger this and
230 therefore it must be done here */
231 wxTheApp->CocoaInstallRequestedIdleHandler();
234 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
236 return wxWindowBase::Close(false);
239 // ----------------------------------------------------------------------------
240 // wxTopLevelWindowCocoa maximize/minimize
241 // ----------------------------------------------------------------------------
243 void wxTopLevelWindowCocoa::Maximize(bool maximize)
247 bool wxTopLevelWindowCocoa::IsMaximized() const
252 void wxTopLevelWindowCocoa::Iconize(bool iconize)
256 bool wxTopLevelWindowCocoa::IsIconized() const
261 void wxTopLevelWindowCocoa::Restore()
265 bool wxTopLevelWindowCocoa::Show(bool show)
267 if(m_isShown == show)
269 wxAutoNSAutoreleasePool pool;
272 // Send the window a size event because wxWindows apps expect it
273 // NOTE: This should really only be done the first time a window
274 // is shown. I doubt this will cause any problems though.
275 wxSizeEvent event(GetSize(), GetId());
276 event.SetEventObject(this);
277 GetEventHandler()->ProcessEvent(event);
279 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
282 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
287 bool wxTopLevelWindowCocoa::Close(bool force)
290 return wxWindowBase::Close(force);
291 // performClose will fake the user clicking the close button which
292 // will invoke windowShouldClose which will call the base class version
293 // of Close() which will NOT Destroy() the window (see below) but
294 // if closing is not stopped, then performClose will go ahead and
295 // close the window which will send the close notifications setting
296 // m_closed to true and Destroy()ing the window.
297 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
301 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
303 // If the event was forced, close the window which will Destroy() it
305 [m_cocoaNSWindow close];
306 // if the event was not forced, it's probably because the user clicked
307 // the close button, or Close(false) was called which (see above) is
308 // redirected to performClose and thus Cocoa itself will close the window
311 // ----------------------------------------------------------------------------
312 // wxTopLevelWindowCocoa misc
313 // ----------------------------------------------------------------------------
315 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
320 bool wxTopLevelWindowCocoa::IsFullScreen() const
325 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
327 // Set the NSView size by setting the frame size to enclose it
328 unsigned int styleMask = [m_cocoaNSWindow styleMask];
329 NSRect frameRect = [m_cocoaNSWindow frame];
330 NSRect contentRect = [NSWindow
331 contentRectForFrameRect: frameRect
332 styleMask: styleMask];
333 contentRect.size.width = width;
334 contentRect.size.height = height;
335 frameRect = [NSWindow
336 frameRectForContentRect: contentRect
337 styleMask: styleMask];
338 [m_cocoaNSWindow setFrame: frameRect display: NO];
341 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
343 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
345 NSRect cocoaRect = NSMakeRect(x,y,width,height);
346 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
349 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
351 NSRect cocoaRect = [m_cocoaNSWindow frame];
353 *w=(int)cocoaRect.size.width;
355 *h=(int)cocoaRect.size.height;
356 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
359 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
361 NSRect cocoaRect = [m_cocoaNSWindow frame];
363 *x=(int)cocoaRect.origin.x;
365 *y=(int)cocoaRect.origin.y;
366 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);