From e39af974ef7846e26686ae39d74e4696c1fef0c3 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Wed, 9 Jul 2003 10:15:21 +0000
Subject: [PATCH] - Moved wxApp::SendIdleEvents and wxApp::ProcessIdle into
 common code. - wxWindow::OnInternalIdle is now used in all ports, and ensures
 that   user OnIdle events do not interfere with crucial internal processing.
 - wxWindow::UpdateWindowUI is now a documented function that   sends
 wxUpdateUIEvents, and can be overridden. It has a helper function  
 DoUpdateWindowUI for taking appropriate wxUpdateUIEvent action. - Added
 functions to wxUpdateUIEvent: Set/GetMode, Set/GetUpdateInterval,  
 CanUpdate, to assist with optimising update event frequency. - Added
 functions to wxIdleEvent: Set/GetMode, CanSend, to   determine whether a
 window should receive idle events. - Added wxWS_EX_PROCESS_IDLE,
 wxWS_EX_PROCESS_UI_UPDATES window   styles for use with conservative idle and
 update event modes. - wxMSW and wxGTK now send menu update events only when a
 menu is   about to be used. - Added WM_INITMENU processing instead of
 WM_ENTERMENULOOP, or   accelerators don't always get called since menu items
 may still   be disabled.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@21789 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |  14 +++++
 docs/latex/wx/idleevt.tex  |  62 ++++++++++++++++++-
 docs/latex/wx/upduievt.tex | 117 +++++++++++++++++++++++++++++++++++
 docs/latex/wx/window.tex   | 110 +++++++++++++++++++++++++++++++++
 include/wx/app.h           |  10 ++-
 include/wx/cocoa/app.h     |   9 +--
 include/wx/defs.h          |  17 ++++++
 include/wx/event.h         |  61 +++++++++++++++++--
 include/wx/frame.h         |   7 ++-
 include/wx/gtk/app.h       |   5 --
 include/wx/gtk1/app.h      |   5 --
 include/wx/mac/app.h       |   9 ---
 include/wx/mac/window.h    |   3 +-
 include/wx/mgl/app.h       |   3 -
 include/wx/mgl/window.h    |   2 +-
 include/wx/motif/app.h     |   9 ---
 include/wx/motif/window.h  |   6 +-
 include/wx/msw/app.h       |   9 ---
 include/wx/msw/frame.h     |   3 +
 include/wx/msw/window.h    |   5 +-
 include/wx/os2/app.h       |   9 ---
 include/wx/tbarbase.h      |   4 +-
 include/wx/textctrl.h      |   3 +
 include/wx/toplevel.h      |   3 +
 include/wx/univ/listbox.h  |   3 +-
 include/wx/univ/scrolbar.h |   6 +-
 include/wx/univ/textctrl.h |   3 +-
 include/wx/window.h        |  15 ++++-
 include/wx/x11/app.h       |   9 ---
 include/wx/x11/textctrl.h  |   2 +-
 include/wx/x11/window.h    |   3 -
 src/cocoa/app.mm           |  54 ----------------
 src/common/appcmn.cpp      |  66 ++++++++++++++++++++
 src/common/event.cpp       |  45 +++++++++++---
 src/common/framecmn.cpp    |  36 +++++++++--
 src/common/tbarbase.cpp    |  13 +---
 src/common/textcmn.cpp     |  14 +++++
 src/common/toplvcmn.cpp    |  13 ++++
 src/common/wincmn.cpp      |  79 +++++++++++++++---------
 src/gtk/app.cpp            |  79 ------------------------
 src/gtk/checkbox.cpp       |   4 +-
 src/gtk/frame.cpp          |   2 +-
 src/gtk/listbox.cpp        |   4 +-
 src/gtk/radiobut.cpp       |   4 +-
 src/gtk/tbargtk.cpp        |   4 +-
 src/gtk/textctrl.cpp       |   4 +-
 src/gtk/tglbtn.cpp         |   4 +-
 src/gtk/window.cpp         |   4 +-
 src/gtk1/app.cpp           |  79 ------------------------
 src/gtk1/checkbox.cpp      |   4 +-
 src/gtk1/frame.cpp         |   2 +-
 src/gtk1/listbox.cpp       |   4 +-
 src/gtk1/radiobut.cpp      |   4 +-
 src/gtk1/tbargtk.cpp       |   4 +-
 src/gtk1/textctrl.cpp      |   4 +-
 src/gtk1/tglbtn.cpp        |   4 +-
 src/gtk1/window.cpp        |   4 +-
 src/mac/app.cpp            |  54 +---------------
 src/mac/carbon/app.cpp     |  54 +---------------
 src/mac/carbon/window.cpp  |   7 +--
 src/mac/window.cpp         |   7 +--
 src/mgl/app.cpp            |  51 ----------------
 src/mgl/evtloop.cpp        |   8 +--
 src/mgl/window.cpp         |   7 +--
 src/motif/app.cpp          |  54 ----------------
 src/motif/window.cpp       |   7 +--
 src/msw/app.cpp            |  51 ----------------
 src/msw/evtloop.cpp        |   8 +--
 src/msw/frame.cpp          |  31 +++++++---
 src/msw/window.cpp         | 122 +++----------------------------------
 src/os2/app.cpp            |  59 ------------------
 src/os2/evtloop.cpp        |   8 +--
 src/os2/window.cpp         |   4 +-
 src/univ/listbox.cpp       |   6 +-
 src/univ/menu.cpp          |   3 +-
 src/univ/scrolbar.cpp      |   4 +-
 src/univ/textctrl.cpp      |   6 +-
 src/x11/app.cpp            |  59 ------------------
 src/x11/evtloop.cpp        |   9 +--
 src/x11/textctrl.cpp       |   5 +-
 src/x11/window.cpp         |   4 +-
 81 files changed, 733 insertions(+), 959 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index 859cdd49e1..45e927310e 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -103,6 +103,20 @@ All GUI ports:
 - Added m_ prefix to wxColourData and wxFontData members
 - Added wxHtmlPrintout::AddFilter so HTML printing can be subject to
   custom filters as well as HTML viewing.
+- Moved wxApp::SendIdleEvents and wxApp::ProcessIdle into common code.
+- wxWindow::OnInternalIdle is now used in all ports, and ensures that
+  user OnIdle events do not interfere with crucial internal processing.
+- wxWindow::UpdateWindowUI is now a documented function that
+  sends wxUpdateUIEvents, and can be overridden. It has a helper function
+  DoUpdateWindowUI for taking appropriate wxUpdateUIEvent action.
+- Added functions to wxUpdateUIEvent: Set/GetMode, Set/GetUpdateInterval,
+  CanUpdate, to assist with optimising update event frequency.
+- Added functions to wxIdleEvent: Set/GetMode, CanSend, to
+  determine whether a window should receive idle events.
+- Added wxWS_EX_PROCESS_IDLE, wxWS_EX_PROCESS_UI_UPDATES window
+  styles for use with conservative idle and update event modes.
+- wxMSW and wxGTK now send menu update events only when a menu is
+  about to be used.
 
 Unix:
 
diff --git a/docs/latex/wx/idleevt.tex b/docs/latex/wx/idleevt.tex
index 5ba984e481..329c0b8ef8 100644
--- a/docs/latex/wx/idleevt.tex
+++ b/docs/latex/wx/idleevt.tex
@@ -2,6 +2,15 @@
 
 This class is used for idle events, which are generated when the system is idle.
 
+By default, idle events are sent to all windows. If this is causing a significant
+overhead in your application, you can call \helpref{wxIdleEvent::SetMode}{wxidleeventsetmode} with
+the value wxIDLE\_PROCESS\_SPECIFIED, and set the wxWS\_EX\_PROCESS\_IDLE extra
+window style for every window which should receive idle events.
+
+The function \helpref{wxWindow::OnInternalIdle}{wxwindowoninternalidle} is
+also provided for internal purposes, and cannot be disabled. wxUpdateUIEvents
+are sent from OnInternalIdle.
+
 \wxheading{Derived from}
 
 \helpref{wxEvent}{wxevent}\\
@@ -27,7 +36,8 @@ Idle events can be caught by the wxApp class, or by top-level window classes.
 
 \wxheading{See also}
 
-\helpref{Event handling overview}{eventhandlingoverview}
+\helpref{Event handling overview}{eventhandlingoverview}, \helpref{wxUpdateUIEvent}{wxupdateuievent}, 
+\helpref{wxWindow::OnInternalIdle}{wxwindowoninternalidle}
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
@@ -37,6 +47,33 @@ Idle events can be caught by the wxApp class, or by top-level window classes.
 
 Constructor.
 
+\membersection{wxIdleEvent::CanSend}\label{wxidleeventcansend}
+
+\func{static bool}{CanSend}{\param{wxWindow*}{ window}}
+
+Returns {\tt true} if it is appropriate to send idle events to
+this window.
+
+This function looks at the mode used (see \helpref{wxIdleEvent::SetMode}{wxidleeventsetmode}),
+and the wxWS\_EX\_PROCESS\_IDLE style in {\it window} to determine whether idle events should be sent to
+this window now. By default this will always return {\tt true} because
+the update mode is initially wxIDLE\_PROCESS\_ALL. You can change the mode
+to only send idle events to windows with the wxWS\_EX\_PROCESS\_IDLE extra window style set.
+
+\wxheading{See also}
+
+\helpref{wxIdleEvent::SetMode}{wxidlesetmode}
+
+\membersection{wxIdleEvent::GetMode}\label{wxidleeventgetmode}
+
+\func{static wxIdleMode}{GetMode}{\void}
+
+Static function returning a value specifying how wxWindows
+will send idle events: to all windows, or only to those which specify that they
+will process the events.
+
+See \helpref{wxIdleEvent::SetMode}{wxidleeventsetmode}.
+
 \membersection{wxIdleEvent::RequestMore}\label{wxidleeventrequestmore}
 
 \func{void}{RequestMore}{\param{bool}{ needMore = true}}
@@ -61,3 +98,26 @@ Returns true if the OnIdle function processing this event requested more process
 
 \helpref{wxIdleEvent::RequestMore}{wxidleeventrequestmore}
 
+\membersection{wxIdleEvent::SetMode}\label{wxidleeventsetmode}
+
+\func{static void}{SetMode}{\param{wxIdleMode }{mode}}
+
+Static function for specifying how wxWindows will send idle events: to
+all windows, or only to those which specify that they
+will process the events.
+
+{\it mode} can be one of the following values.
+The default is wxIDLE\_PROCESS\_ALL.
+
+\begin{verbatim}
+enum wxIdleMode
+{
+        // Send idle events to all windows
+    wxIDLE_PROCESS_ALL,
+
+        // Send idle events to windows that have
+        // the wxWS_EX_PROCESS_IDLE flag specified
+    wxIDLE_PROCESS_SPECIFIED
+};
+\end{verbatim}
+
diff --git a/docs/latex/wx/upduievt.tex b/docs/latex/wx/upduievt.tex
index a82b4af74c..8cb08b8aa5 100644
--- a/docs/latex/wx/upduievt.tex
+++ b/docs/latex/wx/upduievt.tex
@@ -46,6 +46,29 @@ These events will work for popup menus as well as menubars. Just before a menu i
 up, \helpref{wxMenu::UpdateUI}{wxmenuupdateui} is called to process any UI events for
 the window that owns the menu.
 
+If you find that the overhead of UI update processing is affecting
+your application, you can do one or both of the following:
+
+\begin{enumerate}
+\item Call \helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode} with
+a value of wxUPDATE\_UI\_PROCESS\_SPECIFIED, and set the extra style
+wxWS\_EX\_PROCESS\_UPDATE\_EVENTS for every window that should receive update events.
+No other windows will receive update events.
+\item Call \helpref{wxUpdateUIEvent::SetUpdateInterval}{wxupdateuieventsetupdateinterval} with
+a millisecond value to set the delay between updates. You may need
+to call \helpref{wxWindow::UpdateWindowUI}{wxwindowupdatewindowui} at critical
+points, for example when a dialog is about to be shown, in case the user
+sees a slight delay before windows are updated.
+\end{enumerate}
+
+Note that although events are sent in idle time, defining a wxIdleEvent
+handler for a window does not affect this because the events are sent from \helpref{wxWindow::OnInternalIdle}{wxwindowoninternalidle} 
+which is {\bf always} called in idle time.
+
+wxWindows tries to optimize update events on some platforms. On Windows
+and GTK+, events for menubar items are only sent when the menu is about
+to be shown, and not in idle time.
+
 \wxheading{See also}
 
 \helpref{Event handling overview}{eventhandlingoverview}
@@ -95,6 +118,29 @@ true if the application has set the {\bf m\_text} member.
 Holds the text with which the the application wishes to
 update the UI element.
 
