1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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
30 #include "wx/statusbr.h"
31 #include "wx/toolbar.h"
33 #include "wx/settings.h"
40 #pragma message disable nosimpint
43 #if defined(__ultrix) || defined(__sgi)
48 #include <X11/Shell.h>
55 #include <Xm/MwmUtil.h>
56 #include <Xm/BulletinB.h>
59 #include <Xm/RowColumn.h>
61 #include <Xm/AtomMgr.h>
62 #include <Xm/LabelG.h>
65 #include <Xm/Protocols.h>
69 #pragma message enable nosimpint
72 #include "wx/motif/private.h"
73 #include "wx/unix/utilsx11.h"
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
80 XCrossingEvent
* event
);
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 extern wxList wxModelessWindows
;
87 extern wxList wxPendingDelete
;
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
94 EVT_ACTIVATE(wxFrame::OnActivate
)
95 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
98 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
100 // ============================================================================
102 // ============================================================================
104 // ----------------------------------------------------------------------------
105 // frame construction
106 // ----------------------------------------------------------------------------
113 m_frameShell
= (WXWidget
) NULL
;
114 m_mainWidget
= (WXWidget
) NULL
;
115 m_workArea
= (WXWidget
) NULL
;
116 m_clientArea
= (WXWidget
) NULL
;
119 bool wxFrame::Create(wxWindow
*parent
,
121 const wxString
& title
,
125 const wxString
& name
)
127 if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
,
132 wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
133 m_foregroundColour
= *wxBLACK
;
134 m_font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
136 int x
= pos
.x
, y
= pos
.y
;
137 int width
= size
.x
, height
= size
.y
;
139 // Set reasonable values for position and size if defaults have been
142 // MB TODO: something better than these arbitrary values ?
143 // VZ should use X resources for this...
149 int displayW
, displayH
;
150 wxDisplaySize( &displayW
, &displayH
);
154 x
= (displayW
- width
) / 2;
159 y
= (displayH
- height
) / 2;
165 wxLogTrace(wxTRACE_Messages
,
166 "Created frame (0x%p) with work area 0x%p and client "
167 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
169 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,False
,
170 wxUniversalRepaintProc
, (XtPointer
) this);
173 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
175 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
177 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
179 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
183 ChangeBackgroundColour();
187 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
188 sizeEvent
.SetEventObject(this);
190 GetEventHandler()->ProcessEvent(sizeEvent
);
195 bool wxFrame::DoCreate(wxWindow
* parent
,
197 const wxString
& title
,
201 const wxString
& name
)
205 frameShell
= XtCreatePopupShell( name
, topLevelShellWidgetClass
,
206 (Widget
)wxTheApp
->GetTopLevelWidget(),
209 XtVaSetValues(frameShell
,
210 // Allows menu to resize
211 XmNallowShellResize
, True
,
212 XmNdeleteResponse
, XmDO_NOTHING
,
213 XmNmappedWhenManaged
, False
,
214 XmNiconic
, (style
& wxICONIZE
) ? True
: False
,
217 m_frameShell
= (WXWidget
)frameShell
;
219 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
220 xmMainWindowWidgetClass
, frameShell
,
221 XmNresizePolicy
, XmRESIZE_NONE
,
224 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
225 xmFormWidgetClass
, (Widget
) m_mainWidget
,
226 XmNresizePolicy
, XmRESIZE_NONE
,
229 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
230 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
233 XmNrightAttachment
, XmATTACH_FORM
,
234 XmNleftAttachment
, XmATTACH_FORM
,
235 XmNtopAttachment
, XmATTACH_FORM
,
236 XmNbottomAttachment
, XmATTACH_FORM
,
239 XtVaSetValues((Widget
) m_mainWidget
,
240 XmNworkWindow
, (Widget
) m_workArea
,
243 XtManageChild((Widget
) m_clientArea
);
244 XtManageChild((Widget
) m_workArea
);
246 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
247 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
248 XtFree( (char *)ptr
);
250 /* Part of show-&-hide fix */
251 XtAddEventHandler( frameShell
, StructureNotifyMask
,
252 False
, (XtEventHandler
)wxFrameMapProc
,
255 XtRealizeWidget(frameShell
);
257 wxAddWindowToTable( (Widget
)m_workArea
, this);
258 wxAddWindowToTable( (Widget
)m_clientArea
, this);
260 wxModelessWindows
.Append( this );
265 void wxFrame::DoDestroy()
271 m_isBeingDeleted
= true;
275 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, False
,
276 wxUniversalRepaintProc
, (XtPointer
) this);
284 m_frameMenuBar
->DestroyMenuBar();
285 delete m_frameMenuBar
;
286 m_frameMenuBar
= NULL
;
289 if (m_frameStatusBar
)
291 delete m_frameStatusBar
;
292 m_frameStatusBar
= NULL
;
297 Widget frameShell
= (Widget
)GetShellWidget();
300 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
301 False
, (XtEventHandler
)wxFrameMapProc
,
306 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
307 XtDestroyWidget( (Widget
)m_clientArea
);
312 XtVaSetValues( (Widget
)m_mainWidget
,
313 XmNworkWindow
, (Widget
)NULL
,
316 wxDeleteWindowFromTable( (Widget
)m_workArea
);
317 XtDestroyWidget( (Widget
)m_workArea
);
321 XtDestroyWidget( (Widget
)m_mainWidget
);
324 XtDestroyWidget( frameShell
);
327 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
328 void wxFrame::DoGetClientSize(int *x
, int *y
) const
331 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
333 if (m_frameStatusBar
)
336 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
343 m_frameToolBar
->GetSize(& tbw
, & tbh
);
344 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
349 #endif // wxUSE_TOOLBAR
351 //CE found a call here with NULL y pointer
358 // Set the client size (i.e. leave the calculation of borders etc.
360 void wxFrame::DoSetClientSize(int width
, int height
)
362 // Calculate how large the new main window should be
363 // by finding the difference between the client area and the
364 // main window area, and adding on to the new client area
366 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
370 if (m_frameStatusBar
)
373 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
380 m_frameToolBar
->GetSize(& tbw
, & tbh
);
381 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
386 #endif // wxUSE_TOOLBAR
388 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
392 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
393 sizeEvent
.SetEventObject(this);
395 GetEventHandler()->ProcessEvent(sizeEvent
);
399 void wxFrame::DoGetSize(int *width
, int *height
) const
402 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
403 *width
= xx
; *height
= yy
;
406 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
409 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
411 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
413 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
415 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
417 if (!(height
== -1 && width
== -1))
423 bool wxFrame::Show( bool show
)
425 if( !wxWindowBase::Show( show
) )
430 Widget shell
= (Widget
)GetShellWidget();
432 return wxWindow::Show(show
);
434 SetVisibleStatus(show
);
437 XtPopup(shell
, XtGrabNone
);
447 void wxFrame::SetTitle(const wxString
& title
)
449 wxString oldTitle
= GetTitle();
450 if( title
== oldTitle
)
453 wxTopLevelWindow::SetTitle( title
);
456 XtVaSetValues( (Widget
)m_frameShell
,
457 XmNtitle
, title
.c_str(),
458 XmNiconName
, title
.c_str(),
462 void wxFrame::DoSetIcon(const wxIcon
& icon
)
467 if (!icon
.Ok() || !icon
.GetDrawable())
470 XtVaSetValues((Widget
) m_frameShell
,
471 XtNiconPixmap
, icon
.GetDrawable(),
475 void wxFrame::SetIcon(const wxIcon
& icon
)
477 SetIcons( wxIconBundle( icon
) );
480 void wxFrame::SetIcons(const wxIconBundle
& icons
)
482 wxFrameBase::SetIcons( icons
);
487 DoSetIcon( m_icons
.GetIcon( -1 ) );
488 wxSetIconsX11(GetXDisplay(),
489 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
492 void wxFrame::PositionStatusBar()
494 if (!m_frameStatusBar
)
498 GetClientSize(&w
, &h
);
500 m_frameStatusBar
->GetSize(&sw
, &sh
);
502 // Since we wish the status bar to be directly under the client area,
503 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
504 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
507 WXWidget
wxFrame::GetMenuBarWidget() const
510 return GetMenuBar()->GetMainWidget();
512 return (WXWidget
) NULL
;
515 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
519 m_frameMenuBar
= NULL
;
523 // Currently can't set it twice
524 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
528 m_frameMenuBar
->DestroyMenuBar();
529 delete m_frameMenuBar
;
532 m_frameMenuBar
= menuBar
;
533 m_frameMenuBar
->CreateMenuBar(this);
536 // Responds to colour changes, and passes event on to children.
537 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
539 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
542 if ( m_frameStatusBar
)
544 wxSysColourChangedEvent event2
;
545 event2
.SetEventObject( m_frameStatusBar
);
546 m_frameStatusBar
->ProcessEvent(event2
);
549 // Propagate the event to the non-top-level children
550 wxWindow::OnSysColourChanged(event
);
553 // Default activation behaviour - set the focus for the first child
555 void wxFrame::OnActivate(wxActivateEvent
& event
)
557 if (!event
.GetActive())
560 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
;
561 node
= node
->GetNext())
563 // Find a child that's a subwindow, but not a dialog box.
564 wxWindow
*child
= node
->GetData();
565 if (!child
->IsTopLevel())
573 void wxFrame::SendSizeEvent()
575 wxSizeEvent
event(GetSize(), GetId());
576 event
.SetEventObject(this);
577 GetEventHandler()->AddPendingEvent(event
);
582 wxToolBar
* wxFrame::CreateToolBar(long style
,
584 const wxString
& name
)
586 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
591 return m_frameToolBar
;
594 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
596 wxFrameBase::SetToolBar(toolbar
);
600 void wxFrame::PositionToolBar()
602 wxToolBar
* tb
= GetToolBar();
606 GetClientSize(& cw
, &ch
);
609 tb
->GetSize(& tw
, & th
);
611 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
613 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
614 // means, pretend we don't have toolbar/status bar, so we
615 // have the original client size.
620 // Use the 'real' position
624 tb
->SetSize(0, 0, -1, -1, wxSIZE_NO_ADJUSTMENTS
);
627 #endif // wxUSE_TOOLBAR
630 bool wxFrame::PreResize()
634 #endif // wxUSE_TOOLBAR
638 #endif // wxUSE_STATUSBAR
643 WXWidget
wxFrame::GetClientWidget() const
648 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
653 void wxFrame::ChangeBackgroundColour()
655 if (GetClientWidget())
656 wxDoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
659 void wxFrame::ChangeForegroundColour()
661 if (GetClientWidget())
662 wxDoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
665 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
666 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
667 XCrossingEvent
* event
)
669 wxFrame
*tli
= (wxFrame
*)clientData
;
671 XEvent
*e
= (XEvent
*)event
;
673 if( e
->xany
.type
== MapNotify
)
676 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
677 if( !tli
->GetVisibleStatus() )
679 /* We really wanted this to be hidden! */
680 XtUnmapWidget( frameShell
);
683 else if( e
->xany
.type
== UnmapNotify
)
685 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);