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 // TODO: this should be tidied so that any frame can be the 
  93 // static bool wxTopLevelUsed = FALSE; 
  95 // ---------------------------------------------------------------------------- 
  97 // ---------------------------------------------------------------------------- 
  99 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
) 
 100     EVT_ACTIVATE(wxFrame::OnActivate
) 
 101     EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
) 
 104 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
) 
 106 // ============================================================================ 
 108 // ============================================================================ 
 110 // ---------------------------------------------------------------------------- 
 111 // frame construction 
 112 // ---------------------------------------------------------------------------- 
 119     m_frameShell 
= (WXWidget
) NULL
; 
 120     m_mainWidget 
= (WXWidget
) NULL
;; 
 121     m_workArea 
= (WXWidget
) NULL
;; 
 122     m_clientArea 
= (WXWidget
) NULL
;; 
 123     // m_visibleStatus = TRUE; 
 126 bool wxFrame::Create(wxWindow 
*parent
, 
 128                      const wxString
& title
, 
 132                      const wxString
& name
) 
 134     if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
, 
 139         wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
); 
 140     m_foregroundColour 
= *wxBLACK
; 
 141     m_font 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 143     int x 
= pos
.x
, y 
= pos
.y
; 
 144     int width 
= size
.x
, height 
= size
.y
; 
 146     // Set reasonable values for position and size if defaults have been 
 149     // MB TODO: something better than these arbitrary values ? 
 150     // VZ       should use X resources for this... 
 156     int displayW
, displayH
; 
 157     wxDisplaySize( &displayW
, &displayH 
); 
 161         x 
= (displayW 
- width
) / 2; 
 166         y 
= (displayH 
- height
) / 2; 
 172     wxLogTrace(wxTRACE_Messages
, 
 173                "Created frame (0x%p) with work area 0x%p and client " 
 174                "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
); 
 176     XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,FALSE
, 
 177         wxUniversalRepaintProc
, (XtPointer
) this); 
 180         XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
); 
 182         XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
); 
 184         XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
); 
 186         XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
); 
 190     ChangeBackgroundColour(); 
 194     wxSizeEvent 
sizeEvent(wxSize(width
, height
), GetId()); 
 195     sizeEvent
.SetEventObject(this); 
 197     GetEventHandler()->ProcessEvent(sizeEvent
); 
 202 bool wxFrame::DoCreate( wxWindow
* parent
, wxWindowID id
, 
 203                         const wxString
& title
, 
 207                         const wxString
& name 
) 
 209     static bool wxTopLevelUsed 
= FALSE
; /* this is global */ 
 214         // Change suggested by Matthew Flatt 
 215         frameShell 