+\membersection{wxUpdateUIEvent::CanUpdate}\label{wxupdateuieventcanupdate}
+
+\func{static bool}{CanUpdate}{\param{wxWindow*}{ window}}
+
+Returns {\tt true} if it is appropriate to update (send UI update events to)
+this window.
+
+This function looks at the mode used (see \helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode}),
+the wxWS\_EX\_PROCESS\_UPDATE\_EVENTS flag in {\it window},
+the time update events were last sent in idle time, and
+the update interval, to determine whether events should be sent to
+this window now. By default this will always return {\tt true} because
+the update mode is initially wxUPDATE\_UI\_PROCESS\_ALL and
+the interval is set to 0; so update events will be sent as
+often as possible. You can reduce the frequency that events
+are sent by changing the mode and/or setting an update interval.
+
+\wxheading{See also}
+
+\helpref{wxUpdateUIEvent::ResetUpdateTime}{wxupdateuieventresetupdatetime}, 
+\helpref{wxUpdateUIEvent::SetUpdateInterval}{wxupdateuieventsetupdateinterval}, 
+\helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode}
+
 \membersection{wxUpdateUIEvent::Check}\label{wxupdateuieventcheck}
 
 \func{void}{Check}{\param{bool}{ check}}
@@ -143,9 +189,80 @@ Returns true if the application has called {\bf SetText}. For wxWindows internal
 
 Returns the text that should be set for the UI element.
 
+\membersection{wxUpdateUIEvent::GetMode}\label{wxupdateuieventgetmode}
+
+\func{static wxUpdateUIMode}{GetMode}{\void}
+
+Static function returning a value specifying how wxWindows
+will send update events: to all windows, or only to those which specify that they
+will process the events.
+
+See \helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode}.
+
+\membersection{wxUpdateUIEvent::GetUpdateInterval}\label{wxupdateuieventgetupdateinterval}
+
+\func{static long}{GetUpdateInterval}{\void}
+
+Returns the current interval between updates in milliseconds.
+-1 disables updates, 0 updates as frequently as possible.
+
+See \helpref{wxUpdateUIEvent::SetUpdateInterval}{wxupdateuieventsetupdateinterval}.
+
+\membersection{wxUpdateUIEvent::ResetUpdateTime}\label{wxupdateuieventresetupdatetime}
+
+\func{static void}{ResetUpdateTime}{\void}
+
+Used internally to reset the last-updated time to the
+current time. It is assumed that update events are
+normally sent in idle time, so this is called at the end of
+idle processing.
+
+\wxheading{See also}
+
+\helpref{wxUpdateUIEvent::CanUpdate}{wxupdateuieventcanupdate}, 
+\helpref{wxUpdateUIEvent::SetUpdateInterval}{wxupdateuieventsetupdateinterval}, 
+\helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode}
+
+\membersection{wxUpdateUIEvent::SetMode}\label{wxupdateuieventsetmode}
+
+\func{static void}{SetMode}{\param{wxIdleMode }{mode}}
+
+Specify how wxWindows will send update events: to
+all windows, or only to those which specify that they
+will process the events.
+
+{\it mode} may be one of the following values.
+The default is wxUPDATE\_UI\_PROCESS\_ALL.
+
+\begin{verbatim}
+enum wxUpdateUIMode
+{
+        // Send UI update events to all windows
+    wxUPDATE_UI_PROCESS_ALL,
+
+        // Send UI update events to windows that have
+        // the wxWS_EX_PROCESS_UI_UPDATES flag specified
+    wxUPDATE_UI_PROCESS_SPECIFIED
+};
+\end{verbatim}
+
 \membersection{wxUpdateUIEvent::SetText}\label{wxupdateuieventsettext}
 
 \func{void}{SetText}{\param{const wxString\&}{ text}}
 
 Sets the text for this UI element.
 
+\membersection{wxUpdateUIEvent::SetUpdateInterval}\label{wxupdateuieventsetupdateinterval}
+
+\func{static void}{SetUpdateInterval}{\param{long }{updateInterval}}
+
+Sets the interval between updates in milliseconds.
+Set to -1 to disable updates, or to 0 to update as frequently as possible.
+The default is 0.
+
+Use this to reduce the overhead of UI update events if your application
+has a lot of windows. If you set the value to -1 or greater than 0,
+you may also need to call \helpref{wxWindow::UpdateWindowUI}{wxwindowupdatewindowui} 
+at appropriate points in your application, such as when a dialog
+is about to be shown.
+
diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index 666ffa1dcd..752b905bca 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -57,6 +57,30 @@ repainted, then children being painted over them. Windows only.}
 
 See also \helpref{window styles overview}{windowstyles}.
 
+\wxheading{Extra window styles}
+
+The following are extra styles, set using \helpref{wxWindow::SetExtraStyle}{wxwindowsetextrastyle}.
+
+\twocolwidtha{5cm}%
+\begin{twocollist}\itemsep=0pt
+\twocolitem{\windowstyle{wxWS\_EX\_VALIDATE\_RECURSIVELY}}{By default, Validate/TransferDataTo/FromWindow()
+only work on direct children of the window (compatible behaviour). Set this flag to make them recursively
+descend into all subwindows.}
+\twocolitem{\windowstyle{wxWS\_EX\_BLOCK\_EVENTS}}{wxCommandEvents and the objects of the derived classes are forwarded to the
+parent window and so on recursively by default. Using this flag for the
+given window allows to block this propagation at this window, i.e. prevent
+the events from being propagated further upwards. Dialogs have this
+flag on by default.}
+\twocolitem{\windowstyle{wxWS\_EX\_TRANSIENT}}{Don't use this window as an implicit parent for the other windows: this must
+be used with transient windows as otherwise there is the risk of creating a
+dialog/frame with this window as a parent which would lead to a crash if the
+parent is destroyed before the child.}
+\twocolitem{\windowstyle{wxWS\_EX\_PROCESS\_IDLE}}{This window should always process idle events, even
+if the mode set by \helpref{wxIdleEvent::SetMode}{wxidleeventsetmode} is wxIDLE\_PROCESS\_SPECIFIED.}
+\twocolitem{\windowstyle{wxWS\_EX\_PROCESS\_UI\_UPDATES}}{This window should always process UI update events,
+even if the mode set by \helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode} is wxUPDATE\_UI\_PROCESS\_SPECIFIED.}
+\end{twocollist}
+
 \wxheading{See also}
 
 \helpref{Event handling overview}{eventhandlingoverview}
@@ -408,6 +432,31 @@ Disables the window, same as \helpref{Enable({\tt false})}{wxwindowenable}.
 Returns {\tt true} if the window has been disabled, {\tt false} if it had been
 already disabled before the call to this function.
 
+\membersection{wxWindow::DoUpdateWindowUI}\label{wxwindowdoupdatewindowui}
+
+\func{virtual void}{DoUpdateWindowUI}{\param{wxUpdateUIEvent\&}{ event}}
+
+Does the window-specific updating after processing the update event.
+This function is called by \helpref{wxWindow::UpdateWindowUI}{wxwindowupdatewindowui} 
+in order to check return values in the \helpref{wxUpdateUIEvent}{wxupdateuievent} and
+act appropriately. For example, to allow frame and dialog title updating, wxWindows
+implements this function as follows:
+
+\begin{verbatim}
+// do the window-specific processing after processing the update event
+void wxTopLevelWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
+{
+    if ( event.GetSetEnabled() )
+        Enable(event.GetEnabled());
+    
+    if ( event.GetSetText() )
+    {
+        if ( event.GetText() != GetTitle() )
+            SetTitle(event.GetText());
+    }
+}
+\end{verbatim}
+
 \membersection{wxWindow::DragAcceptFiles}\label{wxwindowdragacceptfiles}
 
 \func{virtual void}{DragAcceptFiles}{\param{bool}{ accept}}
@@ -1684,6 +1733,19 @@ implements the following methods:\par
 %% \helpref{wxSysColourChangedEvent}{wxsyscolourchangedevent},\rtfsp
 %% \helpref{Event handling overview}{eventhandlingoverview}
 
+\membersection{wxWindow::OnInternalIdle}\label{wxwindowoninternalidle}
+
+\func{virtual void}{OnInternalIdle}{\void}
+
+This virtual function is normally only used internally, but
+sometimes an application may need it to implement functionality
+that should not be disabled by an application defining an OnIdle
+handler in a derived class.
+
+This function may be used to do delayed painting, for example,
+and most implementations call \helpref{wxWindow::UpdateWindowUI}{wxwindowupdatewindowui} 
+in order to send update events to the window in idle time.
+
 \membersection{wxWindow::PageDown}\label{wxwindowpagedown}
 
 This is just a wrapper for \helpref{ScrollPages()}{wxwindowscrollpages}$(1)$.
@@ -2751,6 +2813,54 @@ nothing if the window hadn't been already repainted. Use
 \helpref{Refresh}{wxwindowrefresh} first if you want to immediately redraw the
 window unconditionally.
 
+\membersection{wxWindow::UpdateWindowUI}\label{wxwindowupdatewindowui}
+
+\func{virtual void}{UpdateWindowUI}{\param{long}{ flags = wxUPDATE_UI_NONE}}
+
+This function sends \helpref{wxUpdateUIEvents}{wxupdateuievent} to
+the window. The particular implementation depends on the window; for
+example a wxToolBar will send an update UI event for each toolbar button,
+and a wxFrame will send an update UI event for each menubar menu item.
+You can call this function from your application to ensure that your
+UI is up-to-date at this point (as far as your wxUpdateUIEvent handlers
+are concerned). This may be necessary if you have called 
+\helpref{wxUpdateUIEvent::SetMode}{wxupdateuieventsetmode} or 
+\helpref{wxUpdateUIEvent::SetUpdateInterval}{wxupdateuieventsetupdateinterval} to
+limit the overhead that wxWindows incurs by sending update UI events in idle time.
+
+{\it flags} should be a bitlist of one or more of the following values.
+
+\begin{verbatim}
+enum wxUpdateUI
+{
+    wxUPDATE_UI_NONE          = 0x0000, // No particular value
+    wxUPDATE_UI_RECURSE       = 0x0001, // Call the function for descendants
+    wxUPDATE_UI_FROMIDLE      = 0x0002  // Invoked from On(Internal)Idle
+};
+\end{verbatim}
+
+If you are calling this function from an OnInternalIdle or OnIdle
+function, make sure you pass the wxUPDATE\_UI\_FROMIDLE flag, since
+this tells the window to only update the UI elements that need
+to be updated in idle time. Some windows update their elements
+only when necessary, for example when a menu is about to be shown.
+The following is an example of how to call UpdateWindowUI from
+an idle function.
+
+\begin{verbatim}
+void MyWindow::OnInternalIdle()
+{
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+}
+\end{verbatim}
+
+\wxheading{See also}
+
+\helpref{wxUpdateUIEvent}{wxupdateuievent}, 
+\helpref{wxWindow::DoUpdateWindowUI}{wxwindowdoupdatewindowui}, 
+\helpref{wxWindow::OnInternalIdle}{wxwindowoninternalidle}
+
 \membersection{wxWindow::Validate}\label{wxwindowvalidate}
 
 \func{virtual bool}{Validate}{\void}
diff --git a/include/wx/app.h b/include/wx/app.h
index c541b9015a..c479f17df7 100644
--- a/include/wx/app.h
+++ b/include/wx/app.h
@@ -379,7 +379,15 @@ public:
         // parties
         //
         // it should return TRUE if more idle events are needed, FALSE if not
-    virtual bool ProcessIdle() = 0;
+    virtual bool ProcessIdle() ;
+
+        // Send idle event to all top-level windows.
+        // Returns TRUE if more idle time is requested.
+    virtual bool SendIdleEvents();
+
+        // Send idle event to window and all subwindows
+        // Returns TRUE if more idle time is requested.
+    virtual bool SendIdleEvents(wxWindow* win);
 
 
     // top level window functions
diff --git a/include/wx/cocoa/app.h b/include/wx/cocoa/app.h
index ea155949a9..02bf4fa5b0 100644
--- a/include/wx/cocoa/app.h
+++ b/include/wx/cocoa/app.h
@@ -51,18 +51,11 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle() { CocoaRequestIdle(); }
     
     /* Idle Processing */
     void OnIdle(wxIdleEvent& event);
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents();
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindowCocoa* win);
-    
+
     virtual bool Initialize(int& argc, wxChar **argv);
     virtual void CleanUp();
     virtual bool CallOnInit();
diff --git a/include/wx/defs.h b/include/wx/defs.h
index 50e98c4c47..85331769e6 100644
--- a/include/wx/defs.h
+++ b/include/wx/defs.h
@@ -1033,6 +1033,12 @@ enum wxBorder
 // possibly be made to work in the future, at least on Windows
 #define wxWS_EX_THEMED_BACKGROUND       0x00000008
 
+// this window should always process idle events
+#define wxWS_EX_PROCESS_IDLE            0x00000010
+
+// this window should always process UI update events
+#define wxWS_EX_PROCESS_UI_UPDATES      0x00000020
+
 // Use this style to add a context-sensitive help to the window (currently for
 // Win32 only and it doesn't work if wxMINIMIZE_BOX or wxMAXIMIZE_BOX are used)
 #define wxFRAME_EX_CONTEXTHELP  0x00000004
@@ -1860,6 +1866,17 @@ enum wxPrintMode
     wxPRINT_MODE_PRINTER = 3    // Send to printer
 };
 
