support wxWindowDisabler on osx_cocoa

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67129 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor
2011-03-05 12:21:20 +00:00
parent dc90b8d411
commit 902ddbfd3e
4 changed files with 231 additions and 42 deletions

View File

@@ -15,6 +15,11 @@ class WXDLLIMPEXP_BASE wxGUIEventLoop : public wxCFEventLoop
{ {
public: public:
wxGUIEventLoop(); wxGUIEventLoop();
~wxGUIEventLoop();
void BeginModalSession( wxWindow* modalWindow );
void EndModalSession();
protected: protected:
virtual int DoDispatchTimeout(unsigned long timeout); virtual int DoDispatchTimeout(unsigned long timeout);
@@ -24,6 +29,9 @@ protected:
virtual void DoStop(); virtual void DoStop();
virtual CFRunLoopRef CFGetCurrentRunLoop() const; virtual CFRunLoopRef CFGetCurrentRunLoop() const;
void* m_modalSession;
WXWindow m_dummyWindow;
}; };
#endif // _WX_OSX_COCOA_EVTLOOP_H_ #endif // _WX_OSX_COCOA_EVTLOOP_H_

View File

@@ -55,6 +55,7 @@ class WXDLLIMPEXP_FWD_BASE wxProcess;
class WXDLLIMPEXP_FWD_CORE wxFrame; class WXDLLIMPEXP_FWD_CORE wxFrame;
class WXDLLIMPEXP_FWD_CORE wxWindow; class WXDLLIMPEXP_FWD_CORE wxWindow;
class WXDLLIMPEXP_FWD_CORE wxWindowList; class WXDLLIMPEXP_FWD_CORE wxWindowList;
class WXDLLIMPEXP_FWD_CORE wxEventLoop;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Arithmetic functions // Arithmetic functions
@@ -714,7 +715,9 @@ private:
// disable all windows except the given one (used by both ctors) // disable all windows except the given one (used by both ctors)
void DoDisable(wxWindow *winToSkip = NULL); void DoDisable(wxWindow *winToSkip = NULL);
#if defined(__WXOSX__) && wxOSX_USE_COCOA
wxEventLoop* m_modalEventLoop;
#endif
wxWindowList *m_winDisabled; wxWindowList *m_winDisabled;
bool m_disabled; bool m_disabled;

View File

@@ -1567,6 +1567,12 @@ void wxEnableTopLevelWindows(bool enable)
node->GetData()->Enable(enable); node->GetData()->Enable(enable);
} }
#if defined(__WXOSX__) && wxOSX_USE_COCOA
// defined in evtloop.mm
#else
wxWindowDisabler::wxWindowDisabler(bool disable) wxWindowDisabler::wxWindowDisabler(bool disable)
{ {
m_disabled = disable; m_disabled = disable;
@@ -1629,6 +1635,8 @@ wxWindowDisabler::~wxWindowDisabler()
delete m_winDisabled; delete m_winDisabled;
} }
#endif
// Yield to other apps/messages and disable user input to all windows except // Yield to other apps/messages and disable user input to all windows except
// the given one // the given one
bool wxSafeYield(wxWindow *win, bool onlyIfNeeded) bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)

View File

