]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/toplevel.mm
Prevent Cocoa from waiting indefinitely when stopping the event loop
[wxWidgets.git] / src / cocoa / toplevel.mm
CommitLineData
fb896a32
DE
1///////////////////////////////////////////////////////////////////////////////
2// Name: cocoa/toplevel.mm
3// Purpose: implements wxTopLevelWindow for Cocoa
4// Author: David Elliott
5// Modified by:
6// Created: 2002/11/27
7// RCS-ID: $Id:
8// Copyright: (c) 2002 David Elliott
9// License: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22#ifndef WX_PRECOMP
23 #include "wx/window.h"
24 #include "wx/toplevel.h"
25 #include "wx/menuitem.h"
26 #include "wx/frame.h"
27 #include "wx/log.h"
28 #include "wx/app.h"
29#endif //WX_PRECOMP
30
7fc77f30 31#include "wx/cocoa/autorelease.h"
da026811 32#include "wx/cocoa/string.h"
33faea0a 33#include "wx/cocoa/mbarman.h"
7fc77f30 34
fe169919 35#import <AppKit/NSView.h>
fb896a32 36#import <AppKit/NSWindow.h>
080c7d56 37#import <AppKit/NSPanel.h>
fb896a32
DE
38// ----------------------------------------------------------------------------
39// globals
40// ----------------------------------------------------------------------------
41
42// list of all frames and modeless dialogs
43wxWindowList wxModelessWindows;
44
45// ============================================================================
46// wxTopLevelWindowCocoa implementation
47// ============================================================================
48
49// ----------------------------------------------------------------------------
50// wxTopLevelWindowCocoa creation
51// ----------------------------------------------------------------------------
fb896a32
DE
52BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
53 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
54END_EVENT_TABLE()
55
56void wxTopLevelWindowCocoa::Init()
57{
58 m_iconized =
59 m_maximizeOnShow =
60 m_closed = false;
61}
62
080c7d56
DE
63unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
64{
65 unsigned int styleMask = 0;
66 if(style & wxCAPTION)
67 styleMask |= NSTitledWindowMask;
68 if(style & wxMINIMIZE_BOX)
69 styleMask |= NSMiniaturizableWindowMask;
70 #if 0
71 if(style & wxMAXIMIZE_BOX)
72 styleMask |= NSWindowMask;
73 #endif
74 if(style & wxCLOSE_BOX)
75 styleMask |= NSClosableWindowMask;
76 if(style & wxRESIZE_BORDER)
77 styleMask |= NSResizableWindowMask;
78 if(style & wxSIMPLE_BORDER)
79 styleMask |= NSBorderlessWindowMask;
80 return styleMask;
81}
82
fb896a32
DE
83bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
84 wxWindowID winid,
85 const wxString& title,
86 const wxPoint& pos,
87 const wxSize& size,
88 long style,
89 const wxString& name)
90{
7fc77f30 91 wxAutoNSAutoreleasePool pool;
fb896a32
DE
92 wxTopLevelWindows.Append(this);
93
94 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
95 return FALSE;
96
97 if ( parent )
98 parent->AddChild(this);
99
080c7d56
DE
100 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
101 if(style & wxFRAME_TOOL_WINDOW)
102 cocoaStyle |= NSUtilityWindowMask;
fb896a32 103
080c7d56
DE
104 // NOTE: y-origin needs to be flipped.
105 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(pos.x,pos.y,size.x,size.y) styleMask:cocoaStyle];
fb896a32
DE
106
107 m_cocoaNSWindow = NULL;
108 m_cocoaNSView = NULL;
080c7d56
DE
109 if(style & wxFRAME_TOOL_WINDOW)
110 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
111 else
112 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
fb896a32
DE
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];
117
080c7d56
DE
118 if(style & wxFRAME_NO_TASKBAR)
119 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
120 if(style & wxSTAY_ON_TOP)
121 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
da026811 122 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
fb896a32
DE
123 return TRUE;
124}
125
126wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
127{
7fc77f30 128 wxAutoNSAutoreleasePool pool;
0b659b0a 129 DestroyChildren();
fb896a32
DE
130 SetNSWindow(NULL);
131}
132
133// ----------------------------------------------------------------------------
134// wxTopLevelWindowCocoa Cocoa Specifics
135// ----------------------------------------------------------------------------
136
137void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
138{
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]);
fe169919 141 DisassociateNSWindow(m_cocoaNSWindow);
fb896a32
DE
142 [cocoaNSWindow retain];
143 [m_cocoaNSWindow release];
144 m_cocoaNSWindow = cocoaNSWindow;
145 if(m_cocoaNSWindow)
146 SetNSView([m_cocoaNSWindow contentView]);
147 else
148 SetNSView(NULL);
fe169919 149 AssociateNSWindow(m_cocoaNSWindow);
fb896a32
DE
150 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
151}
152
448cbf1d
DE
153void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
154{
911e17c6 155 if([m_cocoaNSWindow contentView] == (id)oldView)
448cbf1d
DE
156 [m_cocoaNSWindow setContentView:newView];
157}
158
aa992c59 159void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
5aa417d5 160{
aa992c59 161 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
33faea0a 162 wxMenuBarManager::GetInstance()->WindowDidBecomeKey(this);
5aa417d5
DE
163 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
164 event.SetEventObject(this);
165 GetEventHandler()->ProcessEvent(event);
166}
167
aa992c59 168void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
5aa417d5 169{
aa992c59 170 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
5aa417d5
DE
171 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
172 event.SetEventObject(this);
173 GetEventHandler()->ProcessEvent(event);
33faea0a
DE
174 wxMenuBarManager::GetInstance()->WindowDidResignKey(this);
175}
176
177void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
178{
179 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
180 wxMenuBarManager::GetInstance()->WindowDidBecomeMain(this);
181}
182
183void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
184{
185 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
186 wxMenuBarManager::GetInstance()->WindowDidResignMain(this);
5aa417d5
DE
187}
188
9692f42b 189void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
fb896a32
DE
190{
191 m_closed = true;
192 Destroy();
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();
197}
198
aa992c59 199bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
fb896a32
DE
200{
201 return wxWindowBase::Close(false);
202}
203
204// ----------------------------------------------------------------------------
205// wxTopLevelWindowCocoa maximize/minimize
206// ----------------------------------------------------------------------------
207
208void wxTopLevelWindowCocoa::Maximize(bool maximize)
209{
210}
211
212bool wxTopLevelWindowCocoa::IsMaximized() const
213{
214 return false ;
215}
216
217void wxTopLevelWindowCocoa::Iconize(bool iconize)
218{
219}
220
221bool wxTopLevelWindowCocoa::IsIconized() const
222{
223 return FALSE;
224}
225
226void wxTopLevelWindowCocoa::Restore()
227{
228}
229
230bool wxTopLevelWindowCocoa::Show(bool show)
231{
cbb2499e
DE
232 if(m_isShown == show)
233 return false;
7fc77f30 234 wxAutoNSAutoreleasePool pool;
fb896a32 235 if(show)
275341c0
DE
236 {
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);
243
fb896a32 244 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
275341c0 245 }
fb896a32
DE
246 else
247 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
cbb2499e 248 m_isShown = show;
fb896a32
DE
249 return true;
250}
251
252bool wxTopLevelWindowCocoa::Close(bool force)
253{
254 if(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
9692f42b
DE
260 // close the window which will send the close notifications setting
261 // m_closed to true and Destroy()ing the window.
fb896a32
DE
262 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
263 return m_closed;
264}
265
266void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
267{
268 // If the event was forced, close the window which will Destroy() it
269 if(!event.CanVeto())
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
274}
275
276// ----------------------------------------------------------------------------
277// wxTopLevelWindowCocoa misc
278// ----------------------------------------------------------------------------
279
280bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
281{
282 return FALSE;
283}
284
285bool wxTopLevelWindowCocoa::IsFullScreen() const
286{
287 return FALSE;
288}
289
e08efb8d
DE
290void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
291{
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];
304}
305
fb896a32
DE
306void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
307{
5aa417d5 308// wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
fb896a32
DE
309
310 NSRect cocoaRect = NSMakeRect(x,y,width,height);
311 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
312}
313
314void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
315{
316 NSRect cocoaRect = [m_cocoaNSWindow frame];
317 if(w)
318 *w=(int)cocoaRect.size.width;
319 if(h)
320 *h=(int)cocoaRect.size.height;
5aa417d5 321// wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
fb896a32
DE
322}
323
324void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
325{
326 NSRect cocoaRect = [m_cocoaNSWindow frame];
327 if(x)
328 *x=(int)cocoaRect.origin.x;
329 if(y)
330 *y=(int)cocoaRect.origin.y;
5aa417d5 331// wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
fb896a32
DE
332}
333