+// ----------------------------------------------------------------------------
+// UpdateWindowUI flags
+// ----------------------------------------------------------------------------
+
+enum wxUpdateUI
+{
+    wxUPDATE_UI_NONE          = 0x0000,
+    wxUPDATE_UI_RECURSE       = 0x0001,
+    wxUPDATE_UI_FROMIDLE      = 0x0002 // Invoked from On(Internal)Idle
+};
+
 // ----------------------------------------------------------------------------
 // miscellaneous
 // ----------------------------------------------------------------------------
diff --git a/include/wx/event.h b/include/wx/event.h
index 7287f675fc..a61b0a9d42 100644
--- a/include/wx/event.h
+++ b/include/wx/event.h
@@ -1496,6 +1496,20 @@ private:
  wxEVT_UPDATE_UI
  */
 
+// Whether to always send update events to windows, or
+// to only send update events to those with the
+// wxWS_EX_PROCESS_UI_UPDATES style.
+
+enum wxUpdateUIMode
+{
+        // Send UI update events to all windows
+    wxUPDATE_UI_PROCESS_ALL,
+
+        // Send UI update events to windows that have
+        // the wxWS_EX_PROCESS_UI_UPDATES flag specified
+    wxUPDATE_UI_PROCESS_SPECIFIED
+};
+
 class WXDLLIMPEXP_CORE wxUpdateUIEvent : public wxCommandEvent
 {
 public:
@@ -1531,18 +1545,26 @@ public:
 
     // Sets the interval between updates in milliseconds.
     // Set to -1 to disable updates, or to 0 to update as frequently as possible.
-    static void SetUpdateInterval(long updateInterval) { m_updateInterval = updateInterval; }
+    static void SetUpdateInterval(long updateInterval) { sm_updateInterval = updateInterval; }
 
     // Returns the current interval between updates in milliseconds
-    static long GetUpdateInterval() { return m_updateInterval ; }
+    static long GetUpdateInterval() { return sm_updateInterval ; }
 
-    // Can we update?
-    static bool CanUpdate() ;
+    // Can we update this window?
+    static bool CanUpdate(wxWindow* win) ;
 
     // Reset the update time to provide a delay until the next
     // time we should update
     static void ResetUpdateTime() ;
 
+    // Specify how wxWindows will send update events: to
+    // all windows, or only to those which specify that they
+    // will process the events.
+    static void SetMode(wxUpdateUIMode mode) { sm_updateMode = mode; }
+
+    // Returns the UI update mode
+    static wxUpdateUIMode GetMode() { return sm_updateMode ; }
+
     virtual wxEvent *Clone() const { return new wxUpdateUIEvent(*this); }
 
 protected:
@@ -1553,9 +1575,10 @@ protected:
     bool          m_setChecked;
     wxString      m_text;
 #if wxUSE_LONGLONG
-    static wxLongLong   m_lastUpdate;
+    static wxLongLong       sm_lastUpdate;
 #endif
-    static long         m_updateInterval;
+    static long             sm_updateInterval;
+    static wxUpdateUIMode   sm_updateMode;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxUpdateUIEvent)
@@ -1875,6 +1898,20 @@ private:
  wxEVT_IDLE
  */
 
+// Whether to always send idle events to windows, or
+// to only send update events to those with the
+// wxWS_EX_PROCESS_IDLE style.
+
+enum wxIdleMode
+{
+        // Send idle events to all windows
+    wxIDLE_PROCESS_ALL,
+
+        // Send idle events to windows that have
+        // the wxWS_EX_PROCESS_IDLE flag specified
+    wxIDLE_PROCESS_SPECIFIED
+};
+
 class WXDLLIMPEXP_CORE wxIdleEvent : public wxEvent
 {
 public:
@@ -1892,8 +1929,20 @@ public:
 
     virtual wxEvent *Clone() const { return new wxIdleEvent(*this); }
 
+    // Specify how wxWindows will send idle events: to
+    // all windows, or only to those which specify that they
+    // will process the events.
+    static void SetMode(wxIdleMode mode) { sm_idleMode = mode; }
+
+    // Returns the idle event mode
+    static wxIdleMode GetMode() { return sm_idleMode ; }
+
+    // Can we send an idle event?
+    static bool CanSend(wxWindow* win) ;
+
 protected:
     bool m_requestMore;
+    static wxIdleMode sm_idleMode;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxIdleEvent)
diff --git a/include/wx/frame.h b/include/wx/frame.h
index 02f03cc71d..646cce0a23 100644
--- a/include/wx/frame.h
+++ b/include/wx/frame.h
@@ -141,7 +141,6 @@ public:
     // -------------------------------
 
     // event handlers
-    void OnIdle(wxIdleEvent& event);
     void OnMenuOpen(wxMenuEvent& event);
     void OnMenuHighlight(wxMenuEvent& event);
 
@@ -151,6 +150,12 @@ public:
     void DoMenuUpdates(wxMenu* menu, wxWindow* focusWin);
 #endif // wxUSE_MENUS
 
+    // do the UI update processing for this window
+    virtual void UpdateWindowUI(long flags = wxUPDATE_UI_NONE);
+
+    // Implement internal behaviour (menu updating on some platforms)
+    virtual void OnInternalIdle();
+
     // if there is no real wxTopLevelWindow on this platform we have to define
     // some wxTopLevelWindowBase pure virtual functions here to avoid breaking
     // old ports (wxMotif) which don't define them in wxFrame
diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h
index f03e5aa1ff..9b6143d198 100644
--- a/include/wx/gtk/app.h
+++ b/include/wx/gtk/app.h
@@ -50,13 +50,10 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle();
 
     // implementation only from now on
     void OnIdle( wxIdleEvent &event );
-    bool SendIdleEvents();
-    bool SendIdleEvents( wxWindow* win );
 
     virtual bool Initialize(int& argc, wxChar **argv);
     virtual void CleanUp();
@@ -90,8 +87,6 @@ private:
     bool m_isInAssert;
 #endif // __WXDEBUG__
 
-    bool CallInternalIdle( wxWindow* win );
-
     DECLARE_DYNAMIC_CLASS(wxApp)
     DECLARE_EVENT_TABLE()
 };
diff --git a/include/wx/gtk1/app.h b/include/wx/gtk1/app.h
index f03e5aa1ff..9b6143d198 100644
--- a/include/wx/gtk1/app.h
+++ b/include/wx/gtk1/app.h
@@ -50,13 +50,10 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle();
 
     // implementation only from now on
     void OnIdle( wxIdleEvent &event );
-    bool SendIdleEvents();
-    bool SendIdleEvents( wxWindow* win );
 
     virtual bool Initialize(int& argc, wxChar **argv);
     virtual void CleanUp();
@@ -90,8 +87,6 @@ private:
     bool m_isInAssert;
 #endif // __WXDEBUG__
 
-    bool CallInternalIdle( wxWindow* win );
-
     DECLARE_DYNAMIC_CLASS(wxApp)
     DECLARE_EVENT_TABLE()
 };
diff --git a/include/wx/mac/app.h b/include/wx/mac/app.h
index 99556638d1..7269c6e0d7 100644
--- a/include/wx/mac/app.h
+++ b/include/wx/mac/app.h
@@ -56,7 +56,6 @@ class WXDLLEXPORT wxApp: public wxAppBase
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle();
     
     virtual void SetPrintMode(int mode) { m_printMode = mode; }
@@ -71,14 +70,6 @@ class WXDLLEXPORT wxApp: public wxAppBase
     void OnEndSession(wxCloseEvent& event);
     void OnQueryEndSession(wxCloseEvent& event);
     
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents();
-    
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindowMac* win);
-    
     // Windows only, but for compatibility...
     inline void SetAuto3D(bool flag) { m_auto3D = flag; }
     inline bool GetAuto3D() const { return m_auto3D; }
diff --git a/include/wx/mac/window.h b/include/wx/mac/window.h
index fad0b98ade..c9dcce20c7 100644
--- a/include/wx/mac/window.h
+++ b/include/wx/mac/window.h
@@ -173,7 +173,6 @@ public:
     void OnSetFocus(wxFocusEvent& event) ;
     void OnNcPaint(wxNcPaintEvent& event);
     void OnEraseBackground(wxEraseEvent& event);
-    void OnIdle(wxIdleEvent& event);
     void OnMouseEvent( wxMouseEvent &event ) ;
 
     void MacOnScroll(wxScrollEvent&event ) ;
@@ -181,6 +180,8 @@ public:
     bool AcceptsFocus() const ;
 
 public:
+    void OnInternalIdle();
+
     // For implementation purposes - sometimes decorations make the client area
     // smaller
     virtual wxPoint GetClientAreaOrigin() const;
diff --git a/include/wx/mgl/app.h b/include/wx/mgl/app.h
index 0fd4f65fde..27cf02da75 100644
--- a/include/wx/mgl/app.h
+++ b/include/wx/mgl/app.h
@@ -47,12 +47,9 @@ public:
     virtual bool Initialized();
     virtual bool Pending();
     virtual void Dispatch();
-    virtual bool ProcessIdle();
 
     // implementation only from now on
     void OnIdle(wxIdleEvent &event);
-    bool SendIdleEvents();
-    bool SendIdleEvents(wxWindow* win);
 
     virtual bool Initialize(int& argc, wxChar **argv);
     virtual void CleanUp();
diff --git a/include/wx/mgl/window.h b/include/wx/mgl/window.h
index 7b99981b6c..80a2853909 100644
--- a/include/wx/mgl/window.h
+++ b/include/wx/mgl/window.h
@@ -135,7 +135,7 @@ protected:
     // themselves inside the given rectangle
     virtual void DoMoveWindow(int x, int y, int width, int height);
     
-    void OnIdle(wxIdleEvent& event);
+    void OnInternalIdle();
 
 private:
     // common part of all ctors
diff --git a/include/wx/motif/app.h b/include/wx/motif/app.h
index 246cb618fa..79674e4f89 100644
--- a/include/wx/motif/app.h
+++ b/include/wx/motif/app.h
@@ -59,7 +59,6 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle(); // implemented in motif/evtloop.cpp
     
     virtual bool OnInitGui();
@@ -69,14 +68,6 @@ public:
     
     void OnIdle(wxIdleEvent& event);
     
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents();
-    
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindow* win);
-    
 protected:
     bool                  m_showOnInit;
     
diff --git a/include/wx/motif/window.h b/include/wx/motif/window.h
index 84d7303a64..70857eb954 100644
--- a/include/wx/motif/window.h
+++ b/include/wx/motif/window.h
@@ -151,11 +151,11 @@ public:
     // For implementation purposes - sometimes decorations make the client area
     // smaller
     virtual wxPoint GetClientAreaOrigin() const;
+
+    // Process idle (send update events)
+    void OnInternalIdle();
     
 protected:
-    // event handlers (not virtual by design)
-    void OnIdle(wxIdleEvent& event);
-    
     // Responds to colour changes: passes event on to children.
     void OnSysColourChanged(wxSysColourChangedEvent& event);
     
diff --git a/include/wx/msw/app.h b/include/wx/msw/app.h
index 768833038d..17e363b6b3 100644
--- a/include/wx/msw/app.h
+++ b/include/wx/msw/app.h
@@ -46,7 +46,6 @@ public:
     virtual void Dispatch();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle();
 
     virtual void SetPrintMode(int mode) { m_printMode = mode; }
@@ -57,14 +56,6 @@ public:
     void OnEndSession(wxCloseEvent& event);
     void OnQueryEndSession(wxCloseEvent& event);
 
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents();
-
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindow* win);
-
 protected:
     int    m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
 
diff --git a/include/wx/msw/frame.h b/include/wx/msw/frame.h
index 369f3a3f56..f559b18ee2 100644
--- a/include/wx/msw/frame.h
+++ b/include/wx/msw/frame.h
@@ -128,6 +128,9 @@ protected:
     // window proc for the frames
     long MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
 
+    // handle WM_INITMENU message
+    bool HandleInitMenu();
+
     virtual bool IsMDIChild() const { return FALSE; }
 
     // get default (wxWindows) icon for the frame
diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h
index eaf3ff370f..c44f9d908a 100644
--- a/include/wx/msw/window.h
+++ b/include/wx/msw/window.h
@@ -191,7 +191,6 @@ public:
     // --------------
 
     void OnEraseBackground(wxEraseEvent& event);
-    void OnIdle(wxIdleEvent& event);
     void OnPaint(wxPaintEvent& event);
 
 public:
@@ -415,6 +414,10 @@ public:
     // check if mouse is in the window
     bool IsMouseInWindow() const;
 
+    // virtual function for implementing internal idle
+    // behaviour
+    virtual void OnInternalIdle() ;
+
 protected:
     // the window handle
     WXHWND                m_hWnd;
diff --git a/include/wx/os2/app.h b/include/wx/os2/app.h
index 9a26ede018..048bbc8088 100644
--- a/include/wx/os2/app.h
+++ b/include/wx/os2/app.h
@@ -80,7 +80,6 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle(void);
     virtual void WakeUpIdle(void);
 
     virtual void SetPrintMode(int mode) { m_nPrintMode = mode; }
