]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/frame.cpp
fix for GetParent() in wxTR_HIDE_ROOT case
[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#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
81static void wxFrameEventHandler(Widget wid,
82 XtPointer WXUNUSED(client_data),
83 XEvent* event,
84 Boolean* continueToDispatch);
85static void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
86static void wxFrameFocusProc(Widget workArea, XtPointer clientData,
87 XmAnyCallbackStruct *cbs);
88static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
89 XCrossingEvent * event);
90
91// ----------------------------------------------------------------------------
92// globals
93// ----------------------------------------------------------------------------
94
95extern wxList wxModelessWindows;
96extern wxList wxPendingDelete;
97
98// TODO: this should be tidied so that any frame can be the
99// top frame
100static bool wxTopLevelUsed = FALSE;
101
102// ----------------------------------------------------------------------------
103// wxWin macros
104// ----------------------------------------------------------------------------
105
106BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
107 EVT_ACTIVATE(wxFrame::OnActivate)
108 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
109END_EVENT_TABLE()
110
111IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
112
113// ============================================================================
114// implementation
115// ============================================================================
116
117// ----------------------------------------------------------------------------
118// frame construction
119// ----------------------------------------------------------------------------
120
121void 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
133bool 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
346wxFrame::~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.
419void 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)
468void 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
507void 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
514void 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
536void 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
558bool 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
576void 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
585void wxFrame::Restore()
586{
587 if ( m_frameShell )
588 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
589}
590
591void wxFrame::Maximize(bool maximize)
592{
593 Show(TRUE);
594
595 if ( maximize )
596 Restore();
597}
598
599bool 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?
610bool wxFrame::IsMaximized() const
611{
612 // No maximizing in Motif (?)
613 return FALSE;
614}
615
616void 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
630void 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
643void 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
658WXWidget wxFrame::GetMenuBarWidget() const
659{
660 if (GetMenuBar())
661 return GetMenuBar()->GetMainWidget();
662 else
663 return (WXWidget) NULL;
664}
665
666void 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.
688void 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.
706void 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
726wxToolBar* 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
738void 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
764void 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
781void 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
798void 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 */
808static 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
833bool 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
846WXWidget wxFrame::GetClientWidget() const
847{
848 return m_clientArea;
849}
850
851void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize))
852{
853 // TODO
854}
855
856void wxFrame::ChangeBackgroundColour()
857{
858 if (GetClientWidget())
859 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
860}
861
862void wxFrame::ChangeForegroundColour()
863{
864 if (GetClientWidget())
865 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
866}
867
868void 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
879static 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}