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