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"
42 #pragma message disable nosimpint
45 #if defined(__ultrix) || defined(__sgi)
50 #include <X11/Shell.h>
57 #include <Xm/MwmUtil.h>
58 #include <Xm/BulletinB.h>
61 #include <Xm/RowColumn.h>
63 #include <Xm/AtomMgr.h>
64 #include <Xm/LabelG.h>
67 #include <Xm/Protocols.h>
71 #pragma message enable nosimpint
74 #include "wx/motif/private.h"
75 #include "wx/unix/utilsx11.h"
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
82 XCrossingEvent
* event
);
84 // ----------------------------------------------------------------------------
86 // ----------------------------------------------------------------------------
88 extern wxList wxModelessWindows
;
89 extern wxList wxPendingDelete
;
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
, wxWindow
)
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
,
134 wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
135 m_foregroundColour
= *wxBLACK
;
136 m_font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
138 int x
= pos
.x
, y
= pos
.y
;
139 int width
= size
.x
, height
= size
.y
;
141 // Set reasonable values for position and size if defaults have been
144 // MB TODO: something better than these arbitrary values ?
145 // VZ should use X resources for this...
151 int displayW
, displayH
;
152 wxDisplaySize( &displayW
, &displayH
);
156 x
= (displayW
- width
) / 2;
161 y
= (displayH
- height
) / 2;
167 wxLogTrace(wxTRACE_Messages
,
168 "Created frame (0x%p) with work area 0x%p and client "
169 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
171 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,FALSE
,
172 wxUniversalRepaintProc
, (XtPointer
) this);
175 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
177 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
179 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
181 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
185 ChangeBackgroundColour();
189 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
190 sizeEvent
.SetEventObject(this);
192 GetEventHandler()->ProcessEvent(sizeEvent
);
197 bool wxFrame::DoCreate( wxWindow
* parent
, wxWindowID id
,
198 const wxString
& title
,
202 const wxString
& name
)
206 frameShell
= XtCreatePopupShell( name
, topLevelShellWidgetClass
,
207 (Widget
)wxTheApp
->GetTopLevelWidget(),
210 XtVaSetValues(frameShell
,
211 // Allows menu to resize
212 XmNallowShellResize
, True
,
213 XmNdeleteResponse
, XmDO_NOTHING
,
214 XmNmappedWhenManaged
, False
,
215 XmNiconic
, (style
& wxICONIZE
) ? TRUE
: FALSE
,
218 m_frameShell
= (WXWidget
)frameShell
;
220 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
221 xmMainWindowWidgetClass
, frameShell
,
222 XmNresizePolicy
, XmRESIZE_NONE
,
225 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
226 xmFormWidgetClass
, (Widget
) m_mainWidget
,
227 XmNresizePolicy
, XmRESIZE_NONE
,
230 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
231 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
234 XmNrightAttachment
, XmATTACH_FORM
,
235 XmNleftAttachment
, XmATTACH_FORM
,
236 XmNtopAttachment
, XmATTACH_FORM
,
237 XmNbottomAttachment
, XmATTACH_FORM
,
240 XtVaSetValues((Widget
) m_mainWidget
,
241 XmNworkWindow
, (Widget
) m_workArea
,
244 XtManageChild((Widget
) m_clientArea
);
245 XtManageChild((Widget
) m_workArea
);
247 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
248 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
249 XtFree( (char *)ptr
);
251 /* Part of show-&-hide fix */
252 XtAddEventHandler( frameShell
, StructureNotifyMask
,
253 False
, (XtEventHandler
)wxFrameMapProc
,
256 XtRealizeWidget(frameShell
);
258 wxAddWindowToTable( (Widget
)m_workArea
, this);
259 wxAddWindowToTable( (Widget
)m_clientArea
, this);
261 wxModelessWindows
.Append( this );
268 m_isBeingDeleted
= TRUE
;
272 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, FALSE
,
273 wxUniversalRepaintProc
, (XtPointer
) this);
281 m_frameMenuBar
->DestroyMenuBar();
283 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
284 #if MOTIF_MENUBAR_DELETE_FIX
285 GetMenuBar()->SetMainWidget((WXWidget
) NULL
);
287 delete m_frameMenuBar
;
288 m_frameMenuBar
= NULL
;
291 if (m_frameStatusBar
)
293 delete m_frameStatusBar
;
294 m_frameStatusBar
= NULL
;
301 void wxFrame::DoDestroy()
303 Widget frameShell
= (Widget
)GetShellWidget();
306 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
307 False
, (XtEventHandler
)wxFrameMapProc
,
312 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
313 XtDestroyWidget( (Widget
)m_clientArea
);
318 XtVaSetValues( (Widget
)m_mainWidget
,
319 XmNworkWindow
, (Widget
)NULL
,
322 wxDeleteWindowFromTable( (Widget
)m_workArea
);
323 XtDestroyWidget( (Widget
)m_workArea
);
327 XtDestroyWidget( (Widget
)m_mainWidget
);
330 XtDestroyWidget( frameShell
);
333 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
334 void wxFrame::DoGetClientSize(int *x
, int *y
) const
337 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
339 if (m_frameStatusBar
)
342 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
349 m_frameToolBar
->GetSize(& tbw
, & tbh
);
350 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
355 #endif // wxUSE_TOOLBAR
359 // Set the client size (i.e. leave the calculation of borders etc.
361 void wxFrame::DoSetClientSize(int width
, int height
)
363 // Calculate how large the new main window should be
364 // by finding the difference between the client area and the
365 // main window area, and adding on to the new client area
367 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
371 if (m_frameStatusBar
)
374 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
381 m_frameToolBar
->GetSize(& tbw
, & tbh
);
382 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
387 #endif // wxUSE_TOOLBAR
389 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
393 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
394 sizeEvent
.SetEventObject(this);
396 GetEventHandler()->ProcessEvent(sizeEvent
);
400 void wxFrame::DoGetSize(int *width
, int *height
) const
403 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
404 *width
= xx
; *height
= yy
;
407 void wxFrame::DoGetPosition(int *x
, int *y
) const
409 Window parent_window
= XtWindow((Widget
) m_frameShell
),
410 next_parent
= XtWindow((Widget
) m_frameShell
),
411 root
= RootWindowOfScreen(XtScreen((Widget
) m_frameShell
));
413 // search for the parent that is child of ROOT, because the WM may
414 // reparent twice and notify only the next parent (like FVWM)
415 while (next_parent
!= root
) {
416 Window
*theChildren
; unsigned int n
;
417 parent_window
= next_parent
;
418 XQueryTree(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
,
419 &next_parent
, &theChildren
, &n
);
420 XFree(theChildren
); // not needed
422 int xx
, yy
; unsigned int dummy
;
423 XGetGeometry(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
,
424 &xx
, &yy
, &dummy
, &dummy
, &dummy
, &dummy
);
429 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
432 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
434 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
436 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
438 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
440 if (!(height
== -1 && width
== -1))
446 bool wxFrame::Show( bool show
)
448 if( !wxTopLevelWindowMotif::Show( show
) )
453 Widget shell
= (Widget
)GetShellWidget();
455 return wxWindow::Show(show
);
457 SetVisibleStatus(show
);
461 XRaiseWindow (XtDisplay(shell
), XtWindow(shell
));
465 XtUnmapWidget(shell
);
471 void wxFrame::SetTitle(const wxString
& title
)
473 wxString oldTitle
= GetTitle();
474 if( title
== oldTitle
)
477 wxTopLevelWindow::SetTitle( title
);
480 XtVaSetValues( (Widget
)m_frameShell
,
481 XmNtitle
, title
.c_str(),
482 XmNiconName
, title
.c_str(),
486 void wxFrame::DoSetIcon(const wxIcon
& icon
)
491 if (!icon
.Ok() || !icon
.GetDrawable())
494 XtVaSetValues((Widget
) m_frameShell
,
495 XtNiconPixmap
, icon
.GetDrawable(),
499 void wxFrame::SetIcon(const wxIcon
& icon
)
501 SetIcons( wxIconBundle( icon
) );
504 void wxFrame::SetIcons(const wxIconBundle
& icons
)
506 wxFrameBase::SetIcons( icons
);
511 DoSetIcon( m_icons
.GetIcon( -1 ) );
512 wxSetIconsX11(GetXDisplay(),
513 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
516 void wxFrame::PositionStatusBar()
518 if (!m_frameStatusBar
)
522 GetClientSize(&w
, &h
);
524 m_frameStatusBar
->GetSize(&sw
, &sh
);
526 // Since we wish the status bar to be directly under the client area,
527 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
528 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
531 WXWidget
wxFrame::GetMenuBarWidget() const
534 return GetMenuBar()->GetMainWidget();
536 return (WXWidget
) NULL
;
539 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
543 m_frameMenuBar
= NULL
;
547 // Currently can't set it twice
548 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
552 m_frameMenuBar
->DestroyMenuBar();
553 delete m_frameMenuBar
;
556 m_frameMenuBar
= menuBar
;
557 m_frameMenuBar
->CreateMenuBar(this);
560 // Responds to colour changes, and passes event on to children.
561 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
563 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
566 if ( m_frameStatusBar
)
568 wxSysColourChangedEvent event2
;
569 event2
.SetEventObject( m_frameStatusBar
);
570 m_frameStatusBar
->ProcessEvent(event2
);
573 // Propagate the event to the non-top-level children
574 wxWindow::OnSysColourChanged(event
);
577 // Default activation behaviour - set the focus for the first child
579 void wxFrame::OnActivate(wxActivateEvent
& event
)
581 if (!event
.GetActive())
584 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
;
585 node
= node
->GetNext())
587 // Find a child that's a subwindow, but not a dialog box.
588 wxWindow
*child
= node
->GetData();
589 if (!child
->IsTopLevel())
597 void wxFrame::SendSizeEvent()
599 wxSizeEvent
event(GetSize(), GetId());
600 event
.SetEventObject(this);
601 GetEventHandler()->AddPendingEvent(event
);
606 wxToolBar
* wxFrame::CreateToolBar(long style
,
608 const wxString
& name
)
610 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
615 return m_frameToolBar
;
618 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
620 wxFrameBase::SetToolBar(toolbar
);
624 void wxFrame::PositionToolBar()
626 wxToolBar
* tb
= GetToolBar();
630 GetClientSize(& cw
, &ch
);
633 tb
->GetSize(& tw
, & th
);
635 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
637 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
638 // means, pretend we don't have toolbar/status bar, so we
639 // have the original client size.
644 // Use the 'real' position
648 tb
->SetSize(0, 0, -1, -1, wxSIZE_NO_ADJUSTMENTS
);
651 #endif // wxUSE_TOOLBAR
654 bool wxFrame::PreResize()
658 #endif // wxUSE_TOOLBAR
662 #endif // wxUSE_STATUSBAR
667 WXWidget
wxFrame::GetClientWidget() const
672 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
677 void wxFrame::ChangeBackgroundColour()
679 if (GetClientWidget())
680 wxDoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
683 void wxFrame::ChangeForegroundColour()
685 if (GetClientWidget())
686 wxDoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
689 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
690 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
691 XCrossingEvent
* event
)
693 wxFrame
*tli
= (wxFrame
*)clientData
;
695 XEvent
*e
= (XEvent
*)event
;
697 if( e
->xany
.type
== MapNotify
)
700 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
701 if( !tli
->GetVisibleStatus() )
703 /* We really wanted this to be hidden! */
704 XtUnmapWidget( frameShell
);
707 else if( e
->xany
.type
== UnmapNotify
)
709 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);