@@ -91,14 +90,6 @@ public:
     void OnEndSession(wxCloseEvent& rEvent);
     void OnQueryEndSession(wxCloseEvent& rEvent);
 
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(void);
-
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindow* pWin);
-
     void SetAuto3D(bool bFlag) { m_bAuto3D = bFlag; }
     bool GetAuto3D(void) const { return m_bAuto3D; }
 
diff --git a/include/wx/tbarbase.h b/include/wx/tbarbase.h
index 794859e215..252e43e6f5 100644
--- a/include/wx/tbarbase.h
+++ b/include/wx/tbarbase.h
@@ -525,10 +525,8 @@ public:
 
     size_t GetToolsCount() const { return m_tools.GetCount(); }
 
-    void OnIdle(wxIdleEvent& event);
-
     // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
-    virtual void DoToolbarUpdates();
+    virtual void UpdateWindowUI(long flags = wxUPDATE_UI_NONE) ;
 
     // don't want toolbars to accept the focus
     virtual bool AcceptsFocus() const { return FALSE; }
diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h
index 67373c7db3..9e12d0a49d 100644
--- a/include/wx/textctrl.h
+++ b/include/wx/textctrl.h
@@ -334,6 +334,9 @@ public:
     wxTextCtrl& operator<<(double d);
     wxTextCtrl& operator<<(const wxChar c);
 
+    // do the window-specific processing after processing the update event
+    virtual void DoUpdateWindowUI(wxUpdateUIEvent& event) ;
+
     // obsolete functions
 #if WXWIN_COMPATIBILITY
     bool Modified() const { return IsModified(); }
diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h
index 10231a6c00..c6241a9704 100644
--- a/include/wx/toplevel.h
+++ b/include/wx/toplevel.h
@@ -134,6 +134,9 @@ public:
     // so should be there for all platforms
     void OnActivate(wxActivateEvent &WXUNUSED(event)) { }
 
+    // do the window-specific processing after processing the update event
+    virtual void DoUpdateWindowUI(wxUpdateUIEvent& event) ;
+
 protected:
     // the frame client to screen translation should take account of the
     // toolbar which may shift the origin of the client area
diff --git a/include/wx/univ/listbox.h b/include/wx/univ/listbox.h
index 01ad0a276c..72c9fc48aa 100644
--- a/include/wx/univ/listbox.h
+++ b/include/wx/univ/listbox.h
@@ -169,6 +169,8 @@ public:
     // let wxColourScheme choose the right colours for us
     virtual bool IsContainerWindow() const { return TRUE; }
 
+    // idle processing
+    virtual void OnInternalIdle();
 protected:
     // geometry
     virtual wxSize DoGetBestClientSize() const;
@@ -183,7 +185,6 @@ protected:
     void Init();
 
     // event handlers
-    void OnIdle(wxIdleEvent& event);
     void OnSize(wxSizeEvent& event);
 
     // common part of Clear() and DoSetItems(): clears everything
diff --git a/include/wx/univ/scrolbar.h b/include/wx/univ/scrolbar.h
index 50f987813c..af937ebae4 100644
--- a/include/wx/univ/scrolbar.h
+++ b/include/wx/univ/scrolbar.h
@@ -119,14 +119,14 @@ public:
     // for wxControlRenderer::DrawScrollbar() only
     const wxScrollArrows& GetArrows() const { return m_arrows; }
 
+    // idle processing
+    virtual void OnInternalIdle();
+
 protected:
     virtual wxSize DoGetBestClientSize() const;
     virtual void DoDraw(wxControlRenderer *renderer);
     virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
 
-    // event handlers
-    void OnIdle(wxIdleEvent& event);
-
     // forces update of thumb's visual appearence (does nothing if m_dirty=FALSE)
     void UpdateThumb();
 
diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h
index 947a789c81..3dbaa38f8e 100644
--- a/include/wx/univ/textctrl.h
+++ b/include/wx/univ/textctrl.h
@@ -455,7 +455,6 @@ protected:
 
     // event handlers
     // --------------
-    void OnIdle(wxIdleEvent& event);
     void OnChar(wxKeyEvent& event);
     void OnSize(wxSizeEvent& event);
 
@@ -476,6 +475,8 @@ protected:
     bool DoCut();
     bool DoPaste();
 
+    // idle processing
+    virtual void OnInternalIdle();
 private:
     // all these methods are for multiline text controls only
 
diff --git a/include/wx/window.h b/include/wx/window.h
index 679ceb8067..7839127ea9 100644
--- a/include/wx/window.h
+++ b/include/wx/window.h
@@ -688,7 +688,11 @@ public:
     // get border for the flags of this window
     wxBorder GetBorder() const { return GetBorder(GetWindowStyleFlag()); }
 
-    void UpdateWindowUI();
+    // send wxUpdateUIEvents to this window, and children if recurse is TRUE
+    virtual void UpdateWindowUI(long flags = wxUPDATE_UI_NONE);
+
+    // do the window-specific processing after processing the update event
+    virtual void DoUpdateWindowUI(wxUpdateUIEvent& event) ;
 
 #if wxUSE_MENUS
     bool PopupMenu( wxMenu *menu, const wxPoint& pos )
@@ -858,7 +862,14 @@ public:
     void OnHelp(wxHelpEvent& event);
 #endif // wxUSE_HELP
 
-        // get the haqndle of the window for the underlying window system: this
+        // virtual function for implementing internal idle
+        // behaviour
+        virtual void OnInternalIdle() {}
+
+        // call internal idle recursively
+        void ProcessInternalIdle() ;
+
+        // get the handle of the window for the underlying window system: this
         // is only used for wxWin itself or for user code which wants to call
         // platform-specific APIs
     virtual WXWidget GetHandle() const = 0;
diff --git a/include/wx/x11/app.h b/include/wx/x11/app.h
index f0ca6237ee..71a56be26a 100644
--- a/include/wx/x11/app.h
+++ b/include/wx/x11/app.h
@@ -59,7 +59,6 @@ public:
     virtual void Exit();
 
     virtual bool Yield(bool onlyIfNeeded = FALSE);
-    virtual bool ProcessIdle();
     virtual void WakeUpIdle();
     
     virtual bool OnInitGui();
@@ -69,14 +68,6 @@ public:
     
     void OnIdle(wxIdleEvent& event);
     
-    // Send idle event to all top-level windows.
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents();
-    
-    // Send idle event to window and all subwindows
-    // Returns TRUE if more idle time is requested.
-    bool SendIdleEvents(wxWindow* win);
-    
     // Processes an X event.
     virtual bool ProcessXEvent(WXEvent* event);
     
diff --git a/include/wx/x11/textctrl.h b/include/wx/x11/textctrl.h
index 87fdd5b393..2dd4196a92 100644
--- a/include/wx/x11/textctrl.h
+++ b/include/wx/x11/textctrl.h
@@ -248,10 +248,10 @@ public:
     void OnEraseBackground( wxEraseEvent &event );
     void OnMouse( wxMouseEvent &event );
     void OnChar( wxKeyEvent &event );
-    void OnIdle( wxIdleEvent &event );
     void OnSetFocus( wxFocusEvent& event );
     void OnKillFocus( wxFocusEvent& event );
 
+    void OnInternalIdle();
     void RefreshLine( int n );
     void RefreshDown( int n );
     void MoveCursor( int new_x, int new_y, bool shift = FALSE, bool centre = FALSE );
diff --git a/include/wx/x11/window.h b/include/wx/x11/window.h
index 16ca8b298e..ef09a5ff93 100644
--- a/include/wx/x11/window.h
+++ b/include/wx/x11/window.h
@@ -155,9 +155,6 @@ public:
     // OnInternalIdle
     virtual void OnInternalIdle();
     
-    // For compatibility across platforms (not in event table)
-    void OnIdle(wxIdleEvent& WXUNUSED(event)) {}
-    
 protected:
     // Responds to colour changes: passes event on to children.
     void OnSysColourChanged(wxSysColourChangedEvent& event);
diff --git a/src/cocoa/app.mm b/src/cocoa/app.mm
index c9614997a7..89c16115f3 100644
--- a/src/cocoa/app.mm
+++ b/src/cocoa/app.mm
@@ -249,18 +249,6 @@ int wxApp::MainLoop()
     return 0;
 }
 
-// Returns TRUE if more time is needed.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
     wxLogDebug("wxApp::ExitMailLoop m_isIdle=%d, isRunning=%d",(int)m_isIdle,(int)[m_cocoaApp isRunning]);
@@ -314,48 +302,6 @@ void wxApp::OnIdle(wxIdleEvent& event)
     s_inOnIdle = FALSE;
 }
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-//    wxLogDebug("SendIdleEvents win=%p",win);
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-    win->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowList::Node* node = win->GetChildren().GetFirst();
-    while (node)
-    {
-//        wxLogDebug("child=%p",node->Data());
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore;
-}
-
 // Yield to other processes
 
 bool wxApp::Yield(bool onlyIfNeeded)
diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp
index 845d4ebc44..9424db3196 100644
--- a/src/common/appcmn.cpp
+++ b/src/common/appcmn.cpp
@@ -205,6 +205,72 @@ void wxAppBase::DeletePendingObjects()
     }
 }
 
+// Returns TRUE if more time is needed.
+bool wxAppBase::ProcessIdle()
+{
+    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
+    node = wxTopLevelWindows.GetFirst();
+    while (node)
+    {
+        wxWindow* win = node->GetData();
+        win->ProcessInternalIdle();
+        node = node->GetNext();
+    }
+
+    wxIdleEvent event;
+    event.SetEventObject(this);
+    bool processed = ProcessEvent(event);
+
+    wxUpdateUIEvent::ResetUpdateTime();
+    
+    return processed && event.MoreRequested();
+}
+
+// Send idle event to all top-level windows
+bool wxAppBase::SendIdleEvents()
+{
+    bool needMore = FALSE;
+
+    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
+    while (node)
+    {
+        wxWindow* win = node->GetData();
+        if (SendIdleEvents(win))
+            needMore = TRUE;
+        node = node->GetNext();
+    }
+
+    return needMore;
+}
+
+// Send idle event to window and all subwindows
+bool wxAppBase::SendIdleEvents(wxWindow* win)
+{
+    bool needMore = FALSE;
+    
+    if (wxIdleEvent::CanSend(win))
+    {
+        wxIdleEvent event;
+        event.SetEventObject(win);
+        win->GetEventHandler()->ProcessEvent(event);
+
+        needMore = event.MoreRequested();
+    }
+
+    wxWindowList::Node *node = win->GetChildren().GetFirst();
+    while ( node )
+    {
+        wxWindow *win = node->GetData();
+        if (SendIdleEvents(win))
+            needMore = TRUE;
+
+        node = node->GetNext();
+    }
+
+    return needMore;
+}
+
+
 // ----------------------------------------------------------------------------
 // wxGUIAppTraitsBase
 // ----------------------------------------------------------------------------
diff --git a/src/common/event.cpp b/src/common/event.cpp
index ff13a80111..8474ad0eec 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -370,23 +370,32 @@ wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
  */
 
 #if wxUSE_LONGLONG
-wxLongLong wxUpdateUIEvent::m_lastUpdate = 0;
+wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0;
 #endif
 
-long wxUpdateUIEvent::m_updateInterval = 0;
+long wxUpdateUIEvent::sm_updateInterval = 0;
+
+wxUpdateUIMode wxUpdateUIEvent::sm_updateMode = wxUPDATE_UI_PROCESS_ALL;
 
 // Can we update?
