1 /////////////////////////////////////////////////////////////////////////////
2 // Name: motif/frame.cpp
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "frame.h"
26 #define XtDisplay XTDISPLAY
27 #define XtWindow XTWINDOW
28 #define XtScreen XTSCREEN
32 #include "wx/statusbr.h"
33 #include "wx/toolbar.h"
35 #include "wx/settings.h"
41 #pragma message disable nosimpint
44 #if defined(__ultrix) || defined(__sgi)
49 #include <X11/Shell.h>
56 #include <Xm/MwmUtil.h>
57 #include <Xm/BulletinB.h>
60 #include <Xm/RowColumn.h>
62 #include <Xm/AtomMgr.h>
63 #include <Xm/LabelG.h>
66 #include <Xm/Protocols.h>
70 #pragma message enable nosimpint
73 #include "wx/motif/private.h"
74 #include "wx/unix/utilsx11.h"
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
81 XCrossingEvent
* event
);
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 extern wxList wxModelessWindows
;
88 extern wxList wxPendingDelete
;
90 // TODO: this should be tidied so that any frame can be the
92 // static bool wxTopLevelUsed = FALSE;
94 // ----------------------------------------------------------------------------
96 // ----------------------------------------------------------------------------
98 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
99 EVT_ACTIVATE(wxFrame::OnActivate
)
100 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
103 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
105 // ============================================================================
107 // ============================================================================
109 // ----------------------------------------------------------------------------
110 // frame construction
111 // ----------------------------------------------------------------------------
118 m_frameShell
= (WXWidget
) NULL
;
119 m_mainWidget
= (WXWidget
) NULL
;;
120 m_workArea
= (WXWidget
) NULL
;;
121 m_clientArea
= (WXWidget
) NULL
;;
122 // m_visibleStatus = TRUE;
125 bool wxFrame::Create(wxWindow
*parent
,
127 const wxString
& title
,
131 const wxString
& name
)
133 if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
,
138 wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
139 m_foregroundColour
= *wxBLACK
;
140 m_font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
142 int x
= pos
.x
, y
= pos
.y
;
143 int width
= size
.x
, height
= size
.y
;
145 // Set reasonable values for position and size if defaults have been
148 // MB TODO: something better than these arbitrary values ?
149 // VZ should use X resources for this...
155 int displayW
, displayH
;
156 wxDisplaySize( &displayW
, &displayH
);
160 x
= (displayW
- width
) / 2;
165 y
= (displayH
- height
) / 2;
171 wxLogTrace(wxTRACE_Messages
,
172 "Created frame (0x%p) with work area 0x%p and client "
173 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
175 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,FALSE
,
176 wxUniversalRepaintProc
, (XtPointer
) this);
179 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
181 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
183 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
185 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
189 ChangeBackgroundColour();
193 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
194 sizeEvent
.SetEventObject(this);
196 GetEventHandler()->ProcessEvent(sizeEvent
);
201 bool wxFrame::DoCreate( wxWindow
* parent
, wxWindowID id
,
202 const wxString
& title
,
206 const wxString
& name
)
208 static bool wxTopLevelUsed
= FALSE
; /* this is global */
213 // Change suggested by Matthew Flatt
214 frameShell
= (WXWidget
)XtAppCreateShell( name
,
215 wxTheApp
->GetClassName(),
216 topLevelShellWidgetClass
,
217 (Display
*) wxGetDisplay(),
222 frameShell
= wxTheApp
->GetTopLevelWidget();
223 wxTopLevelUsed
= TRUE
;
226 XtVaSetValues((Widget
) frameShell
,
227 // Allows menu to resize
228 XmNallowShellResize
, True
,
229 XmNdeleteResponse
, XmDO_NOTHING
,
230 XmNmappedWhenManaged
, False
,
231 XmNiconic
, (style
& wxICONIZE
) ? TRUE
: FALSE
,
234 m_frameShell
= frameShell
;
236 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
237 xmMainWindowWidgetClass
, (Widget
) frameShell
,
238 XmNresizePolicy
, XmRESIZE_NONE
,
241 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
242 xmFormWidgetClass
, (Widget
) m_mainWidget
,
243 XmNresizePolicy
, XmRESIZE_NONE
,
246 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
247 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
250 XmNrightAttachment
, XmATTACH_FORM
,
251 XmNleftAttachment
, XmATTACH_FORM
,
252 XmNtopAttachment
, XmATTACH_FORM
,
253 XmNbottomAttachment
, XmATTACH_FORM
,
256 XtVaSetValues((Widget
) m_mainWidget
,
257 XmNworkWindow
, (Widget
) m_workArea
,
260 XtManageChild((Widget
) m_clientArea
);
261 XtManageChild((Widget
) m_workArea
);
263 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
264 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
265 XtFree( (char *)ptr
);
267 /* Part of show-&-hide fix */
268 XtAddEventHandler( (Widget
)frameShell
, StructureNotifyMask
,
269 False
, (XtEventHandler
)wxFrameMapProc
,
272 XtRealizeWidget((Widget
) frameShell
);
274 wxAddWindowToTable( (Widget
)m_workArea
, this);
275 wxAddWindowToTable( (Widget
)m_clientArea
, this);
277 wxModelessWindows
.Append( this );
284 m_isBeingDeleted
= TRUE
;
288 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, FALSE
,
289 wxUniversalRepaintProc
, (XtPointer
) this);
297 m_frameMenuBar
->DestroyMenuBar();
299 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
300 #if MOTIF_MENUBAR_DELETE_FIX
301 GetMenuBar()->SetMainWidget((WXWidget
) NULL
);
303 delete m_frameMenuBar
;
304 m_frameMenuBar
= NULL
;
307 if (m_frameStatusBar
)
309 delete m_frameStatusBar
;
310 m_frameStatusBar
= NULL
;
314 void wxFrame::DoDestroy()
316 Widget frameShell
= (Widget
)GetShellWidget();
318 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
319 False
, (XtEventHandler
)wxFrameMapProc
,
324 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
325 XtDestroyWidget( (Widget
)m_clientArea
);
330 XtVaSetValues( (Widget
)m_mainWidget
,
331 XmNworkWindow
, (Widget
)NULL
,
334 wxDeleteWindowFromTable( (Widget
)m_workArea
);
335 XtDestroyWidget( (Widget
)m_workArea
);
339 XtDestroyWidget( (Widget
)m_mainWidget
);
342 XtDestroyWidget( frameShell
);
345 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
346 void wxFrame::DoGetClientSize(int *x
, int *y
) const
349 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
351 if (m_frameStatusBar
)
354 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
361 m_frameToolBar
->GetSize(& tbw
, & tbh
);
362 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
367 #endif // wxUSE_TOOLBAR
371 // Set the client size (i.e. leave the calculation of borders etc.
373 void wxFrame::DoSetClientSize(int width
, int height
)
375 // Calculate how large the new main window should be
376 // by finding the difference between the client area and the
377 // main window area, and adding on to the new client area
379 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
383 if (m_frameStatusBar
)
386 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
393 m_frameToolBar
->GetSize(& tbw
, & tbh
);
394 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
399 #endif // wxUSE_TOOLBAR
401 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
405 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
406 sizeEvent
.SetEventObject(this);
408 GetEventHandler()->ProcessEvent(sizeEvent
);
412 void wxFrame::DoGetSize(int *width
, int *height
) const
415 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
416 *width
= xx
; *height
= yy
;
419 void wxFrame::DoGetPosition(int *x
, int *y
) const
421 Window parent_window
= XtWindow((Widget
) m_frameShell
),
422 next_parent
= XtWindow((Widget
) m_frameShell
),
423 root
= RootWindowOfScreen(XtScreen((Widget
) m_frameShell
));
425 // search for the parent that is child of ROOT, because the WM may
426 // reparent twice and notify only the next parent (like FVWM)
427 while (next_parent
!= root
) {
428 Window
*theChildren
; unsigned int n
;
429 parent_window
= next_parent
;
430 XQueryTree(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
,
431 &next_parent
, &theChildren
, &n
);
432 XFree(theChildren
); // not needed
434 int xx
, yy
; unsigned int dummy
;
435 XGetGeometry(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
,
436 &xx
, &yy
, &dummy
, &dummy
, &dummy
, &dummy
);
441 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
444 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
446 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
448 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
450 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
452 if (!(height
== -1 && width
== -1))
458 bool wxFrame::Show( bool show
)
460 if( !wxTopLevelWindowMotif::Show( show
) )
465 Widget shell
= (Widget
)GetShellWidget();
467 return wxWindow::Show(show
);
469 SetVisibleStatus(show
);
473 XRaiseWindow (XtDisplay(shell
), XtWindow(shell
));
477 XtUnmapWidget(shell
);
483 void wxFrame::SetTitle(const wxString
& title
)
485 wxString oldTitle
= GetTitle();
486 if( title
== oldTitle
)
489 wxTopLevelWindow::SetTitle( title
);
492 XtVaSetValues( (Widget
)m_frameShell
,
493 XmNtitle
, title
.c_str(),
494 XmNiconName
, title
.c_str(),
498 void wxFrame::DoSetIcon(const wxIcon
& icon
)
503 if (!icon
.Ok() || !icon
.GetPixmap())
506 XtVaSetValues((Widget
) m_frameShell
, XtNiconPixmap
, icon
.GetPixmap(), NULL
);
509 void wxFrame::SetIcon(const wxIcon
& icon
)
511 SetIcons( wxIconBundle( icon
) );
514 void wxFrame::SetIcons(const wxIconBundle
& icons
)
516 wxFrameBase::SetIcons( icons
);
521 DoSetIcon( m_icons
.GetIcon( -1 ) );
522 wxSetIconsX11(GetXDisplay(),
523 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
526 void wxFrame::PositionStatusBar()
528 if (!m_frameStatusBar
)
532 GetClientSize(&w
, &h
);
534 m_frameStatusBar
->GetSize(&sw
, &sh
);
536 // Since we wish the status bar to be directly under the client area,
537 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
538 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
541 WXWidget
wxFrame::GetMenuBarWidget() const
544 return GetMenuBar()->GetMainWidget();
546 return (WXWidget
) NULL
;
549 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
553 m_frameMenuBar
= NULL
;
557 // Currently can't set it twice
558 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
562 m_frameMenuBar
->DestroyMenuBar();
563 delete m_frameMenuBar
;
566 m_frameMenuBar
= menuBar
;
567 m_frameMenuBar
->CreateMenuBar(this);
570 // Responds to colour changes, and passes event on to children.
571 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
573 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
576 if ( m_frameStatusBar
)
578 wxSysColourChangedEvent event2
;
579 event2
.SetEventObject( m_frameStatusBar
);
580 m_frameStatusBar
->ProcessEvent(event2
);
583 // Propagate the event to the non-top-level children
584 wxWindow::OnSysColourChanged(event
);
587 // Default activation behaviour - set the focus for the first child
589 void wxFrame::OnActivate(wxActivateEvent
& event
)
591 if (!event
.GetActive())
594 for(wxWindowList::Node
*node
= GetChildren().GetFirst(); node
;
595 node
= node
->GetNext())
597 // Find a child that's a subwindow, but not a dialog box.
598 wxWindow
*child
= node
->GetData();
599 if (!child
->IsTopLevel())
607 void wxFrame::SendSizeEvent()
609 wxSizeEvent
event(GetSize(), GetId());
610 event
.SetEventObject(this);
611 GetEventHandler()->AddPendingEvent(event
);
616 wxToolBar
* wxFrame::CreateToolBar(long style
,
618 const wxString
& name
)
620 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
625 return m_frameToolBar
;
628 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
630 wxFrameBase::SetToolBar(toolbar
);
634 void wxFrame::PositionToolBar()
636 wxToolBar
* tb
= GetToolBar();
640 GetClientSize(& cw
, &ch
);
643 tb
->GetSize(& tw
, & th
);
645 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
647 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
648 // means, pretend we don't have toolbar/status bar, so we
649 // have the original client size.
654 // Use the 'real' position
658 tb
->SetSize(0, 0, tw
, th
, wxSIZE_NO_ADJUSTMENTS
);
661 #endif // wxUSE_TOOLBAR
664 bool wxFrame::PreResize()
668 #endif // wxUSE_TOOLBAR
672 #endif // wxUSE_STATUSBAR
677 WXWidget
wxFrame::GetClientWidget() const
682 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
687 void wxFrame::ChangeBackgroundColour()
689 if (GetClientWidget())
690 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
693 void wxFrame::ChangeForegroundColour()
695 if (GetClientWidget())
696 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
699 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
700 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
701 XCrossingEvent
* event
)
703 wxFrame
*tli
= (wxFrame
*)clientData
;
705 XEvent
*e
= (XEvent
*)event
;
707 if( e
->xany
.type
== MapNotify
)
710 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
711 if( !tli
->GetVisibleStatus() )
713 /* We really wanted this to be hidden! */
714 XtUnmapWidget( frameShell
);
717 else if( e
->xany
.type
== UnmapNotify
)
719 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);