]> git.saurik.com Git - wxWidgets.git/blob - src/motif/frame.cpp
refresh and flicker even more to ensure proper refresh in the resizeable dialogs
[wxWidgets.git] / src / motif / frame.cpp
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
83 static void wxFrameEventHandler(Widget wid,
84 XtPointer WXUNUSED(client_data),
85 XEvent* event,
86 Boolean* continueToDispatch);
87 static void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
88 static void wxFrameFocusProc(Widget workArea, XtPointer clientData,
89 XmAnyCallbackStruct *cbs);
90 static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
91 XCrossingEvent * event);
92
93 // ----------------------------------------------------------------------------
94 // globals
95 // ----------------------------------------------------------------------------
96
97 extern wxList wxModelessWindows;
98 extern wxList wxPendingDelete;
99
100 // TODO: this should be tidied so that any frame can be the
101 // top frame
102 static bool wxTopLevelUsed = FALSE;
103
104 // ----------------------------------------------------------------------------
105 // wxWin macros
106 // ----------------------------------------------------------------------------
107
108 BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
109 EVT_ACTIVATE(wxFrame::OnActivate)
110 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
111 END_EVENT_TABLE()
112
113 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
114
115 // ============================================================================
116 // implementation
117 // ============================================================================
118
119 // ----------------------------------------------------------------------------
120 // frame construction
121 // ----------------------------------------------------------------------------
122
123 void 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
135 bool 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
348 wxFrame::~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 DestroyChildren();
387
388 if (m_workArea)
389 {
390 wxDeleteWindowFromTable((Widget) m_workArea);
391
392 XtDestroyWidget ((Widget) m_workArea);
393 }
394
395 if (m_frameWidget)
396 {
397 wxDeleteWindowFromTable((Widget) m_frameWidget);
398 XtDestroyWidget ((Widget) m_frameWidget);
399 }
400
401 if (m_frameShell)
402 XtDestroyWidget ((Widget) m_frameShell);
403
404 SetMainWidget((WXWidget) NULL);
405
406 /* Check if it's the last top-level window */
407
408 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
409 {
410 wxTheApp->SetTopWindow(NULL);
411
412 if (wxTheApp->GetExitOnFrameDelete())
413 {
414 // Signal to the app that we're going to close
415 wxTheApp->ExitMainLoop();
416 }
417 }
418 }
419
420 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
421 void wxFrame::DoGetClientSize(int *x, int *y) const
422 {
423 Dimension xx, yy;
424 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
425
426 if (m_frameStatusBar)
427 {
428 int sbw, sbh;
429 m_frameStatusBar->GetSize(& sbw, & sbh);
430 yy -= sbh;
431 }
432 #if wxUSE_TOOLBAR
433 if (m_frameToolBar)
434 {
435 int tbw, tbh;
436 m_frameToolBar->GetSize(& tbw, & tbh);
437 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
438 xx -= tbw;
439 else
440 yy -= tbh;
441 }
442 #endif // wxUSE_TOOLBAR
443 /*
444 if (GetMenuBar() != (wxMenuBar*) NULL)
445 {
446 // it seems that if a frame holds a panel, the menu bar size
447 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
448 bool hasSubPanel = FALSE;
449 for(wxNode* node = GetChildren().First(); node; node = node->Next())
450 {
451 wxWindow *win = (wxWindow *)node->Data();
452 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
453
454 if (hasSubPanel)
455 break;
456 }
457 if (! hasSubPanel) {
458 Dimension ys;
459 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
460 yy -= ys;
461 }
462 }
463 */
464
465 *x = xx; *y = yy;
466 }
467
468 // Set the client size (i.e. leave the calculation of borders etc.
469 // to wxWindows)
470 void wxFrame::DoSetClientSize(int width, int height)
471 {
472 // Calculate how large the new main window should be
473 // by finding the difference between the client area and the
474 // main window area, and adding on to the new client area
475 if (width > -1)
476 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
477
478 if (height > -1)
479 {
480 if (m_frameStatusBar)
481 {
482 int sbw, sbh;
483 m_frameStatusBar->GetSize(& sbw, & sbh);
484 height += sbh;
485 }
486 #if wxUSE_TOOLBAR
487 if (m_frameToolBar)
488 {
489 int tbw, tbh;
490 m_frameToolBar->GetSize(& tbw, & tbh);
491 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
492 width += tbw;
493 else
494 height += tbh;
495 }
496 #endif // wxUSE_TOOLBAR
497
498 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
499 }
500 PreResize();
501
502 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
503 sizeEvent.SetEventObject(this);
504
505 GetEventHandler()->ProcessEvent(sizeEvent);
506
507 }
508
509 void wxFrame::DoGetSize(int *width, int *height) const
510 {
511 Dimension xx, yy;
512 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
513 *width = xx; *height = yy;
514 }
515
516 void wxFrame::DoGetPosition(int *x, int *y) const
517 {
518 Window parent_window = XtWindow((Widget) m_frameShell),
519 next_parent = XtWindow((Widget) m_frameShell),
520 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
521
522 // search for the parent that is child of ROOT, because the WM may
523 // reparent twice and notify only the next parent (like FVWM)
524 while (next_parent != root) {
525 Window *theChildren; unsigned int n;
526 parent_window = next_parent;
527 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
528 &next_parent, &theChildren, &n);
529 XFree(theChildren); // not needed
530 }
531 int xx, yy; unsigned int dummy;
532 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
533 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
534 if (x) *x = xx;
535 if (y) *y = yy;
536 }
537
538 void wxFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags))
539 {
540 if (x > -1)
541 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
542 if (y > -1)
543 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
544 if (width > -1)
545 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
546 if (height > -1)
547 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
548
549 if (!(height == -1 && width == -1))
550 {
551 PreResize();
552
553 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
554 sizeEvent.SetEventObject(this);
555
556 GetEventHandler()->ProcessEvent(sizeEvent);
557 }
558 }
559
560 bool wxFrame::Show(bool show)
561 {
562 if (!m_frameShell)
563 return wxWindow::Show(show);
564
565 m_visibleStatus = show; /* show-&-hide fix */
566
567 m_isShown = show;
568 if (show) {
569 XtMapWidget((Widget) m_frameShell);
570 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
571 } else {
572 XtUnmapWidget((Widget) m_frameShell);
573 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
574 }
575 return TRUE;
576 }
577
578 void wxFrame::Iconize(bool iconize)
579 {
580 if (!iconize)
581 Show(TRUE);
582
583 if (m_frameShell)
584 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
585 }
586
587 void wxFrame::Restore()
588 {
589 if ( m_frameShell )
590 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
591 }
592
593 void wxFrame::Maximize(bool maximize)
594 {
595 Show(TRUE);
596
597 if ( maximize )
598 Restore();
599 }
600
601 bool wxFrame::IsIconized() const
602 {
603 if (!m_frameShell)
604 return FALSE;
605
606 Boolean iconic;
607 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
608 return iconic;
609 }
610
611 // Is it maximized?
612 bool wxFrame::IsMaximized() const
613 {
614 // No maximizing in Motif (?)
615 return FALSE;
616 }
617
618 void wxFrame::SetTitle(const wxString& title)
619 {
620 if (title == m_title)
621 return;
622
623 m_title = title;
624
625 if (!title.IsNull())
626 XtVaSetValues((Widget) m_frameShell,
627 XmNtitle, title.c_str(),
628 XmNiconName, title.c_str(),
629 NULL);
630 }
631
632 void wxFrame::DoSetIcon(const wxIcon& icon)
633 {
634 if (!m_frameShell)
635 return;
636
637 if (!icon.Ok() || !icon.GetPixmap())
638 return;
639
640 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
641 }
642
643 void wxFrame::SetIcon(const wxIcon& icon)
644 {
645 SetIcons( wxIconBundle( icon ) );
646 }
647
648 void wxFrame::SetIcons(const wxIconBundle& icons)
649 {
650 wxFrameBase::SetIcons( icons );
651
652 if (!m_frameShell)
653 return;
654
655 DoSetIcon( m_icons.GetIcon( -1 ) );
656 wxSetIconsX11(GetXDisplay(),
657 (WXWindow) XtWindow( (Widget) m_frameShell ), icons);
658 }
659
660 void wxFrame::PositionStatusBar()
661 {
662 if (!m_frameStatusBar)
663 return;
664
665 int w, h;
666 GetClientSize(&w, &h);
667 int sw, sh;
668 m_frameStatusBar->GetSize(&sw, &sh);
669
670 // Since we wish the status bar to be directly under the client area,
671 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
672 m_frameStatusBar->SetSize(0, h, w, sh);
673 }
674
675 WXWidget wxFrame::GetMenuBarWidget() const
676 {
677 if (GetMenuBar())
678 return GetMenuBar()->GetMainWidget();
679 else
680 return (WXWidget) NULL;
681 }
682
683 void wxFrame::SetMenuBar(wxMenuBar *menuBar)
684 {
685 if (!menuBar)
686 {
687 m_frameMenuBar = NULL;
688 return;
689 }
690
691 // Currently can't set it twice
692 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
693
694 if (m_frameMenuBar)
695 {
696 m_frameMenuBar->DestroyMenuBar();
697 delete m_frameMenuBar;
698 }
699
700 m_frameMenuBar = menuBar;
701 m_frameMenuBar->CreateMenuBar(this);
702 }
703
704 // Responds to colour changes, and passes event on to children.
705 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
706 {
707 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
708 Refresh();
709
710 if ( m_frameStatusBar )
711 {
712 wxSysColourChangedEvent event2;
713 event2.SetEventObject( m_frameStatusBar );
714 m_frameStatusBar->ProcessEvent(event2);
715 }
716
717 // Propagate the event to the non-top-level children
718 wxWindow::OnSysColourChanged(event);
719 }
720
721 // Default activation behaviour - set the focus for the first child
722 // subwindow found.
723 void wxFrame::OnActivate(wxActivateEvent& event)
724 {
725 if (!event.GetActive())
726 return;
727
728 for(wxNode *node = GetChildren().First(); node; node = node->Next())
729 {
730 // Find a child that's a subwindow, but not a dialog box.
731 wxWindow *child = (wxWindow *)node->Data();
732 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
733 !child->IsKindOf(CLASSINFO(wxDialog)))
734 {
735 child->SetFocus();
736 return;
737 }
738 }
739 }
740
741 #if wxUSE_TOOLBAR
742
743 wxToolBar* wxFrame::CreateToolBar(long style,
744 wxWindowID id,
745 const wxString& name)
746 {
747 if ( wxFrameBase::CreateToolBar(style, id, name) )
748 {
749 PositionToolBar();
750 }
751
752 return m_frameToolBar;
753 }
754
755 void wxFrame::PositionToolBar()
756 {
757 if (GetToolBar())
758 {
759 int cw, ch;
760 GetClientSize(& cw, &ch);
761
762 int tw, th;
763 GetToolBar()->GetSize(& tw, & th);
764
765 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
766 {
767 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
768 // means, pretend we don't have toolbar/status bar, so we
769 // have the original client size.
770 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
771 }
772 else
773 {
774 // Use the 'real' position
775 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
776 }
777 }
778 }
779 #endif // wxUSE_TOOLBAR
780
781 void wxFrame::Raise()
782 {
783 Window parent_window = XtWindow((Widget) m_frameShell),
784 next_parent = XtWindow((Widget) m_frameShell),
785 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
786 // search for the parent that is child of ROOT, because the WM may
787 // reparent twice and notify only the next parent (like FVWM)
788 while (next_parent != root) {
789 Window *theChildren; unsigned int n;
790 parent_window = next_parent;
791 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
792 &next_parent, &theChildren, &n);
793 XFree(theChildren); // not needed
794 }
795 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
796 }
797
798 void wxFrame::Lower()
799 {
800 Window parent_window = XtWindow((Widget) m_frameShell),
801 next_parent = XtWindow((Widget) m_frameShell),
802 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
803 // search for the parent that is child of ROOT, because the WM may
804 // reparent twice and notify only the next parent (like FVWM)
805 while (next_parent != root) {
806 Window *theChildren; unsigned int n;
807 parent_window = next_parent;
808 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
809 &next_parent, &theChildren, &n);
810 XFree(theChildren); // not needed
811 }
812 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
813 }
814
815 void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData),
816 XmAnyCallbackStruct *WXUNUSED(cbs))
817 {
818 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
819 // TODO
820 // wxFrame *frame = (wxFrame *)clientData;
821 // frame->GetEventHandler()->OnSetFocus();
822 }
823
824 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
825 static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
826 XCrossingEvent * event)
827 {
828 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
829
830 if (frame) {
831 XEvent *e = (XEvent *)event;
832
833 if (e->xany.type == MapNotify)
834 {
835 // Iconize fix
836 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
837 if (!frame->GetVisibleStatus())
838 {
839 /* We really wanted this to be hidden! */
840 XtUnmapWidget((Widget) frame->GetShellWidget());
841 }
842 }
843 else if (e->xany.type == UnmapNotify)
844 // Iconize fix
845 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
846 }
847 }
848
849 //// Motif-specific
850 bool wxFrame::PreResize()
851 {
852 #if wxUSE_TOOLBAR
853 PositionToolBar();
854 #endif // wxUSE_TOOLBAR
855
856 #if wxUSE_STATUSBAR
857 PositionStatusBar();
858 #endif // wxUSE_STATUSBAR
859
860 return TRUE;
861 }
862
863 WXWidget wxFrame::GetClientWidget() const
864 {
865 return m_clientArea;
866 }
867
868 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize))
869 {
870 // TODO
871 }
872
873 void wxFrame::ChangeBackgroundColour()
874 {
875 if (GetClientWidget())
876 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
877 }
878
879 void wxFrame::ChangeForegroundColour()
880 {
881 if (GetClientWidget())
882 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
883 }
884
885 void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs))
886 {
887 wxFrame *frame = (wxFrame *)client_data;
888
889 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
890 closeEvent.SetEventObject(frame);
891
892 // May delete the frame (with delayed deletion)
893 frame->GetEventHandler()->ProcessEvent(closeEvent);
894 }
895
896 static void wxFrameEventHandler(Widget wid,
897 XtPointer WXUNUSED(client_data),
898 XEvent* event,
899 Boolean* continueToDispatch)
900 {
901 wxFrame *frame = (wxFrame *)wxGetWindowFromTable(wid);
902 if (frame)
903 {
904 wxMouseEvent wxevent(wxEVT_NULL);
905 if (wxTranslateMouseEvent(wxevent, frame, wid, event))
906 {
907 wxevent.SetEventObject(frame);
908 wxevent.SetId(frame->GetId());
909 frame->GetEventHandler()->ProcessEvent(wxevent);
910 }
911 else
912 {
913 // An attempt to implement OnCharHook by calling OnCharHook first;
914 // if this returns TRUE, set continueToDispatch to False
915 // (don't continue processing).
916 // Otherwise set it to True and call OnChar.
917 wxKeyEvent keyEvent(wxEVT_CHAR);
918 if (wxTranslateKeyEvent(keyEvent, frame, wid, event))
919 {
920 keyEvent.SetEventObject(frame);
921 keyEvent.SetId(frame->GetId());
922 keyEvent.SetEventType(wxEVT_CHAR_HOOK);
923 if (frame->GetEventHandler()->ProcessEvent(keyEvent))
924 {
925 *continueToDispatch = False;
926 return;
927 }
928 else
929 {
930 // For simplicity, OnKeyDown is the same as OnChar
931 // TODO: filter modifier key presses from OnChar
932 keyEvent.SetEventType(wxEVT_KEY_DOWN);
933
934 // Only process OnChar if OnKeyDown didn't swallow it
935 if (!frame->GetEventHandler()->ProcessEvent (keyEvent))
936 {
937 keyEvent.SetEventType(wxEVT_CHAR);
938 frame->GetEventHandler()->ProcessEvent(keyEvent);
939 }
940 }
941 }
942 }
943 }
944 *continueToDispatch = True;
945 }