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