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 // ----------------------------------------------------------------------------
49 // wxTopLevelWindowCocoa creation
50 // ----------------------------------------------------------------------------
51 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
52 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
55 void wxTopLevelWindowCocoa::Init()
62 unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
64 unsigned int styleMask = 0;
66 styleMask |= NSTitledWindowMask;
67 if(style & wxMINIMIZE_BOX)
68 styleMask |= NSMiniaturizableWindowMask;
70 if(style & wxMAXIMIZE_BOX)
71 styleMask |= NSWindowMask;
73 if(style & wxCLOSE_BOX)
74 styleMask |= NSClosableWindowMask;
75 if(style & wxRESIZE_BORDER)
76 styleMask |= NSResizableWindowMask;
77 if(style & wxSIMPLE_BORDER)
78 styleMask |= NSBorderlessWindowMask;
82 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
84 const wxString& title,
90 wxAutoNSAutoreleasePool pool;
91 wxTopLevelWindows.Append(this);
93 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
97 parent->AddChild(this);
99 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
100 if(style & wxFRAME_TOOL_WINDOW)
101 cocoaStyle |= NSUtilityWindowMask;
103 wxPoint realpos = pos;
104 wxSize realsize = size;
105 // FIXME: this is lame
114 // NOTE: y-origin needs to be flipped.
115 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(realpos.x,realpos.y,realsize.x,realsize.y) styleMask:cocoaStyle];
117 m_cocoaNSWindow = NULL;
118 m_cocoaNSView = NULL;
119 if(style & wxFRAME_TOOL_WINDOW)
120 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
122 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
123 // NOTE: SetNSWindow has retained the Cocoa object for this object.
124 // Because we do not release on close, the following release matches the
125 // above alloc and thus the retain count will be 1.
126 [m_cocoaNSWindow release];
128 if(style & wxFRAME_NO_TASKBAR)
129 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
130 if(style & wxSTAY_ON_TOP)
131 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
132 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
136 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
138 wxAutoNSAutoreleasePool pool;
143 // ----------------------------------------------------------------------------
144 // wxTopLevelWindowCocoa Cocoa Specifics
145 // ----------------------------------------------------------------------------
147 wxMenuBar* wxTopLevelWindowCocoa::GetAppMenuBar(wxCocoaNSWindow *win)
149 wxTopLevelWindowCocoa *parent = wxDynamicCast(GetParent(),wxTopLevelWindow);
151 return parent->GetAppMenuBar(win);
155 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
157 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
158 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
159 DisassociateNSWindow(m_cocoaNSWindow);
160 [cocoaNSWindow retain];
161 [m_cocoaNSWindow release];
162 m_cocoaNSWindow = cocoaNSWindow;
164 SetNSView([m_cocoaNSWindow contentView]);
167 AssociateNSWindow(m_cocoaNSWindow);
168 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
171 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
173 if([m_cocoaNSWindow contentView] == (id)oldView)
174 [m_cocoaNSWindow setContentView:newView];
177 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
179 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
180 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
181 event.SetEventObject(this);
182 GetEventHandler()->ProcessEvent(event);
185 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
187 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
188 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
189 event.SetEventObject(this);
190 GetEventHandler()->ProcessEvent(event);
193 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
195 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
198 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
200 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
203 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
207 /* Be SURE that idle events get ran. If the window was not active when
208 it was closed, then there will be no more events to trigger this and
209 therefore it must be done here */
210 wxTheApp->CocoaInstallRequestedIdleHandler();
213 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
215 return wxWindowBase::Close(false);
218 // ----------------------------------------------------------------------------
219 // wxTopLevelWindowCocoa maximize/minimize
220 // ----------------------------------------------------------------------------
222 void wxTopLevelWindowCocoa::Maximize(bool maximize)
226 bool wxTopLevelWindowCocoa::IsMaximized() const
231 void wxTopLevelWindowCocoa::Iconize(bool iconize)
235 bool wxTopLevelWindowCocoa::IsIconized() const
240 void wxTopLevelWindowCocoa::Restore()
244 bool wxTopLevelWindowCocoa::Show(bool show)
246 if(m_isShown == show)
248 wxAutoNSAutoreleasePool pool;
251 // Send the window a size event because wxWindows apps expect it
252 // NOTE: This should really only be done the first time a window
253 // is shown. I doubt this will cause any problems though.
254 wxSizeEvent event(GetSize(), GetId());
255 event.SetEventObject(this);
256 GetEventHandler()->ProcessEvent(event);
258 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
261 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
266 bool wxTopLevelWindowCocoa::Close(bool force)
269 return wxWindowBase::Close(force);
270 // performClose will fake the user clicking the close button which
271 // will invoke windowShouldClose which will call the base class version
272 // of Close() which will NOT Destroy() the window (see below) but
273 // if closing is not stopped, then performClose will go ahead and
274 // close the window which will send the close notifications setting
275 // m_closed to true and Destroy()ing the window.
276 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
280 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
282 // If the event was forced, close the window which will Destroy() it
284 [m_cocoaNSWindow close];
285 // if the event was not forced, it's probably because the user clicked
286 // the close button, or Close(false) was called which (see above) is
287 // redirected to performClose and thus Cocoa itself will close the window
290 // ----------------------------------------------------------------------------
291 // wxTopLevelWindowCocoa misc
292 // ----------------------------------------------------------------------------
294 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
299 bool wxTopLevelWindowCocoa::IsFullScreen() const
304 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
306 // Set the NSView size by setting the frame size to enclose it
307 unsigned int styleMask = [m_cocoaNSWindow styleMask];
308 NSRect frameRect = [m_cocoaNSWindow frame];
309 NSRect contentRect = [NSWindow
310 contentRectForFrameRect: frameRect
311 styleMask: styleMask];
312 contentRect.size.width = width;
313 contentRect.size.height = height;
314 frameRect = [NSWindow
315 frameRectForContentRect: contentRect
316 styleMask: styleMask];
317 [m_cocoaNSWindow setFrame: frameRect display: NO];
320 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
322 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
324 NSRect cocoaRect = NSMakeRect(x,y,width,height);
325 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
328 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
330 NSRect cocoaRect = [m_cocoaNSWindow frame];
332 *w=(int)cocoaRect.size.width;
334 *h=(int)cocoaRect.size.height;
335 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
338 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
340 NSRect cocoaRect = [m_cocoaNSWindow frame];
342 *x=(int)cocoaRect.origin.x;
344 *y=(int)cocoaRect.origin.y;
345 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);