1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/frame.cpp
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
24 #define XtDisplay XTDISPLAY
25 #define XtWindow XTWINDOW
26 #define XtScreen XTSCREEN
37 #include "wx/settings.h"
38 #include "wx/toolbar.h"
39 #include "wx/statusbr.h"
43 #pragma message disable nosimpint
46 #if defined(__ultrix) || defined(__sgi)
51 #include <X11/Shell.h>
58 #include <Xm/MwmUtil.h>
59 #include <Xm/BulletinB.h>
62 #include <Xm/RowColumn.h>
64 #include <Xm/AtomMgr.h>
65 #include <Xm/LabelG.h>
68 #include <Xm/Protocols.h>
72 #pragma message enable nosimpint
75 #include "wx/motif/private.h"
76 #include "wx/unix/utilsx11.h"
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
83 XCrossingEvent
* event
);
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 extern wxList wxModelessWindows
;
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
96 EVT_ACTIVATE(wxFrame::OnActivate
)
97 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
100 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
102 // ============================================================================
104 // ============================================================================
106 // ----------------------------------------------------------------------------
107 // frame construction
108 // ----------------------------------------------------------------------------
115 m_frameShell
= (WXWidget
) NULL
;
116 m_mainWidget
= (WXWidget
) NULL
;
117 m_workArea
= (WXWidget
) NULL
;
118 m_clientArea
= (WXWidget
) NULL
;
121 bool wxFrame::Create(wxWindow
*parent
,
123 const wxString
& title
,
127 const wxString
& name
)
129 if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
,
133 int x
= pos
.x
, y
= pos
.y
;
134 int width
= size
.x
, height
= size
.y
;
136 // Set reasonable values for position and size if defaults have been
139 // MB TODO: something better than these arbitrary values ?
140 // VZ should use X resources for this...
146 int displayW
, displayH
;
147 wxDisplaySize( &displayW
, &displayH
);
151 x
= (displayW
- width
) / 2;
156 y
= (displayH
- height
) / 2;
162 wxLogTrace(wxTRACE_Messages
,
163 "Created frame (0x%p) with work area 0x%p and client "
164 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
166 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,False
,
167 wxUniversalRepaintProc
, (XtPointer
) this);
170 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
172 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
174 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
176 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
181 wxSize
newSize(width
, height
);
182 wxSizeEvent
sizeEvent(newSize
, GetId());
183 sizeEvent
.SetEventObject(this);
185 GetEventHandler()->ProcessEvent(sizeEvent
);
190 bool wxFrame::XmDoCreateTLW(wxWindow
* WXUNUSED(parent
),
191 wxWindowID
WXUNUSED(id
),
192 const wxString
& WXUNUSED(title
),
193 const wxPoint
& WXUNUSED(pos
),
194 const wxSize
& WXUNUSED(size
),
196 const wxString
& name
)
200 frameShell
= XtCreatePopupShell( name
, topLevelShellWidgetClass
,
201 (Widget
)wxTheApp
->GetTopLevelWidget(),
204 XtVaSetValues(frameShell
,
205 // Allows menu to resize
206 XmNallowShellResize
, True
,
207 XmNdeleteResponse
, XmDO_NOTHING
,
208 XmNmappedWhenManaged
, False
,
209 XmNiconic
, (style
& wxICONIZE
) ? True
: False
,
212 m_frameShell
= (WXWidget
)frameShell
;
214 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
215 xmMainWindowWidgetClass
, frameShell
,
216 XmNresizePolicy
, XmRESIZE_NONE
,
219 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
220 xmFormWidgetClass
, (Widget
) m_mainWidget
,
221 XmNresizePolicy
, XmRESIZE_NONE
,
224 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
225 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
228 XmNrightAttachment
, XmATTACH_FORM
,
229 XmNleftAttachment
, XmATTACH_FORM
,
230 XmNtopAttachment
, XmATTACH_FORM
,
231 XmNbottomAttachment
, XmATTACH_FORM
,
234 XtVaSetValues((Widget
) m_mainWidget
,
235 XmNworkWindow
, (Widget
) m_workArea
,
238 XtManageChild((Widget
) m_clientArea
);
239 XtManageChild((Widget
) m_workArea
);
241 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
242 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
243 XtFree( (char *)ptr
);
245 /* Part of show-&-hide fix */
246 XtAddEventHandler( frameShell
, StructureNotifyMask
,
247 False
, (XtEventHandler
)wxFrameMapProc
,
250 XtRealizeWidget(frameShell
);
252 wxAddWindowToTable( (Widget
)m_workArea
, this);
253 wxAddWindowToTable( (Widget
)m_clientArea
, this);
255 wxModelessWindows
.Append( this );
262 m_isBeingDeleted
= true;
266 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, False
,
267 wxUniversalRepaintProc
, (XtPointer
) this);
275 m_frameMenuBar
->DestroyMenuBar();
276 delete m_frameMenuBar
;
277 m_frameMenuBar
= NULL
;
280 if (m_frameStatusBar
)
282 delete m_frameStatusBar
;
283 m_frameStatusBar
= NULL
;
288 Widget frameShell
= (Widget
)GetShellWidget();
291 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
292 False
, (XtEventHandler
)wxFrameMapProc
,
297 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
298 XtDestroyWidget( (Widget
)m_clientArea
);
303 XtVaSetValues( (Widget
)m_mainWidget
,
304 XmNworkWindow
, (Widget
)NULL
,
307 wxDeleteWindowFromTable( (Widget
)m_workArea
);
308 XtDestroyWidget( (Widget
)m_workArea
);
312 XtDestroyWidget( (Widget
)m_mainWidget
);
315 XtDestroyWidget( frameShell
);
318 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
319 void wxFrame::DoGetClientSize(int *x
, int *y
) const
322 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
324 if (m_frameStatusBar
)
327 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
328 yy
= (Dimension
)(yy
- sbh
);
334 m_frameToolBar
->GetSize(& tbw
, & tbh
);
335 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
336 xx
= (Dimension
)(xx
- tbw
);
338 yy
= (Dimension
)(yy
- tbh
);
340 #endif // wxUSE_TOOLBAR
342 //CE found a call here with NULL y pointer
349 // Set the client size (i.e. leave the calculation of borders etc.
351 void wxFrame::DoSetClientSize(int width
, int height
)
353 // Calculate how large the new main window should be
354 // by finding the difference between the client area and the
355 // main window area, and adding on to the new client area
357 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
361 if (m_frameStatusBar
)
364 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
371 m_frameToolBar
->GetSize(& tbw
, & tbh
);
372 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
377 #endif // wxUSE_TOOLBAR
379 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
383 wxSize
newSize(width
, height
);
384 wxSizeEvent
sizeEvent(newSize
, GetId());
385 sizeEvent
.SetEventObject(this);
387 GetEventHandler()->ProcessEvent(sizeEvent
);
391 void wxFrame::DoGetSize(int *width
, int *height
) const
395 *width
= -1; *height
= -1;
400 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
401 *width
= xx
; *height
= yy
;
404 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
407 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
409 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
411 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
413 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
415 if (!(height
== -1 && width
== -1))
421 bool wxFrame::Show( bool show
)
423 if( !wxWindowBase::Show( show
) )
428 Widget shell
= (Widget
)GetShellWidget();
430 return wxWindow::Show(show
);
432 SetVisibleStatus(show
);
435 XtPopup(shell
, XtGrabNone
);
445 void wxFrame::SetTitle(const wxString
& title
)
447 wxString oldTitle
= GetTitle();
448 if( title
== oldTitle
)
451 wxTopLevelWindow::SetTitle( title
);
454 XtVaSetValues( (Widget
)m_frameShell
,
455 XmNtitle
, title
.mb_str(),
456 XmNiconName
, title
.mb_str(),
460 void wxFrame::DoSetIcon(const wxIcon
& icon
)
465 if (!icon
.Ok() || !icon
.GetDrawable())
468 XtVaSetValues((Widget
) m_frameShell
,
469 XtNiconPixmap
, icon
.GetDrawable(),
473 void wxFrame::SetIcons(const wxIconBundle
& icons
)
475 wxFrameBase::SetIcons( icons
);
480 DoSetIcon( m_icons
.GetIcon( -1 ) );
481 wxSetIconsX11(GetXDisplay(),
482 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
485 void wxFrame::PositionStatusBar()
487 if (!m_frameStatusBar
)
491 GetClientSize(&w
, &h
);
493 m_frameStatusBar
->GetSize(&sw
, &sh
);
495 // Since we wish the status bar to be directly under the client area,
496 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
497 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
500 WXWidget
wxFrame::GetMenuBarWidget() const
503 return GetMenuBar()->GetMainWidget();
505 return (WXWidget
) NULL
;
508 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
512 m_frameMenuBar
= NULL
;
516 // Currently can't set it twice
517 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
521 m_frameMenuBar
->DestroyMenuBar();
522 delete m_frameMenuBar
;
525 m_frameMenuBar
= menuBar
;
526 m_frameMenuBar
->CreateMenuBar(this);
529 // Responds to colour changes, and passes event on to children.
530 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
532 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
535 if ( m_frameStatusBar
)
537 wxSysColourChangedEvent event2
;
538 event2
.SetEventObject( m_frameStatusBar
);
539 m_frameStatusBar
->GetEventHandler()->ProcessEvent(event2
);
542 // Propagate the event to the non-top-level children
543 wxWindow::OnSysColourChanged(event
);
546 // Default activation behaviour - set the focus for the first child
548 void wxFrame::OnActivate(wxActivateEvent
& event
)
550 if (!event
.GetActive())
553 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
;
554 node
= node
->GetNext())
556 // Find a child that's a subwindow, but not a dialog box.
557 wxWindow
*child
= node
->GetData();
558 if (!child
->IsTopLevel())
566 void wxFrame::SendSizeEvent()
568 wxSizeEvent
event(GetSize(), GetId());
569 event
.SetEventObject(this);
570 GetEventHandler()->AddPendingEvent(event
);
575 wxToolBar
* wxFrame::CreateToolBar(long style
,
577 const wxString
& name
)
579 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
584 return m_frameToolBar
;
587 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
589 wxFrameBase::SetToolBar(toolbar
);
593 void wxFrame::PositionToolBar()
595 wxToolBar
* tb
= GetToolBar();
599 GetClientSize(& cw
, &ch
);
602 tb
->GetSize(& tw
, & th
);
604 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
606 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
607 // means, pretend we don't have toolbar/status bar, so we
608 // have the original client size.
613 // Use the 'real' position
617 tb
->SetSize(0, 0, -1, -1, wxSIZE_NO_ADJUSTMENTS
);
620 #endif // wxUSE_TOOLBAR
623 bool wxFrame::PreResize()
627 #endif // wxUSE_TOOLBAR
631 #endif // wxUSE_STATUSBAR
636 WXWidget
wxFrame::GetClientWidget() const
641 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
646 void wxFrame::ChangeBackgroundColour()
648 if (GetClientWidget())
649 wxDoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
652 void wxFrame::ChangeForegroundColour()
654 if (GetClientWidget())
655 wxDoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
658 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
659 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
660 XCrossingEvent
* event
)
662 wxFrame
*tli
= (wxFrame
*)clientData
;
664 XEvent
*e
= (XEvent
*)event
;
666 if( e
->xany
.type
== MapNotify
)
669 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
670 if( !tli
->GetVisibleStatus() )
672 /* We really wanted this to be hidden! */
673 XtUnmapWidget( frameShell
);
676 else if( e
->xany
.type
== UnmapNotify
)
678 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);