= (WXWidget
)XtAppCreateShell( name
, 
 216                                                  wxTheApp
->GetClassName(), 
 217                                                  topLevelShellWidgetClass
, 
 218                                                  (Display
*) wxGetDisplay(), 
 223         frameShell 
= wxTheApp
->GetTopLevelWidget(); 
 224         wxTopLevelUsed 
= TRUE
; 
 227     XtVaSetValues((Widget
) frameShell
, 
 228         // Allows menu to resize 
 229         XmNallowShellResize
, True
, 
 230         XmNdeleteResponse
, XmDO_NOTHING
, 
 231         XmNmappedWhenManaged
, False
, 
 232         XmNiconic
, (style 
& wxICONIZE
) ? TRUE 
: FALSE
, 
 235     m_frameShell 
= frameShell
; 
 237     m_mainWidget 
= (WXWidget
) XtVaCreateManagedWidget("main_window", 
 238         xmMainWindowWidgetClass
, (Widget
) frameShell
, 
 239         XmNresizePolicy
, XmRESIZE_NONE
, 
 242     m_workArea 
= (WXWidget
) XtVaCreateWidget("form", 
 243         xmFormWidgetClass
, (Widget
) m_mainWidget
, 
 244         XmNresizePolicy
, XmRESIZE_NONE
, 
 247     m_clientArea 
= (WXWidget
) XtVaCreateWidget("client", 
 248         xmBulletinBoardWidgetClass
, (Widget
) m_workArea
, 
 251         XmNrightAttachment
, XmATTACH_FORM
, 
 252         XmNleftAttachment
, XmATTACH_FORM
, 
 253         XmNtopAttachment
, XmATTACH_FORM
, 
 254         XmNbottomAttachment
, XmATTACH_FORM
, 
 257     XtVaSetValues((Widget
) m_mainWidget
, 
 258         XmNworkWindow
, (Widget
) m_workArea
, 
 261     XtManageChild((Widget
) m_clientArea
); 
 262     XtManageChild((Widget
) m_workArea
); 
 264     XtTranslations ptr 
= XtParseTranslationTable( "<Configure>: resize()" ); 
 265     XtOverrideTranslations( (Widget
) m_workArea
, ptr 
); 
 266     XtFree( (char *)ptr 
); 
 268     /* Part of show-&-hide fix */ 
 269     XtAddEventHandler( (Widget
)frameShell
, StructureNotifyMask
, 
 270                        False
, (XtEventHandler
)wxFrameMapProc
, 
 273     XtRealizeWidget((Widget
) frameShell
); 
 275     wxAddWindowToTable( (Widget
)m_workArea
, this); 
 276     wxAddWindowToTable( (Widget
)m_clientArea
, this); 
 278     wxModelessWindows
.Append( this ); 
 285     m_isBeingDeleted 
= TRUE
; 
 289       XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, FALSE
, 
 290           wxUniversalRepaintProc
, (XtPointer
) this); 
 298         m_frameMenuBar
->DestroyMenuBar(); 
 300         // Hack to stop core dump on Ultrix, OSF, for some strange reason. 
 301 #if MOTIF_MENUBAR_DELETE_FIX 
 302         GetMenuBar()->SetMainWidget((WXWidget
) NULL
); 
 304         delete m_frameMenuBar
; 
 305         m_frameMenuBar 
= NULL
; 
 308     if (m_frameStatusBar
) 
 310         delete m_frameStatusBar
; 
 311         m_frameStatusBar 
= NULL
; 
 315 void wxFrame::DoDestroy() 
 317     Widget frameShell 
= (Widget
)GetShellWidget(); 
 319     XtRemoveEventHandler( frameShell
, StructureNotifyMask
, 
 320                           False
, (XtEventHandler
)wxFrameMapProc
, 
 325         wxDeleteWindowFromTable( (Widget
)m_clientArea 
); 
 326         XtDestroyWidget( (Widget
)m_clientArea 
); 
 331         XtVaSetValues( (Widget
)m_mainWidget
, 
 332                        XmNworkWindow
, (Widget
)NULL
, 
 335         wxDeleteWindowFromTable( (Widget
)m_workArea 
); 
 336         XtDestroyWidget( (Widget
)m_workArea 
); 
 340         XtDestroyWidget( (Widget
)m_mainWidget 
); 
 343         XtDestroyWidget( frameShell 
); 
 346 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. 
 347 void wxFrame::DoGetClientSize(int *x
, int *y
) const 
 350     XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
); 
 352     if (m_frameStatusBar
) 
 355         m_frameStatusBar
->GetSize(& sbw
, & sbh
); 
 362         m_frameToolBar
->GetSize(& tbw
, & tbh
); 
 363         if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
) 
 368 #endif // wxUSE_TOOLBAR 
 372 // Set the client size (i.e. leave the calculation of borders etc. 
 374 void wxFrame::DoSetClientSize(int width
, int height
) 
 376     // Calculate how large the new main window should be 
 377     // by finding the difference between the client area and the 
 378     // main window area, and adding on to the new client area 
 380         XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
); 
 384         if (m_frameStatusBar
) 
 387             m_frameStatusBar
->GetSize(& sbw
, & sbh
); 
 394             m_frameToolBar
->GetSize(& tbw
, & tbh
); 
 395             if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
) 
 400 #endif // wxUSE_TOOLBAR 
 402         XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
); 
 406     wxSizeEvent 
sizeEvent(wxSize(width
, height
), GetId()); 
 407     sizeEvent
.SetEventObject(this); 
 409     GetEventHandler()->ProcessEvent(sizeEvent
); 
 413 void wxFrame::DoGetSize(int *width
, int *height
) const 
 416     XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
); 
 417     *width 
= xx
; *height 
= yy
; 
 420 void wxFrame::DoGetPosition(int *x
, int *y
) const 
 422     Window parent_window 
= XtWindow((Widget
) m_frameShell
), 
 423         next_parent   
= XtWindow((Widget
) m_frameShell
), 
 424         root          
= RootWindowOfScreen(XtScreen((Widget
) m_frameShell
)); 
 426     // search for the parent that is child of ROOT, because the WM may 
 427     // reparent twice and notify only the next parent (like FVWM) 
 428     while (next_parent 
!= root
) { 
 429         Window 
*theChildren
; unsigned int n
; 
 430         parent_window 
= next_parent
; 
 431         XQueryTree(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
, 
 432             &next_parent
, &theChildren
, &n
); 
 433         XFree(theChildren
); // not needed 
 435     int xx
, yy
; unsigned int dummy
; 
 436     XGetGeometry(XtDisplay((Widget
) m_frameShell
), parent_window
, &root
, 
 437         &xx
, &yy
, &dummy
, &dummy
, &dummy
, &dummy
); 
 442 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
)) 
 445         XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
); 
 447         XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
); 
 449         XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
); 
 451         XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
); 
 453     if (!(height 
== -1 && width 
== -1)) 
 459 bool wxFrame::Show( bool show 
) 
 461     if( !wxTopLevelWindowMotif::Show( show 
) ) 
 466     Widget shell 
