X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/83df96d63a52ebb08b9e32549dc255354b4a18d0..e7300ec6d9ebbd1cfa2fcf12c0ce6e5aee85a152:/src/x11/toplevel.cpp?ds=sidebyside diff --git a/src/x11/toplevel.cpp b/src/x11/toplevel.cpp index 14b660afe3..c9babe3825 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,237 @@ // ---------------------------------------------------------------------------- #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 -#endif - -#include -#include -#if XmVersion >= 1002 - #include -#else - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if XmVersion > 1000 - #include -#endif +#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 -#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); - -// ---------------------------------------------------------------------------- -// globals -// ---------------------------------------------------------------------------- +#include "wx/settings.h" +#include "wx/x11/private.h" +#include "X11/Xutil.h" -extern wxList wxModelessWindows; -extern wxList wxPendingDelete; +#include "wx/unix/utilsx11.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_needResizeInIdle = FALSE; + + m_x = -1; + m_y = -1; + m_width = 20; + m_height = 20; } -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 ) + m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE); + m_backgroundColour.CalcPixel( (WXColormap) cm ); + m_hasBgCol = TRUE; + + m_x = pos.x; + if (m_x < -1) + m_x = 10; + + m_y = pos.y; + if (m_y < 0) + m_y = 10; + + m_width = size.x; + if (m_width < 0) + m_width = 500; + + m_height = size.y; + if (m_height < 0) + m_height = 380; + +#if !wxUSE_NANOX + XSetWindowAttributes xattributes; + + long xattributes_mask = + CWBorderPixel | CWBackPixel; + + xattributes.background_pixel = m_backgroundColour.GetPixel(); + xattributes.border_pixel = BlackPixel( xdisplay, xscreen ); + + if (HasFlag( wxNO_BORDER )) { - x = (displayW - width) / 2; - if (x < 10) x = 10; + xattributes_mask |= CWOverrideRedirect; + xattributes.override_redirect = True; } - if ( y == -1 ) + + if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE )) { - y = (displayH - height) / 2; - if (y < 10) y = 10; + xattributes_mask |= CWBitGravity; + xattributes.bit_gravity = NorthWestGravity; } - - // 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; - } - - 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(": 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 - { - if (style == 0) - XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL); - } - 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); + + xattributes_mask |= CWEventMask; + xattributes.event_mask = + ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | + ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | + KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | + PropertyChangeMask; + + Window xwindow = XCreateWindow( xdisplay, xparent, m_x, m_y, m_width, m_height, + 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes ); #else - XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this); -#endif + 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, m_x, m_y, m_width, m_height, + 0, 0, InputOutput, xvisual, backColor, foreColor); #endif - ChangeBackgroundColour(); - - PreResize(); - - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); - - GetEventHandler()->ProcessEvent(sizeEvent); - - return TRUE; -} - -wxFrame::~wxFrame() -{ - 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); + m_mainWindow = (WXWindow) xwindow; + m_clientWindow = (WXWindow) xwindow; + wxAddWindowToTable( xwindow, (wxWindow*) this ); + +#if wxUSE_NANOX + XSelectInput( xdisplay, xwindow, + GR_EVENT_MASK_CLOSE_REQ | + ExposureMask | + KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + ButtonMotionMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + KeymapStateMask | + FocusChangeMask | + ColormapChangeMask | + StructureNotifyMask | + PropertyChangeMask + ); #endif - delete m_frameMenuBar; - m_frameMenuBar = NULL; - } - wxTopLevelWindows.DeleteObject(this); - wxModelessWindows.DeleteObject(this); + // Set background to None which will prevent X11 from clearing the + // background completely. + XSetWindowBackgroundPixmap( xdisplay, xwindow, None ); - if (m_frameStatusBar) +#if !wxUSE_NANOX + if (HasFlag( wxSTAY_ON_TOP )) { - delete m_frameStatusBar; - m_frameStatusBar = NULL; + Window xroot = RootWindow( xdisplay, xscreen ); + XSetTransientForHint( xdisplay, xwindow, xroot ); } - - DestroyChildren(); - - if (m_workArea) + else { - wxDeleteWindowFromTable((Widget) m_workArea); - - XtDestroyWidget ((Widget) m_workArea); + if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + { + if (GetParent() && GetParent()->GetMainWindow()) + { + Window xparentwindow = (Window) GetParent()->GetMainWindow(); + XSetTransientForHint( xdisplay, xwindow, xparentwindow ); + } + } } - if (m_frameWidget) - { - wxDeleteWindowFromTable((Widget) m_frameWidget); - XtDestroyWidget ((Widget) m_frameWidget); + XSizeHints size_hints; + size_hints.flags = PSize | PPosition | PWinGravity; + size_hints.x = m_x; + size_hints.y = m_y; + size_hints.width = m_width; + size_hints.height = m_height; + size_hints.win_gravity = NorthWestGravity; + XSetWMNormalHints( xdisplay, xwindow, &size_hints); + + XWMHints wm_hints; + wm_hints.flags = InputHint | StateHint; + if (GetParent()) + { + wm_hints.flags |= WindowGroupHint; + wm_hints.window_group = (Window) GetParent()->GetMainWindow(); } + wm_hints.input = True; + wm_hints.initial_state = NormalState; + XSetWMHints( xdisplay, xwindow, &wm_hints); - if (m_frameShell) - XtDestroyWidget ((Widget) m_frameShell); + 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); - SetMainWidget((WXWidget) NULL); +#endif + + wxSetWMDecorations( xwindow, style); - /* Check if it's the last top-level window */ + SetTitle(title); + + return TRUE; +} - if (wxTheApp && (wxTopLevelWindows.Number() == 0)) +wxTopLevelWindowX11::~wxTopLevelWindowX11() +{ + wxTopLevelWindows.DeleteObject(this); + + // If this is the last top-level window, exit. + if ( wxTheApp && (wxTopLevelWindows.Number() == 0) ) { wxTheApp->SetTopWindow(NULL); @@ -417,514 +260,521 @@ wxFrame::~wxFrame() } } -// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. -void wxFrame::DoGetClientSize(int *x, int *y) const +void wxTopLevelWindowX11::OnInternalIdle() { - Dimension xx, yy; - XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL); - - if (m_frameStatusBar) + wxWindow::OnInternalIdle(); + + // Do this only after the last idle event so that + // all windows have been updated before a new + // round of size events is sent + if (m_needResizeInIdle && !wxTheApp->Pending()) { - int sbw, sbh; - m_frameStatusBar->GetSize(& sbw, & sbh); - yy -= sbh; + wxSizeEvent event( GetClientSize(), GetId() ); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent( event ); + + m_needResizeInIdle = FALSE; } -#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; } -// Set the client size (i.e. leave the calculation of borders etc. -// to wxWindows) -void wxFrame::DoSetClientSize(int width, int height) -{ - // 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); +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 showing +// ---------------------------------------------------------------------------- - if (height > -1) +bool wxTopLevelWindowX11::Show(bool show) +{ + if (show) { - 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); + wxSizeEvent event(GetSize(), GetId()); + + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + + m_needResizeInIdle = FALSE; } - PreResize(); - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); + bool ret = wxWindowX11::Show(show); + + return ret; +} - GetEventHandler()->ProcessEvent(sizeEvent); +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 maximize/minimize +// ---------------------------------------------------------------------------- +void wxTopLevelWindowX11::Maximize(bool maximize) +{ + // TODO } -void wxFrame::DoGetSize(int *width, int *height) const +bool wxTopLevelWindowX11::IsMaximized() const { - Dimension xx, yy; - XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL); - *width = xx; *height = yy; + // TODO + return TRUE; } -void wxFrame::DoGetPosition(int *x, int *y) const +void wxTopLevelWindowX11::Iconize(bool iconize) { - Window parent_window = XtWindow((Widget) m_frameShell), - next_parent = XtWindow((Widget) m_frameShell), - root = RootWindowOfScreen(XtScreen((Widget) m_frameShell)); + if (!m_iconized && GetMainWindow()) + { + if (XIconifyWindow(wxGlobalDisplay(), + (Window) GetMainWindow(), DefaultScreen(wxGlobalDisplay())) != 0) + m_iconized = TRUE; + } +} - // 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 +bool wxTopLevelWindowX11::IsIconized() const +{ + return m_iconized; +} + +void wxTopLevelWindowX11::Restore() +{ + // 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; + + m_fsIsShowing = FALSE; + + // TODO + return TRUE; } } -bool wxFrame::Show(bool show) +// ---------------------------------------------------------------------------- +// wxTopLevelWindowX11 misc +// ---------------------------------------------------------------------------- + +void wxTopLevelWindowX11::DoSetIcon(const wxIcon& icon) { - if (!m_frameShell) - return wxWindow::Show(show); + if (icon.Ok() && GetMainWindow()) + { +#if wxUSE_NANOX +#else + XWMHints *wmHints = XAllocWMHints(); + wmHints->icon_pixmap = (Pixmap) icon.GetPixmap(); + + wmHints->flags = IconPixmapHint; - m_visibleStatus = show; /* show-&-hide fix */ + if (icon.GetMask()) + { + wmHints->flags |= IconMaskHint; + wmHints->icon_mask = (Pixmap) icon.GetMask()->GetBitmap(); + } - 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 + XSetWMHints(wxGlobalDisplay(), (Window) GetMainWindow(), wmHints); + XFree(wmHints); +#endif } - return TRUE; } -void wxFrame::Iconize(bool iconize) +void wxTopLevelWindowX11::SetIcons(const wxIconBundle& icons ) { - if (!iconize) - Show(TRUE); + // this sets m_icon + wxTopLevelWindowBase::SetIcons( icons ); - if (m_frameShell) - XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL); + DoSetIcon( icons.GetIcon( -1 ) ); + wxSetIconsX11( wxGlobalDisplay(), GetMainWindow(), icons ); } -void wxFrame::Restore() +void wxTopLevelWindowX11::SetTitle(const wxString& title) { - if ( m_frameShell ) - XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL); + m_title = title; + + if (GetMainWindow()) + { + XStoreName(wxGlobalDisplay(), (Window) GetMainWindow(), + (const char*) title); + XSetIconName(wxGlobalDisplay(), (Window) GetMainWindow(), + (const char*) title); + } } -void wxFrame::Maximize(bool maximize) +wxString wxTopLevelWindowX11::GetTitle() const { - Show(TRUE); - - if ( maximize ) - Restore(); + return m_title; } -bool wxFrame::IsIconized() const +// For implementation purposes - sometimes decorations make the client area +// smaller +wxPoint wxTopLevelWindowX11::GetClientAreaOrigin() const { - if (!m_frameShell) - return FALSE; - - Boolean iconic; - XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL); - return iconic; + // wxFrame::GetClientAreaOrigin + // does the required calculation already. + return wxPoint(0, 0); } -// Is it maximized? -bool wxFrame::IsMaximized() const +void wxTopLevelWindowX11::DoGetClientSize( int *width, int *height ) const { - // No maximizing in Motif (?) - return FALSE; + if (width) + *width = m_width; + if (height) + *height = m_height; } -void wxFrame::SetTitle(const wxString& title) +void wxTopLevelWindowX11::DoGetSize( int *width, int *height ) const { - if (title == m_title) - return; + // TODO add non-client size - m_title = title; - - if (!title.IsNull()) - XtVaSetValues((Widget) m_frameShell, - XmNtitle, title.c_str(), - XmNiconName, title.c_str(), - NULL); + if (width) + *width = m_width; + if (height) + *height = m_height; } -void wxFrame::SetIcon(const wxIcon& icon) +void wxTopLevelWindowX11::DoSetClientSize(int width, int height) { - m_icon = icon; + int old_width = m_width; + int old_height = m_height; - if (!m_frameShell) + m_width = width; + m_height = height; + + if (m_width == old_width && m_height == old_height) return; - - if (!icon.Ok() || !icon.GetPixmap()) - return; - - XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL); -} - -void wxFrame::PositionStatusBar() -{ - if (!m_frameStatusBar) + + // wxLogDebug("DoSetClientSize: %s (%ld) %dx%d", GetClassInfo()->GetClassName(), GetId(), width, height); + +#if !wxUSE_NANOX + XSizeHints size_hints; + size_hints.flags = PSize; + size_hints.width = width; + size_hints.height = height; + XSetWMNormalHints( wxGlobalDisplay(), (Window) GetMainWindow(), &size_hints ); +#endif + + wxWindowX11::DoSetClientSize(width, height); +} + +void wxTopLevelWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags) +{ + int old_x = m_x; + int old_y = m_y; + int old_width = m_width; + int old_height = m_height; + + if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + m_x = x; + + if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + m_y = y; + + if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + m_width = width; + + if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) + m_height = height; + + if (m_x == old_x && m_y == old_y && m_width == old_width && m_height == old_height) return; + + // wxLogDebug("DoSetSize: %s (%ld) %d, %d %dx%d", GetClassInfo()->GetClassName(), GetId(), x, y, width, height); + +#if !wxUSE_NANOX + XSizeHints size_hints; + size_hints.flags = 0; + size_hints.flags |= PPosition; + size_hints.flags |= PSize; + size_hints.x = m_x; + size_hints.y = m_y; + size_hints.width = m_width; + size_hints.height = m_height; + XSetWMNormalHints( wxGlobalDisplay(), (Window) GetMainWindow(), &size_hints); +#endif - int w, h; - GetClientSize(&w, &h); - int sw, sh; - m_frameStatusBar->GetSize(&sw, &sh); - - // 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); -} + wxWindowX11::DoSetSize(x, y, width, height, sizeFlags); + +#if 0 + Display *display = wxGlobalDisplay(); + Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display)); + Window parent_window = window, + next_parent = window; -WXWidget wxFrame::GetMenuBarWidget() const -{ - if (GetMenuBar()) - return GetMenuBar()->GetMainWidget(); - else - return (WXWidget) NULL; -} - -void wxFrame::SetMenuBar(wxMenuBar *menuBar) -{ - if (!menuBar) - { - m_frameMenuBar = NULL; - return; + // 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; +#if wxUSE_NANOX + GR_COUNT n; +#else + unsigned int n; +#endif + parent_window = next_parent; + XQueryTree(display, parent_window, &root, + &next_parent, &theChildren, &n); + XFree(theChildren); // not needed } - // Currently can't set it twice - // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once"); + XWindowChanges windowChanges; + windowChanges.x = x; + windowChanges.y = y; + windowChanges.width = width; + windowChanges.height = height; + windowChanges.stack_mode = 0; + int valueMask = CWX | CWY | CWWidth | CWHeight; - if (m_frameMenuBar) + if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) { - m_frameMenuBar->DestroyMenuBar(); - delete m_frameMenuBar; + valueMask |= CWX; } - - m_frameMenuBar = menuBar; - m_frameMenuBar->CreateMenuBar(this); -} - -// Responds to colour changes, and passes event on to children. -void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) -{ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); - Refresh(); - - if ( m_frameStatusBar ) + if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) { - wxSysColourChangedEvent event2; - event2.SetEventObject( m_frameStatusBar ); - m_frameStatusBar->ProcessEvent(event2); + valueMask |= CWY; } - - // Propagate the event to the non-top-level children - wxWindow::OnSysColourChanged(event); -} - -// Default activation behaviour - set the focus for the first child -// subwindow found. -void wxFrame::OnActivate(wxActivateEvent& event) -{ - if (!event.GetActive()) - return; - - for(wxNode *node = GetChildren().First(); node; node = node->Next()) + if (width != -1) { - // 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; - } + windowChanges.width = wxMax(1, width); + valueMask |= CWWidth; } -} - -#if wxUSE_TOOLBAR - -wxToolBar* wxFrame::CreateToolBar(long style, - wxWindowID id, - const wxString& name) -{ - if ( wxFrameBase::CreateToolBar(style, id, name) ) + if (height != -1) { - PositionToolBar(); + windowChanges.height = wxMax(1, height); + valueMask |= CWHeight; } - return m_frameToolBar; + XConfigureWindow( display, parent_window, valueMask, &windowChanges ); +#endif } -void wxFrame::PositionToolBar() +void wxTopLevelWindowX11::DoGetPosition(int *x, int *y) const { - if (GetToolBar()) - { - int cw, ch; - GetClientSize(& cw, &ch); - - int tw, th; - GetToolBar()->GetSize(& tw, & th); + XSync(wxGlobalDisplay(), False); + Window window = (Window) m_mainWindow; + if (!window) + return ; - 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 + Display *display = wxGlobalDisplay(); + Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display)); + Window parent_window = window, + next_parent = window; -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; + Window *theChildren; +#if wxUSE_NANOX + GR_COUNT n; +#else + unsigned int n; +#endif parent_window = next_parent; - XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root, + XQueryTree(display, parent_window, &root, &next_parent, &theChildren, &n); XFree(theChildren); // not needed } - XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window); -} - -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 +#if 0 + int xx, yy; unsigned int dummy; + XGetGeometry(display, parent_window, &root, + &xx, &yy, &dummy, &dummy, &dummy, &dummy); + if (x) *x = xx; + if (y) *y = yy; +#else + XWindowAttributes attr; + Status status = XGetWindowAttributes( wxGlobalDisplay(), parent_window, & attr); + if (status) + { + if (x) *x = attr.x; + if (y) *y = attr.y; } - XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window); + else + { + if (x) *x = 0; + if (y) *y = 0; + } +#endif } -void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData), - XmAnyCallbackStruct *WXUNUSED(cbs)) -{ - // wxDebugMsg("focus proc from frame %ld\n",(long)frame); - // TODO - // wxFrame *frame = (wxFrame *)clientData; - // frame->GetEventHandler()->OnSetFocus(); -} -/* MATTEW: Used to insure that hide-&-show within an event cycle works */ -static void wxFrameMapProc(Widget frameShell, XtPointer clientData, - XCrossingEvent * event) -{ - wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData); +#ifndef MWM_DECOR_BORDER - if (frame) { - XEvent *e = (XEvent *)event; +#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) - 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); - } -} +#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) -//// Motif-specific -bool wxFrame::PreResize() -{ -#if wxUSE_TOOLBAR - PositionToolBar(); -#endif // wxUSE_TOOLBAR +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) -#if wxUSE_STATUSBAR - PositionStatusBar(); -#endif // wxUSE_STATUSBAR +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 +#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL - return TRUE; -} +#define MWM_TEAROFF_WINDOW (1L<<0) -WXWidget wxFrame::GetClientWidget() const -{ - return m_clientArea; -} +#endif -void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize)) -{ - // TODO -} +struct MwmHints { + long flags; + long functions; + long decorations; + long input_mode; +}; -void wxFrame::ChangeBackgroundColour() -{ - if (GetClientWidget()) - DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour); -} +#define PROP_MOTIF_WM_HINTS_ELEMENTS 5 -void wxFrame::ChangeForegroundColour() +// Set the window manager decorations according to the +// given wxWindows style +bool wxSetWMDecorations(Window w, long style) { - if (GetClientWidget()) - DoChangeForegroundColour(GetClientWidget(), m_foregroundColour); -} +#if wxUSE_NANOX + GR_WM_PROPERTIES wmProp; -void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs)) -{ - wxFrame *frame = (wxFrame *)client_data; + wmProp.flags = 0; + wmProp.props = 0; - wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId()); - closeEvent.SetEventObject(frame); + if (style & wxRESIZE_BORDER) + { + wmProp.props |= GR_WM_PROPS_APPFRAME ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } - // May delete the frame (with delayed deletion) - frame->GetEventHandler()->ProcessEvent(closeEvent); -} + if (style & wxSYSTEM_MENU) + { + wmProp.props |= GR_WM_PROPS_CLOSEBOX ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } -static void wxFrameEventHandler(Widget wid, - XtPointer WXUNUSED(client_data), - XEvent* event, - Boolean* continueToDispatch) -{ - wxFrame *frame = (wxFrame *)wxGetWindowFromTable(wid); - if (frame) + if ((style & wxCAPTION) || + (style & wxTINY_CAPTION_HORIZ) || + (style & wxTINY_CAPTION_VERT)) + { + wmProp.props |= GR_WM_PROPS_CAPTION ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + + // 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; + } + + if (style & wxTHICK_FRAME) + { + wmProp.props |= GR_WM_PROPS_APPFRAME ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } + + if (style & wxSIMPLE_BORDER) + { + wmProp.props |= GR_WM_PROPS_BORDER ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } + + if (style & wxMINIMIZE_BOX) + { + } + + if (style & wxMAXIMIZE_BOX) + { + wmProp.props |= GR_WM_PROPS_MAXIMIZE ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } + + if (((style & wxBORDER) != wxBORDER) && ((style & wxTHICK_FRAME) != wxTHICK_FRAME) + && ((style & wxRESIZE_BORDER) != wxRESIZE_BORDER)) { - wxMouseEvent wxevent(wxEVT_NULL); - if (wxTranslateMouseEvent(wxevent, frame, wid, event)) + wmProp.props |= GR_WM_PROPS_NODECORATE ; + wmProp.flags |= GR_WM_FLAGS_PROPS ; + } + + GrSetWMProperties(w, & wmProp); + +#else + + Atom mwm_wm_hints = XInternAtom(wxGlobalDisplay(),"_MOTIF_WM_HINTS", False); + if (mwm_wm_hints == 0) + return FALSE; + + MwmHints hints; + hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; + hints.decorations = 0; + hints.functions = 0; + + if ((style & wxSIMPLE_BORDER) || (style & wxNO_BORDER)) + { + // leave zeros + } + else + { + hints.decorations = MWM_DECOR_BORDER; + hints.functions = MWM_FUNC_MOVE; + + if ((style & wxCAPTION) != 0) + hints.decorations |= MWM_DECOR_TITLE; + + if ((style & wxSYSTEM_MENU) != 0) { - wxevent.SetEventObject(frame); - wxevent.SetId(frame->GetId()); - frame->GetEventHandler()->ProcessEvent(wxevent); + hints.functions |= MWM_FUNC_CLOSE; + hints.decorations |= MWM_DECOR_MENU; } - else + + if ((style & wxMINIMIZE_BOX) != 0) { - // 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); - } - } - } + hints.functions |= MWM_FUNC_MINIMIZE; + hints.decorations |= MWM_DECOR_MINIMIZE; + } + + if ((style & wxMAXIMIZE_BOX) != 0) + { + hints.functions |= MWM_FUNC_MAXIMIZE; + hints.decorations |= MWM_DECOR_MAXIMIZE; + } + + if ((style & wxRESIZE_BORDER) != 0) + { + hints.functions |= MWM_FUNC_RESIZE; + hints.decorations |= MWM_DECOR_RESIZEH; } } - *continueToDispatch = True; + + XChangeProperty(wxGlobalDisplay(), + w, + mwm_wm_hints, mwm_wm_hints, + 32, PropModeReplace, + (unsigned char *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS); + +#endif + return TRUE; } + +