wxApp();
virtual ~wxApp();
- virtual bool OnInitGui(void);
-
// override base class (pure) virtuals
- virtual int MainLoop(void);
- virtual void ExitMainLoop(void);
- virtual bool Initialized(void);
- virtual bool Pending(void) ;
- virtual bool Dispatch(void);
+ virtual bool Initialize(int& argc, wxChar **argv);
+ virtual void CleanUp(void);
- virtual void Exit();
+ virtual bool Initialized(void);
+ virtual bool OnInitGui(void);
virtual bool Yield(bool onlyIfNeeded = FALSE);
virtual void WakeUpIdle(void);
public:
// Implementation
- virtual bool Initialize(int& argc, wxChar **argv);
- virtual void CleanUp(void);
-
static bool RegisterWindowClasses(HAB vHab);
- virtual void DoMessage(WXMSG *pMsg);
- virtual bool DoMessage(void);
- virtual bool ProcessMessage(WXMSG* pMsg);
public:
int m_nCmdShow;
HMQ m_hMq;
protected:
- bool m_bKeepGoing ;
-
DECLARE_EVENT_TABLE()
+ DECLARE_NO_COPY_CLASS(wxApp)
};
#endif
// _WX_APP_H_
WXDLLEXPORT_DATA(extern const char*) wxDialogNameStr;
+class WXDLLEXPORT wxDialogModalData;
+
//
// Dialog boxes
//
private:
wxWindow* m_pOldFocus;
+ // this pointer is non-NULL only while the modal event loop is running
+ wxDialogModalData *m_modalData;
+
//
// While we are showing a modal dialog we disable the other windows using
// this object
#include "wx/dynarray.h"
#include "wx/wxchar.h"
#include "wx/icon.h"
- #include "wx/timer.h"
#endif
#include "wx/log.h"
#if wxUSE_THREADS
#include "wx/thread.h"
-
- // define the array of QMSG strutures
- WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
-
- #include "wx/arrimpl.cpp"
-
- WX_DEFINE_OBJARRAY(wxMsgArray);
#endif // wxUSE_THREADS
#if wxUSE_TOOLTIPS
extern wxCursor* g_globalCursor;
HAB vHabmain = NULLHANDLE;
-QMSG svCurrentMsg;
HICON wxSTD_FRAME_ICON = (HICON) NULL;
return FALSE;
} // end of wxApp::Initialized
-//
-// Get and process a message, returning FALSE if WM_QUIT
-// received (and also set the flag telling the app to exit the main loop)
-//
-
-bool wxApp::DoMessage()
-{
- BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
-
- if (bRc == 0)
- {
- // got WM_QUIT
- m_bKeepGoing = FALSE;
- return FALSE;
- }
- else if (bRc == -1)
- {
- // should never happen, but let's test for it nevertheless
- wxLogLastError("GetMessage");
- }
- else
- {
-#if wxUSE_THREADS
- wxASSERT_MSG( wxThread::IsMain()
- ,wxT("only the main thread can process Windows messages")
- );
-
- static bool sbHadGuiLock = TRUE;
- static wxMsgArray svSavedMessages;
-
- //
- // If a secondary thread owns is doing GUI calls, save all messages for
- // later processing - we can't process them right now because it will
- // lead to recursive library calls (and we're not reentrant)
- //
- if (!wxGuiOwnedByMainThread())
- {
- sbHadGuiLock = FALSE;
-
- //
- // Leave out WM_COMMAND messages: too dangerous, sometimes
- // the message will be processed twice
- //
- if ( !wxIsWaitingForThread() ||
- svCurrentMsg.msg != WM_COMMAND )
- {
- svSavedMessages.Add(svCurrentMsg);
- }
- return TRUE;
- }
- else
- {
- //
- // Have we just regained the GUI lock? if so, post all of the saved
- // messages
- //
- if (!sbHadGuiLock )
- {
- sbHadGuiLock = TRUE;
-
- size_t nCount = svSavedMessages.Count();
-
- for (size_t n = 0; n < nCount; n++)
- {
- QMSG vMsg = svSavedMessages[n];
-
- DoMessage((WXMSG*)&vMsg);
- }
- svSavedMessages.Empty();
- }
- }
-#endif // wxUSE_THREADS
-
- //
- // Process the message
- //
- DoMessage((WXMSG *)&svCurrentMsg);
- }
- return TRUE;
-} // end of wxApp::DoMessage
-
-void wxApp::DoMessage(
- WXMSG* pMsg
-)
-{
- if (!ProcessMessage((WXMSG *)&svCurrentMsg))
- {
- ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
- }
-} // end of wxApp::DoMessage
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Keep trying to process messages until WM_QUIT
-// received.
-//
-// If there are messages to be processed, they will all be
-// processed and OnIdle will not be called.
-// When there are no more messages, OnIdle is called.
-// If OnIdle requests more time,
-// it will be repeatedly called so long as there are no pending messages.
-// A 'feature' of this is that once OnIdle has decided that no more processing
-// is required, then it won't get processing time until further messages
-// are processed (it'll sit in DoMessage).
-//
-//////////////////////////////////////////////////////////////////////////////
-int wxApp::MainLoop()
-{
- m_bKeepGoing = TRUE;
-
- while (m_bKeepGoing)
- {
-#if wxUSE_THREADS
- wxMutexGuiLeaveOrEnter();
-#endif // wxUSE_THREADS
- while (!Pending() && ProcessIdle())
- {
- HandleSockets();
- wxUsleep(10);
- }
- HandleSockets();
- if (Pending())
- DoMessage();
- else
- wxUsleep(10);
-
- }
- return (int)svCurrentMsg.mp1;
-} // end of wxApp::MainLoop
-
-void wxApp::ExitMainLoop()
-{
- ::WinPostMsg(NULL, WM_QUIT, 0, 0);
-} // end of wxApp::ExitMainLoop
-
-bool wxApp::Pending()
-{
- return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
-} // end of wxApp::Pending
-
-bool wxApp::Dispatch()
-{
- return DoMessage();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Give all windows a chance to preprocess
-// the message. Some may have accelerator tables, or have
-// MDI complications.
-//
-//////////////////////////////////////////////////////////////////////////////
-bool wxApp::ProcessMessage(
- WXMSG* pWxmsg
-)
-{
- QMSG* pMsg = (PQMSG)pWxmsg;
- HWND hWnd = pMsg->hwnd;
- wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
- wxWindow* pWnd;
-
- //
- // Pass non-system timer messages to the wxTimerProc
- //
- if (pMsg->msg == WM_TIMER &&
- (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
- SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
- SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
- SHORT1FROMMP(pMsg->mp1) != 0x0000
- ))
- wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
-
- //
- // Allow the window to prevent certain messages from being
- // translated/processed (this is currently used by wxTextCtrl to always
- // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
- //
- if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg))
- {
- return FALSE;
- }
-
- //
- // For some composite controls (like a combobox), wndThis might be NULL
- // because the subcontrol is not a wxWindow, but only the control itself
- // is - try to catch this case
- //
- while (hWnd && !pWndThis)
- {
- hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
- pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
- }
-
- //
- // Try translations first; find the youngest window with
- // a translation table. OS/2 has case sensative accels, so
- // this block, coded by BK, removes that and helps make them
- // case insensative.
- //
- if(pMsg->msg == WM_CHAR)
- {
- PBYTE pChmsg = (PBYTE)&(pMsg->msg);
- USHORT uSch = CHARMSG(pChmsg)->chr;
- bool bRc;
-
- //
- // Do not process keyup events
- //
- if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
- {
- if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
- CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
-
-
- for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
- {
- if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
- break;
- }
-
- if(!bRc) // untranslated, should restore original value
- CHARMSG(pChmsg)->chr = uSch;
- }
- }
- //
- // Anyone for a non-translation message? Try youngest descendants first.
- //
-// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
-// {
-// if (pWnd->OS2ProcessMessage(pWxmsg))
-// return TRUE;
-// }
- return FALSE;
-} // end of wxApp::ProcessMessage
-
bool gbInOnIdle = FALSE;
void wxApp::OnIdle(
}
} // end of wxApp::OnQueryEndSession
-void wxApp::Exit()
-{
- wxApp::CleanUp();
-
- // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
- wxAppConsole::Exit();
-} // end of wxExit
-
//
// Yield to incoming messages
//
#if wxUSE_THREADS
wxMutexGuiLeaveOrEnter();
#endif // wxUSE_THREADS
- if (!wxTheApp->DoMessage())
+ if (!wxTheApp->Dispatch())
break;
}
//
#include "wx/os2/private.h"
#include "wx/log.h"
+#include "wx/evtloop.h"
+#include "wx/ptr_scpd.h"
#define wxDIALOG_DEFAULT_X 300
#define wxDIALOG_DEFAULT_Y 300
EVT_CLOSE(wxDialog::OnCloseWindow)
END_EVENT_TABLE()
+// ----------------------------------------------------------------------------
+// wxDialogModalData
+// ----------------------------------------------------------------------------
+
+// this is simply a container for any data we need to implement modality which
+// allows us to avoid changing wxDialog each time the implementation changes
+class wxDialogModalData
+{
+public:
+ wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { }
+
+ void RunLoop()
+ {
+ m_evtLoop.Run();
+ }
+
+ void ExitLoop()
+ {
+ m_evtLoop.Exit();
+ }
+
+private:
+ wxModalEventLoop m_evtLoop;
+};
+
+wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData);
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxDialog construction
+// ----------------------------------------------------------------------------
+
void wxDialog::Init()
{
m_pOldFocus = (wxWindow *)NULL;
gbInOnIdle = FALSE;
- //
- // Enter the modal loop
- //
- while ( IsModalShowing() )
+ // enter the modal loop
{
-#if wxUSE_THREADS
- wxMutexGuiLeaveOrEnter();
-#endif // wxUSE_THREADS
-
- while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
- ;
-
- // a message came or no more idle processing to do
- wxTheApp->DoMessage();
+ wxDialogModalDataTiedPtr modalData(&m_modalData,
+ new wxDialogModalData(this));
+ modalData->RunLoop();
}
gbInOnIdle = bWasInOnIdle;
//
- // Snd restore focus
+ // and restore focus
// Note that this code MUST NOT access the dialog object's data
// in case the object has been deleted (which will be the case
// for a modal dialog that has been destroyed before calling EndModal).
#ifndef WX_PRECOMP
#include "wx/window.h"
#include "wx/app.h"
+ #include "wx/timer.h"
#endif //WX_PRECOMP
#include "wx/evtloop.h"
+#include "wx/log.h"
#include "wx/tooltip.h"
+#include "wx/ptr_scpd.h"
#include "wx/os2/private.h"
#if wxUSE_THREADS
// define the array of QMSG strutures
WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
- // VS: this is a bit dirty - it duplicates same declaration in app.cpp
- // (and there's no WX_DEFINE_OBJARRAY for that reason - it is already
- // defined in app.cpp).
+
+ #include "wx/arrimpl.cpp"
+
+ WX_DEFINE_OBJARRAY(wxMsgArray);
#endif
-extern HAB vHabMain;
+extern HAB vHabmain;
// ----------------------------------------------------------------------------
// wxEventLoopImpl
int m_exitcode;
};
+// ----------------------------------------------------------------------------
+// helper class
+// ----------------------------------------------------------------------------
+
+wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoopImpl);
+
+// this object sets the wxEventLoop given to the ctor as the currently active
+// one and unsets it in its dtor
+class wxEventLoopActivator
+{
+public:
+ wxEventLoopActivator(wxEventLoop **pActive,
+ wxEventLoop *evtLoop)
+ {
+ m_pActive = pActive;
+ m_evtLoopOld = *pActive;
+ *pActive = evtLoop;
+ }
+
+ ~wxEventLoopActivator()
+ {
+ // restore the previously active event loop
+ *m_pActive = m_evtLoopOld;
+ }
+
+private:
+ wxEventLoop *m_evtLoopOld;
+ wxEventLoop **m_pActive;
+};
+
// ============================================================================
// wxEventLoopImpl implementation
// ============================================================================
if ( !PreProcessMessage(msg) )
{
// if it wasn't done, dispatch it to the corresponding window
- ::WinDispatchMsg(vHabMain, msg);
+ ::WinDispatchMsg(vHabmain, msg);
}
}
-bool wxEventLoopImpl::PreProcessMessage(QMSG *msg)
+bool wxEventLoopImpl::PreProcessMessage(QMSG *pMsg)
{
- HWND hWnd = msg->hwnd;
- wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd);
-
-#if wxUSE_TOOLTIPS
- // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
- // popup the tooltip bubbles
- if ( wndThis && (msg->message == WM_MOUSEMOVE) )
+ HWND hWnd = pMsg->hwnd;
+ wxWindow *pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
+ wxWindow *pWnd;
+
+ //
+ // Pass non-system timer messages to the wxTimerProc
+ //
+ if (pMsg->msg == WM_TIMER &&
+ (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
+ SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
+ SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
+ SHORT1FROMMP(pMsg->mp1) != 0x0000
+ ))
+ wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
+
+ // Allow the window to prevent certain messages from being
+ // translated/processed (this is currently used by wxTextCtrl to always
+ // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
+ //
+ if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage((WXMSG*)pMsg))
{
- wxToolTip *tt = wndThis->GetToolTip();
- if ( tt )
- {
- tt->RelayEvent((WXMSG *)msg);
- }
+ return FALSE;
}
-#endif // wxUSE_TOOLTIPS
- // try translations first; find the youngest window with a translation
- // table.
- wxWindow *wnd;
- for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
+ //
+ // For some composite controls (like a combobox), wndThis might be NULL
+ // because the subcontrol is not a wxWindow, but only the control itself
+ // is - try to catch this case
+ //
+ while (hWnd && !pWndThis)
{
- if ( wnd->OS2TranslateMessage((WXMSG *)msg) )
- return TRUE;
+ hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
+ pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
}
- // Anyone for a non-translation message? Try youngest descendants first.
- for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
+
+ //
+ // Try translations first; find the youngest window with
+ // a translation table. OS/2 has case sensiive accels, so
+ // this block, coded by BK, removes that and helps make them
+ // case insensitive.
+ //
+ if(pMsg->msg == WM_CHAR)
{
- if ( wnd->OS2ProcessMessage((WXMSG *)msg) )
- return TRUE;
+ PBYTE pChmsg = (PBYTE)&(pMsg->msg);
+ USHORT uSch = CHARMSG(pChmsg)->chr;
+ bool bRc = FALSE;
+
+ //
+ // Do not process keyup events
+ //
+ if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
+ {
+ if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
+ CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
+
+
+ for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
+ {
+ if((bRc = pWnd->OS2TranslateMessage((WXMSG*)pMsg)) == TRUE)
+ return TRUE;
+ // break;
+ // stop at first top level window, i.e. don't try to process the
+ // key strokes originating in a dialog using the accelerators of
+ // the parent frame - this doesn't make much sense
+ if ( pWnd->IsTopLevel() )
+ break;
+ }
+
+ if(!bRc) // untranslated, should restore original value
+ CHARMSG(pChmsg)->chr = uSch;
+ }
}
-
+ //
+ // Anyone for a non-translation message? Try youngest descendants first.
+ //
+// for (pWnd = pWndThis->GetParent(); pWnd; pWnd = pWnd->GetParent())
+// {
+// if (pWnd->OS2ProcessMessage(pWxmsg))
+// return TRUE;
+// }
return FALSE;
}
return m_impl != NULL;
}
+//////////////////////////////////////////////////////////////////////////////
+//
+// Keep trying to process messages until WM_QUIT
+// received.
+//
+// If there are messages to be processed, they will all be
+// processed and OnIdle will not be called.
+// When there are no more messages, OnIdle is called.
+// If OnIdle requests more time,
+// it will be repeatedly called so long as there are no pending messages.
+// A 'feature' of this is that once OnIdle has decided that no more processing
+// is required, then it won't get processing time until further messages
+// are processed (it'll sit in Dispatch).
+//
+//////////////////////////////////////////////////////////////////////////////
+class CallEventLoopMethod
+{
+public:
+ typedef void (wxEventLoop::*FuncType)();
+
+ CallEventLoopMethod(wxEventLoop *evtLoop, FuncType fn)
+ : m_evtLoop(evtLoop), m_fn(fn) { }
+ ~CallEventLoopMethod() { (m_evtLoop->*m_fn)(); }
+
+private:
+ wxEventLoop *m_evtLoop;
+ FuncType m_fn;
+};
+
int wxEventLoop::Run()
{
// event loops are not recursive, you need to create another loop!
wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
- m_impl = new wxEventLoopImpl;
+ // SendIdleMessage() and Dispatch() below may throw so the code here should
+ // be exception-safe, hence we must use local objects for all actions we
+ // should undo
+ wxEventLoopActivator activate(&ms_activeLoop, this);
+ wxEventLoopImplTiedPtr impl(&m_impl, new wxEventLoopImpl);
- wxEventLoop *oldLoop = ms_activeLoop;
- ms_activeLoop = this;
+ CallEventLoopMethod callOnExit(this, &wxEventLoop::OnExit);
for ( ;; )
{
// generate and process idle events for as long as we don't have
// anything else to do
while ( !Pending() && m_impl->SendIdleMessage() )
- ;
-
- // a message came or no more idle processing to do, sit in Dispatch()
- // waiting for the next message
- if ( !Dispatch() )
- {
- // we got WM_QUIT
- break;
- }
+ {
+ wxTheApp->HandleSockets();
+ wxUsleep(10);
+ }
+
+ wxTheApp->HandleSockets();
+ if (Pending())
+ {
+ if ( !Dispatch() )
+ {
+ // we got WM_QUIT
+ break;
+ }
+ }
+ else
+ wxUsleep(10);
}
- int exitcode = m_impl->GetExitCode();
- delete m_impl;
- m_impl = NULL;
-
- ms_activeLoop = oldLoop;
-
- return exitcode;
+ return m_impl->GetExitCode();
}
void wxEventLoop::Exit(int rc)
bool wxEventLoop::Pending() const
{
QMSG msg;
- return ::WinPeekMsg(vHabMain, &msg, 0, 0, 0, PM_NOREMOVE) != 0;
+ return ::WinPeekMsg(vHabmain, &msg, 0, 0, 0, PM_NOREMOVE) != 0;
}
bool wxEventLoop::Dispatch()
wxCHECK_MSG( IsRunning(), FALSE, _T("can't call Dispatch() if not running") );
QMSG msg;
- BOOL rc = ::WinGetMsg(vHabMain, &msg, (HWND) NULL, 0, 0);
+ BOOL bRc = ::WinGetMsg(vHabmain, &msg, (HWND) NULL, 0, 0);
- if ( rc == 0 )
+ if ( bRc == 0 )
{
// got WM_QUIT
return FALSE;
}
- if ( rc == -1 )
- {
- // should never happen, but let's test for it nevertheless
- wxLogLastError(wxT("GetMessage"));
-
- // still break from the loop
- return FALSE;
- }
-
#if wxUSE_THREADS
wxASSERT_MSG( wxThread::IsMain(),
wxT("only the main thread can process Windows messages") );
// leave out WM_COMMAND messages: too dangerous, sometimes
// the message will be processed twice
- if ( !wxIsWaitingForThread() || msg.message != WM_COMMAND )
+ if ( !wxIsWaitingForThread() || msg.msg != WM_COMMAND )
{
s_aSavedMessages.Add(msg);
}
size_t count = s_aSavedMessages.Count();
for ( size_t n = 0; n < count; n++ )
{
- MSG& msg = s_aSavedMessages[n];
+ QMSG& msg = s_aSavedMessages[n];
m_impl->ProcessMessage(&msg);
}
while (::WinPeekMsg(vHabmain, &vMsg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
&& vMsg.msg != WM_QUIT)
{
- wxTheApp->DoMessage((WXMSG*)&vMsg);
+ // luckily (as we don't have access to wxEventLoopImpl method from here
+ // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
+ // immediately
+ ::WinDispatchMsg(vHabmain, &vMsg);
}
if (vMsg.msg == WM_QUIT)
::WinPostMsg(NULL, WM_QUIT, 0, 0);