= (Widget
)GetShellWidget(); 
 468         return wxWindow::Show(show
); 
 470     SetVisibleStatus(show
); 
 474         XRaiseWindow (XtDisplay(shell
), XtWindow(shell
)); 
 478         XtUnmapWidget(shell
); 
 484 void wxFrame::SetTitle(const wxString
& title
) 
 486     wxString oldTitle 
= GetTitle(); 
 487     if( title 
== oldTitle 
) 
 490     wxTopLevelWindow::SetTitle( title 
); 
 493         XtVaSetValues( (Widget
)m_frameShell
, 
 494                        XmNtitle
, title
.c_str(), 
 495                        XmNiconName
, title
.c_str(), 
 499 void wxFrame::DoSetIcon(const wxIcon
& icon
) 
 504     if (!icon
.Ok() || !icon
.GetPixmap()) 
 507     XtVaSetValues((Widget
) m_frameShell
, XtNiconPixmap
, icon
.GetPixmap(), NULL
); 
 510 void wxFrame::SetIcon(const wxIcon
& icon
) 
 512     SetIcons( wxIconBundle( icon 
) ); 
 515 void wxFrame::SetIcons(const wxIconBundle
& icons
) 
 517     wxFrameBase::SetIcons( icons 
); 
 522     DoSetIcon( m_icons
.GetIcon( -1 ) ); 
 523     wxSetIconsX11(GetXDisplay(), 
 524                   (WXWindow
) XtWindow( (Widget
) m_frameShell 
), icons
); 
 527 void wxFrame::PositionStatusBar() 
 529     if (!m_frameStatusBar
) 
 533     GetClientSize(&w
, &h
); 
 535     m_frameStatusBar
->GetSize(&sw
, &sh
); 
 537     // Since we wish the status bar to be directly under the client area, 
 538     // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS. 
 539     m_frameStatusBar
->SetSize(0, h
, w
, sh
); 
 542 WXWidget 
wxFrame::GetMenuBarWidget() const 
 545         return GetMenuBar()->GetMainWidget(); 
 547         return (WXWidget
) NULL
; 
 550 void wxFrame::SetMenuBar(wxMenuBar 
*menuBar
) 
 554         m_frameMenuBar 
= NULL
; 
 558     // Currently can't set it twice 
 559     //    wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once"); 
 563         m_frameMenuBar
->DestroyMenuBar(); 
 564         delete m_frameMenuBar
; 
 567     m_frameMenuBar 
= menuBar
; 
 568     m_frameMenuBar
->CreateMenuBar(this); 
 571 // Responds to colour changes, and passes event on to children. 
 572 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
 574     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
)); 
 577     if ( m_frameStatusBar 
) 
 579         wxSysColourChangedEvent event2
