]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/frame.cpp
Don't pass zero width or height to SetVirtualSize or layout is
[wxWidgets.git] / src / motif / frame.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: motif/frame.cpp
3// Purpose: wxFrame
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "frame.h"
22#endif
23
24
25#ifdef __VMS
26#define XtDisplay XTDISPLAY
27#define XtWindow XTWINDOW
28#define XtScreen XTSCREEN
29#endif
30
31# include "wx/frame.h"
32#include "wx/statusbr.h"
33#include "wx/toolbar.h"
34#include "wx/menuitem.h"
35#include "wx/menu.h"
36#include "wx/dcclient.h"
37#include "wx/dialog.h"
38#include "wx/settings.h"
39#include "wx/app.h"
40#include "wx/utils.h"
41#include "wx/log.h"
42
43#ifdef __VMS__
44 #pragma message disable nosimpint
45#endif
46
47#if defined(__ultrix) || defined(__sgi)
48 #include <Xm/Frame.h>
49#endif
50
51#include <Xm/Xm.h>
52#include <X11/Shell.h>
53#include <X11/Core.h>
54#if XmVersion >= 1002
55 #include <Xm/XmAll.h>
56#else
57 #include <Xm/Frame.h>
58#endif
59#include <Xm/MwmUtil.h>
60#include <Xm/BulletinB.h>
61#include <Xm/Form.h>
62#include <Xm/MainW.h>
63#include <Xm/RowColumn.h>
64#include <Xm/Label.h>
65#include <Xm/AtomMgr.h>
66#include <Xm/LabelG.h>
67#include <Xm/Frame.h>
68#if XmVersion > 1000
69 #include <Xm/Protocols.h>
70#endif
71
72#ifdef __VMS__
73 #pragma message enable nosimpint
74#endif
75
76#include "wx/motif/private.h"
77#include "wx/unix/utilsx11.h"
78
79// ----------------------------------------------------------------------------
80// private functions
81// ----------------------------------------------------------------------------
82
83static void wxFrameEventHandler(Widget wid,
84 XtPointer WXUNUSED(client_data),
85 XEvent* event,
86 Boolean* continueToDispatch);
87static void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
88static void wxFrameFocusProc(Widget workArea, XtPointer clientData,
89 XmAnyCallbackStruct *cbs);
90static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
91 XCrossingEvent * event);
92
93// ----------------------------------------------------------------------------
94// globals
95// ----------------------------------------------------------------------------
96
97extern wxList wxModelessWindows;
98extern wxList wxPendingDelete;
99
100// TODO: this should be tidied so that any frame can be the
101// top frame
102static bool wxTopLevelUsed = FALSE;
103
104// ----------------------------------------------------------------------------
105// wxWin macros
106// ----------------------------------------------------------------------------
107
108BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
109 EVT_ACTIVATE(wxFrame::OnActivate)
110 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
111END_EVENT_TABLE()
112
113IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
114
115// ============================================================================
116// implementation
117// ============================================================================
118
119// ----------------------------------------------------------------------------
120// frame construction
121// ----------------------------------------------------------------------------
122
123void wxFrame::Init()
124{
125 m_iconized = FALSE;
126
127 //// Motif-specific
128 m_frameShell = (WXWidget) NULL;
129 m_frameWidget = (WXWidget) NULL;;
130 m_workArea = (WXWidget) NULL;;
131 m_clientArea = (WXWidget) NULL;;
132 m_visibleStatus = TRUE;
133}
134
135bool wxFrame::Create(wxWindow *parent,
136 wxWindowID id,
137 const wxString& title,
138 const wxPoint& pos,
139 const wxSize& size,
140 long style,
141 const wxString& name)
142{
143 if ( parent )
144 parent->AddChild(this);
145 else
146 wxTopLevelWindows.Append(this);
147
148 wxModelessWindows.Append(this);
149
150 SetName(name);
151
152 m_windowStyle = style;
153
154 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
155 m_foregroundColour = *wxBLACK;
156 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
157
158 if ( id > -1 )
159 m_windowId = id;
160 else
161 m_windowId = (int)NewControlId();
162
163 int x = pos.x, y = pos.y;
164 int width = size.x, height = size.y;
165
166 // Set reasonable values for position and size if defaults have been
167 // requested
168 //
169 // MB TODO: something better than these arbitrary values ?
170 // VZ should use X resources for this...
171 if ( width == -1 )
172 width = 400;
173 if ( height == -1 )
174 height = 400;
175
176 int displayW, displayH;
177 wxDisplaySize( &displayW, &displayH );
178
179 if ( x == -1 )
180 {
181 x = (displayW - width) / 2;
182 if (x < 10) x = 10;
183 }
184 if ( y == -1 )
185 {
186 y = (displayH - height) / 2;
187 if (y < 10) y = 10;
188 }
189
190 // VZ: what does this do??
191 if (wxTopLevelUsed)
192 {
193 // Change suggested by Matthew Flatt
194 m_frameShell = (WXWidget)XtAppCreateShell
195 (
196 name,
197 wxTheApp->GetClassName(),
198 topLevelShellWidgetClass,
199 (Display*) wxGetDisplay(),
200 NULL,
201 0
202 );
203 }
204 else
205 {
206 m_frameShell = wxTheApp->GetTopLevelWidget();
207 wxTopLevelUsed = TRUE;
208 }
209
210 XtVaSetValues((Widget) m_frameShell,
211 // Allows menu to resize
212 XmNallowShellResize, True,
213 XmNdeleteResponse, XmDO_NOTHING,
214 XmNmappedWhenManaged, False,
215 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
216 NULL);
217
218 if (!title.IsEmpty())
219 XtVaSetValues((Widget) m_frameShell,
220 XmNtitle, title.c_str(),
221 NULL);
222
223 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
224 xmMainWindowWidgetClass, (Widget) m_frameShell,
225 XmNresizePolicy, XmRESIZE_NONE,
226 NULL);
227
228 m_workArea = (WXWidget) XtVaCreateWidget("form",
229 xmFormWidgetClass, (Widget) m_frameWidget,
230 XmNresizePolicy, XmRESIZE_NONE,
231 NULL);
232
233 m_clientArea = (WXWidget) XtVaCreateWidget("client",
234 xmBulletinBoardWidgetClass, (Widget) m_workArea,
235 XmNmarginWidth, 0,
236 XmNmarginHeight, 0,
237 XmNrightAttachment, XmATTACH_FORM,
238 XmNleftAttachment, XmATTACH_FORM,
239 XmNtopAttachment, XmATTACH_FORM,
240 XmNbottomAttachment, XmATTACH_FORM,
241 // XmNresizePolicy, XmRESIZE_ANY,
242 NULL);
243
244 wxLogTrace(wxTRACE_Messages,
245 "Created frame (0x%08x) with work area 0x%08x and client "
246 "area 0x%08x", m_frameWidget, m_workArea, m_clientArea);
247
248 XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE,
249 wxUniversalRepaintProc, (XtPointer) this);
250
251 XtAddEventHandler((Widget) m_clientArea,
252 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask,
253 FALSE,
254 wxFrameEventHandler,
255 (XtPointer)this);
256
257 XtVaSetValues((Widget) m_frameWidget,
258 XmNworkWindow, (Widget) m_workArea,
259 NULL);
260
261 XtManageChild((Widget) m_clientArea);
262 XtManageChild((Widget) m_workArea);
263
264 wxAddWindowToTable((Widget) m_workArea, this);
265 wxAddWindowToTable((Widget) m_clientArea, this);
266
267 XtTranslations ptr;
268
269 XtOverrideTranslations((Widget) m_workArea,
270 ptr = XtParseTranslationTable("<Configure>: resize()"));
271
272 XtFree((char *)ptr);
273
274 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
275 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
276
277 /* Part of show-&-hide fix */
278 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
279 False, (XtEventHandler)wxFrameMapProc,
280 (XtPointer)m_workArea);
281
282 if (x > -1)
283 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
284 if (y > -1)
285 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
286 if (width > -1)
287 XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL);
288 if (height > -1)
289 XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL);
290
291 m_mainWidget = m_frameWidget;
292
293 ChangeFont(FALSE);
294
295 // This patch comes from Torsten Liermann lier@lier1.muc.de
296 if (XmIsMotifWMRunning( (Widget) m_frameShell ))
297 {
298 int decor = 0;
299 if (style & wxRESIZE_BORDER)
300 decor |= MWM_DECOR_RESIZEH;
301 if (style & wxSYSTEM_MENU)
302 decor |= MWM_DECOR_MENU;
303 if ((style & wxCAPTION) ||
304 (style & wxTINY_CAPTION_HORIZ) ||
305 (style & wxTINY_CAPTION_VERT))
306 decor |= MWM_DECOR_TITLE;
307 if (style & wxTHICK_FRAME)
308 decor |= MWM_DECOR_BORDER;
309 if (style & wxMINIMIZE_BOX)
310 decor |= MWM_DECOR_MINIMIZE;
311 if (style & wxMAXIMIZE_BOX)
312 decor |= MWM_DECOR_MAXIMIZE;
313 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL);
314 }
315 // This allows non-Motif window managers to support at least the
316 // no-decorations case.
317 else
318 {
319 if (style == 0)
320 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
321 }
322 XtRealizeWidget((Widget) m_frameShell);
323
324 // Intercept CLOSE messages from the window manager
325 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
326#if (XmREVISION > 1 || XmVERSION > 1)
327 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
328#else
329#if XmREVISION == 1
330 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
331#else
332 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
333#endif
334#endif
335
336 ChangeBackgroundColour();
337
338 PreResize();
339
340 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
341 sizeEvent.SetEventObject(this);
342
343 GetEventHandler()->ProcessEvent(sizeEvent);
344
345 return TRUE;
346}
347
348wxFrame::~wxFrame()
349{
350 m_isBeingDeleted = TRUE;
351
352 if (m_clientArea)
353 {
354 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
355 wxUniversalRepaintProc, (XtPointer) this);
356 XtRemoveEventHandler((Widget) m_clientArea, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask,
357 FALSE,
358 wxFrameEventHandler, (XtPointer) this);
359 wxDeleteWindowFromTable((Widget) m_clientArea);
360 }
361
362 if (GetMainWidget())
363 Show(FALSE);
364
365 if (m_frameMenuBar)
366 {
367 m_frameMenuBar->DestroyMenuBar();
368
369 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
370#if MOTIF_MENUBAR_DELETE_FIX
371 GetMenuBar()->SetMainWidget((WXWidget) NULL);
372#endif
373 delete m_frameMenuBar;
374 m_frameMenuBar = NULL;
375 }
376
377 wxTopLevelWindows.DeleteObject(this);
378 wxModelessWindows.DeleteObject(this);
379
380 if (m_frameStatusBar)
381 {
382 delete m_frameStatusBar;
383 m_frameStatusBar = NULL;
384 }
385
386 if (m_frameToolBar)
387 {
388 delete m_frameToolBar;
389 m_frameToolBar = NULL;
390 }
391
392 DestroyChildren();
393
394 if (m_workArea)
395 {
396 wxDeleteWindowFromTable((Widget) m_workArea);
397
398 XtDestroyWidget ((Widget) m_workArea);
399 }
400
401 // We need to destroy the base class icons here before we stop
402 // the event loop. This is a hack until we have a real top level
403 // window (which would be responsible for killing the event loop).
404 m_icons.m_icons.Empty();
405
406 if (m_frameWidget)
407 {
408 wxDeleteWindowFromTable((Widget) m_frameWidget);
409 XtDestroyWidget ((Widget) m_frameWidget);
410 }
411
412 if (m_frameShell)
413 XtDestroyWidget ((Widget) m_frameShell);
414
415 SetMainWidget((WXWidget) NULL);
416
417 /* Check if it's the last top-level window */
418
419 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
420 {
421 wxTheApp->SetTopWindow(NULL);
422
423 if (wxTheApp->GetExitOnFrameDelete())
424 {
425 // Signal to the app that we're going to close
426 wxTheApp->ExitMainLoop();
427 }
428 }
429}
430
431// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
432void wxFrame::DoGetClientSize(int *x, int *y) const
433{
434 Dimension xx, yy;
435 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
436
437 if (m_frameStatusBar)
438 {
439 int sbw, sbh;
440 m_frameStatusBar->GetSize(& sbw, & sbh);
441 yy -= sbh;
442 }
443#if wxUSE_TOOLBAR
444 if (m_frameToolBar)
445 {
446 int tbw, tbh;
447 m_frameToolBar->GetSize(& tbw, & tbh);
448 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
449 xx -= tbw;
450 else
451 yy -= tbh;
452 }
453#endif // wxUSE_TOOLBAR
454 /*
455 if (GetMenuBar() != (wxMenuBar*) NULL)
456 {
457 // it seems that if a frame holds a panel, the menu bar size
458 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
459 bool hasSubPanel = FALSE;
460 for(wxNode* node = GetChildren().First(); node; node = node->Next())
461 {
462 wxWindow *win = (wxWindow *)node->Data();
463 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
464
465 if (hasSubPanel)
466 break;
467 }
468 if (! hasSubPanel) {
469 Dimension ys;
470 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
471 yy -= ys;
472 }
473 }
474 */
475
476 *x = xx; *y = yy;
477}
478
479// Set the client size (i.e. leave the calculation of borders etc.
480// to wxWindows)
481void wxFrame::DoSetClientSize(int width, int height)
482{
483 // Calculate how large the new main window should be
484 // by finding the difference between the client area and the
485 // main window area, and adding on to the new client area
486 if (width > -1)
487 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
488
489 if (height > -1)
490 {
491 if (m_frameStatusBar)
492 {
493 int sbw, sbh;
494 m_frameStatusBar->GetSize(& sbw, & sbh);
495 height += sbh;
496 }
497#if wxUSE_TOOLBAR
498 if (m_frameToolBar)
499 {
500 int tbw, tbh;
501 m_frameToolBar->GetSize(& tbw, & tbh);
502 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
503 width += tbw;
504 else
505 height += tbh;
506 }
507#endif // wxUSE_TOOLBAR
508
509 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
510 }
511 PreResize();
512
513 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
514 sizeEvent.SetEventObject(this);
515
516 GetEventHandler()->ProcessEvent(sizeEvent);
517
518}
519
520void wxFrame::DoGetSize(int *width, int *height) const
521{
522 Dimension xx, yy;
523 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
524 *width = xx; *height = yy;
525}
526
527void wxFrame::DoGetPosition(int *x, int *y) const
528{
529 Window parent_window = XtWindow((Widget) m_frameShell),
530 next_parent = XtWindow((Widget) m_frameShell),
531 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
532
533 // search for the parent that is child of ROOT, because the WM may
534 // reparent twice and notify only the next parent (like FVWM)
535 while (next_parent != root) {
536 Window *theChildren; unsigned int n;
537 parent_window = next_parent;
538 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
539 &next_parent, &theChildren, &n);
540 XFree(theChildren); // not needed
541 }
542 int xx, yy; unsigned int dummy;
543 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
544 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
545 if (x) *x = xx;
546 if (y) *y = yy;
547}
548
549void wxFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags))
550{
551 if (x > -1)
552 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
553 if (y > -1)
554 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
555 if (width > -1)
556 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
557 if (height > -1)
558 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
559
560 if (!(height == -1 && width == -1))
561 {
562 PreResize();
563
564 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
565 sizeEvent.SetEventObject(this);
566
567 GetEventHandler()->ProcessEvent(sizeEvent);
568 }
569}
570
571bool wxFrame::Show(bool show)
572{
573 if (!m_frameShell)
574 return wxWindow::Show(show);
575
576 m_visibleStatus = show; /* show-&-hide fix */
577
578 m_isShown = show;
579 if (show) {
580 XtMapWidget((Widget) m_frameShell);
581 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
582 } else {
583 XtUnmapWidget((Widget) m_frameShell);
584 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
585 }
586 return TRUE;
587}
588
589void wxFrame::Iconize(bool iconize)
590{
591 if (!iconize)
592 Show(TRUE);
593
594 if (m_frameShell)
595 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
596}
597
598void wxFrame::Restore()
599{
600 if ( m_frameShell )
601 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
602}
603
604void wxFrame::Maximize(bool maximize)
605{
606 Show(TRUE);
607
608 if ( maximize )
609 Restore();
610}
611
612bool wxFrame::IsIconized() const
613{
614 if (!m_frameShell)
615 return FALSE;
616
617 Boolean iconic;
618 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
619 return iconic;
620}
621
622// Is it maximized?
623bool wxFrame::IsMaximized() const
624{
625 // No maximizing in Motif (?)
626 return FALSE;
627}
628
629void wxFrame::SetTitle(const wxString& title)
630{
631 if (title == m_title)
632 return;
633
634 m_title = title;
635
636 if (!title.IsNull())
637 XtVaSetValues((Widget) m_frameShell,
638 XmNtitle, title.c_str(),
639 XmNiconName, title.c_str(),
640 NULL);
641}
642
643void wxFrame::DoSetIcon(const wxIcon& icon)
644{
645 if (!m_frameShell)
646 return;
647
648 if (!icon.Ok() || !icon.GetPixmap())
649 return;
650
651 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
652}
653
654void wxFrame::SetIcon(const wxIcon& icon)
655{
656 SetIcons( wxIconBundle( icon ) );
657}
658
659void wxFrame::SetIcons(const wxIconBundle& icons)
660{
661 wxFrameBase::SetIcons( icons );
662
663 if (!m_frameShell)
664 return;
665
666 DoSetIcon( m_icons.GetIcon( -1 ) );
667 wxSetIconsX11(GetXDisplay(),
668 (WXWindow) XtWindow( (Widget) m_frameShell ), icons);
669}
670
671void wxFrame::PositionStatusBar()
672{
673 if (!m_frameStatusBar)
674 return;
675
676 int w, h;
677 GetClientSize(&w, &h);
678 int sw, sh;
679 m_frameStatusBar->GetSize(&sw, &sh);
680
681 // Since we wish the status bar to be directly under the client area,
682 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
683 m_frameStatusBar->SetSize(0, h, w, sh);
684}
685
686WXWidget wxFrame::GetMenuBarWidget() const
687{
688 if (GetMenuBar())
689 return GetMenuBar()->GetMainWidget();
690 else
691 return (WXWidget) NULL;
692}
693
694void wxFrame::SetMenuBar(wxMenuBar *menuBar)
695{
696 if (!menuBar)
697 {
698 m_frameMenuBar = NULL;
699 return;
700 }
701
702 // Currently can't set it twice
703 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
704
705 if (m_frameMenuBar)
706 {
707 m_frameMenuBar->DestroyMenuBar();
708 delete m_frameMenuBar;
709 }
710
711 m_frameMenuBar = menuBar;
712 m_frameMenuBar->CreateMenuBar(this);
713}
714
715// Responds to colour changes, and passes event on to children.
716void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
717{
718 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
719 Refresh();
720
721 if ( m_frameStatusBar )
722 {
723 wxSysColourChangedEvent event2;
724 event2.SetEventObject( m_frameStatusBar );
725 m_frameStatusBar->ProcessEvent(event2);
726 }
727
728 // Propagate the event to the non-top-level children
729 wxWindow::OnSysColourChanged(event);
730}
731
732// Default activation behaviour - set the focus for the first child
733// subwindow found.
734void wxFrame::OnActivate(wxActivateEvent& event)
735{
736 if (!event.GetActive())
737 return;
738
739 for(wxNode *node = GetChildren().First(); node; node = node->Next())
740 {
741 // Find a child that's a subwindow, but not a dialog box.
742 wxWindow *child = (wxWindow *)node->Data();
743 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
744 !child->IsKindOf(CLASSINFO(wxDialog)))
745 {
746 child->SetFocus();
747 return;
748 }
749 }
750}
751
752#if wxUSE_TOOLBAR
753
754wxToolBar* wxFrame::CreateToolBar(long style,
755 wxWindowID id,
756 const wxString& name)
757{
758 if ( wxFrameBase::CreateToolBar(style, id, name) )
759 {
760 PositionToolBar();
761 }
762
763 return m_frameToolBar;
764}
765
766void wxFrame::PositionToolBar()
767{
768 if (GetToolBar())
769 {
770 int cw, ch;
771 GetClientSize(& cw, &ch);
772
773 int tw, th;
774 GetToolBar()->GetSize(& tw, & th);
775
776 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
777 {
778 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
779 // means, pretend we don't have toolbar/status bar, so we
780 // have the original client size.
781 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
782 }
783 else
784 {
785 // Use the 'real' position
786 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
787 }
788 }
789}
790#endif // wxUSE_TOOLBAR
791
792void wxFrame::Raise()
793{
794 Window parent_window = XtWindow((Widget) m_frameShell),
795 next_parent = XtWindow((Widget) m_frameShell),
796 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
797 // search for the parent that is child of ROOT, because the WM may
798 // reparent twice and notify only the next parent (like FVWM)
799 while (next_parent != root) {
800 Window *theChildren; unsigned int n;
801 parent_window = next_parent;
802 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
803 &next_parent, &theChildren, &n);
804 XFree(theChildren); // not needed
805 }
806 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
807}
808
809void wxFrame::Lower()
810{
811 Window parent_window = XtWindow((Widget) m_frameShell),
812 next_parent = XtWindow((Widget) m_frameShell),
813 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
814 // search for the parent that is child of ROOT, because the WM may
815 // reparent twice and notify only the next parent (like FVWM)
816 while (next_parent != root) {
817 Window *theChildren; unsigned int n;
818 parent_window = next_parent;
819 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
820 &next_parent, &theChildren, &n);
821 XFree(theChildren); // not needed
822 }
823 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
824}
825
826void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData),
827 XmAnyCallbackStruct *WXUNUSED(cbs))
828{
829 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
830 // TODO
831 // wxFrame *frame = (wxFrame *)clientData;
832 // frame->GetEventHandler()->OnSetFocus();
833}
834
835/* MATTEW: Used to insure that hide-&-show within an event cycle works */
836static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
837 XCrossingEvent * event)
838{
839 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
840
841 if (frame) {
842 XEvent *e = (XEvent *)event;
843
844 if (e->xany.type == MapNotify)
845 {
846 // Iconize fix
847 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
848 if (!frame->GetVisibleStatus())
849 {
850 /* We really wanted this to be hidden! */
851 XtUnmapWidget((Widget) frame->GetShellWidget());
852 }
853 }
854 else if (e->xany.type == UnmapNotify)
855 // Iconize fix
856 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
857 }
858}
859
860//// Motif-specific
861bool wxFrame::PreResize()
862{
863#if wxUSE_TOOLBAR
864 PositionToolBar();
865#endif // wxUSE_TOOLBAR
866
867#if wxUSE_STATUSBAR
868 PositionStatusBar();
869#endif // wxUSE_STATUSBAR
870
871 return TRUE;
872}
873
874WXWidget wxFrame::GetClientWidget() const
875{
876 return m_clientArea;
877}
878
879void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize))
880{
881 // TODO
882}
883
884void wxFrame::ChangeBackgroundColour()
885{
886 if (GetClientWidget())
887 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
888}
889
890void wxFrame::ChangeForegroundColour()
891{
892 if (GetClientWidget())
893 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
894}
895
896void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs))
897{
898 wxFrame *frame = (wxFrame *)client_data;
899
900 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
901 closeEvent.SetEventObject(frame);
902
903 // May delete the frame (with delayed deletion)
904 frame->GetEventHandler()->ProcessEvent(closeEvent);
905}
906
907static void wxFrameEventHandler(Widget wid,
908 XtPointer WXUNUSED(client_data),
909 XEvent* event,
910 Boolean* continueToDispatch)
911{
912 wxFrame *frame = (wxFrame *)wxGetWindowFromTable(wid);
913 if (frame)
914 {
915 wxMouseEvent wxevent(wxEVT_NULL);
916 if (wxTranslateMouseEvent(wxevent, frame, wid, event))
917 {
918 wxevent.SetEventObject(frame);
919 wxevent.SetId(frame->GetId());
920 frame->GetEventHandler()->ProcessEvent(wxevent);
921 }
922 else
923 {
924 // An attempt to implement OnCharHook by calling OnCharHook first;
925 // if this returns TRUE, set continueToDispatch to False
926 // (don't continue processing).
927 // Otherwise set it to True and call OnChar.
928 wxKeyEvent keyEvent(wxEVT_CHAR);
929 if (wxTranslateKeyEvent(keyEvent, frame, wid, event))
930 {
931 keyEvent.SetEventObject(frame);
932 keyEvent.SetId(frame->GetId());
933 keyEvent.SetEventType(wxEVT_CHAR_HOOK);
934 if (frame->GetEventHandler()->ProcessEvent(keyEvent))
935 {
936 *continueToDispatch = False;
937 return;
938 }
939 else
940 {
941 // For simplicity, OnKeyDown is the same as OnChar
942 // TODO: filter modifier key presses from OnChar
943 keyEvent.SetEventType(wxEVT_KEY_DOWN);
944
945 // Only process OnChar if OnKeyDown didn't swallow it
946 if (!frame->GetEventHandler()->ProcessEvent (keyEvent))
947 {
948 keyEvent.SetEventType(wxEVT_CHAR);
949 frame->GetEventHandler()->ProcessEvent(keyEvent);
950 }
951 }
952 }
953 }
954 }
955 *continueToDispatch = True;
956}