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