; 
 580         event2
.SetEventObject( m_frameStatusBar 
); 
 581         m_frameStatusBar
->ProcessEvent(event2
); 
 584     // Propagate the event to the non-top-level children 
 585     wxWindow::OnSysColourChanged(event
); 
 588 // Default activation behaviour - set the focus for the first child 
 590 void wxFrame::OnActivate(wxActivateEvent
& event
) 
 592     if (!event
.GetActive()) 
 595     for(wxWindowList::Node 
*node 
= GetChildren().GetFirst(); node
; 
 596         node 
= node
->GetNext()) 
 598         // Find a child that's a subwindow, but not a dialog box. 
 599         wxWindow 
*child 
= node
->GetData(); 
 600         if (!child
->IsTopLevel()) 
 608 void wxFrame::SendSizeEvent() 
 610     wxSizeEvent 
event(GetSize(), GetId()); 
 611     event
.SetEventObject(this); 
 612     GetEventHandler()->AddPendingEvent(event
); 
 617 wxToolBar
* wxFrame::CreateToolBar(long style
, 
 619                                   const wxString
& name
) 
 621     if ( wxFrameBase::CreateToolBar(style
, id
, name
) ) 
 626     return m_frameToolBar
; 
 629 void wxFrame::SetToolBar(wxToolBar 
*toolbar
) 
 631     wxFrameBase::SetToolBar(toolbar
); 
 635 void wxFrame::PositionToolBar() 
 637     wxToolBar
* tb 
= GetToolBar(); 
 641         GetClientSize(& cw
, &ch
); 
 644         tb
->GetSize(& tw
, & th
); 
 646         if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
) 
 648             // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS 
 649             // means, pretend we don't have toolbar/status bar, so we 
 650             // have the original client size. 
 655             // Use the 'real' position 
 659         tb
->SetSize(0, 0, tw
, th
, wxSIZE_NO_ADJUSTMENTS
); 
 662 #endif // wxUSE_TOOLBAR 
 665 bool wxFrame::PreResize() 
 669 #endif // wxUSE_TOOLBAR 
 673 #endif // wxUSE_STATUSBAR 
 678 WXWidget 
wxFrame::GetClientWidget() const 
 683 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
)) 
 688 void wxFrame::ChangeBackgroundColour() 
 690     if (GetClientWidget()) 
 691         DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
); 
 694 void wxFrame::ChangeForegroundColour() 
 696     if (GetClientWidget()) 
 697         DoChangeForegroundColour(GetClientWidget(), m_foregroundColour
); 
 700 /* MATTEW: Used to insure that hide-&-show within an event cycle works */ 
 701 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
, 
 702                             XCrossingEvent
* event 
) 
 704     wxFrame 
*tli 
= (wxFrame
*)clientData
; 
 706     XEvent 
*e 
= (XEvent 
*)event
; 
 708     if( e
->xany
.type 
== MapNotify 
) 
 711         XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL 
); 
 712         if( !tli
->GetVisibleStatus() ) 
 714             /* We really wanted this to be hidden! */ 
 715             XtUnmapWidget( frameShell 
); 
 718     else if( e
->xany
.type 
== UnmapNotify 
) 
 720         XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL 
);