]> git.saurik.com Git - wxWidgets.git/blame - src/motif/toplevel.cpp
don't try to access empty wxIconBundle in gtk_frame_realized_callback
[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
MB
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,
96be256b 85 False,
0de6dfa7
MB
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{
96be256b 98 m_isShown = false;
0de6dfa7
MB
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);
f58585c0 113
0de6dfa7
MB
114 wxTopLevelWindows.Append(this);
115
116 m_windowId = ( id > -1 ) ? id : NewControlId();
105fbe1f
MB
117 // MBN: More backward compatible, but uglier
118 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
119 m_inheritFont = true;
0de6dfa7 120
02bcd285 121 bool retval = XmDoCreateTLW( parent, id, title, pos, size, style, name );
0de6dfa7 122
96be256b 123 if( !retval ) return false;
0de6dfa7
MB
124
125 // Intercept CLOSE messages from the window manager
126 Widget shell = (Widget)GetShellWidget();
127 Atom WM_DELETE_WINDOW = XmInternAtom( XtDisplay( shell ),
128 "WM_DELETE_WINDOW", False );
129
130 // Remove and add WM_DELETE_WINDOW so ours is only handler
131 // This only appears to be necessary for wxDialog, but does not hurt
132 // for wxFrame
133 XmRemoveWMProtocols( shell, &WM_DELETE_WINDOW, 1 );
134 XmAddWMProtocols( shell, &WM_DELETE_WINDOW, 1 );
135 XmActivateWMProtocol( shell, WM_DELETE_WINDOW );
136
137 // Modified Steve Hammes for Motif 2.0
138#if (XmREVISION > 1 || XmVERSION > 1)
139 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
f58585c0 140 (XtCallbackProc)wxCloseTLWCallback,
0de6dfa7
MB
141 (XtPointer)this );
142#elif XmREVISION == 1
143 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
144 (XtCallbackProc)wxCloseTLWCallback,
145 (caddr_t)this );
146#else
147 XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW,
148 (void (*)())wxCloseTLWCallback, (caddr_t)this );
149#endif
150
151 // This patch come from Torsten Liermann lier@lier1.muc.de
152 if( XmIsMotifWMRunning( shell ) )
153 {
154 int decor = 0 ;
8b7b0d67
MB
155 if( !(m_windowStyle & wxNO_BORDER) )
156 decor |= MWM_DECOR_BORDER;
0de6dfa7
MB
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;
1c067fe3 165 if( m_windowStyle & wxRESIZE_BORDER )
0de6dfa7
MB
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,
96be256b 182 XmNoverrideRedirect, True,
0de6dfa7
MB
183 NULL );
184 }
185
186 XtAddEventHandler( (Widget)GetClientWidget(),
f58585c0 187 ButtonPressMask | ButtonReleaseMask |
0de6dfa7 188 PointerMotionMask | KeyPressMask,
96be256b 189 False,
0de6dfa7
MB
190 wxTLWEventHandler,
191 (XtPointer)this );
192
193 return retval;
194}
195
dad6a47e
MB
196void wxTopLevelWindowMotif::DoGetPosition(int *x, int *y) const
197{
198 Widget top = (Widget) GetTopWidget();
199 Window parent_window = XtWindow((Widget) top),
200 next_parent = XtWindow((Widget) top),
201 root = RootWindowOfScreen(XtScreen((Widget) top));
202
203 // search for the parent that is child of ROOT, because the WM may
204 // reparent twice and notify only the next parent (like FVWM)
205 while (next_parent != root) {
206 Window *theChildren; unsigned int n;
207 parent_window = next_parent;
208 XQueryTree(XtDisplay((Widget) top), parent_window, &root,
209 &next_parent, &theChildren, &n);
210 XFree(theChildren); // not needed
211 }
212 int xx, yy; unsigned int dummy;
213 XGetGeometry(XtDisplay((Widget) top), parent_window, &root,
214 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
215 if (x) *x = xx;
216 if (y) *y = yy;
217}
218
0de6dfa7
MB
219void wxTopLevelWindowMotif::Raise()
220{
221 Widget top = (Widget) GetTopWidget();
222 Window parent_window = XtWindow( top ),
223 next_parent = XtWindow( top ),
224 root = RootWindowOfScreen( XtScreen( top ) );
225 // search for the parent that is child of ROOT, because the WM may
226 // reparent twice and notify only the next parent (like FVWM)
227 while( next_parent != root )
228 {
229 Window *theChildren;
230 unsigned int n;
231
232 parent_window = next_parent;
233 XQueryTree( XtDisplay( top ), parent_window, &root,
234 &next_parent, &theChildren, &n );
235 XFree( theChildren ); // not needed
236 }
237 XRaiseWindow( XtDisplay( top ), parent_window );
238}
239
240void wxTopLevelWindowMotif::Lower()
241{
242 Widget top = (Widget) GetTopWidget();
243 Window parent_window = XtWindow( top ),
244 next_parent = XtWindow( top ),
245 root = RootWindowOfScreen( XtScreen( top ) );
246 // search for the parent that is child of ROOT, because the WM may
247 // reparent twice and notify only the next parent (like FVWM)
248 while( next_parent != root )
249 {
250 Window *theChildren;
251 unsigned int n;
252
253 parent_window = next_parent;
254 XQueryTree( XtDisplay( top ), parent_window, &root,
255 &next_parent, &theChildren, &n );
256 XFree( theChildren ); // not needed
257 }
258 XLowerWindow( XtDisplay( top ), parent_window );
259}
260
261static inline Widget GetShell( const wxTopLevelWindowMotif* tlw )
262{
263 Widget main = (Widget) tlw->GetMainWidget();
264 if( !main ) return (Widget) NULL;
265
266 return XtParent( main );
267}
268
269WXWidget wxTopLevelWindowMotif::GetShellWidget() const
270{
271 return (WXWidget) GetShell( this );
272}
273
355b4d3d
WS
274bool wxTopLevelWindowMotif::ShowFullScreen( bool WXUNUSED(show),
275 long WXUNUSED(style) )
0de6dfa7
MB
276{
277 // TODO, see wxGTK
96be256b 278 return false;
0de6dfa7
MB
279}
280
281bool wxTopLevelWindowMotif::IsFullScreen() const
282{
283 // TODO, see wxGTK
96be256b 284 return false;
0de6dfa7
MB
285}
286
287void wxTopLevelWindowMotif::Restore()
288{
289 Widget shell = GetShell( this );
290
291 if( shell )
292 XtVaSetValues( shell,
96be256b 293 XmNiconic, False,
0de6dfa7
MB
294 NULL );
295}
296
0ec6fd04 297void wxTopLevelWindowMotif::Iconize( bool iconize )
0de6dfa7
MB
298{
299 Widget shell = GetShell( this );
300 if( !shell ) return;
301
302 if( !iconize )
96be256b 303 Show( true );
0de6dfa7
MB
304
305 XtVaSetValues( shell,
306 XmNiconic, (Boolean)iconize,
307 NULL );
308}
309
310bool wxTopLevelWindowMotif::IsIconized() const
311{
312 Widget shell = GetShell( this );
313
314 if( !shell )
96be256b 315 return false;
0de6dfa7
MB
316
317 Boolean iconic;
318 XtVaGetValues( shell,
319 XmNiconic, &iconic,
320 NULL );
321
355b4d3d 322 return (iconic == True);
0de6dfa7
MB
323}
324
0ec6fd04 325void wxTopLevelWindowMotif::Maximize( bool maximize )
0de6dfa7 326{
96be256b 327 Show( true );
0de6dfa7
MB
328
329 if( maximize )
330 Restore();
331}
332
333bool wxTopLevelWindowMotif::IsMaximized() const
334{
96be256b 335 return false;
0de6dfa7
MB
336}
337
024f89f9
VS
338void wxTopLevelWindowMotif::DoSetSizeHints( int minW, int minH,
339 int maxW, int maxH,
340 int incW, int incH )
66f8b9ac 341{
024f89f9 342 wxTopLevelWindowBase::DoSetSizeHints( minW, minH, maxW, maxH, incW, incH );
66f8b9ac
MB
343
344 int count = 0;
345 Arg args[6];
346
347 if( minW > -1 ) { XtSetArg( args[count], XmNminWidth, minW ); ++count; }
348 if( minH > -1 ) { XtSetArg( args[count], XmNminHeight, minH ); ++count; }
349 if( maxW > -1 ) { XtSetArg( args[count], XmNmaxWidth, maxW ); ++count; }
350 if( maxH > -1 ) { XtSetArg( args[count], XmNmaxHeight, maxH ); ++count; }
351 if( incW > -1 ) { XtSetArg( args[count], XmNwidthInc, incW ); ++count; }
352 if( incH > -1 ) { XtSetArg( args[count], XmNheightInc, incH ); ++count; }
353
f58585c0 354 XtSetValues( (Widget)GetShellWidget(), args, count );
66f8b9ac
MB
355}
356
f7f78039
MB
357bool wxTopLevelWindowMotif::SetShape( const wxRegion& region )
358{
359 return wxDoSetShape( (Display*)GetXDisplay(),
360 XtWindow( (Widget)GetShellWidget() ),
361 region );
362}
363
0de6dfa7
MB
364// ---------------------------------------------------------------------------
365// Callback definition
366// ---------------------------------------------------------------------------
367
368// Handle a close event from the window manager
369static void wxCloseTLWCallback( Widget WXUNUSED(widget), XtPointer client_data,
370 XmAnyCallbackStruct *WXUNUSED(cbs) )
371{
372 wxTopLevelWindowMotif* tlw = (wxTopLevelWindowMotif*)client_data;
373 wxCloseEvent closeEvent( wxEVT_CLOSE_WINDOW, tlw->GetId() );
374 closeEvent.SetEventObject( tlw );
375
376 // May delete the dialog (with delayed deletion)
377 tlw->GetEventHandler()->ProcessEvent(closeEvent);
378}
379
380void wxTLWEventHandler( Widget wid,
381 XtPointer WXUNUSED(client_data),
382 XEvent* event,
383 Boolean* continueToDispatch)
384{
385 wxTopLevelWindowMotif* tlw =
386 (wxTopLevelWindowMotif*)wxGetWindowFromTable( wid );
387
388 if( tlw )
389 {
390 wxMouseEvent wxevent( wxEVT_NULL );
391
392 if( wxTranslateMouseEvent( wxevent, tlw, wid, event ) )
393 {
394 wxevent.SetEventObject( tlw );
395 wxevent.SetId( tlw->GetId() );
396 tlw->GetEventHandler()->ProcessEvent( wxevent );
397 }
398 else
399 {
400 // An attempt to implement OnCharHook by calling OnCharHook first;
96be256b 401 // if this returns true, set continueToDispatch to False
0de6dfa7
MB
402 // (don't continue processing).
403 // Otherwise set it to True and call OnChar.
404 wxKeyEvent keyEvent( wxEVT_CHAR );
405 if( wxTranslateKeyEvent( keyEvent, tlw, wid, event ))
406 {
407 keyEvent.SetEventObject( tlw );
408 keyEvent.SetId( tlw->GetId() );
409 keyEvent.SetEventType( wxEVT_CHAR_HOOK );
410 if( tlw->GetEventHandler()->ProcessEvent( keyEvent ) )
411 {
412 *continueToDispatch = False;
413 return;
414 }
415 else
416 {
417 // For simplicity, OnKeyDown is the same as OnChar
418 // TODO: filter modifier key presses from OnChar
419 keyEvent.SetEventType( wxEVT_KEY_DOWN );
420
421 // Only process OnChar if OnKeyDown didn't swallow it
422 if( !tlw->GetEventHandler()->ProcessEvent( keyEvent ) )
423 {
424 keyEvent.SetEventType( wxEVT_CHAR );
425 tlw->GetEventHandler()->ProcessEvent( keyEvent );
426 }
427 }
428 }
429 }
430 }
431
432 *continueToDispatch = True;
433}