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