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