@@ -39,45 +39,76 @@
// wxEventLoop implementation // wxEventLoop implementation
// ============================================================================ // ============================================================================
/*
static int CalculateNSEventMaskFromEventCategory(wxEventCategory cat) static NSUInteger CalculateNSEventMaskFromEventCategory(wxEventCategory cat)
{ {
// the masking system doesn't really help, as only the lowlevel UI events
// are split in a useful way, all others are way to broad
if ( (cat | wxEVT_CATEGORY_USER_INPUT) && (cat | (~wxEVT_CATEGORY_USER_INPUT) ) )
return NSAnyEventMask;
NSUInteger mask = 0;
if ( cat | wxEVT_CATEGORY_USER_INPUT )
{
mask |=
NSLeftMouseDownMask | NSLeftMouseDownMask |
NSLeftMouseUpMask | NSLeftMouseUpMask |
NSRightMouseDownMask | NSRightMouseDownMask |
NSRightMouseUpMask = 1 << NSRightMouseUp, NSRightMouseUpMask |
NSMouseMovedMask = 1 << NSMouseMoved, NSMouseMovedMask |
NSLeftMouseDraggedMask = 1 << NSLeftMouseDragged, NSLeftMouseDraggedMask |
NSRightMouseDraggedMask = 1 << NSRightMouseDragged, NSRightMouseDraggedMask |
NSMouseEnteredMask = 1 << NSMouseEntered, NSMouseEnteredMask |
NSMouseExitedMask = 1 << NSMouseExited, NSMouseExitedMask |
NSScrollWheelMask = 1 << NSScrollWheel, NSScrollWheelMask |
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
NSTabletPointMask = 1 << NSTabletPoint, NSTabletPointMask |
NSTabletProximityMask = 1 << NSTabletProximity, NSTabletProximityMask |
#endif #endif
NSOtherMouseDownMask = 1 << NSOtherMouseDown, NSOtherMouseDownMask |
NSOtherMouseUpMask = 1 << NSOtherMouseUp, NSOtherMouseUpMask |
NSOtherMouseDraggedMask = 1 << NSOtherMouseDragged, NSOtherMouseDraggedMask |
NSKeyDownMask |
NSKeyUpMask |
NSKeyDownMask = 1 << NSKeyDown, NSFlagsChangedMask |
NSKeyUpMask = 1 << NSKeyUp, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
NSFlagsChangedMask = 1 << NSFlagsChanged, NSEventMaskGesture |
NSEventMaskMagnify |
NSAppKitDefinedMask = 1 << NSAppKitDefined, NSEventMaskSwipe |
NSSystemDefinedMask = 1 << NSSystemDefined, NSEventMaskRotate |
NSApplicationDefinedMask = 1 << NSApplicationDefined, NSEventMaskBeginGesture |
NSPeriodicMask = 1 << NSPeriodic, NSEventMaskEndGesture |
NSCursorUpdateMask = 1 << NSCursorUpdate, #endif
0;
NSAnyEventMask = 0xffffffffU
} }
*/
if ( cat | (~wxEVT_CATEGORY_USER_INPUT) )
{
mask |=
NSAppKitDefinedMask |
NSSystemDefinedMask |
NSApplicationDefinedMask |
NSPeriodicMask |
NSCursorUpdateMask;
}
return mask;
}
wxGUIEventLoop::wxGUIEventLoop() wxGUIEventLoop::wxGUIEventLoop()
{ {
m_modalSession = nil;
m_dummyWindow = nil;
}
wxGUIEventLoop::~wxGUIEventLoop()
{
wxASSERT( m_modalSession == nil );
wxASSERT( m_dummyWindow == nil );
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -156,6 +187,35 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
{ {
wxMacAutoreleasePool autoreleasepool; wxMacAutoreleasePool autoreleasepool;
if ( m_modalSession )
{
NSInteger response = [NSApp runModalSession:(NSModalSession)m_modalSession];
switch (response)
{
case NSRunContinuesResponse:
{
if ( [[NSApplication sharedApplication]
nextEventMatchingMask: NSAnyEventMask
untilDate: nil
inMode: NSDefaultRunLoopMode
dequeue: NO] != nil )
return 1;
return -1;
}
case NSRunStoppedResponse:
case NSRunAbortedResponse:
return -1;
default:
wxFAIL_MSG("unknown response code");
return -1;
break;
}
}
else
{
NSEvent *event = [NSApp NSEvent *event = [NSApp
nextEventMatchingMask:NSAnyEventMask nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000] untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000]
@@ -169,6 +229,7 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
return 1; return 1;
} }
}
void wxGUIEventLoop::DoRun() void wxGUIEventLoop::DoRun()
{ {
@@ -240,3 +301,112 @@ void wxModalEventLoop::DoStop()
[NSApp stopModal]; [NSApp stopModal];
} }
void wxGUIEventLoop::BeginModalSession( wxWindow* modalWindow )
{
WXWindow nsnow = nil;
if ( modalWindow )
{
wxNonOwnedWindow* now = dynamic_cast<wxNonOwnedWindow*> (modalWindow);
wxASSERT_MSG( now != NULL, "must pass in a toplevel window for modal event loop" );
nsnow = now ? now->GetWXWindow() : nil;
}
else
{
NSRect r = NSMakeRect(10, 10, 0, 0);
nsnow = [NSPanel alloc];
[nsnow initWithContentRect:r
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:YES
];
[nsnow orderOut:nil];
m_dummyWindow = nsnow;
}
m_modalSession = [NSApp beginModalSessionForWindow:nsnow];
}
void wxGUIEventLoop::EndModalSession()
{
wxASSERT_MSG(m_modalSession != NULL, "no modal session active");
[NSApp endModalSession:(NSModalSession)m_modalSession];
m_modalSession = nil;
if ( m_dummyWindow )
{
[m_dummyWindow release];
m_dummyWindow = nil;
}
}
//
//
//
wxWindowDisabler::wxWindowDisabler(bool disable)
{
m_modalEventLoop = NULL;
m_disabled = disable;
if ( disable )
DoDisable();
}
wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
{
m_disabled = true;
DoDisable(winToSkip);
}
void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
{
// remember the top level windows which were already disabled, so that we
// don't reenable them later
m_winDisabled = NULL;
wxWindowList::compatibility_iterator node;
for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
{
wxWindow *winTop = node->GetData();
if ( winTop == winToSkip )
continue;
// we don't need to disable the hidden or already disabled windows
if ( winTop->IsEnabled() && winTop->IsShown() )
{
winTop->Disable();
}
else
{
if ( !m_winDisabled )
{
m_winDisabled = new wxWindowList;
}
m_winDisabled->Append(winTop);
}
}
m_modalEventLoop = (wxEventLoop*)wxEventLoopBase::GetActive();
m_modalEventLoop->BeginModalSession(winToSkip);
}
wxWindowDisabler::~wxWindowDisabler()
{
if ( !m_disabled )
return;
m_modalEventLoop->EndModalSession();
wxWindowList::compatibility_iterator node;
for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
{
wxWindow *winTop = node->GetData();
if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
{
winTop->Enable();
}
//else: had been already disabled, don't reenable
}
delete m_winDisabled;
}