1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/toplevel.mm
3 // Purpose: implements wxTopLevelWindow for Cocoa
4 // Author: David Elliott
8 // Copyright: (c) 2002 David Elliott
9 // License: wxWindows license
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"
33 #include "wx/cocoa/mbarman.h"
35 #import <AppKit/NSView.h>
36 #import <AppKit/NSWindow.h>
37 #import <AppKit/NSPanel.h>
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 // list of all frames and modeless dialogs
43 wxWindowList wxModelessWindows;
45 // ============================================================================
46 // wxTopLevelWindowCocoa implementation
47 // ============================================================================
49 // ----------------------------------------------------------------------------
50 // wxTopLevelWindowCocoa creation
51 // ----------------------------------------------------------------------------
52 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
53 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
56 void wxTopLevelWindowCocoa::Init()
63 unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
65 unsigned int styleMask = 0;
67 styleMask |= NSTitledWindowMask;
68 if(style & wxMINIMIZE_BOX)
69 styleMask |= NSMiniaturizableWindowMask;
71 if(style & wxMAXIMIZE_BOX)
72 styleMask |= NSWindowMask;
74 if(style & wxCLOSE_BOX)
75 styleMask |= NSClosableWindowMask;
76 if(style & wxRESIZE_BORDER)
77 styleMask |= NSResizableWindowMask;
78 if(style & wxSIMPLE_BORDER)
79 styleMask |= NSBorderlessWindowMask;
83 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
85 const wxString& title,
91 wxAutoNSAutoreleasePool pool;
92 wxTopLevelWindows.Append(this);
94 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
98 parent->AddChild(this);
100 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
101 if(style & wxFRAME_TOOL_WINDOW)
102 cocoaStyle |= NSUtilityWindowMask;
104 // NOTE: y-origin needs to be flipped.
105 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(pos.x,pos.y,size.x,size.y) styleMask:cocoaStyle];
107 m_cocoaNSWindow = NULL;
108 m_cocoaNSView = NULL;
109 if(style & wxFRAME_TOOL_WINDOW)
110 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
112 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
113 // NOTE: SetNSWindow has retained the Cocoa object for this object.
114 // Because we do not release on close, the following release matches the
115 // above alloc and thus the retain count will be 1.
116 [m_cocoaNSWindow release];
118 if(style & wxFRAME_NO_TASKBAR)
119 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
120 if(style & wxSTAY_ON_TOP)
121 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
122 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
126 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
128 wxAutoNSAutoreleasePool pool;
133 // ----------------------------------------------------------------------------
134 // wxTopLevelWindowCocoa Cocoa Specifics
135 // ----------------------------------------------------------------------------
137 wxMenuBar* wxTopLevelWindowCocoa::GetAppMenuBar(wxCocoaNSWindow *win)
139 wxTopLevelWindowCocoa *parent = wxDynamicCast(GetParent(),wxTopLevelWindow);
141 return parent->GetAppMenuBar(win);
145 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
147 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
148 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
149 DisassociateNSWindow(m_cocoaNSWindow);
150 [cocoaNSWindow retain];
151 [m_cocoaNSWindow release];
152 m_cocoaNSWindow = cocoaNSWindow;
154 SetNSView([m_cocoaNSWindow contentView]);
157 AssociateNSWindow(m_cocoaNSWindow);
158 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
161 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
163 if([m_cocoaNSWindow contentView] == (id)oldView)
164 [m_cocoaNSWindow setContentView:newView];
167 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
169 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
170 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
171 event.SetEventObject(this);
172 GetEventHandler()->ProcessEvent(event);
175 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
177 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
178 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
179 event.SetEventObject(this);
180 GetEventHandler()->ProcessEvent(event);
183 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
185 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
188 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
190 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
193 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
197 /* Be SURE that idle events get ran. If the window was not active when
198 it was closed, then there will be no more events to trigger this and
199 therefore it must be done here */
200 wxTheApp->CocoaInstallRequestedIdleHandler();
203 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
205 return wxWindowBase::Close(false);
208 // ----------------------------------------------------------------------------
209 // wxTopLevelWindowCocoa maximize/minimize
210 // ----------------------------------------------------------------------------
212 void wxTopLevelWindowCocoa::Maximize(bool maximize)
216 bool wxTopLevelWindowCocoa::IsMaximized() const
221 void wxTopLevelWindowCocoa::Iconize(bool iconize)
225 bool wxTopLevelWindowCocoa::IsIconized() const
230 void wxTopLevelWindowCocoa::Restore()
234 bool wxTopLevelWindowCocoa::Show(bool show)
236 if(m_isShown == show)
238 wxAutoNSAutoreleasePool pool;
241 // Send the window a size event because wxWindows apps expect it
242 // NOTE: This should really only be done the first time a window
243 // is shown. I doubt this will cause any problems though.
244 wxSizeEvent event(GetSize(), GetId());
245 event.SetEventObject(this);
246 GetEventHandler()->ProcessEvent(event);
248 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
251 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
256 bool wxTopLevelWindowCocoa::Close(bool force)
259 return wxWindowBase::Close(force);
260 // performClose will fake the user clicking the close button which
261 // will invoke windowShouldClose which will call the base class version
262 // of Close() which will NOT Destroy() the window (see below) but
263 // if closing is not stopped, then performClose will go ahead and
264 // close the window which will send the close notifications setting
265 // m_closed to true and Destroy()ing the window.
266 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
270 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
272 // If the event was forced, close the window which will Destroy() it
274 [m_cocoaNSWindow close];
275 // if the event was not forced, it's probably because the user clicked
276 // the close button, or Close(false) was called which (see above) is
277 // redirected to performClose and thus Cocoa itself will close the window
280 // ----------------------------------------------------------------------------
281 // wxTopLevelWindowCocoa misc
282 // ----------------------------------------------------------------------------
284 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
289 bool wxTopLevelWindowCocoa::IsFullScreen() const
294 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
296 // Set the NSView size by setting the frame size to enclose it
297 unsigned int styleMask = [m_cocoaNSWindow styleMask];
298 NSRect frameRect = [m_cocoaNSWindow frame];
299 NSRect contentRect = [NSWindow
300 contentRectForFrameRect: frameRect
301 styleMask: styleMask];
302 contentRect.size.width = width;
303 contentRect.size.height = height;
304 frameRect = [NSWindow
305 frameRectForContentRect: contentRect
306 styleMask: styleMask];
307 [m_cocoaNSWindow setFrame: frameRect display: NO];
310 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
312 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
314 NSRect cocoaRect = NSMakeRect(x,y,width,height);
315 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
318 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
320 NSRect cocoaRect = [m_cocoaNSWindow frame];
322 *w=(int)cocoaRect.size.width;
324 *h=(int)cocoaRect.size.height;
325 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
328 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
330 NSRect cocoaRect = [m_cocoaNSWindow frame];
332 *x=(int)cocoaRect.origin.x;
334 *y=(int)cocoaRect.origin.y;
335 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);