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