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