X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/83df96d63a52ebb08b9e32549dc255354b4a18d0..cd560c961a09a8ae80b9c32856e195ed784cc547:/src/x11/toplevel.cpp diff --git a/src/x11/toplevel.cpp b/src/x11/toplevel.cpp index 14b660afe3..d191faf6f1 100644 --- a/src/x11/toplevel.cpp +++ b/src/x11/toplevel.cpp @@ -1,13 +1,13 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: motif/frame.cpp -// Purpose: wxFrame +/////////////////////////////////////////////////////////////////////////////// +// Name: x11/toplevel.cpp +// Purpose: implements wxTopLevelWindow for X11 // Author: Julian Smart // Modified by: -// Created: 17/09/98 +// Created: 24.09.01 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// +// Copyright: (c) 2002 Julian Smart +// License: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations @@ -18,394 +18,202 @@ // ---------------------------------------------------------------------------- #ifdef __GNUG__ - #pragma implementation "frame.h" + #pragma implementation "toplevel.h" #endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" -#ifdef __VMS -#define XtDisplay XTDISPLAY -#define XtWindow XTWINDOW -#define XtScreen XTSCREEN +#ifdef __BORLANDC__ + #pragma hdrstop #endif -# include "wx/frame.h" -#include "wx/statusbr.h" -#include "wx/toolbar.h" -#include "wx/menuitem.h" -#include "wx/menu.h" -#include "wx/dcclient.h" -#include "wx/dialog.h" -#include "wx/settings.h" -#include "wx/app.h" -#include "wx/utils.h" -#include "wx/log.h" - -#ifdef __VMS__ - #pragma message disable nosimpint -#endif - -#if defined(__ultrix) || defined(__sgi) - #include <Xm/Frame.h> -#endif - -#include <Xm/Xm.h> -#include <X11/Shell.h> -#if XmVersion >= 1002 - #include <Xm/XmAll.h> -#else - #include <Xm/Frame.h> -#endif -#include <Xm/MwmUtil.h> -#include <Xm/BulletinB.h> -#include <Xm/Form.h> -#include <Xm/MainW.h> -#include <Xm/RowColumn.h> -#include <Xm/Label.h> -#include <Xm/AtomMgr.h> -#include <Xm/LabelG.h> -#include <Xm/Frame.h> -#if XmVersion > 1000 - #include <Xm/Protocols.h> -#endif - -#ifdef __VMS__ - #pragma message enable nosimpint -#endif - -#include "wx/motif/private.h" - -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- - -static void wxFrameEventHandler(Widget wid, - XtPointer WXUNUSED(client_data), - XEvent* event, - Boolean* continueToDispatch); -static void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs); -static void wxFrameFocusProc(Widget workArea, XtPointer clientData, - XmAnyCallbackStruct *cbs); -static void wxFrameMapProc(Widget frameShell, XtPointer clientData, - XCrossingEvent * event); +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/toplevel.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/intl.h" + #include "wx/frame.h" + #include "wx/menu.h" + #include "wx/statusbr.h" +#endif //WX_PRECOMP -// ---------------------------------------------------------------------------- -// globals -// ---------------------------------------------------------------------------- - -extern wxList wxModelessWindows; -extern wxList wxPendingDelete; +#include "wx/settings.h" +#include "wx/x11/private.h" +#include "X11/Xutil.h" -// TODO: this should be tidied so that any frame can be the -// top frame -static bool wxTopLevelUsed = FALSE; +bool wxMWMIsRunning(Window w); // ---------------------------------------------------------------------------- -// wxWin macros +// wxTopLevelWindowX11 creation // ---------------------------------------------------------------------------- -BEGIN_EVENT_TABLE(wxFrame, wxFrameBase) - EVT_ACTIVATE(wxFrame::OnActivate) - EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged) -END_EVENT_TABLE() - -IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow) - -// ============================================================================ -// implementation -// ============================================================================ +void wxTopLevelWindowX11::Init() +{ + m_iconized = + m_maximizeOnShow = FALSE; -// ---------------------------------------------------------------------------- -// frame construction -// ---------------------------------------------------------------------------- + // unlike (almost?) all other windows, frames are created hidden + m_isShown = FALSE; -void wxFrame::Init() -{ - m_iconized = FALSE; - - //// Motif-specific - m_frameShell = (WXWidget) NULL; - m_frameWidget = (WXWidget) NULL;; - m_workArea = (WXWidget) NULL;; - m_clientArea = (WXWidget) NULL;; - m_visibleStatus = TRUE; + // Data to save/restore when calling ShowFullScreen + m_fsStyle = 0; + m_fsIsMaximized = FALSE; + m_fsIsShowing = FALSE; + + m_focusWidget = NULL; } -bool wxFrame::Create(wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) +bool wxTopLevelWindowX11::Create(wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) { - if ( parent ) - parent->AddChild(this); - else - wxTopLevelWindows.Append(this); + // init our fields + Init(); - wxModelessWindows.Append(this); + m_windowStyle = style; + m_parent = parent; SetName(name); - m_windowStyle = style; + m_windowId = id == -1 ? NewControlId() : id; - m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE); - m_foregroundColour = *wxBLACK; - m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + if (parent) + parent->AddChild(this); - if ( id > -1 ) - m_windowId = id; + wxTopLevelWindows.Append(this); + + Display *xdisplay = wxGlobalDisplay(); + int xscreen = DefaultScreen( xdisplay ); + Visual *xvisual = DefaultVisual( xdisplay, xscreen ); + Window xparent = RootWindow( xdisplay, xscreen ); + Colormap cm = DefaultColormap( xdisplay, xscreen ); + + if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); else - m_windowId = (int)NewControlId(); - - int x = pos.x, y = pos.y; - int width = size.x, height = size.y; - - // Set reasonable values for position and size if defaults have been - // requested - // - // MB TODO: something better than these arbitrary values ? - // VZ should use X resources for this... - if ( width == -1 ) - width = 400; - if ( height == -1 ) - height = 400; - - int displayW, displayH; - wxDisplaySize( &displayW, &displayH ); - - if ( x == -1 ) - { - x = (displayW - width) / 2; - if (x < 10) x = 10; - } - if ( y == -1 ) - { - y = (displayH - height) / 2; - if (y < 10) y = 10; - } + m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE); + m_backgroundColour.CalcPixel( (WXColormap) cm ); + m_hasBgCol = TRUE; + + wxSize size2(size); + if (size2.x == -1) + size2.x = 100; + if (size2.y == -1) + size2.y = 100; + + wxPoint pos2(pos); + if (pos2.x == -1) + pos2.x = 100; + if (pos2.y == -1) + pos2.y = 100; + +#if !wxUSE_NANOX + XSetWindowAttributes xattributes; + XSizeHints size_hints; + + long xattributes_mask = + CWOverrideRedirect | + CWBorderPixel | CWBackPixel; + + xattributes.background_pixel = m_backgroundColour.GetPixel(); + xattributes.border_pixel = BlackPixel( xdisplay, xscreen ); + + // TODO: if we want no border, caption etc., + // I think we set this to True to remove decorations + // No. RR. + xattributes.override_redirect = False; +#endif + +#if wxUSE_NANOX + long backColor, foreColor; + backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue()); + foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue()); + + Window xwindow = XCreateWindowWithColor( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, + 0, 0, InputOutput, xvisual, backColor, foreColor); +#else + Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, + 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes ); +#endif + m_mainWidget = (WXWindow) xwindow; - // VZ: what does this do?? - if (wxTopLevelUsed) - { - // Change suggested by Matthew Flatt - m_frameShell = (WXWidget)XtAppCreateShell - ( - name, - wxTheApp->GetClassName(), - topLevelShellWidgetClass, - (Display*) wxGetDisplay(), - NULL, - 0 - ); - } - else - { - m_frameShell = wxTheApp->GetTopLevelWidget(); - wxTopLevelUsed = TRUE; - } + int extraFlags = 0; +#if wxUSE_NANOX + extraFlags |= GR_EVENT_MASK_CLOSE_REQ; +#endif - XtVaSetValues((Widget) m_frameShell, - // Allows menu to resize - XmNallowShellResize, True, - XmNdeleteResponse, XmDO_NOTHING, - XmNmappedWhenManaged, False, - XmNiconic, (style & wxICONIZE) ? TRUE : FALSE, - NULL); - - if (!title.IsEmpty()) - XtVaSetValues((Widget) m_frameShell, - XmNtitle, title.c_str(), - NULL); - - m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window", - xmMainWindowWidgetClass, (Widget) m_frameShell, - XmNresizePolicy, XmRESIZE_NONE, - NULL); - - m_workArea = (WXWidget) XtVaCreateWidget("form", - xmFormWidgetClass, (Widget) m_frameWidget, - XmNresizePolicy, XmRESIZE_NONE, - NULL); - - m_clientArea = (WXWidget) XtVaCreateWidget("client", - xmBulletinBoardWidgetClass, (Widget) m_workArea, - XmNmarginWidth, 0, - XmNmarginHeight, 0, - XmNrightAttachment, XmATTACH_FORM, - XmNleftAttachment, XmATTACH_FORM, - XmNtopAttachment, XmATTACH_FORM, - XmNbottomAttachment, XmATTACH_FORM, - // XmNresizePolicy, XmRESIZE_ANY, - NULL); - - wxLogTrace(wxTRACE_Messages, - "Created frame (0x%08x) with work area 0x%08x and client " - "area 0x%08x", m_frameWidget, m_workArea, m_clientArea); - - XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE, - wxUniversalRepaintProc, (XtPointer) this); - - XtAddEventHandler((Widget) m_clientArea, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask, - FALSE, - wxFrameEventHandler, - (XtPointer)this); - - XtVaSetValues((Widget) m_frameWidget, - XmNworkWindow, (Widget) m_workArea, - NULL); - - XtManageChild((Widget) m_clientArea); - XtManageChild((Widget) m_workArea); - - wxAddWindowToTable((Widget) m_workArea, this); - wxAddWindowToTable((Widget) m_clientArea, this); - - XtTranslations ptr; - - XtOverrideTranslations((Widget) m_workArea, - ptr = XtParseTranslationTable("<Configure>: resize()")); - - XtFree((char *)ptr); - - XtAddCallback((Widget) m_workArea, XmNfocusCallback, - (XtCallbackProc)wxFrameFocusProc, (XtPointer)this); - - /* Part of show-&-hide fix */ - XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask, - False, (XtEventHandler)wxFrameMapProc, - (XtPointer)m_workArea); - - if (x > -1) - XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL); - if (y > -1) - XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL); - if (width > -1) - XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL); - if (height > -1) - XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL); - - m_mainWidget = m_frameWidget; - - ChangeFont(FALSE); - - // This patch comes from Torsten Liermann lier@lier1.muc.de - if (XmIsMotifWMRunning( (Widget) m_frameShell )) - { - int decor = 0; - if (style & wxRESIZE_BORDER) - decor |= MWM_DECOR_RESIZEH; - if (style & wxSYSTEM_MENU) - decor |= MWM_DECOR_MENU; - if ((style & wxCAPTION) || - (style & wxTINY_CAPTION_HORIZ) || - (style & wxTINY_CAPTION_VERT)) - decor |= MWM_DECOR_TITLE; - if (style & wxTHICK_FRAME) - decor |= MWM_DECOR_BORDER; - if (style & wxTHICK_FRAME) - decor |= MWM_DECOR_BORDER; - if (style & wxMINIMIZE_BOX) - decor |= MWM_DECOR_MINIMIZE; - if (style & wxMAXIMIZE_BOX) - decor |= MWM_DECOR_MAXIMIZE; - XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL); - } - // This allows non-Motif window managers to support at least the - // no-decorations case. - else + XSelectInput( xdisplay, xwindow, + extraFlags | + ExposureMask | + KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + ButtonMotionMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + KeymapStateMask | + FocusChangeMask | + ColormapChangeMask | + StructureNotifyMask | + PropertyChangeMask + ); + + wxAddWindowToTable( xwindow, (wxWindow*) this ); + + // Set background to None which will prevent X11 from clearing the + // background completely. + XSetWindowBackgroundPixmap( xdisplay, xwindow, None ); + +#if !wxUSE_NANOX + if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) { - if (style == 0) - XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL); + if (GetParent() && GetParent()->GetMainWindow()) + { + Window xparentwindow = (Window) GetParent()->GetMainWindow(); + XSetTransientForHint( xdisplay, xwindow, xparentwindow ); + } } - XtRealizeWidget((Widget) m_frameShell); - // Intercept CLOSE messages from the window manager - Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False); -#if (XmREVISION > 1 || XmVERSION > 1) - XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this); -#else -#if XmREVISION == 1 - XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this); -#else - XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this); -#endif + size_hints.flags = PSize | PPosition; + size_hints.x = pos2.x; + size_hints.y = pos2.y; + size_hints.width = size2.x; + size_hints.height = size2.y; + XSetWMNormalHints( xdisplay, xwindow, &size_hints); + + XWMHints wm_hints; + wm_hints.flags = InputHint | StateHint /* | WindowGroupHint */; + wm_hints.input = True; + wm_hints.initial_state = NormalState; + XSetWMHints( xdisplay, xwindow, &wm_hints); + + Atom wm_protocols[2]; + wm_protocols[0] = XInternAtom( xdisplay, "WM_DELETE_WINDOW", False ); + wm_protocols[1] = XInternAtom( xdisplay, "WM_TAKE_FOCUS", False ); + XSetWMProtocols( xdisplay, xwindow, wm_protocols, 2); #endif + + wxSetWMDecorations( xwindow, style); - ChangeBackgroundColour(); - - PreResize(); - - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); - - GetEventHandler()->ProcessEvent(sizeEvent); - + SetTitle(title); + return TRUE; } -wxFrame::~wxFrame() +wxTopLevelWindowX11::~wxTopLevelWindowX11() { - m_isBeingDeleted = TRUE; - - if (m_clientArea) - { - XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE, - wxUniversalRepaintProc, (XtPointer) this); - XtRemoveEventHandler((Widget) m_clientArea, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask, - FALSE, - wxFrameEventHandler, (XtPointer) this); - wxDeleteWindowFromTable((Widget) m_clientArea); - } - - if (GetMainWidget()) - Show(FALSE); - - if (m_frameMenuBar) - { - m_frameMenuBar->DestroyMenuBar(); - - // Hack to stop core dump on Ultrix, OSF, for some strange reason. -#if MOTIF_MENUBAR_DELETE_FIX - GetMenuBar()->SetMainWidget((WXWidget) NULL); -#endif - delete m_frameMenuBar; - m_frameMenuBar = NULL; - } - wxTopLevelWindows.DeleteObject(this); - wxModelessWindows.DeleteObject(this); - - if (m_frameStatusBar) - { - delete m_frameStatusBar; - m_frameStatusBar = NULL; - } - DestroyChildren(); - - if (m_workArea) - { - wxDeleteWindowFromTable((Widget) m_workArea); - - XtDestroyWidget ((Widget) m_workArea); - } - - if (m_frameWidget) - { - wxDeleteWindowFromTable((Widget) m_frameWidget); - XtDestroyWidget ((Widget) m_frameWidget); - } - - if (m_frameShell) - XtDestroyWidget ((Widget) m_frameShell); - - SetMainWidget((WXWidget) NULL); - - /* Check if it's the last top-level window */ - - if (wxTheApp && (wxTopLevelWindows.Number() == 0)) + // If this is the last top-level window, exit. + if ( wxTheApp && (wxTopLevelWindows.Number() == 0) ) { wxTheApp->SetTopWindow(NULL); @@ -417,514 +225,463 @@ wxFrame::~wxFrame() } } -// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. -void wxFrame::DoGetClientSize(int *x, int *y) const +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 showing +// ---------------------------------------------------------------------------- + +bool wxTopLevelWindowX11::Show(bool show) { - Dimension xx, yy; - XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL); + return wxWindowX11::Show(show); +} - if (m_frameStatusBar) - { - int sbw, sbh; - m_frameStatusBar->GetSize(& sbw, & sbh); - yy -= sbh; - } -#if wxUSE_TOOLBAR - if (m_frameToolBar) - { - int tbw, tbh; - m_frameToolBar->GetSize(& tbw, & tbh); - if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL) - xx -= tbw; - else - yy -= tbh; - } -#endif // wxUSE_TOOLBAR - /* - if (GetMenuBar() != (wxMenuBar*) NULL) - { - // it seems that if a frame holds a panel, the menu bar size - // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95 - bool hasSubPanel = FALSE; - for(wxNode* node = GetChildren().First(); node; node = node->Next()) - { - wxWindow *win = (wxWindow *)node->Data(); - hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog))); - - if (hasSubPanel) - break; - } - if (! hasSubPanel) { - Dimension ys; - XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL); - yy -= ys; - } - } - */ - - *x = xx; *y = yy; +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 maximize/minimize +// ---------------------------------------------------------------------------- + +void wxTopLevelWindowX11::Maximize(bool maximize) +{ + // TODO } -// Set the client size (i.e. leave the calculation of borders etc. -// to wxWindows) -void wxFrame::DoSetClientSize(int width, int height) +bool wxTopLevelWindowX11::IsMaximized() const { - // Calculate how large the new main window should be - // by finding the difference between the client area and the - // main window area, and adding on to the new client area - if (width > -1) - XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL); + // TODO + return TRUE; +} - if (height > -1) +void wxTopLevelWindowX11::Iconize(bool iconize) +{ + if (!m_iconized && GetMainWindow()) { - if (m_frameStatusBar) - { - int sbw, sbh; - m_frameStatusBar->GetSize(& sbw, & sbh); - height += sbh; - } -#if wxUSE_TOOLBAR - if (m_frameToolBar) - { - int tbw, tbh; - m_frameToolBar->GetSize(& tbw, & tbh); - if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL) - width += tbw; - else - height += tbh; - } -#endif // wxUSE_TOOLBAR - - XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL); + if (XIconifyWindow(wxGlobalDisplay(), + (Window) GetMainWindow(), DefaultScreen(wxGlobalDisplay())) != 0) + m_iconized = TRUE; } - PreResize(); - - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); - - GetEventHandler()->ProcessEvent(sizeEvent); - } -void wxFrame::DoGetSize(int *width, int *height) const +bool wxTopLevelWindowX11::IsIconized() const { - Dimension xx, yy; - XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL); - *width = xx; *height = yy; + return m_iconized; } -void wxFrame::DoGetPosition(int *x, int *y) const +void wxTopLevelWindowX11::Restore() { - Window parent_window = XtWindow((Widget) m_frameShell), - next_parent = XtWindow((Widget) m_frameShell), - root = RootWindowOfScreen(XtScreen((Widget) m_frameShell)); - - // search for the parent that is child of ROOT, because the WM may - // reparent twice and notify only the next parent (like FVWM) - while (next_parent != root) { - Window *theChildren; unsigned int n; - parent_window = next_parent; - XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root, - &next_parent, &theChildren, &n); - XFree(theChildren); // not needed + // This is the way to deiconify the window, according to the X FAQ + if (m_iconized && GetMainWindow()) + { + XMapWindow(wxGlobalDisplay(), (Window) GetMainWindow()); + m_iconized = FALSE; } - int xx, yy; unsigned int dummy; - XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root, - &xx, &yy, &dummy, &dummy, &dummy, &dummy); - if (x) *x = xx; - if (y) *y = yy; } -void wxFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags)) +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 fullscreen +// ---------------------------------------------------------------------------- + +bool wxTopLevelWindowX11::ShowFullScreen(bool show, long style) { - if (x > -1) - XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL); - if (y > -1) - XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL); - if (width > -1) - XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL); - if (height > -1) - XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL); - - if (!(height == -1 && width == -1)) + if (show) { - PreResize(); + if (IsFullScreen()) + return FALSE; + + m_fsIsShowing = TRUE; + m_fsStyle = style; - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); + // TODO - GetEventHandler()->ProcessEvent(sizeEvent); + return TRUE; } -} + else + { + if (!IsFullScreen()) + return FALSE; -bool wxFrame::Show(bool show) -{ - if (!m_frameShell) - return wxWindow::Show(show); - - m_visibleStatus = show; /* show-&-hide fix */ - - m_isShown = show; - if (show) { - XtMapWidget((Widget) m_frameShell); - XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell)); - } else { - XtUnmapWidget((Widget) m_frameShell); - // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes + m_fsIsShowing = FALSE; + + // TODO + return TRUE; } - return TRUE; } -void wxFrame::Iconize(bool iconize) +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 misc +// ---------------------------------------------------------------------------- + +void wxTopLevelWindowX11::SetIcon(const wxIcon& icon) { - if (!iconize) - Show(TRUE); + // this sets m_icon + wxTopLevelWindowBase::SetIcon(icon); - if (m_frameShell) - XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL); -} + if (icon.Ok() && GetMainWindow()) + { +#if wxUSE_NANOX +#else + XWMHints *wmHints = XAllocWMHints(); + wmHints->icon_pixmap = (Pixmap) icon.GetPixmap(); -void wxFrame::Restore() -{ - if ( m_frameShell ) - XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL); -} + wmHints->flags = IconPixmapHint; -void wxFrame::Maximize(bool maximize) -{ - Show(TRUE); + if (icon.GetMask()) + { + wmHints->flags |= IconMaskHint; + wmHints->icon_mask = (Pixmap) icon.GetMask()->GetBitmap(); + } - if ( maximize ) - Restore(); + XSetWMHints(wxGlobalDisplay(), (Window) GetMainWindow(), wmHints); + XFree(wmHints); +#endif + } } -bool wxFrame::IsIconized() const +void wxTopLevelWindowX11::SetTitle(const wxString& title) { - if (!m_frameShell) - return FALSE; - - Boolean iconic; - XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL); - return iconic; + m_title = title; + if (GetMainWindow()) + { + XStoreName(wxGlobalDisplay(), (Window) GetMainWindow(), + (const char*) title); + XSetIconName(wxGlobalDisplay(), (Window) GetMainWindow(), + (const char*) title); + + // Use this if the platform doesn't supply the above functions. +#if 0 + XTextProperty textProperty; + textProperty.value = (unsigned char*) title; + textProperty.encoding = XA_STRING; + textProperty.format = 8; + textProperty.nitems = 1; + + XSetTextProperty(wxGlobalDisplay(), (Window) GetMainWindow(), + & textProperty, WM_NAME); +#endif + } } -// Is it maximized? -bool wxFrame::IsMaximized() const +wxString wxTopLevelWindowX11::GetTitle() const { - // No maximizing in Motif (?) - return FALSE; + return m_title; } -void wxFrame::SetTitle(const wxString& title) -{ - if (title == m_title) - return; +#ifndef MWM_DECOR_BORDER +/* bit definitions for MwmHints.flags */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) - m_title = title; +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) +#endif - if (!title.IsNull()) - XtVaSetValues((Widget) m_frameShell, - XmNtitle, title.c_str(), - XmNiconName, title.c_str(), - NULL); -} +struct MwmHints { + long flags; + long functions; + long decorations; + long input_mode; +}; -void wxFrame::SetIcon(const wxIcon& icon) +#define PROP_MOTIF_WM_HINTS_ELEMENTS 5 + +// Set the window manager decorations according to the +// given wxWindows style +bool wxSetWMDecorations(Window w, long style) { - m_icon = icon; +#if wxUSE_NANOX + GR_WM_PROPERTIES wmProp; - if (!m_frameShell) - return; + wmProp.flags = 0; + wmProp.props = 0; - if (!icon.Ok() || !icon.GetPixmap()) - return; + if (style & wxRESIZE_BORDER) + { + wmProp.props |= GR_WM_PROPS_APPFRAME ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } - XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL); -} + if (style & wxSYSTEM_MENU) + { + wmProp.props |= GR_WM_PROPS_CLOSEBOX ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } -void wxFrame::PositionStatusBar() -{ - if (!m_frameStatusBar) - return; + if ((style & wxCAPTION) || + (style & wxTINY_CAPTION_HORIZ) || + (style & wxTINY_CAPTION_VERT)) + { + wmProp.props |= GR_WM_PROPS_CAPTION ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; - int w, h; - GetClientSize(&w, &h); - int sw, sh; - m_frameStatusBar->GetSize(&sw, &sh); + // The default dialog style doesn't include any kind + // of border, which is a bit odd. Anyway, inclusion + // of a caption surely implies a border. + style |= wxTHICK_FRAME; + } - // Since we wish the status bar to be directly under the client area, - // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS. - m_frameStatusBar->SetSize(0, h, w, sh); -} + if (style & wxTHICK_FRAME) + { + wmProp.props |= GR_WM_PROPS_APPFRAME ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } -WXWidget wxFrame::GetMenuBarWidget() const -{ - if (GetMenuBar()) - return GetMenuBar()->GetMainWidget(); - else - return (WXWidget) NULL; -} + if (style & wxSIMPLE_BORDER) + { + wmProp.props |= GR_WM_PROPS_BORDER ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } -void wxFrame::SetMenuBar(wxMenuBar *menuBar) -{ - if (!menuBar) + if (style & wxMINIMIZE_BOX) { - m_frameMenuBar = NULL; - return; } - // Currently can't set it twice - // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once"); + if (style & wxMAXIMIZE_BOX) + { + wmProp.props |= GR_WM_PROPS_MAXIMIZE ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } - if (m_frameMenuBar) + if (((style & wxBORDER) != wxBORDER) && ((style & wxTHICK_FRAME) != wxTHICK_FRAME) + && ((style & wxRESIZE_BORDER) != wxRESIZE_BORDER)) { - m_frameMenuBar->DestroyMenuBar(); - delete m_frameMenuBar; + wmProp.props |= GR_WM_PROPS_NODECORATE ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; } - m_frameMenuBar = menuBar; - m_frameMenuBar->CreateMenuBar(this); -} + GrSetWMProperties(w, & wmProp); + +#else + if (!wxMWMIsRunning(w)) + return FALSE; -// Responds to colour changes, and passes event on to children. -void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) -{ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); - Refresh(); + Atom mwm_wm_hints = XInternAtom(wxGlobalDisplay(),"_MOTIF_WM_HINTS", False); + MwmHints hints; + hints.flags = 0; + hints.decorations = 0; - if ( m_frameStatusBar ) + if (style & wxRESIZE_BORDER) { - wxSysColourChangedEvent event2; - event2.SetEventObject( m_frameStatusBar ); - m_frameStatusBar->ProcessEvent(event2); + // wxLogDebug("MWM_DECOR_RESIZEH"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_RESIZEH; } - // Propagate the event to the non-top-level children - wxWindow::OnSysColourChanged(event); -} + if (style & wxSYSTEM_MENU) + { + // wxLogDebug("MWM_DECOR_MENU"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_MENU; + } -// Default activation behaviour - set the focus for the first child -// subwindow found. -void wxFrame::OnActivate(wxActivateEvent& event) -{ - if (!event.GetActive()) - return; + if ((style & wxCAPTION) || + (style & wxTINY_CAPTION_HORIZ) || + (style & wxTINY_CAPTION_VERT)) + { + // wxLogDebug("MWM_DECOR_TITLE"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_TITLE; + } - for(wxNode *node = GetChildren().First(); node; node = node->Next()) + if ((style & wxTHICK_FRAME) || (style & wxSIMPLE_BORDER) || (style & wxCAPTION)) { - // Find a child that's a subwindow, but not a dialog box. - wxWindow *child = (wxWindow *)node->Data(); - if (!child->IsKindOf(CLASSINFO(wxFrame)) && - !child->IsKindOf(CLASSINFO(wxDialog))) - { - child->SetFocus(); - return; - } + // wxLogDebug("MWM_DECOR_BORDER"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_BORDER; } -} -#if wxUSE_TOOLBAR + if (style & wxMINIMIZE_BOX) + { + // wxLogDebug("MWM_DECOR_MINIMIZE"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_MINIMIZE; + } -wxToolBar* wxFrame::CreateToolBar(long style, - wxWindowID id, - const wxString& name) -{ - if ( wxFrameBase::CreateToolBar(style, id, name) ) + if (style & wxMAXIMIZE_BOX) { - PositionToolBar(); + // wxLogDebug("MWM_DECOR_MAXIMIZE"); + hints.flags |= MWM_HINTS_DECORATIONS; + hints.decorations |= MWM_DECOR_MAXIMIZE; } - return m_frameToolBar; + XChangeProperty(wxGlobalDisplay(), + w, + mwm_wm_hints, mwm_wm_hints, + 32, PropModeReplace, + (unsigned char *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS); + +#endif + return TRUE; } -void wxFrame::PositionToolBar() +bool wxMWMIsRunning(Window w) { - if (GetToolBar()) - { - int cw, ch; - GetClientSize(& cw, &ch); +#if wxUSE_NANOX + return FALSE; +#else + Display *dpy = (Display*)wxGetDisplay(); + Atom motifWmInfo = XInternAtom(dpy, "_MOTIF_WM_INFO", False); - int tw, th; - GetToolBar()->GetSize(& tw, & th); + unsigned long length, bytesafter; + unsigned char value[20]; + unsigned char *ptr = &value[0]; + int ret, format; + Atom type; - if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL) - { - // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS - // means, pretend we don't have toolbar/status bar, so we - // have the original client size. - GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS); - } - else - { - // Use the 'real' position - GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS); - } - } -} -#endif // wxUSE_TOOLBAR + type = format = length = 0; + value[0] = 0; -void wxFrame::Raise() -{ - Window parent_window = XtWindow((Widget) m_frameShell), - next_parent = XtWindow((Widget) m_frameShell), - root = RootWindowOfScreen(XtScreen((Widget) m_frameShell)); - // search for the parent that is child of ROOT, because the WM may - // reparent twice and notify only the next parent (like FVWM) - while (next_parent != root) { - Window *theChildren; unsigned int n; - parent_window = next_parent; - XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root, - &next_parent, &theChildren, &n); - XFree(theChildren); // not needed - } - XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window); -} + ret = XGetWindowProperty(wxGlobalDisplay(), w, motifWmInfo, + 0L, 2, False, motifWmInfo, + &type, &format, &length, &bytesafter, &ptr); -void wxFrame::Lower() -{ - Window parent_window = XtWindow((Widget) m_frameShell), - next_parent = XtWindow((Widget) m_frameShell), - root = RootWindowOfScreen(XtScreen((Widget) m_frameShell)); - // search for the parent that is child of ROOT, because the WM may - // reparent twice and notify only the next parent (like FVWM) - while (next_parent != root) { - Window *theChildren; unsigned int n; - parent_window = next_parent; - XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root, - &next_parent, &theChildren, &n); - XFree(theChildren); // not needed - } - XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window); + return (ret == Success); +#endif } - -void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData), - XmAnyCallbackStruct *WXUNUSED(cbs)) + +// For implementation purposes - sometimes decorations make the client area +// smaller +wxPoint wxTopLevelWindowX11::GetClientAreaOrigin() const { - // wxDebugMsg("focus proc from frame %ld\n",(long)frame); - // TODO - // wxFrame *frame = (wxFrame *)clientData; - // frame->GetEventHandler()->OnSetFocus(); + // In fact wxFrame::GetClientAreaOrigin + // does the required calculation already. +#if 0 + if (this->IsKindOf(CLASSINFO(wxFrame))) + { + wxFrame* frame = (wxFrame*) this; + if (frame->GetMenuBar()) + return wxPoint(0, frame->GetMenuBar()->GetSize().y); + } +#endif + return wxPoint(0, 0); } -/* MATTEW: Used to insure that hide-&-show within an event cycle works */ -static void wxFrameMapProc(Widget frameShell, XtPointer clientData, - XCrossingEvent * event) +void wxTopLevelWindowX11::DoGetClientSize( int *width, int *height ) const { - wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData); - - if (frame) { - XEvent *e = (XEvent *)event; - - if (e->xany.type == MapNotify) - { - // Iconize fix - XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL); - if (!frame->GetVisibleStatus()) - { - /* We really wanted this to be hidden! */ - XtUnmapWidget((Widget) frame->GetShellWidget()); - } - } - else if (e->xany.type == UnmapNotify) - // Iconize fix - XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL); + wxWindowX11::DoGetClientSize(width, height); + // Done by wxTopLevelWindow +#if 0 + if (this->IsKindOf(CLASSINFO(wxFrame))) + { + wxFrame* frame = (wxFrame*) this; + if (frame->GetMenuBar()) + (*height) -= frame->GetMenuBar()->GetSize().y; + if (frame->GetStatusBar()) + (*height) -= frame->GetStatusBar()->GetSize().y; } +#endif } -//// Motif-specific -bool wxFrame::PreResize() +void wxTopLevelWindowX11::DoSetClientSize(int width, int height) { -#if wxUSE_TOOLBAR - PositionToolBar(); -#endif // wxUSE_TOOLBAR + wxWindowX11::DoSetClientSize(width, height); -#if wxUSE_STATUSBAR - PositionStatusBar(); -#endif // wxUSE_STATUSBAR +#if 0 + if (!GetMainWindow()) + return; - return TRUE; -} + XWindowChanges windowChanges; + int valueMask = 0; -WXWidget wxFrame::GetClientWidget() const -{ - return m_clientArea; + if (width != -1) + { + windowChanges.width = width ; + valueMask |= CWWidth; + } + if (height != -1) + { + windowChanges.height = height ; + valueMask |= CWHeight; + } + XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(), + valueMask, & windowChanges); +#endif } -void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize)) +void wxTopLevelWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags) { - // TODO -} + // wxLogDebug( "Setting pos: %d, %d", x, y ); + wxWindowX11::DoSetSize(x, y, width, height, sizeFlags); -void wxFrame::ChangeBackgroundColour() -{ - if (GetClientWidget()) - DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour); -} +#if 0 + wxPoint pt = GetPosition(); + // wxLogDebug( "After, pos: %d, %d", pt.x, pt.y ); -void wxFrame::ChangeForegroundColour() -{ - if (GetClientWidget()) - DoChangeForegroundColour(GetClientWidget(), m_foregroundColour); -} + XSync(wxGlobalDisplay(), False); + int w, h; + GetSize(& w, & h); + wxString msg; + msg.Printf("Before setting size: %d, %d", w, h); + wxLogDebug(msg); + if (!GetMainWindow()) + return; -void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs)) -{ - wxFrame *frame = (wxFrame *)client_data; + XWindowChanges windowChanges; + int valueMask = 0; - wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId()); - closeEvent.SetEventObject(frame); + if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + { + int yy = 0; + AdjustForParentClientOrigin( x, yy, sizeFlags); + windowChanges.x = x; + valueMask |= CWX; + } + if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + { + int xx = 0; + AdjustForParentClientOrigin( xx, y, sizeFlags); + windowChanges.y = y; + valueMask |= CWY; + } + if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + { + windowChanges.width = width /* - m_borderSize*2 */; + valueMask |= CWWidth; + } + if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + { + windowChanges.height = height /* -m_borderSize*2*/; + valueMask |= CWHeight; + } - // May delete the frame (with delayed deletion) - frame->GetEventHandler()->ProcessEvent(closeEvent); + XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(), + valueMask, & windowChanges); + XSync(wxGlobalDisplay(), False); + GetSize(& w, & h); + msg.Printf("Tried to set to %d, %d. After setting size: %d, %d", width, height, w, h); + wxLogDebug(msg); +#endif } -static void wxFrameEventHandler(Widget wid, - XtPointer WXUNUSED(client_data), - XEvent* event, - Boolean* continueToDispatch) +void wxTopLevelWindowX11::DoGetPosition(int *x, int *y) const { - wxFrame *frame = (wxFrame *)wxGetWindowFromTable(wid); - if (frame) + XSync(wxGlobalDisplay(), False); + Window window = (Window) m_mainWidget; + if (window) { - wxMouseEvent wxevent(wxEVT_NULL); - if (wxTranslateMouseEvent(wxevent, frame, wid, event)) - { - wxevent.SetEventObject(frame); - wxevent.SetId(frame->GetId()); - frame->GetEventHandler()->ProcessEvent(wxevent); - } - else + int offsetX = 0; + int offsetY = 0; + +#if !wxUSE_NANOX + // wxLogDebug("Translating..."); + Window childWindow; + XTranslateCoordinates(wxGlobalDisplay(), window, XDefaultRootWindow(wxGlobalDisplay()), + 0, 0, & offsetX, & offsetY, & childWindow); + + // wxLogDebug("Offset: %d, %d", offsetX, offsetY); +#endif + + XWindowAttributes attr; + Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr); + wxASSERT(status); + + if (status) { - // An attempt to implement OnCharHook by calling OnCharHook first; - // if this returns TRUE, set continueToDispatch to False - // (don't continue processing). - // Otherwise set it to True and call OnChar. - wxKeyEvent keyEvent(wxEVT_CHAR); - if (wxTranslateKeyEvent(keyEvent, frame, wid, event)) - { - keyEvent.SetEventObject(frame); - keyEvent.SetId(frame->GetId()); - keyEvent.SetEventType(wxEVT_CHAR_HOOK); - if (frame->GetEventHandler()->ProcessEvent(keyEvent)) - { - *continueToDispatch = False; - return; - } - else - { - // For simplicity, OnKeyDown is the same as OnChar - // TODO: filter modifier key presses from OnChar - keyEvent.SetEventType(wxEVT_KEY_DOWN); - - // Only process OnChar if OnKeyDown didn't swallow it - if (!frame->GetEventHandler()->ProcessEvent (keyEvent)) - { - keyEvent.SetEventType(wxEVT_CHAR); - frame->GetEventHandler()->ProcessEvent(keyEvent); - } - } - } + *x = attr.x + offsetX; + *y = attr.y + offsetY; } } - *continueToDispatch = True; }