]> git.saurik.com Git - wxWidgets.git/blob - src/motif/toplevel.cpp
If -1 is used for width/height, use best size.
[wxWidgets.git] / src / motif / toplevel.cpp
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
46 wxList wxModelessWindows; // Frames and modeless dialogs
47
48 // ---------------------------------------------------------------------------
49 // Callbacks
50 // ---------------------------------------------------------------------------
51
52 static void wxCloseTLWCallback( Widget widget, XtPointer client_data,
53 XmAnyCallbackStruct *cbs );
54 static void wxTLWEventHandler( Widget wid,
55 XtPointer client_data,
56 XEvent* event,
57 Boolean *continueToDispatch );
58
59 // ===========================================================================
60 // wxTopLevelWindowMotif implementation
61 // ===========================================================================
62
63 wxTopLevelWindowMotif::~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.
90 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
91 {
92 wxTheApp->SetTopWindow(NULL);
93
94 if (wxTheApp->GetExitOnFrameDelete())
95 {
96 wxTheApp->ExitMainLoop();
97 }
98 }
99 }
100
101 void wxTopLevelWindowMotif::Init()
102 {
103 m_isShown = FALSE;
104 }
105
106 bool 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
196 void 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
217 void 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
238 static 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
246 WXWidget wxTopLevelWindowMotif::GetShellWidget() const
247 {
248 return (WXWidget) GetShell( this );
249 }
250
251 bool wxTopLevelWindowMotif::ShowFullScreen( bool show,
252 long style = wxFULLSCREEN_ALL )
253 {
254 // TODO, see wxGTK
255 return FALSE;
256 }
257
258 bool wxTopLevelWindowMotif::IsFullScreen() const
259 {
260 // TODO, see wxGTK
261 return FALSE;
262 }
263
264 void wxTopLevelWindowMotif::Restore()
265 {
266 Widget shell = GetShell( this );
267
268 if( shell )
269 XtVaSetValues( shell,
270 XmNiconic, FALSE,
271 NULL );
272 }
273
274 void wxTopLevelWindowMotif::Iconize( bool iconize = TRUE )
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
287 bool 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
302 void wxTopLevelWindowMotif::Maximize( bool maximize = TRUE )
303 {
304 Show( TRUE );
305
306 if( maximize )
307 Restore();
308 }
309
310 bool wxTopLevelWindowMotif::IsMaximized() const
311 {
312 return FALSE;
313 }
314
315 // ---------------------------------------------------------------------------
316 // Callback definition
317 // ---------------------------------------------------------------------------
318
319 // Handle a close event from the window manager
320 static 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
331 void 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