From 0de6dfa701964fdabfd1f4027e68b4c7c5520107 Mon Sep 17 00:00:00 2001 From: Mattia Barbon Date: Mon, 6 Jan 2003 20:54:54 +0000 Subject: [PATCH] Implemented wxToplevelWindowMotif. (forgot to commit) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18604 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/motif/toplevel.h | 81 ++++++++ src/motif/toplevel.cpp | 385 ++++++++++++++++++++++++++++++++++++ 2 files changed, 466 insertions(+) create mode 100644 include/wx/motif/toplevel.h create mode 100644 src/motif/toplevel.cpp diff --git a/include/wx/motif/toplevel.h b/include/wx/motif/toplevel.h new file mode 100644 index 0000000000..6d16717756 --- /dev/null +++ b/include/wx/motif/toplevel.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/motif/toplevel.h +// Purpose: wxTopLevelWindow Motif implementation +// Author: Mattia Barbon +// Modified by: +// Created: 12/10/2002 +// RCS-ID: $Id$ +// Copyright: (c) Mattia Barbon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __MOTIFTOPLEVELH__ +#define __MOTIFTOPLEVELH__ + +#if defined(__GNUG__) && !defined(__APPLE__) + #pragma interface "toplevel.h" +#endif + +class wxTopLevelWindowMotif : public wxTopLevelWindowBase +{ +public: + wxTopLevelWindowMotif() { Init(); } + wxTopLevelWindowMotif( wxWindow* parent, wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr ) + { + Init(); + + Create( parent, id, title, pos, size, style, name ); + } + + bool Create( wxWindow* parent, wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr ); + + virtual ~wxTopLevelWindowMotif(); + + virtual bool ShowFullScreen( bool show, long style = wxFULLSCREEN_ALL ); + virtual bool IsFullScreen() const; + + virtual void Maximize(bool maximize = TRUE); + virtual void Restore(); + virtual void Iconize(bool iconize = TRUE); + virtual bool IsMaximized() const; + virtual bool IsIconized() const; + + virtual void Raise(); + virtual void Lower(); + + virtual wxString GetTitle() const { return m_title; } + virtual void SetTitle( const wxString& title ) { m_title = title; } + + WXWidget GetShellWidget() const; +protected: + // common part of all constructors + void Init(); + +private: + // both these functions should be pure virtual + virtual bool DoCreate( wxWindow* parent, wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name ) + { + return FALSE; + } + + virtual void DoDestroy() { } + + wxString m_title; +}; + +#endif // __MOTIFTOPLEVELH__ diff --git a/src/motif/toplevel.cpp b/src/motif/toplevel.cpp new file mode 100644 index 0000000000..b0180f7a8b --- /dev/null +++ b/src/motif/toplevel.cpp @@ -0,0 +1,385 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: motif/toplevel.cpp +// Purpose: wxTopLevelWindow Motif implementation +// Author: Mattia Barbon +// Modified by: +// Created: 12/10/2002 +// RCS-ID: $Id$ +// Copyright: (c) Mattia Barbon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(__APPLE__) + #pragma implementation "toplevel.h" +#endif + +#include "wx/toplevel.h" +#include "wx/app.h" + +#ifdef __VMS__ + #pragma message disable nosimpint +#endif + +#include +#include +#include +#if XmVersion >= 1002 + #include +#else + #include +#endif + +#ifdef __VMS__ + #pragma message enable nosimpint +#endif + +#include "wx/motif/private.h" + +wxList wxModelessWindows; // Frames and modeless dialogs + +// --------------------------------------------------------------------------- +// Callbacks +// --------------------------------------------------------------------------- + +static void wxCloseTLWCallback( Widget widget, XtPointer client_data, + XmAnyCallbackStruct *cbs ); +static void wxTLWEventHandler( Widget wid, + XtPointer client_data, + XEvent* event, + Boolean *continueToDispatch ); + +// =========================================================================== +// wxTopLevelWindowMotif implementation +// =========================================================================== + +wxTopLevelWindowMotif::~wxTopLevelWindowMotif() +{ + wxTopLevelWindows.DeleteObject(this); + + if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL ) + wxModelessWindows.DeleteObject(this); + + m_icons.m_icons.Empty(); + + DestroyChildren(); + + // MessageDialog and FileDialog do not have a client widget + if( GetClientWidget() ) + { + XtRemoveEventHandler( (Widget)GetClientWidget(), + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | KeyPressMask, + FALSE, + wxTLWEventHandler, + (XtPointer)this ); + } + + DoDestroy(); + + SetMainWidget( (WXWidget)0 ); + + // If this is the last top-level window, exit. + if (wxTheApp && (wxTopLevelWindows.Number() == 0)) + { + wxTheApp->SetTopWindow(NULL); + + if (wxTheApp->GetExitOnFrameDelete()) + { + wxTheApp->ExitMainLoop(); + } + } +} + +void wxTopLevelWindowMotif::Init() +{ + m_isShown = FALSE; +} + +bool wxTopLevelWindowMotif::Create( wxWindow *parent, wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name ) +{ + SetName(name); + m_windowStyle = style; + + if ( parent ) + parent->AddChild(this); + + wxTopLevelWindows.Append(this); + + m_windowId = ( id > -1 ) ? id : NewControlId(); + + bool retval = DoCreate( parent, id, title, pos, size, style, name ); + + if( !retval ) return FALSE; + + // Intercept CLOSE messages from the window manager + Widget shell = (Widget)GetShellWidget(); + Atom WM_DELETE_WINDOW = XmInternAtom( XtDisplay( shell ), + "WM_DELETE_WINDOW", False ); + + // Remove and add WM_DELETE_WINDOW so ours is only handler + // This only appears to be necessary for wxDialog, but does not hurt + // for wxFrame + XmRemoveWMProtocols( shell, &WM_DELETE_WINDOW, 1 ); + XmAddWMProtocols( shell, &WM_DELETE_WINDOW, 1 ); + XmActivateWMProtocol( shell, WM_DELETE_WINDOW ); + + // Modified Steve Hammes for Motif 2.0 +#if (XmREVISION > 1 || XmVERSION > 1) + XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW, + (XtCallbackProc)wxCloseTLWCallback, + (XtPointer)this ); +#elif XmREVISION == 1 + XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW, + (XtCallbackProc)wxCloseTLWCallback, + (caddr_t)this ); +#else + XmAddWMProtocolCallback( shell, WM_DELETE_WINDOW, + (void (*)())wxCloseTLWCallback, (caddr_t)this ); +#endif + + // This patch come from Torsten Liermann lier@lier1.muc.de + if( XmIsMotifWMRunning( shell ) ) + { + int decor = 0 ; + if( m_windowStyle & wxRESIZE_BORDER ) + decor |= MWM_DECOR_RESIZEH; + if( m_windowStyle & wxSYSTEM_MENU ) + decor |= MWM_DECOR_MENU; + if( ( m_windowStyle & wxCAPTION ) || + ( m_windowStyle & wxTINY_CAPTION_HORIZ ) || + ( m_windowStyle & wxTINY_CAPTION_VERT ) ) + decor |= MWM_DECOR_TITLE; + if( m_windowStyle & wxTHICK_FRAME ) + decor |= MWM_DECOR_BORDER; + if( m_windowStyle & wxMINIMIZE_BOX ) + decor |= MWM_DECOR_MINIMIZE; + if( m_windowStyle & wxMAXIMIZE_BOX ) + decor |= MWM_DECOR_MAXIMIZE; + + XtVaSetValues( shell, + XmNmwmDecorations, decor, + NULL ); + } + else + { + // This allows non-Motif window managers to support at least the + // no-decorations case. + if( ( m_windowStyle & wxCAPTION ) != wxCAPTION ) + XtVaSetValues( shell, + XmNoverrideRedirect, TRUE, + NULL ); + } + + XtAddEventHandler( (Widget)GetClientWidget(), + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | KeyPressMask, + FALSE, + wxTLWEventHandler, + (XtPointer)this ); + + return retval; +} + +void wxTopLevelWindowMotif::Raise() +{ + Widget top = (Widget) GetTopWidget(); + Window parent_window = XtWindow( top ), + next_parent = XtWindow( top ), + root = RootWindowOfScreen( XtScreen( top ) ); + // 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( top ), parent_window, &root, + &next_parent, &theChildren, &n ); + XFree( theChildren ); // not needed + } + XRaiseWindow( XtDisplay( top ), parent_window ); +} + +void wxTopLevelWindowMotif::Lower() +{ + Widget top = (Widget) GetTopWidget(); + Window parent_window = XtWindow( top ), + next_parent = XtWindow( top ), + root = RootWindowOfScreen( XtScreen( top ) ); + // 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( top ), parent_window, &root, + &next_parent, &theChildren, &n ); + XFree( theChildren ); // not needed + } + XLowerWindow( XtDisplay( top ), parent_window ); +} + +static inline Widget GetShell( const wxTopLevelWindowMotif* tlw ) +{ + Widget main = (Widget) tlw->GetMainWidget(); + if( !main ) return (Widget) NULL; + + return XtParent( main ); +} + +WXWidget wxTopLevelWindowMotif::GetShellWidget() const +{ + return (WXWidget) GetShell( this ); +} + +bool wxTopLevelWindowMotif::ShowFullScreen( bool show, + long style = wxFULLSCREEN_ALL ) +{ + // TODO, see wxGTK + return FALSE; +} + +bool wxTopLevelWindowMotif::IsFullScreen() const +{ + // TODO, see wxGTK + return FALSE; +} + +void wxTopLevelWindowMotif::Restore() +{ + Widget shell = GetShell( this ); + + if( shell ) + XtVaSetValues( shell, + XmNiconic, FALSE, + NULL ); +} + +void wxTopLevelWindowMotif::Iconize( bool iconize = TRUE ) +{ + Widget shell = GetShell( this ); + if( !shell ) return; + + if( !iconize ) + Show( TRUE ); + + XtVaSetValues( shell, + XmNiconic, (Boolean)iconize, + NULL ); +} + +bool wxTopLevelWindowMotif::IsIconized() const +{ + Widget shell = GetShell( this ); + + if( !shell ) + return FALSE; + + Boolean iconic; + XtVaGetValues( shell, + XmNiconic, &iconic, + NULL ); + + return iconic; +} + +void wxTopLevelWindowMotif::Maximize( bool maximize = TRUE ) +{ + Show( TRUE ); + + if( maximize ) + Restore(); +} + +bool wxTopLevelWindowMotif::IsMaximized() const +{ + return FALSE; +} + +// --------------------------------------------------------------------------- +// Callback definition +// --------------------------------------------------------------------------- + +// Handle a close event from the window manager +static void wxCloseTLWCallback( Widget WXUNUSED(widget), XtPointer client_data, + XmAnyCallbackStruct *WXUNUSED(cbs) ) +{ + wxTopLevelWindowMotif* tlw = (wxTopLevelWindowMotif*)client_data; + wxCloseEvent closeEvent( wxEVT_CLOSE_WINDOW, tlw->GetId() ); + closeEvent.SetEventObject( tlw ); + + // May delete the dialog (with delayed deletion) + tlw->GetEventHandler()->ProcessEvent(closeEvent); +} + +void wxTLWEventHandler( Widget wid, + XtPointer WXUNUSED(client_data), + XEvent* event, + Boolean* continueToDispatch) +{ + wxTopLevelWindowMotif* tlw = + (wxTopLevelWindowMotif*)wxGetWindowFromTable( wid ); + + if( tlw ) + { + wxMouseEvent wxevent( wxEVT_NULL ); + + if( wxTranslateMouseEvent( wxevent, tlw, wid, event ) ) + { + wxevent.SetEventObject( tlw ); + wxevent.SetId( tlw->GetId() ); + tlw->GetEventHandler()->ProcessEvent( wxevent ); + } + else + { + // 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, tlw, wid, event )) + { + keyEvent.SetEventObject( tlw ); + keyEvent.SetId( tlw->GetId() ); + keyEvent.SetEventType( wxEVT_CHAR_HOOK ); + if( tlw->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( !tlw->GetEventHandler()->ProcessEvent( keyEvent ) ) + { + keyEvent.SetEventType( wxEVT_CHAR ); + tlw->GetEventHandler()->ProcessEvent( keyEvent ); + } + } + } + } + } + + *continueToDispatch = True; +} + -- 2.45.2