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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "frame.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
28 #define XtDisplay XTDISPLAY
29 #define XtWindow XTWINDOW
30 #define XtScreen XTSCREEN
34 #include "wx/statusbr.h"
35 #include "wx/toolbar.h"
37 #include "wx/settings.h"
44 #pragma message disable nosimpint
47 #if defined(__ultrix) || defined(__sgi)
52 #include <X11/Shell.h>
59 #include <Xm/MwmUtil.h>
60 #include <Xm/BulletinB.h>
63 #include <Xm/RowColumn.h>
65 #include <Xm/AtomMgr.h>
66 #include <Xm/LabelG.h>
69 #include <Xm/Protocols.h>
73 #pragma message enable nosimpint
76 #include "wx/motif/private.h"
77 #include "wx/unix/utilsx11.h"
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
84 XCrossingEvent
* event
);
86 // ----------------------------------------------------------------------------
88 // ----------------------------------------------------------------------------
90 extern wxList wxModelessWindows
;
91 extern wxList wxPendingDelete
;
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
98 EVT_ACTIVATE(wxFrame::OnActivate
)
99 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
102 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
104 // ============================================================================
106 // ============================================================================
108 // ----------------------------------------------------------------------------
109 // frame construction
110 // ----------------------------------------------------------------------------
117 m_frameShell
= (WXWidget
) NULL
;
118 m_mainWidget
= (WXWidget
) NULL
;;
119 m_workArea
= (WXWidget
) NULL
;;
120 m_clientArea
= (WXWidget
) NULL
;;
123 bool wxFrame::Create(wxWindow
*parent
,
125 const wxString
& title
,
129 const wxString
& name
)
131 if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
,
136 wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
137 m_foregroundColour
= *wxBLACK
;
138 m_font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
140 int x
= pos
.x
, y
= pos
.y
;
141 int width
= size
.x
, height
= size
.y
;
143 // Set reasonable values for position and size if defaults have been
146 // MB TODO: something better than these arbitrary values ?
147 // VZ should use X resources for this...
153 int displayW
, displayH
;
154 wxDisplaySize( &displayW
, &displayH
);
158 x
= (displayW
- width
) / 2;
163 y
= (displayH
- height
) / 2;
169 wxLogTrace(wxTRACE_Messages
,
170 "Created frame (0x%p) with work area 0x%p and client "
171 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
173 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,FALSE
,
174 wxUniversalRepaintProc
, (XtPointer
) this);
177 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
179 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
181 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
183 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
187 ChangeBackgroundColour();
191 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
192 sizeEvent
.SetEventObject(this);
194 GetEventHandler()->ProcessEvent(sizeEvent
);
199 bool wxFrame::DoCreate( wxWindow
* parent
, wxWindowID id
,
200 const wxString
& title
,
204 const wxString
& name
)
208 frameShell
= XtCreatePopupShell( name
, topLevelShellWidgetClass
,
209 (Widget
)wxTheApp
->GetTopLevelWidget(),
212 XtVaSetValues(frameShell
,
213 // Allows menu to resize
214 XmNallowShellResize
, True
,
215 XmNdeleteResponse
, XmDO_NOTHING
,
216 XmNmappedWhenManaged
, False
,
217 XmNiconic
, (style
& wxICONIZE
) ? TRUE
: FALSE
,
220 m_frameShell
= (WXWidget
)frameShell
;
222 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
223 xmMainWindowWidgetClass
, frameShell
,
224 XmNresizePolicy
, XmRESIZE_NONE
,
227 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
228 xmFormWidgetClass
, (Widget
) m_mainWidget
,
229 XmNresizePolicy
, XmRESIZE_NONE
,
232 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
233 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
236 XmNrightAttachment
, XmATTACH_FORM
,
237 XmNleftAttachment
, XmATTACH_FORM
,
238 XmNtopAttachment
, XmATTACH_FORM
,
239 XmNbottomAttachment
, XmATTACH_FORM
,
242 XtVaSetValues((Widget
) m_mainWidget
,
243 XmNworkWindow
, (Widget
) m_workArea
,
246 XtManageChild((Widget
) m_clientArea
);
247 XtManageChild((Widget
) m_workArea
);
249 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
250 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
251 XtFree( (char *)ptr
);
253 /* Part of show-&-hide fix */
254 XtAddEventHandler( frameShell
, StructureNotifyMask
,
255 False
, (XtEventHandler
)wxFrameMapProc
,
258 XtRealizeWidget(frameShell
);
260 wxAddWindowToTable( (Widget
)m_workArea
, this);
261 wxAddWindowToTable( (Widget
)m_clientArea
, this);
263 wxModelessWindows
.Append( this );
270 m_isBeingDeleted
= TRUE
;
274 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, FALSE
,
275 wxUniversalRepaintProc
, (XtPointer
) this);
283 m_frameMenuBar
->DestroyMenuBar();
285 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
286 #if MOTIF_MENUBAR_DELETE_FIX
287 GetMenuBar()->SetMainWidget((WXWidget
) NULL
);
289 delete m_frameMenuBar
;
290 m_frameMenuBar
= NULL
;
293 if (m_frameStatusBar
)
295 delete m_frameStatusBar
;
296 m_frameStatusBar
= NULL
;
303 void wxFrame::DoDestroy()
305 Widget frameShell
= (Widget
)GetShellWidget();
308 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
309 False
, (XtEventHandler
)wxFrameMapProc
,
314 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
315 XtDestroyWidget( (Widget
)m_clientArea
);
320 XtVaSetValues( (Widget
)m_mainWidget
,
321 XmNworkWindow
, (Widget
)NULL
,
324 wxDeleteWindowFromTable( (Widget
)m_workArea
);
325 XtDestroyWidget( (Widget
)m_workArea
);
329 XtDestroyWidget( (Widget
)m_mainWidget
);
332 XtDestroyWidget( frameShell
);
335 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
336 void wxFrame::DoGetClientSize(int *x
, int *y
) const
339 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
341 if (m_frameStatusBar
)
344 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
351 m_frameToolBar
->GetSize(& tbw
, & tbh
);
352 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
357 #endif // wxUSE_TOOLBAR
359 //CE found a call here with NULL y pointer
366 // Set the client size (i.e. leave the calculation of borders etc.
368 void wxFrame::DoSetClientSize(int width
, int height
)
370 // Calculate how large the new main window should be
371 // by finding the difference between the client area and the
372 // main window area, and adding on to the new client area
374 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
378 if (m_frameStatusBar
)
381 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
388 m_frameToolBar
->GetSize(& tbw
, & tbh
);
389 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
394 #endif // wxUSE_TOOLBAR
396 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
400 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
401 sizeEvent
.SetEventObject(this);
403 GetEventHandler()->ProcessEvent(sizeEvent
);
407 void wxFrame::DoGetSize(int *width
, int *height
) const
410 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
411 *width
= xx
; *height
= yy
;
414 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
417 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
419 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
421 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
423 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
425 if (!(height
== -1 && width
== -1))
431 bool wxFrame::Show( bool show
)
433 if( !wxTopLevelWindowMotif::Show( show
) )
438 Widget shell
= (Widget
)GetShellWidget();
440 return wxWindow::Show(show
);
442 SetVisibleStatus(show
);
446 XRaiseWindow (XtDisplay(shell
), XtWindow(shell
));
450 XtUnmapWidget(shell
);
456 void wxFrame::SetTitle(const wxString
& title
)
458 wxString oldTitle
= GetTitle();
459 if( title
== oldTitle
)
462 wxTopLevelWindow::SetTitle( title
);
465 XtVaSetValues( (Widget
)m_frameShell
,
466 XmNtitle
, title
.c_str(),
467 XmNiconName
, title
.c_str(),
471 void wxFrame::DoSetIcon(const wxIcon
& icon
)
476 if (!icon
.Ok() || !icon
.GetDrawable())
479 XtVaSetValues((Widget
) m_frameShell
,
480 XtNiconPixmap
, icon
.GetDrawable(),
484 void wxFrame::SetIcon(const wxIcon
& icon
)
486 SetIcons( wxIconBundle( icon
) );
489 void wxFrame::SetIcons(const wxIconBundle
& icons
)
491 wxFrameBase::SetIcons( icons
);
496 DoSetIcon( m_icons
.GetIcon( -1 ) );
497 wxSetIconsX11(GetXDisplay(),
498 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
501 void wxFrame::PositionStatusBar()
503 if (!m_frameStatusBar
)
507 GetClientSize(&w
, &h
);
509 m_frameStatusBar
->GetSize(&sw
, &sh
);
511 // Since we wish the status bar to be directly under the client area,
512 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
513 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
516 WXWidget
wxFrame::GetMenuBarWidget() const
519 return GetMenuBar()->GetMainWidget();
521 return (WXWidget
) NULL
;
524 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
528 m_frameMenuBar
= NULL
;
532 // Currently can't set it twice
533 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
537 m_frameMenuBar
->DestroyMenuBar();
538 delete m_frameMenuBar
;
541 m_frameMenuBar
= menuBar
;
542 m_frameMenuBar
->CreateMenuBar(this);
545 // Responds to colour changes, and passes event on to children.
546 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
548 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
551 if ( m_frameStatusBar
)
553 wxSysColourChangedEvent event2
;
554 event2
.SetEventObject( m_frameStatusBar
);
555 m_frameStatusBar
->ProcessEvent(event2
);
558 // Propagate the event to the non-top-level children
559 wxWindow::OnSysColourChanged(event
);
562 // Default activation behaviour - set the focus for the first child
564 void wxFrame::OnActivate(wxActivateEvent
& event
)
566 if (!event
.GetActive())
569 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
;
570 node
= node
->GetNext())
572 // Find a child that's a subwindow, but not a dialog box.
573 wxWindow
*child
= node
->GetData();
574 if (!child
->IsTopLevel())
582 void wxFrame::SendSizeEvent()
584 wxSizeEvent
event(GetSize(), GetId());
585 event
.SetEventObject(this);
586 GetEventHandler()->AddPendingEvent(event
);
591 wxToolBar
* wxFrame::CreateToolBar(long style
,
593 const wxString
& name
)
595 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
600 return m_frameToolBar
;
603 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
605 wxFrameBase::SetToolBar(toolbar
);
609 void wxFrame::PositionToolBar()
611 wxToolBar
* tb
= GetToolBar();
615 GetClientSize(& cw
, &ch
);
618 tb
->GetSize(& tw
, & th
);
620 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
622 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
623 // means, pretend we don't have toolbar/status bar, so we
624 // have the original client size.
629 // Use the 'real' position
633 tb
->SetSize(0, 0, -1, -1, wxSIZE_NO_ADJUSTMENTS
);
636 #endif // wxUSE_TOOLBAR
639 bool wxFrame::PreResize()
643 #endif // wxUSE_TOOLBAR
647 #endif // wxUSE_STATUSBAR
652 WXWidget
wxFrame::GetClientWidget() const
657 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
662 void wxFrame::ChangeBackgroundColour()
664 if (GetClientWidget())
665 wxDoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
668 void wxFrame::ChangeForegroundColour()
670 if (GetClientWidget())
671 wxDoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
674 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
675 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
676 XCrossingEvent
* event
)
678 wxFrame
*tli
= (wxFrame
*)clientData
;
680 XEvent
*e
= (XEvent
*)event
;
682 if( e
->xany
.type
== MapNotify
)
685 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
686 if( !tli
->GetVisibleStatus() )
688 /* We really wanted this to be hidden! */
689 XtUnmapWidget( frameShell
);
692 else if( e
->xany
.type
== UnmapNotify
)
694 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);