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