-bool wxUpdateUIEvent::CanUpdate()
+bool wxUpdateUIEvent::CanUpdate(wxWindow* win)
 {
-    if (m_updateInterval == -1)
+    // Don't update if we've switched global updating off
+    // and this window doesn't support updates.
+    if (win &&
+       (GetMode() == wxUPDATE_UI_PROCESS_SPECIFIED &&
+       ((win->GetExtraStyle() & wxWS_EX_PROCESS_UI_UPDATES) == 0)))
+        return FALSE;
+    
+    if (sm_updateInterval == -1)
         return FALSE;
-    else if (m_updateInterval == 0)
+    else if (sm_updateInterval == 0)
         return TRUE;
     else
     {
 #if wxUSE_STOPWATCH && wxUSE_LONGLONG
         wxLongLong now = wxGetLocalTimeMillis();
-        if (now > (m_lastUpdate + m_updateInterval))
+        if (now > (sm_lastUpdate + sm_updateInterval))
         {
             return TRUE;
         }
@@ -404,17 +413,35 @@ bool wxUpdateUIEvent::CanUpdate()
 void wxUpdateUIEvent::ResetUpdateTime()
 {
 #if wxUSE_STOPWATCH && wxUSE_LONGLONG
-    if (m_updateInterval > 0)
+    if (sm_updateInterval > 0)
     {
         wxLongLong now = wxGetLocalTimeMillis();
-        if (now > (m_lastUpdate + m_updateInterval))
+        if (now > (sm_lastUpdate + sm_updateInterval))
         {
-            m_lastUpdate = now;
+            sm_lastUpdate = now;
         }
     }
 #endif
 }
 
+/*
+ * Idle events
+ */
+ 
+wxIdleMode wxIdleEvent::sm_idleMode = wxIDLE_PROCESS_ALL;
+
+// Can we send an idle event?
+bool wxIdleEvent::CanSend(wxWindow* win)
+{
+    // Don't update if we've switched global updating off
+    // and this window doesn't support updates.
+    if (win &&
+       (GetMode() == wxIDLE_PROCESS_SPECIFIED &&
+       ((win->GetExtraStyle() & wxWS_EX_PROCESS_IDLE) == 0)))
+        return FALSE;
+    
+    return TRUE;
+}
 
 /*
  * Scroll events
diff --git a/src/common/framecmn.cpp b/src/common/framecmn.cpp
index 7e64059805..42669bd92e 100644
--- a/src/common/framecmn.cpp
+++ b/src/common/framecmn.cpp
@@ -46,9 +46,6 @@
 // ----------------------------------------------------------------------------
 
 BEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow)
-#if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
-    EVT_IDLE(wxFrameBase::OnIdle)
-#endif
 #if wxUSE_MENUS && !wxUSE_IDLEMENUUPDATES
     EVT_MENU_OPEN(wxFrameBase::OnMenuOpen)
 #endif
@@ -211,6 +208,34 @@ bool wxFrameBase::ProcessCommand(int id)
 #endif // wxUSE_MENUS/!wxUSE_MENUS
 }
 
+// Do the UI update processing for this window. This is
+// provided for the application to call if it wants to
+// force a UI update, particularly for the menus and toolbar.
+void wxFrameBase::UpdateWindowUI(long flags)
+{
+    wxWindowBase::UpdateWindowUI(flags);
+    
+#if wxUSE_TOOLBAR
+    if (GetToolBar())
+        GetToolBar()->UpdateWindowUI(flags);
+#endif
+
+#if wxUSE_MENUS
+    if (GetMenuBar())
+    {
+        if ((flags & wxUPDATE_UI_FROMIDLE) && !wxUSE_IDLEMENUUPDATES)
+        {
+            // If coming from an idle event, we only
+            // want to update the menus if we're
+            // in the wxUSE_IDLEMENUUPDATES configuration:
+            // so if we're not, do nothing
+        }
+        else
+            DoMenuUpdates();
+    }
+#endif
+}
+
 // ----------------------------------------------------------------------------
 // event handlers
 // ----------------------------------------------------------------------------
@@ -222,10 +247,11 @@ void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
 #endif // wxUSE_STATUSBAR
 }
 
-void wxFrameBase::OnIdle(wxIdleEvent& WXUNUSED(event) )
+// Implement internal behaviour (menu updating on some platforms)
+void wxFrameBase::OnInternalIdle()
 {
 #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
-    if (wxUpdateUIEvent::CanUpdate())
+    if (wxUpdateUIEvent::CanUpdate(this))
         DoMenuUpdates();
 #endif
 }
diff --git a/src/common/tbarbase.cpp b/src/common/tbarbase.cpp
index e53657dea2..9b03daccee 100644
--- a/src/common/tbarbase.cpp
+++ b/src/common/tbarbase.cpp
@@ -47,7 +47,6 @@
 IMPLEMENT_CLASS(wxToolBarBase, wxControl)
 
 BEGIN_EVENT_TABLE(wxToolBarBase, wxControl)
-    EVT_IDLE(wxToolBarBase::OnIdle)
 END_EVENT_TABLE()
 
 #include "wx/listimpl.cpp"
@@ -581,17 +580,11 @@ void wxToolBarBase::OnMouseEnter(int id)
 // UI updates
 // ----------------------------------------------------------------------------
 
-void wxToolBarBase::OnIdle(wxIdleEvent& event)
-{
-    if (wxUpdateUIEvent::CanUpdate())
-        DoToolbarUpdates();
-
-    event.Skip();
-}
-
 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
-void wxToolBarBase::DoToolbarUpdates()
+void wxToolBarBase::UpdateWindowUI(long flags)
 {
+    wxWindowBase::UpdateWindowUI(flags);
+
     wxEvtHandler* evtHandler = GetEventHandler() ;
 
     for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp
index 57e584a310..ff02305ca2 100644
--- a/src/common/textcmn.cpp
+++ b/src/common/textcmn.cpp
@@ -469,6 +469,20 @@ wxString wxTextCtrlBase::GetRange(long from, long to) const
     return sel;
 }
 
+// do the window-specific processing after processing the update event
+void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
+{
+    if ( event.GetSetEnabled() )
+        Enable(event.GetEnabled());
+    
+    if ( event.GetSetText() )
+    {
+        if ( event.GetText() != GetValue() )
+            SetValue(event.GetText());
+    }    
+}
+
+
 #else // !wxUSE_TEXTCTRL
 
 // define this one even if !wxUSE_TEXTCTRL because it is also used by other
diff --git a/src/common/toplvcmn.cpp b/src/common/toplvcmn.cpp
index 4c640caae4..8768de7360 100644
--- a/src/common/toplvcmn.cpp
+++ b/src/common/toplvcmn.cpp
@@ -215,4 +215,17 @@ bool wxTopLevelWindowBase::SendIconizeEvent(bool iconized)
     return GetEventHandler()->ProcessEvent(event);
 }
 
+// do the window-specific processing after processing the update event
+void wxTopLevelWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
+{
+    if ( event.GetSetEnabled() )
+        Enable(event.GetEnabled());
+    
+    if ( event.GetSetText() )
+    {
+        if ( event.GetText() != GetTitle() )
+            SetTitle(event.GetText());
+    }
+}
+
 // vi:sts=4:sw=4:et
diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp
index 810d518d9d..d7492c0a39 100644
--- a/src/common/wincmn.cpp
+++ b/src/common/wincmn.cpp
@@ -1770,42 +1770,46 @@ void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) co
 // do Update UI processing for child controls
 // ----------------------------------------------------------------------------
 
-// TODO: should this be implemented for the child window rather
-// than the parent? Then you can override it e.g. for wxCheckBox
-// to do the Right Thing rather than having to assume a fixed number
-// of control classes.
-void wxWindowBase::UpdateWindowUI()
+void wxWindowBase::UpdateWindowUI(long flags)
 {
-#if wxUSE_CONTROLS
     wxUpdateUIEvent event(GetId());
     event.m_eventObject = this;
 
     if ( GetEventHandler()->ProcessEvent(event) )
     {
-        if ( event.GetSetEnabled() )
-            Enable(event.GetEnabled());
+        DoUpdateWindowUI(event);
+    }
 
-        if ( event.GetSetText() )
+    if (flags & wxUPDATE_UI_RECURSE)
+    {
+        wxWindowList::Node* node = GetChildren().GetFirst();
+        while (node)
         {
-            wxControl *control = wxDynamicCastThis(wxControl);
-            if ( control )
-            {
-#if wxUSE_TEXTCTRL
-                wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
-                if ( text )
-                {
-                	if ( event.GetText() != text->GetValue() )
-                    	text->SetValue(event.GetText());
-                }
-                else
-#endif // wxUSE_TEXTCTRL
-				{
-					if ( event.GetText() != control->GetLabel() )
-                    	control->SetLabel(event.GetText());
-                }
-            }
+            wxWindow* child = (wxWindow*) node->GetData();
+            child->UpdateWindowUI(flags);
+            node = node->GetNext();
         }
+    }
+}
 
+// do the window-specific processing after processing the update event
+// TODO: take specific knowledge out of this function and
+// put in each control's base class. Unfortunately we don't
+// yet have base implementation files for wxCheckBox and wxRadioButton.
+void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
+{
+    if ( event.GetSetEnabled() )
+        Enable(event.GetEnabled());
+    
+#if wxUSE_CONTROLS
+    if ( event.GetSetText() )
+    {
+        wxControl *control = wxDynamicCastThis(wxControl);
+        if ( control )
+        {
+            if ( event.GetText() != control->GetLabel() )
+                control->SetLabel(event.GetText());
+        }
 #if wxUSE_CHECKBOX
         wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
         if ( checkbox )
@@ -1823,8 +1827,22 @@ void wxWindowBase::UpdateWindowUI()
                 radiobtn->SetValue(event.GetChecked());
         }
 #endif // wxUSE_RADIOBTN
+    }    
+#endif
+}
+
+// call internal idle recursively
+void wxWindowBase::ProcessInternalIdle()
+{
+    OnInternalIdle();
+
+    wxWindowList::Node  *node = GetChildren().GetFirst();
+    while (node)
+    {
+        wxWindow *child = node->GetData();
+        child->ProcessInternalIdle();
+        node = node->GetNext();
     }
-#endif // wxUSE_CONTROLS
 }
 
 // ----------------------------------------------------------------------------
@@ -1880,10 +1898,15 @@ void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
     }
 }
 
-// the default action is to populate dialog with data when it's created
+// the default action is to populate dialog with data when it's created,
+// and nudge the UI into displaying itself correctly in case
+// we've turned the wxUpdateUIEvents frequency down low.
 void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
 {
     TransferDataToWindow();
+    
+    // Update the UI at this point
+    UpdateWindowUI(wxUPDATE_UI_RECURSE);
 }
 
 // process Ctrl-Alt-mclick
diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp
index b598da0307..06afb50f12 100644
--- a/src/gtk/app.cpp
+++ b/src/gtk/app.cpp
@@ -534,27 +534,6 @@ GdkVisual *wxApp::GetGdkVisual()
     return visual;
 }
 
-bool wxApp::ProcessIdle()
-{
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        CallInternalIdle( win );
-
-        node = node->GetNext();
-    }
-
-    wxIdleEvent event;
-    event.SetEventObject( this );
-    ProcessEvent( event );
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::OnIdle( wxIdleEvent &event )
 {
     static bool s_inOnIdle = FALSE;
@@ -581,64 +560,6 @@ void wxApp::OnIdle( wxIdleEvent &event )
     s_inOnIdle = FALSE;
 }
 
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-bool wxApp::CallInternalIdle( wxWindow* win )
-{
-    win->OnInternalIdle();
-
-    wxWindowList::Node  *node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow    *win = node->GetData();
-
-        CallInternalIdle( win );
-        node = node->GetNext();
-    }
-
-    return TRUE;
-}
-
-bool wxApp::SendIdleEvents( wxWindow* win )
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-
-    win->GetEventHandler()->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowList::Node  *node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow    *win = node->GetData();
-
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
 int wxApp::MainLoop()
 {
     gtk_main();
diff --git a/src/gtk/checkbox.cpp b/src/gtk/checkbox.cpp
index 4099d8406f..fb6cc16c42 100644
--- a/src/gtk/checkbox.cpp
+++ b/src/gtk/checkbox.cpp
@@ -220,8 +220,8 @@ void wxCheckBox::OnInternalIdle()
         }
     }
     
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxCheckBox::DoGetBestSize() const
diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp
index 7e1ed2b2ba..fd6e17f28a 100644
--- a/src/gtk/frame.cpp
+++ b/src/gtk/frame.cpp
@@ -508,7 +508,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
 
 void wxFrame::OnInternalIdle()
 {
-    wxTopLevelWindow::OnInternalIdle();
+    wxFrameBase::OnInternalIdle();
 
 #if wxUSE_MENUS_NATIVE
     if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
diff --git a/src/gtk/listbox.cpp b/src/gtk/listbox.cpp
index 4f166e489e..da15521495 100644
--- a/src/gtk/listbox.cpp
+++ b/src/gtk/listbox.cpp
@@ -1039,8 +1039,8 @@ void wxListBox::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxListBox::DoGetBestSize() const
diff --git a/src/gtk/radiobut.cpp b/src/gtk/radiobut.cpp
index a3b09060d5..49a6ddb76b 100644
--- a/src/gtk/radiobut.cpp
+++ b/src/gtk/radiobut.cpp
@@ -239,8 +239,8 @@ void wxRadioButton::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxRadioButton::DoGetBestSize() const
diff --git a/src/gtk/tbargtk.cpp b/src/gtk/tbargtk.cpp
index 326ff64c76..a5a5b2b946 100644
--- a/src/gtk/tbargtk.cpp
+++ b/src/gtk/tbargtk.cpp
@@ -673,8 +673,8 @@ void wxToolBar::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 #endif // wxUSE_TOOLBAR_NATIVE
diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp
index b87712e0c1..23b5a380f2 100644
--- a/src/gtk/textctrl.cpp
+++ b/src/gtk/textctrl.cpp
@@ -1591,8 +1591,8 @@ void wxTextCtrl::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxTextCtrl::DoGetBestSize() const
diff --git a/src/gtk/tglbtn.cpp b/src/gtk/tglbtn.cpp
index 9ad3fceec1..f103789376 100644
--- a/src/gtk/tglbtn.cpp
+++ b/src/gtk/tglbtn.cpp
@@ -166,8 +166,8 @@ void wxToggleButton::OnInternalIdle()
         gdk_window_set_cursor(win, cursor.GetCursor());
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // wxSize DoGetBestSize() const
diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp
index bb9d472179..13eda5a41d 100644
--- a/src/gtk/window.cpp
+++ b/src/gtk/window.cpp
@@ -3022,8 +3022,8 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp
index b598da0307..06afb50f12 100644
--- a/src/gtk1/app.cpp
+++ b/src/gtk1/app.cpp
@@ -534,27 +534,6 @@ GdkVisual *wxApp::GetGdkVisual()
     return visual;
 }
 
-bool wxApp::ProcessIdle()
-{
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        CallInternalIdle( win );
-
-        node = node->GetNext();
-    }
-
-    wxIdleEvent event;
-    event.SetEventObject( this );
-    ProcessEvent( event );
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::OnIdle( wxIdleEvent &event )
 {
     static bool s_inOnIdle = FALSE;
@@ -581,64 +560,6 @@ void wxApp::OnIdle( wxIdleEvent &event )
     s_inOnIdle = FALSE;
 }
 
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-bool wxApp::CallInternalIdle( wxWindow* win )
-{
-    win->OnInternalIdle();
-
-    wxWindowList::Node  *node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow    *win = node->GetData();
-
-        CallInternalIdle( win );
-        node = node->GetNext();
-    }
-
-    return TRUE;
-}
-
-bool wxApp::SendIdleEvents( wxWindow* win )
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-
-    win->GetEventHandler()->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowList::Node  *node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow    *win = node->GetData();
-
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
 int wxApp::MainLoop()
 {
     gtk_main();
diff --git a/src/gtk1/checkbox.cpp b/src/gtk1/checkbox.cpp
index 4099d8406f..fb6cc16c42 100644
--- a/src/gtk1/checkbox.cpp
+++ b/src/gtk1/checkbox.cpp
@@ -220,8 +220,8 @@ void wxCheckBox::OnInternalIdle()
         }
     }
     
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxCheckBox::DoGetBestSize() const
diff --git a/src/gtk1/frame.cpp b/src/gtk1/frame.cpp
index 7e1ed2b2ba..fd6e17f28a 100644
--- a/src/gtk1/frame.cpp
+++ b/src/gtk1/frame.cpp
@@ -508,7 +508,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
 
 void wxFrame::OnInternalIdle()
 {
-    wxTopLevelWindow::OnInternalIdle();
+    wxFrameBase::OnInternalIdle();
 
 #if wxUSE_MENUS_NATIVE
     if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
diff --git a/src/gtk1/listbox.cpp b/src/gtk1/listbox.cpp
index 4f166e489e..da15521495 100644
--- a/src/gtk1/listbox.cpp
+++ b/src/gtk1/listbox.cpp
@@ -1039,8 +1039,8 @@ void wxListBox::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxListBox::DoGetBestSize() const
diff --git a/src/gtk1/radiobut.cpp b/src/gtk1/radiobut.cpp
index a3b09060d5..49a6ddb76b 100644
--- a/src/gtk1/radiobut.cpp
+++ b/src/gtk1/radiobut.cpp
@@ -239,8 +239,8 @@ void wxRadioButton::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxRadioButton::DoGetBestSize() const
diff --git a/src/gtk1/tbargtk.cpp b/src/gtk1/tbargtk.cpp
index 326ff64c76..a5a5b2b946 100644
--- a/src/gtk1/tbargtk.cpp
+++ b/src/gtk1/tbargtk.cpp
@@ -673,8 +673,8 @@ void wxToolBar::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 #endif // wxUSE_TOOLBAR_NATIVE
diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp
index b87712e0c1..23b5a380f2 100644
--- a/src/gtk1/textctrl.cpp
+++ b/src/gtk1/textctrl.cpp
@@ -1591,8 +1591,8 @@ void wxTextCtrl::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 wxSize wxTextCtrl::DoGetBestSize() const
diff --git a/src/gtk1/tglbtn.cpp b/src/gtk1/tglbtn.cpp
index 9ad3fceec1..f103789376 100644
--- a/src/gtk1/tglbtn.cpp
+++ b/src/gtk1/tglbtn.cpp
@@ -166,8 +166,8 @@ void wxToggleButton::OnInternalIdle()
         gdk_window_set_cursor(win, cursor.GetCursor());
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // wxSize DoGetBestSize() const
diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp
index bb9d472179..13eda5a41d 100644
--- a/src/gtk1/window.cpp
+++ b/src/gtk1/window.cpp
@@ -3022,8 +3022,8 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
diff --git a/src/mac/app.cpp b/src/mac/app.cpp
index e1e9dba922..1af5aa871f 100644
--- a/src/mac/app.cpp
+++ b/src/mac/app.cpp
@@ -971,18 +971,6 @@ int wxApp::MainLoop()
     return 0;
 }
 
-// Returns TRUE if more time is needed.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
       m_keepGoing = FALSE;
@@ -996,7 +984,7 @@ bool wxApp::Pending()
 #else
     EventRecord event ;
 
-      return EventAvail( everyEvent , &event ) ;
+    return EventAvail( everyEvent , &event ) ;
 #endif
 }
 
@@ -1044,46 +1032,6 @@ void wxApp::WakeUpIdle()
     wxMacWakeUp() ;
 }
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-    wxWindowListNode* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-    win->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowListNode* node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore ;
-}
-
 void wxApp::Exit()
 {
     wxApp::CleanUp();
diff --git a/src/mac/carbon/app.cpp b/src/mac/carbon/app.cpp
index e1e9dba922..1af5aa871f 100644
--- a/src/mac/carbon/app.cpp
+++ b/src/mac/carbon/app.cpp
@@ -971,18 +971,6 @@ int wxApp::MainLoop()
     return 0;
 }
 
-// Returns TRUE if more time is needed.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
       m_keepGoing = FALSE;
@@ -996,7 +984,7 @@ bool wxApp::Pending()
 #else
     EventRecord event ;
 
-      return EventAvail( everyEvent , &event ) ;
+    return EventAvail( everyEvent , &event ) ;
 #endif
 }
 
@@ -1044,46 +1032,6 @@ void wxApp::WakeUpIdle()
     wxMacWakeUp() ;
 }
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-    wxWindowListNode* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-    win->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowListNode* node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore ;
-}
-
 void wxApp::Exit()
 {
     wxApp::CleanUp();
diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp
index a75c421466..ddb8eebf2b 100644
--- a/src/mac/carbon/window.cpp
+++ b/src/mac/carbon/window.cpp
@@ -75,7 +75,6 @@ BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
   EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
   EVT_SYS_COLOUR_CHANGED(wxWindowMac::OnSysColourChanged)
   EVT_INIT_DIALOG(wxWindowMac::OnInitDialog)
-  EVT_IDLE(wxWindowMac::OnIdle)
   EVT_SET_FOCUS(wxWindowMac::OnSetFocus)
   EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
 END_EVENT_TABLE()
@@ -1367,12 +1366,12 @@ void wxWindowMac::SetupColours()
         SetBackgroundColour(GetParent()->GetBackgroundColour());
 }
 
-void wxWindowMac::OnIdle(wxIdleEvent& event)
+void wxWindowMac::OnInternalIdle()
 {
     // This calls the UI-update mechanism (querying windows for
     // menu/toolbar/control state information)
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // Raise the window to the top of the Z order
diff --git a/src/mac/window.cpp b/src/mac/window.cpp
index a75c421466..ddb8eebf2b 100644
--- a/src/mac/window.cpp
+++ b/src/mac/window.cpp
@@ -75,7 +75,6 @@ BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
   EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
   EVT_SYS_COLOUR_CHANGED(wxWindowMac::OnSysColourChanged)
   EVT_INIT_DIALOG(wxWindowMac::OnInitDialog)
-  EVT_IDLE(wxWindowMac::OnIdle)
   EVT_SET_FOCUS(wxWindowMac::OnSetFocus)
   EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
 END_EVENT_TABLE()
@@ -1367,12 +1366,12 @@ void wxWindowMac::SetupColours()
         SetBackgroundColour(GetParent()->GetBackgroundColour());
 }
 
-void wxWindowMac::OnIdle(wxIdleEvent& event)
+void wxWindowMac::OnInternalIdle()
 {
     // This calls the UI-update mechanism (querying windows for
     // menu/toolbar/control state information)
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // Raise the window to the top of the Z order
diff --git a/src/mgl/app.cpp b/src/mgl/app.cpp
index fba01c5b4b..45f77b88ae 100644
--- a/src/mgl/app.cpp
+++ b/src/mgl/app.cpp
@@ -272,17 +272,6 @@ bool wxApp::OnInitGui()
     return TRUE;
 }
 
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::OnIdle(wxIdleEvent &event)
 {
     static bool s_inOnIdle = FALSE;
@@ -312,46 +301,6 @@ void wxApp::OnIdle(wxIdleEvent &event)
     s_inOnIdle = FALSE;
 }
 
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if ( SendIdleEvents(win) )
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-
-    win->GetEventHandler()->ProcessEvent(event);
-
-    if ( event.MoreRequested() )
-        needMore = TRUE;
-
-    wxNode* node = win->GetChildren().First();
-    while (node)
-    {
-        wxWindow* win = (wxWindow*) node->Data();
-        if ( SendIdleEvents(win) )
-            needMore = TRUE;
-
-        node = node->Next();
-    }
-    return needMore;
-}
-
 int wxApp::MainLoop()
 {
     int rt;
diff --git a/src/mgl/evtloop.cpp b/src/mgl/evtloop.cpp
index 34c9c24422..95270cda46 100644
--- a/src/mgl/evtloop.cpp
+++ b/src/mgl/evtloop.cpp
@@ -97,13 +97,7 @@ void wxEventLoopImpl::Dispatch()
 
 bool wxEventLoopImpl::SendIdleEvent()
 {
-    wxIdleEvent event;
-
-    bool processed = wxTheApp->ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();    
-    
-    return processed && event.MoreRequested();
+    return wxTheApp->ProcessIdle();
 }
 
 // ============================================================================
diff --git a/src/mgl/window.cpp b/src/mgl/window.cpp
index bd8fa401a7..60b95bff99 100644
--- a/src/mgl/window.cpp
+++ b/src/mgl/window.cpp
@@ -524,7 +524,6 @@ static ibool MGLAPI wxWindowKeybHandler(window_t *wnd, event_t *e)
 IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL, wxWindowBase)
 
 BEGIN_EVENT_TABLE(wxWindowMGL, wxWindowBase)
-    EVT_IDLE(wxWindowMGL::OnIdle)
 END_EVENT_TABLE()
 
 // ===========================================================================
@@ -1276,8 +1275,8 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
 // idle events processing
 // ---------------------------------------------------------------------------
 
-void wxWindowMGL::OnIdle(wxIdleEvent& WXUNUSED(event))
+void wxWindowMGL::OnInternalIdle()
 {
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
diff --git a/src/motif/app.cpp b/src/motif/app.cpp
index 64758e0572..c391382b47 100644
--- a/src/motif/app.cpp
+++ b/src/motif/app.cpp
@@ -170,19 +170,6 @@ int wxApp::MainLoop()
     return 0;
 }
 
-// Processes an idle event.
-// Returns TRUE if more time is needed.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-
-    bool processed = ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return processed && event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
     if( m_eventLoop->IsRunning() )
@@ -255,47 +242,6 @@ void wxApp::OnIdle(wxIdleEvent& event)
     inOnIdle = FALSE;
 }
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-    win->GetEventHandler()->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowList::Node* node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-    return needMore ;
-}
-
 static char *fallbackResources[] = {
     "*menuBar.marginHeight: 0",
     "*menuBar.shadowThickness: 1",
diff --git a/src/motif/window.cpp b/src/motif/window.cpp
index 2684299552..d9555d5917 100644
--- a/src/motif/window.cpp
+++ b/src/motif/window.cpp
@@ -145,7 +145,6 @@ static int str16len(const char *s)
 
     BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
         EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
-        EVT_IDLE(wxWindow::OnIdle)
     END_EVENT_TABLE()
 
 // ============================================================================
@@ -1683,12 +1682,12 @@ void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
     }
 }
 
-void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
+void wxWindow::OnInternalIdle()
 {
     // This calls the UI-update mechanism (querying windows for
     // menu/toolbar/control state information)
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/msw/app.cpp b/src/msw/app.cpp
index 08579d8319..4e58a0bba6 100644
--- a/src/msw/app.cpp
+++ b/src/msw/app.cpp
@@ -684,18 +684,6 @@ int wxApp::MainLoop()
     return s_currentMsg.wParam;
 }
 
-// Returns TRUE if more time is needed.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
     // this will set m_keepGoing to FALSE a bit later
@@ -841,45 +829,6 @@ void wxApp::OnIdle(wxIdleEvent& event)
     wxIsInOnIdleFlag = FALSE;
 }
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    wxIdleEvent event;
-    event.SetEventObject(win);
-    win->GetEventHandler()->ProcessEvent(event);
-
-    bool needMore = event.MoreRequested();
-
-    wxWindowList::Node *node = win->GetChildren().GetFirst();
-    while ( node )
-    {
-        wxWindow *win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
 void wxApp::WakeUpIdle()
 {
     // Send the top window a dummy message so idle handler processing will
diff --git a/src/msw/evtloop.cpp b/src/msw/evtloop.cpp
index f61cc55e7f..86ad5ac4b8 100644
--- a/src/msw/evtloop.cpp
+++ b/src/msw/evtloop.cpp
@@ -137,13 +137,7 @@ bool wxEventLoopImpl::PreProcessMessage(MSG *msg)
 
 bool wxEventLoopImpl::SendIdleMessage()
 {
-    wxIdleEvent event;
-
-    bool processed = wxTheApp->ProcessEvent(event) ;
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return processed && event.MoreRequested();
+    return wxTheApp->ProcessIdle();
 }
 
 // ============================================================================
diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp
index 9c9dc1d35f..2e3515e690 100644
--- a/src/msw/frame.cpp
+++ b/src/msw/frame.cpp
@@ -191,12 +191,7 @@ void wxFrame::DoGetClientSize(int *x, int *y) const
 
 void wxFrame::Raise()
 {
-#ifdef __WIN16__
-    // no SetForegroundWindow() in Win16
-    wxFrameBase::Raise();
-#else // Win32
     ::SetForegroundWindow(GetHwnd());
-#endif // Win16/32
 }
 
 // generate an artificial resize event
@@ -749,6 +744,10 @@ long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
             }
             break;
 
+        case WM_INITMENU:
+            processed = HandleInitMenu();
+            break;
+
         case WM_PAINT:
             processed = HandlePaint();
             break;
@@ -763,16 +762,18 @@ long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
                 processed = HandleMenuSelect(item, flags, hmenu);
             }
             break;
-
-#ifndef __WIN16__
+            
+        // We don't need to send the wxEVT_MENU_OPEN
+        // when we get WM_ENTERMENULOOP now, because we send
+        // it when we get WM_INITMENU.
+#if 0
         case WM_ENTERMENULOOP:
             processed = HandleMenuLoop(wxEVT_MENU_OPEN, wParam);
             break;
-
+#endif
         case WM_EXITMENULOOP:
             processed = HandleMenuLoop(wxEVT_MENU_CLOSE, wParam);
             break;
-#endif // __WIN16__
 
         case WM_QUERYDRAGICON:
             {
@@ -792,3 +793,15 @@ long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
     return rc;
 }
 
+// handle WM_INITMENU message
+bool wxFrame::HandleInitMenu()
+{
+    wxMenuEvent event(wxEVT_MENU_OPEN, 0);
+    event.SetEventObject(this);
+
+    return GetEventHandler()->ProcessEvent(event);
+    
+    return TRUE;
+}
+
+
diff --git a/src/msw/window.cpp b/src/msw/window.cpp
index 57ebce9a76..afba07ad53 100644
--- a/src/msw/window.cpp
+++ b/src/msw/window.cpp
@@ -233,7 +233,6 @@ BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
-    EVT_IDLE(wxWindowMSW::OnIdle)
 END_EVENT_TABLE()
 
 // ===========================================================================
@@ -1146,7 +1145,7 @@ bool wxWindowMSW::IsMouseInWindow() const
     return hwnd != NULL;
 }
 
-void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
+void wxWindowMSW::OnInternalIdle()
 {
     // Check if we need to send a LEAVE event
     if ( m_mouseInWindow )
@@ -1159,7 +1158,7 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
             m_mouseInWindow = FALSE;
 
             // Unfortunately the mouse button and keyboard state may have
-            // changed by the time the OnIdle function is called, so 'state'
+            // changed by the time the OnInternalIdle function is called, so 'state'
             // may be meaningless.
             int state = 0;
             if ( wxIsShiftDown() )
@@ -1192,8 +1191,8 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // Set this window to be the child of 'parent'.
@@ -1266,7 +1265,7 @@ void wxWindowMSW::Update()
         wxLogLastError(_T("UpdateWindow"));
     }
 
-#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+#if !defined(__WXMICROWIN__)
     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
     // handler needs to be really drawn right now
     (void)::GdiFlush();
@@ -2030,11 +2029,9 @@ bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg))
 }
 
 // ---------------------------------------------------------------------------
-// message params unpackers (different for Win16 and Win32)
+// message params unpackers
 // ---------------------------------------------------------------------------
 
-#ifdef __WIN32__
-
 void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
                              WORD *id, WXHWND *hwnd, WORD *cmd)
 {
@@ -2077,50 +2074,6 @@ void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
     *hmenu = (WXHMENU)lParam;
 }
 
-#else // Win16
-
-void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
-                             WXWORD *id, WXHWND *hwnd, WXWORD *cmd)
-{
-    *id = (WXWORD)wParam;
-    *hwnd = (WXHWND)LOWORD(lParam);
-    *cmd = HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
-                              WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
-{
-    *state = (WXWORD)wParam;
-    *minimized = LOWORD(lParam);
-    *hwnd = (WXHWND)HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
-                            WXWORD *code, WXWORD *pos, WXHWND *hwnd)
-{
-    *code = (WXWORD)wParam;
-    *pos = LOWORD(lParam);
-    *hwnd = (WXHWND)HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
-                              WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
-{
-    *hwnd = (WXHWND)LOWORD(lParam);
-    *nCtlColor = (int)HIWORD(lParam);
-    *hdc = (WXHDC)wParam;
-}
-
-void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
-                                WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
-{
-    *item = (WXWORD)wParam;
-    *flags = LOWORD(lParam);
-    *hmenu = (WXHMENU)HIWORD(lParam);
-}
-
-#endif // Win32/16
-
 // ---------------------------------------------------------------------------
 // Main wxWindows window proc and the window proc for wxWindow
 // ---------------------------------------------------------------------------
@@ -2612,7 +2565,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
         // CTLCOLOR messages are sent by children to query the parent for their
         // colors#ifndef __WXMICROWIN__
 #ifndef __WXMICROWIN__
-#ifdef __WIN32__
         case WM_CTLCOLORMSGBOX:
         case WM_CTLCOLOREDIT:
         case WM_CTLCOLORLISTBOX:
@@ -2620,9 +2572,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
         case WM_CTLCOLORDLG:
         case WM_CTLCOLORSCROLLBAR:
         case WM_CTLCOLORSTATIC:
-#else // Win16
-        case WM_CTLCOLOR:
-#endif // Win32/16
             {
                 WXWORD nCtlColor;
                 WXHDC hdc;
@@ -2724,7 +2673,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             }
 #endif
 
-#if defined(__WIN32__) && defined(WM_HELP)
+#if defined(WM_HELP)
         case WM_HELP:
             {
                 HELPINFO* info = (HELPINFO*) lParam;
@@ -2785,7 +2734,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
                 }
             }
             break;
-#endif // __WIN32__
+#endif
     }
 
     if ( !processed )
@@ -3356,15 +3305,10 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
     // first ask the user code - it may wish to set the cursor in some very
     // specific way (for example, depending on the current position)
     POINT pt;
-#ifdef __WIN32__
     if ( !::GetCursorPos(&pt) )
     {
         wxLogLastError(wxT("GetCursorPos"));
     }
-#else
-    // In WIN16 it doesn't return a value.
-    ::GetCursorPos(&pt);
-#endif
 
     int x = pt.x,
         y = pt.y;
@@ -3769,7 +3713,6 @@ bool wxWindowMSW::HandlePaint()
 //    if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
 //        return FALSE;
 
-#ifdef __WIN32__
     HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
     if ( !hRegion )
         wxLogLastError(wxT("CreateRectRgn"));
@@ -3777,14 +3720,6 @@ bool wxWindowMSW::HandlePaint()
         wxLogLastError(wxT("GetUpdateRgn"));
 
     m_updateRegion = wxRegion((WXHRGN) hRegion);
-#else // Win16
-    RECT updateRect;
-    ::GetUpdateRect(GetHwnd(), &updateRect, FALSE);
-
-    m_updateRegion = wxRegion(updateRect.left, updateRect.top,
-                              updateRect.right - updateRect.left,
-                              updateRect.bottom - updateRect.top);
-#endif // Win32/16
 
     wxPaintEvent event(m_windowId);
     event.SetEventObject(this);
@@ -4120,7 +4055,6 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) //
     HWND hwnd = GetHwndOf(win),
          hwndUnderMouse;
 
-#ifdef __WIN32__
     hwndUnderMouse = ::ChildWindowFromPointEx
                        (
                         hwnd,
@@ -4131,7 +4065,6 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) //
                        );
 
     if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
-#endif // __WIN32__
     {
         // now try any child window at all
         hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
@@ -4234,7 +4167,6 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
     event.m_wheelRotation = (short)HIWORD(wParam);
     event.m_wheelDelta = WHEEL_DELTA;
 
-#ifdef __WIN32__
     static int s_linesPerRotation = -1;
     if ( s_linesPerRotation == -1 )
     {
@@ -4248,10 +4180,6 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
             s_linesPerRotation = 3;
         }
     }
-#else // Win16
-    // no SystemParametersInfo() under Win16
-    static const int s_linesPerRotation = 3;
-#endif
 
     event.m_linesPerAction = s_linesPerRotation;
     return GetEventHandler()->ProcessEvent(event);
@@ -4408,8 +4336,6 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
     return FALSE;
 }
 
-#ifdef __WIN32__
-
 int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
 {
     const HMENU hmenu = (HMENU)lParam;
@@ -4458,7 +4384,7 @@ int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
                 }
             }
         }
-        else // failed ot get the menu text?
+        else // failed to get the menu text?
         {
             // it's not fatal, so don't show error, but still log
             // it
@@ -4469,8 +4395,6 @@ int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
     return wxNOT_FOUND;
 }
 
-#endif // __WIN32__
-
 // ---------------------------------------------------------------------------
 // joystick
 // ---------------------------------------------------------------------------
@@ -4606,7 +4530,6 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
 
     case SB_THUMBPOSITION:
     case SB_THUMBTRACK:
-#ifdef __WIN32__
         // under Win32, the scrollbar range and position are 32 bit integers,
         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
         // explicitly query the scrollbar for the correct position (this must
@@ -4626,7 +4549,6 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
 
             event.SetPosition(scrollInfo.nTrackPos);
         }
-#endif // Win32
 
         event.m_eventType = wParam == SB_THUMBPOSITION
                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
@@ -4874,9 +4796,6 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
         win = wxFindWinFromHandle((WXHWND)hwnd);
         if ( !win )
         {
-            // all these hacks only work under Win32 anyhow
-#ifdef __WIN32__
-
 #if wxUSE_RADIOBOX
             // native radiobuttons return DLGC_RADIOBUTTON here and for any
             // wxWindow class which overrides WM_GETDLGCODE processing to
@@ -4896,8 +4815,6 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
                 win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
             }
 #endif // wxUSE_SPINCTRL
-
-#endif // Win32
         }
     }
 
@@ -4942,23 +4859,13 @@ void wxSetKeyboardHook(bool doIt)
         wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
         wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
 
-#if defined(__WIN32__)
             GetCurrentThreadId()
         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
-#else
-            GetCurrentTask()
-#endif
             );
     }
     else
     {
         UnhookWindowsHookEx(wxTheKeyboardHook);
-
-        // avoids warning about statement with no effect (FreeProcInstance
-        // doesn't do anything under Win32)
-#if !defined(__WIN32__) && !defined(__NT__)
-        FreeProcInstance(wxTheKeyboardHookProc);
-#endif
     }
 }
 
@@ -5066,7 +4973,6 @@ const char *wxGetMessageName(int message)
         case 0x0047: return "WM_WINDOWPOSCHANGED";
         case 0x0048: return "WM_POWER";
 
-#ifdef  __WIN32__
         case 0x004A: return "WM_COPYDATA";
         case 0x004B: return "WM_CANCELJOURNAL";
         case 0x004E: return "WM_NOTIFY";
@@ -5082,7 +4988,6 @@ const char *wxGetMessageName(int message)
         case 0x007E: return "WM_DISPLAYCHANGE";
         case 0x007F: return "WM_GETICON";
         case 0x0080: return "WM_SETICON";
-#endif  //WIN32
 
         case 0x0081: return "WM_NCCREATE";
         case 0x0082: return "WM_NCDESTROY";
@@ -5111,11 +5016,9 @@ const char *wxGetMessageName(int message)
         case 0x0107: return "WM_SYSDEADCHAR";
         case 0x0108: return "WM_KEYLAST";
 
-#ifdef  __WIN32__
         case 0x010D: return "WM_IME_STARTCOMPOSITION";
         case 0x010E: return "WM_IME_ENDCOMPOSITION";
         case 0x010F: return "WM_IME_COMPOSITION";
-#endif  //WIN32
 
         case 0x0110: return "WM_INITDIALOG";
         case 0x0111: return "WM_COMMAND";
@@ -5143,14 +5046,12 @@ const char *wxGetMessageName(int message)
         case 0x0211: return "WM_ENTERMENULOOP";
         case 0x0212: return "WM_EXITMENULOOP";
 
-#ifdef  __WIN32__
         case 0x0213: return "WM_NEXTMENU";
         case 0x0214: return "WM_SIZING";
         case 0x0215: return "WM_CAPTURECHANGED";
         case 0x0216: return "WM_MOVING";
         case 0x0218: return "WM_POWERBROADCAST";
         case 0x0219: return "WM_DEVICECHANGE";
-#endif  //WIN32
 
         case 0x0220: return "WM_MDICREATE";
         case 0x0221: return "WM_MDIDESTROY";
@@ -5165,7 +5066,6 @@ const char *wxGetMessageName(int message)
         case 0x0230: return "WM_MDISETMENU";
         case 0x0233: return "WM_DROPFILES";
 
-#ifdef  __WIN32__
         case 0x0281: return "WM_IME_SETCONTEXT";
         case 0x0282: return "WM_IME_NOTIFY";
         case 0x0283: return "WM_IME_CONTROL";
@@ -5174,7 +5074,6 @@ const char *wxGetMessageName(int message)
         case 0x0286: return "WM_IME_CHAR";
         case 0x0290: return "WM_IME_KEYDOWN";
         case 0x0291: return "WM_IME_KEYUP";
-#endif  //WIN32
 
         case 0x0300: return "WM_CUT";
         case 0x0301: return "WM_COPY";
@@ -5195,7 +5094,6 @@ const char *wxGetMessageName(int message)
         case 0x0310: return "WM_PALETTEISCHANGING";
         case 0x0311: return "WM_PALETTECHANGED";
 
-#ifdef __WIN32__
         // common controls messages - although they're not strictly speaking
         // standard, it's nice to decode them nevertheless
 
@@ -5417,8 +5315,6 @@ const char *wxGetMessageName(int message)
         case WM_USER+61: return "TB_GETTEXTROWS";
         case WM_USER+41: return "TB_GETBITMAPFLAGS";
 
-#endif //WIN32
-
         default:
             static char s_szBuf[128];
             sprintf(s_szBuf, "<unknown message = %d>", message);
diff --git a/src/os2/app.cpp b/src/os2/app.cpp
index d7539983f9..6ea69bbc90 100644
--- a/src/os2/app.cpp
+++ b/src/os2/app.cpp
@@ -659,19 +659,6 @@ int wxApp::MainLoop()
     return (int)svCurrentMsg.mp1;
 } // end of wxApp::MainLoop
 
-//
-// Returns TRUE if more time is needed.
-//
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent                     vEvent;
-
-    vEvent.SetEventObject(this);
-    ProcessEvent(vEvent);
-    wxUpdateUIEvent::ResetUpdateTime();    
-    return vEvent.MoreRequested();
-} // end of wxApp::ProcessIdle
-
 void wxApp::ExitMainLoop()
 {
     ::WinPostMsg(NULL, WM_QUIT, 0, 0);
@@ -835,52 +822,6 @@ void wxApp::OnIdle(
     gbInOnIdle = FALSE;
 } // end of wxApp::OnIdle
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool                            bNeedMore = FALSE;
-    wxWindowList::Node*             pNode = wxTopLevelWindows.GetFirst();
-
-    while (pNode)
-    {
-        wxWindow*                   pWin = pNode->GetData();
-
-        if (SendIdleEvents(pWin))
-            bNeedMore = TRUE;
-        pNode = pNode->GetNext();
-    }
-    return bNeedMore;
-} // end of wxApp::SendIdleEvents
-
-//
-// Send idle event to window and all subwindows
-//
-bool wxApp::SendIdleEvents(
-  wxWindow*                         pWin
-)
-{
-    bool                            bNeedMore = FALSE;
-    wxIdleEvent                     vEvent;
-
-    vEvent.SetEventObject(pWin);
-    pWin->GetEventHandler()->ProcessEvent(vEvent);
-
-    if (vEvent.MoreRequested())
-        bNeedMore = TRUE;
-
-    wxNode*                         pNode = pWin->GetChildren().First();
-
-    while (pNode)
-    {
-        wxWindow*                   pWin = (wxWindow*) pNode->Data();
-
-        if (SendIdleEvents(pWin))
-            bNeedMore = TRUE;
-        pNode = pNode->Next();
-    }
-    return bNeedMore;
-} // end of wxApp::SendIdleEvents
-
 void wxApp::OnEndSession(
   wxCloseEvent&                     WXUNUSED(rEvent))
 {
diff --git a/src/os2/evtloop.cpp b/src/os2/evtloop.cpp
index e177f38ee0..2b72b4088d 100644
--- a/src/os2/evtloop.cpp
+++ b/src/os2/evtloop.cpp
@@ -138,13 +138,7 @@ bool wxEventLoopImpl::PreProcessMessage(QMSG *msg)
 
 bool wxEventLoopImpl::SendIdleMessage()
 {
-    wxIdleEvent event;
-
-    bool processed = wxTheApp->ProcessEvent(event) ;
-
-    wxUpdateUIEvent::ResetUpdateTime();    
-    
-    return processed && event.MoreRequested();
+    return wxTheApp->ProcessIdle() ;
 }
 
 // ============================================================================
diff --git a/src/os2/window.cpp b/src/os2/window.cpp
index 7903c10e6c..affeabe47e 100644
--- a/src/os2/window.cpp
+++ b/src/os2/window.cpp
@@ -1364,8 +1364,8 @@ void wxWindowOS2::OnIdle(
             (void)GetEventHandler()->ProcessEvent(rEvent);
         }
     }
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 } // end of wxWindowOS2::OnIdle
 
 //
diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp
index 7ae71b51fe..4612caa01d 100644
--- a/src/univ/listbox.cpp
+++ b/src/univ/listbox.cpp
@@ -49,8 +49,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
 
 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
     EVT_SIZE(wxListBox::OnSize)
-
-    EVT_IDLE(wxListBox::OnIdle)
 END_EVENT_TABLE()
 
 // ----------------------------------------------------------------------------
@@ -601,7 +599,7 @@ void wxListBox::UpdateItems()
     }
 }
 
-void wxListBox::OnIdle(wxIdleEvent& event)
+void wxListBox::OnInternalIdle()
 {
     if ( m_updateScrollbarY || m_updateScrollbarX )
     {
@@ -624,8 +622,6 @@ void wxListBox::OnIdle(wxIdleEvent& event)
 
         m_updateCount = 0;
     }
-
-    event.Skip();
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp
index bba605997f..a4e1176552 100644
--- a/src/univ/menu.cpp
+++ b/src/univ/menu.cpp
@@ -2463,8 +2463,7 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
     wxLog::FlushActive();
 
     // some controls update themselves from OnIdle() call - let them do it
-    wxIdleEvent event;
-    wxTheApp->ProcessEvent(event);
+    wxTheApp->ProcessIdle();
 
     // if the window hadn't been refreshed yet, the menu can adversely affect
     // its next OnPaint() handler execution - i.e. scrolled window refresh
diff --git a/src/univ/scrolbar.cpp b/src/univ/scrolbar.cpp
index b13034d837..372b3b3fe9 100644
--- a/src/univ/scrolbar.cpp
+++ b/src/univ/scrolbar.cpp
@@ -83,7 +83,6 @@ private:
 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
 
 BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase)
-    EVT_IDLE(wxScrollBar::OnIdle)
 END_EVENT_TABLE()
 
 // ----------------------------------------------------------------------------
@@ -322,10 +321,9 @@ wxScrollArrows::Arrow wxScrollBar::HitTest(const wxPoint& pt) const
 // drawing
 // ----------------------------------------------------------------------------
 
-void wxScrollBar::OnIdle(wxIdleEvent& event)
+void wxScrollBar::OnInternalIdle()
 {
     UpdateThumb();
-    event.Skip();
 }
 
 void wxScrollBar::UpdateThumb()
diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp
index ae45b1e13a..afd8751329 100644
--- a/src/univ/textctrl.cpp
+++ b/src/univ/textctrl.cpp
@@ -608,8 +608,6 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
     EVT_CHAR(wxTextCtrl::OnChar)
 
     EVT_SIZE(wxTextCtrl::OnSize)
-
-    EVT_IDLE(wxTextCtrl::OnIdle)
 END_EVENT_TABLE()
 
 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
@@ -3571,7 +3569,7 @@ void wxTextCtrl::UpdateScrollbars()
     MData().m_updateScrollbarY = FALSE;
 }
 
-void wxTextCtrl::OnIdle(wxIdleEvent& event)
+void wxTextCtrl::OnInternalIdle()
 {
     // notice that single line text control never has scrollbars
     if ( !IsSingleLine() &&
@@ -3579,8 +3577,6 @@ void wxTextCtrl::OnIdle(wxIdleEvent& event)
     {
         UpdateScrollbars();
     }
-
-    event.Skip();
 }
 
 bool wxTextCtrl::SendAutoScrollEvents(wxScrollWinEvent& event) const
diff --git a/src/x11/app.cpp b/src/x11/app.cpp
index 87fcdb4ea1..ff91c2fb6b 100644
--- a/src/x11/app.cpp
+++ b/src/x11/app.cpp
@@ -672,20 +672,6 @@ bool wxApp::ProcessXEvent(WXEvent* _event)
     return FALSE;
 }
 
-// Returns TRUE if more time is needed.
-// Note that this duplicates wxEventLoopImpl::SendIdleEvent
-// but ProcessIdle may be needed by apps, so is kept.
-bool wxApp::ProcessIdle()
-{
-    wxIdleEvent event;
-    event.SetEventObject(this);
-    ProcessEvent(event);
-
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return event.MoreRequested();
-}
-
 void wxApp::ExitMainLoop()
 {
     if (m_mainLoop)
@@ -748,51 +734,6 @@ void wxApp::WakeUpIdle()
 }
 
 
-// Send idle event to all top-level windows
-bool wxApp::SendIdleEvents()
-{
-    bool needMore = FALSE;
-
-    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
-    while (node)
-    {
-        wxWindow* win = node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-        node = node->GetNext();
-    }
-
-    return needMore;
-}
-
-// Send idle event to window and all subwindows
-bool wxApp::SendIdleEvents(wxWindow* win)
-{
-    bool needMore = FALSE;
-
-    wxIdleEvent event;
-    event.SetEventObject(win);
-
-    win->GetEventHandler()->ProcessEvent(event);
-
-    if (event.MoreRequested())
-        needMore = TRUE;
-
-    wxWindowListNode* node = win->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow* win = (wxWindow*) node->GetData();
-        if (SendIdleEvents(win))
-            needMore = TRUE;
-
-        node = node->GetNext();
-    }
-
-    win->OnInternalIdle();
-
-    return needMore;
-}
-
 // Create display, and other initialization
 bool wxApp::OnInitGui()
 {
diff --git a/src/x11/evtloop.cpp b/src/x11/evtloop.cpp
index d236f1afc8..20da77c3e7 100644
--- a/src/x11/evtloop.cpp
+++ b/src/x11/evtloop.cpp
@@ -335,14 +335,7 @@ bool wxEventLoopImpl::PreProcessEvent(XEvent *event)
 
 bool wxEventLoopImpl::SendIdleEvent()
 {
-    wxIdleEvent event;
-    event.SetEventObject(wxTheApp);
-
-    bool processed = wxTheApp->ProcessEvent(event) ;
-    
-    wxUpdateUIEvent::ResetUpdateTime();
-    
-    return processed && event.MoreRequested();
+    return wxTheApp->ProcessIdle();
 }
 
 // ============================================================================
diff --git a/src/x11/textctrl.cpp b/src/x11/textctrl.cpp
index 7381cfef0f..9f69ec1a21 100644
--- a/src/x11/textctrl.cpp
+++ b/src/x11/textctrl.cpp
@@ -135,7 +135,6 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
     EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground)
     EVT_CHAR(wxTextCtrl::OnChar)
     EVT_MOUSE_EVENTS(wxTextCtrl::OnMouse)
-    EVT_IDLE(wxTextCtrl::OnIdle)
     EVT_KILL_FOCUS(wxTextCtrl::OnKillFocus)
     EVT_SET_FOCUS(wxTextCtrl::OnSetFocus)
     
@@ -1962,14 +1961,12 @@ void wxTextCtrl::OnChar( wxKeyEvent &event )
     event.Skip();
 }
 
-void wxTextCtrl::OnIdle( wxIdleEvent &event )
+void wxTextCtrl::OnInternalIdle()
 {
     m_ignoreInput = FALSE;
     
     if (m_lang != wxSOURCE_LANG_NONE)
         SearchForBrackets();
-    
-    event.Skip( TRUE );
 }
 
 void wxTextCtrl::Indent()
diff --git a/src/x11/window.cpp b/src/x11/window.cpp
index d787a4eaef..4ae7c1468b 100644
--- a/src/x11/window.cpp
+++ b/src/x11/window.cpp
@@ -1287,8 +1287,8 @@ void wxWindowX11::OnInternalIdle()
 
     // This calls the UI-update mechanism (querying windows for
     // menu/toolbar/control state information)
-    if (wxUpdateUIEvent::CanUpdate())
-        UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 
     // Set the input focus if couldn't do it before
     if (m_needsInputFocus)
-- 
2.45.2

