]> git.saurik.com Git - wxWidgets.git/blame - src/motif/toplevel.cpp
wxMenu Review, added Carbon Events and full OSX Support
[wxWidgets.git] / src / motif / toplevel.cpp
CommitLineData
0de6dfa7
MB
1/////////////////////////////////////////////////////////////////////////////
2// Name: motif/toplevel.cpp
3// Purpose: wxTopLevelWindow Motif implementation
4// Author: Mattia Barbon
5// Modified by:
6// Created: 12/10/2002
7// RCS-ID: $Id$
8// Copyright: (c) Mattia Barbon
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#if defined(__GNUG__) && !defined(__APPLE__)
21 #pragma implementation "toplevel.h"
22#endif
23
24#include "wx/toplevel.h"
25#include "wx/app.h"
26
27#ifdef __VMS__
28 #pragma message disable nosimpint
29#endif
30
31#include <Xm/Xm.h>
32#include <X11/Shell.h>
33#include <X11/Core.h>
34#if XmVersion >= 1002
35 #include <Xm/XmAll.h>
36#else
37 #include <Xm/Frame.h>
38#endif
39
40#ifdef __VMS__
41 #pragma message enable nosimpint
42#endif
43
44#include "wx/motif/private.h"
45
46wxList wxModelessWindows; // Frames and modeless dialogs
47
48// ---------------------------------------------------------------------------
49// Callbacks
50// ---------------------------------------------------------------------------
51
52static void wxCloseTLWCallback( Widget widget, XtPointer client_data,
53 XmAnyCallbackStruct *cbs );
54static void wxTLWEventHandler( Widget wid,
55 XtPointer client_data,
56 XEvent* event,
57 Boolean *continueToDispatch );
58
59// ===========================================================================
60// wxTopLevelWindowMotif implementation
61// ===========================================================================
62
63wxTopLevelWindowMotif::~wxTopLevelWindowMotif()
64{
65 wxTopLevelWindows.DeleteObject(this);
66
67 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
68 wxModelessWindows.DeleteObject(this);
69
70 m_icons.m_icons.Empty();
71
72 DestroyChildren();
73
74 // MessageDialog and FileDialog do not have a client widget
75 if( GetClientWidget() )
76 {
77 XtRemoveEventHandler( (Widget)GetClientWidget(),
78 ButtonPressMask | ButtonReleaseMask |
79 PointerMotionMask | KeyPressMask,
80 FALSE,
81 wxTLWEventHandler,
82 (XtPointer)this );
83 }
84
85 DoDestroy();
86
87 SetMainWidget( (WXWidget)0 );
88
89 // If this is the last top-level window, exit.
1bc822df 90 if (wxTheApp && (wxTopLevelWindows.GetCount() == 0))
0de6dfa7
MB
91 {
92 wxTheApp->SetTopWindow(NULL);
93
94 if (wxTheApp->GetExitOnFrameDelete())
95 {
96 wxTheApp->ExitMainLoop();
97 }
98 }
99}
100
101void wxTopLevelWindowMotif::Init()
102{
103 m_isShown = FALSE;
104}
105
106bool wxTopLevelWindowMotif::Create( wxWindow *parent, wxWindowID id,
107 const wxString& title,
108 const wxPoint& pos,
109 const wxSize& size,
110 long style,
111 const wxString& name )
112{
113 SetName(name);
114 m_windowStyle = style;
115
116 if ( parent )
117 parent->AddChild(this);
118
119 wxTopLevelWindows.Append(this);
120
121 m_windowId = ( id > -1 ) ? id : NewControlId();
122
123 bool retval = DoCreate( parent, id, title, pos, size, style, name );
124
125 if( !retval ) return FALSE;
126
127 // Intercept CLOSE messages from the window manager
128 Widget shell = (Widget)GetShellWidget();
129 Atom WM_DELETE_WINDOW = XmInternAtom( XtDisplay( shell ),
130 "WM_DELETE_WINDOW", False );
131
132 // Remove and add WM_DELETE_WINDOW so ours is only handler
133 // This only appears to be necessary for wxDialog, but does not hurt
134 // for wxFrame
135 XmRemoveWMProtocols( shell, &WM_DELETE_WINDOW, 1 );
136 XmAddWMProtocols( shell, &WM_DELETE_WINDOW, 1 );
137 XmActivateWMProtocol( shell, WM_DELETE_WINDOW );
138
139 // Modified Steve Hammes for Motif 2.0
140#if (XmREVISION > 1 || XmVERSION > 1)
141 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
142 (XtCallbackProc)wxCloseTLWCallback,
143 (XtPointer)this );
144#elif XmREVISION == 1
145 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
146 (XtCallbackProc)wxCloseTLWCallback,
147 (caddr_t)this );
148#else
149 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
150 (void (*)())wxCloseTLWCallback, (caddr_t)this );
151#endif
152
153 // This patch come from Torsten Liermann lier@lier1.muc.de
154 if( XmIsMotifWMRunning( shell ) )
155 {
156 int decor = 0 ;
157 if( m_windowStyle & wxRESIZE_BORDER )
158 decor |= MWM_DECOR_RESIZEH;
159 if( m_windowStyle & wxSYSTEM_MENU )
160 decor |= MWM_DECOR_MENU;
161 if( ( m_windowStyle & wxCAPTION ) ||
162 ( m_windowStyle & wxTINY_CAPTION_HORIZ ) ||
163 ( m_windowStyle & wxTINY_CAPTION_VERT ) )
164 decor |= MWM_DECOR_TITLE;
165 if( m_windowStyle & wxTHICK_FRAME )
166 decor |= MWM_DECOR_BORDER;
167 if( m_windowStyle & wxMINIMIZE_BOX )
168 decor |= MWM_DECOR_MINIMIZE;
169 if( m_windowStyle & wxMAXIMIZE_BOX )
170 decor |= MWM_DECOR_MAXIMIZE;
171
172 XtVaSetValues( shell,
173 XmNmwmDecorations, decor,
174 NULL );
175 }
176 else
177 {
178 // This allows non-Motif window managers to support at least the
179 // no-decorations case.
180 if( ( m_windowStyle & wxCAPTION ) != wxCAPTION )
181 XtVaSetValues( shell,
182 XmNoverrideRedirect, TRUE,
183 NULL );
184 }
185
186 XtAddEventHandler( (Widget)GetClientWidget(),
187 ButtonPressMask | ButtonReleaseMask |
188 PointerMotionMask | KeyPressMask,
189 FALSE,
190 wxTLWEventHandler,
191 (XtPointer)this );
192
193 return retval;
194}
195
196void wxTopLevelWindowMotif::Raise()
197{
198 Widget top = (Widget) GetTopWidget();
199 Window parent_window = XtWindow( top ),
200 next_parent = XtWindow( top ),
201 root = RootWindowOfScreen( XtScreen( top ) );
202 // search for the parent that is child of ROOT, because the WM may
203 // reparent twice and notify only the next parent (like FVWM)
204 while( next_parent != root )
205 {
206 Window *theChildren;
207 unsigned int n;
208
209 parent_window = next_parent;
210 XQueryTree( XtDisplay( top ), parent_window, &root,
211 &next_parent, &theChildren, &n );
212 XFree( theChildren ); // not needed
213 }
214 XRaiseWindow( XtDisplay( top ), parent_window );
215}
216
217void wxTopLevelWindowMotif::Lower()
218{
219 Widget top = (Widget) GetTopWidget();
220 Window parent_window = XtWindow( top ),
221 next_parent = XtWindow( top ),
222 root = RootWindowOfScreen( XtScreen( top ) );
223 // search for the parent that is child of ROOT, because the WM may
224 // reparent twice and notify only the next parent (like FVWM)
225 while( next_parent != root )
226 {
227 Window *theChildren;
228 unsigned int n;
229
230 parent_window = next_parent;
231 XQueryTree( XtDisplay( top ), parent_window, &root,
232 &next_parent, &theChildren, &n );
233 XFree( theChildren ); // not needed
234 }
235 XLowerWindow( XtDisplay( top ), parent_window );
236}
237
238static inline Widget GetShell( const wxTopLevelWindowMotif* tlw )
239{
240 Widget main = (Widget) tlw->GetMainWidget();
241 if( !main ) return (Widget) NULL;
242
243 return XtParent( main );
244}
245
246WXWidget wxTopLevelWindowMotif::GetShellWidget() const
247{
248 return (WXWidget) GetShell( this );
249}
250
251bool wxTopLevelWindowMotif::ShowFullScreen( bool show,
0ec6fd04 252 long style )
0de6dfa7
MB
253{
254 // TODO, see wxGTK
255 return FALSE;
256}
257
258bool wxTopLevelWindowMotif::IsFullScreen() const
259{
260 // TODO, see wxGTK
261 return FALSE;
262}
263
264void wxTopLevelWindowMotif::Restore()
265{
266 Widget shell = GetShell( this );
267
268 if( shell )
269 XtVaSetValues( shell,
270 XmNiconic, FALSE,
271 NULL );
272}
273
0ec6fd04 274void wxTopLevelWindowMotif::Iconize( bool iconize )
0de6dfa7
MB
275{
276 Widget shell = GetShell( this );
277 if( !shell ) return;
278
279 if( !iconize )
280 Show( TRUE );
281
282 XtVaSetValues( shell,
283 XmNiconic, (Boolean)iconize,
284 NULL );
285}
286
287bool wxTopLevelWindowMotif::IsIconized() const
288{
289 Widget shell = GetShell( this );
290
291 if( !shell )
292 return FALSE;
293
294 Boolean iconic;
295 XtVaGetValues( shell,
296 XmNiconic, &iconic,
297 NULL );
298
299 return iconic;
300}
301
0ec6fd04 302void wxTopLevelWindowMotif::Maximize( bool maximize )
0de6dfa7
MB
303{
304 Show( TRUE );
305
306 if( maximize )
307 Restore();
308}
309
310bool wxTopLevelWindowMotif::IsMaximized() const
311{
312 return FALSE;
313}
314
315// ---------------------------------------------------------------------------
316// Callback definition
317// ---------------------------------------------------------------------------
318
319// Handle a close event from the window manager
320static void wxCloseTLWCallback( Widget WXUNUSED(widget), XtPointer client_data,
321 XmAnyCallbackStruct *WXUNUSED(cbs) )
322{
323 wxTopLevelWindowMotif* tlw = (wxTopLevelWindowMotif*)client_data;
324 wxCloseEvent closeEvent( wxEVT_CLOSE_WINDOW, tlw->GetId() );
325 closeEvent.SetEventObject( tlw );
326
327 // May delete the dialog (with delayed deletion)
328 tlw->GetEventHandler()->ProcessEvent(closeEvent);
329}
330
331void wxTLWEventHandler( Widget wid,
332 XtPointer WXUNUSED(client_data),
333 XEvent* event,
334 Boolean* continueToDispatch)
335{
336 wxTopLevelWindowMotif* tlw =
337 (wxTopLevelWindowMotif*)wxGetWindowFromTable( wid );
338
339 if( tlw )
340 {
341 wxMouseEvent wxevent( wxEVT_NULL );
342
343 if( wxTranslateMouseEvent( wxevent, tlw, wid, event ) )
344 {
345 wxevent.SetEventObject( tlw );
346 wxevent.SetId( tlw->GetId() );
347 tlw->GetEventHandler()->ProcessEvent( wxevent );
348 }
349 else
350 {
351 // An attempt to implement OnCharHook by calling OnCharHook first;
352 // if this returns TRUE, set continueToDispatch to False
353 // (don't continue processing).
354 // Otherwise set it to True and call OnChar.
355 wxKeyEvent keyEvent( wxEVT_CHAR );
356 if( wxTranslateKeyEvent( keyEvent, tlw, wid, event ))
357 {
358 keyEvent.SetEventObject( tlw );
359 keyEvent.SetId( tlw->GetId() );
360 keyEvent.SetEventType( wxEVT_CHAR_HOOK );
361 if( tlw->GetEventHandler()->ProcessEvent( keyEvent ) )
362 {
363 *continueToDispatch = False;
364 return;
365 }
366 else
367 {
368 // For simplicity, OnKeyDown is the same as OnChar
369 // TODO: filter modifier key presses from OnChar
370 keyEvent.SetEventType( wxEVT_KEY_DOWN );
371
372 // Only process OnChar if OnKeyDown didn't swallow it
373 if( !tlw->GetEventHandler()->ProcessEvent( keyEvent ) )
374 {
375 keyEvent.SetEventType( wxEVT_CHAR );
376 tlw->GetEventHandler()->ProcessEvent( keyEvent );
377 }
378 }
379 }
380 }
381 }
382
383 *continueToDispatch = True;
384}
385