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 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
139 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
140 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
141 DisassociateNSWindow(m_cocoaNSWindow);
142 [cocoaNSWindow retain];
143 [m_cocoaNSWindow release];
144 m_cocoaNSWindow = cocoaNSWindow;
146 SetNSView([m_cocoaNSWindow contentView]);
149 AssociateNSWindow(m_cocoaNSWindow);
150 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
153 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
155 if([m_cocoaNSWindow contentView] == (id)oldView)
156 [m_cocoaNSWindow setContentView:newView];
159 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
161 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
162 wxMenuBarManager::GetInstance()->WindowDidBecomeKey(this);
163 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
164 event.SetEventObject(this);
165 GetEventHandler()->ProcessEvent(event);
168 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
170 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
171 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
172 event.SetEventObject(this);
173 GetEventHandler()->ProcessEvent(event);
174 wxMenuBarManager::GetInstance()->WindowDidResignKey(this);
177 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
179 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
180 wxMenuBarManager::GetInstance()->WindowDidBecomeMain(this);
183 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
185 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
186 wxMenuBarManager::GetInstance()->WindowDidResignMain(this);
189 void wxTopLevelWindowCocoa::Cocoa_close(void)
193 /* Be SURE that idle events get ran. If the window was not active when
194 it was closed, then there will be no more events to trigger this and
195 therefore it must be done here */
196 wxTheApp->CocoaInstallRequestedIdleHandler();
199 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
201 return wxWindowBase::Close(false);
204 // ----------------------------------------------------------------------------
205 // wxTopLevelWindowCocoa maximize/minimize
206 // ----------------------------------------------------------------------------
208 void wxTopLevelWindowCocoa::Maximize(bool maximize)
212 bool wxTopLevelWindowCocoa::IsMaximized() const
217 void wxTopLevelWindowCocoa::Iconize(bool iconize)
221 bool wxTopLevelWindowCocoa::IsIconized() const
226 void wxTopLevelWindowCocoa::Restore()
230 bool wxTopLevelWindowCocoa::Show(bool show)
232 if(m_isShown == show)
234 wxAutoNSAutoreleasePool pool;
237 // Send the window a size event because wxWindows apps expect it
238 // NOTE: This should really only be done the first time a window
239 // is shown. I doubt this will cause any problems though.
240 wxSizeEvent event(GetSize(), GetId());
241 event.SetEventObject(this);
242 GetEventHandler()->ProcessEvent(event);
244 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
247 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
252 bool wxTopLevelWindowCocoa::Close(bool force)
255 return wxWindowBase::Close(force);
256 // performClose will fake the user clicking the close button which
257 // will invoke windowShouldClose which will call the base class version
258 // of Close() which will NOT Destroy() the window (see below) but
259 // if closing is not stopped, then performClose will go ahead and
260 // close the window which will invoke Cocoa_close() setting m_closed
261 // to true and Destroy()ing the window.
262 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
266 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
268 // If the event was forced, close the window which will Destroy() it
270 [m_cocoaNSWindow close];
271 // if the event was not forced, it's probably because the user clicked
272 // the close button, or Close(false) was called which (see above) is
273 // redirected to performClose and thus Cocoa itself will close the window
276 // ----------------------------------------------------------------------------
277 // wxTopLevelWindowCocoa misc
278 // ----------------------------------------------------------------------------
280 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
285 bool wxTopLevelWindowCocoa::IsFullScreen() const
290 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
292 // Set the NSView size by setting the frame size to enclose it
293 unsigned int styleMask = [m_cocoaNSWindow styleMask];
294 NSRect frameRect = [m_cocoaNSWindow frame];
295 NSRect contentRect = [NSWindow
296 contentRectForFrameRect: frameRect
297 styleMask: styleMask];
298 contentRect.size.width = width;
299 contentRect.size.height = height;
300 frameRect = [NSWindow
301 frameRectForContentRect: contentRect
302 styleMask: styleMask];
303 [m_cocoaNSWindow setFrame: frameRect display: NO];
306 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
308 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
310 NSRect cocoaRect = NSMakeRect(x,y,width,height);
311 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
314 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
316 NSRect cocoaRect = [m_cocoaNSWindow frame];
318 *w=(int)cocoaRect.size.width;
320 *h=(int)cocoaRect.size.height;
321 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
324 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
326 NSRect cocoaRect = [m_cocoaNSWindow frame];
328 *x=(int)cocoaRect.origin.x;
330 *y=(int)cocoaRect.origin.y;
331 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);