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:
wxGUIEventLoop();
~wxGUIEventLoop();
void BeginModalSession( wxWindow* modalWindow );
void EndModalSession();
protected:
virtual int DoDispatchTimeout(unsigned long timeout);
@ -24,6 +29,9 @@ protected:
virtual void DoStop();
virtual CFRunLoopRef CFGetCurrentRunLoop() const;
void* m_modalSession;
WXWindow m_dummyWindow;
};
#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 wxWindow;
class WXDLLIMPEXP_FWD_CORE wxWindowList;
class WXDLLIMPEXP_FWD_CORE wxEventLoop;
// ----------------------------------------------------------------------------
// Arithmetic functions
@ -714,7 +715,9 @@ private:
// disable all windows except the given one (used by both ctors)
void DoDisable(wxWindow *winToSkip = NULL);
#if defined(__WXOSX__) && wxOSX_USE_COCOA
wxEventLoop* m_modalEventLoop;
#endif
wxWindowList *m_winDisabled;
bool m_disabled;

View File

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

View File

@ -39,45 +39,76 @@
// wxEventLoop implementation
// ============================================================================
/*
static int CalculateNSEventMaskFromEventCategory(wxEventCategory cat)
static NSUInteger CalculateNSEventMaskFromEventCategory(wxEventCategory cat)
{
NSLeftMouseDownMask |
NSLeftMouseUpMask |
NSRightMouseDownMask |
NSRightMouseUpMask = 1 << NSRightMouseUp,
NSMouseMovedMask = 1 << NSMouseMoved,
NSLeftMouseDraggedMask = 1 << NSLeftMouseDragged,
NSRightMouseDraggedMask = 1 << NSRightMouseDragged,
NSMouseEnteredMask = 1 << NSMouseEntered,
NSMouseExitedMask = 1 << NSMouseExited,
NSScrollWheelMask = 1 << NSScrollWheel,
// 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 |
NSLeftMouseUpMask |
NSRightMouseDownMask |
NSRightMouseUpMask |
NSMouseMovedMask |
NSLeftMouseDraggedMask |
NSRightMouseDraggedMask |
NSMouseEnteredMask |
NSMouseExitedMask |
NSScrollWheelMask |
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
NSTabletPointMask = 1 << NSTabletPoint,
NSTabletProximityMask = 1 << NSTabletProximity,
NSTabletPointMask |
NSTabletProximityMask |
#endif
NSOtherMouseDownMask = 1 << NSOtherMouseDown,
NSOtherMouseUpMask = 1 << NSOtherMouseUp,
NSOtherMouseDraggedMask = 1 << NSOtherMouseDragged,
NSOtherMouseDownMask |
NSOtherMouseUpMask |
NSOtherMouseDraggedMask |
NSKeyDownMask = 1 << NSKeyDown,
NSKeyUpMask = 1 << NSKeyUp,
NSFlagsChangedMask = 1 << NSFlagsChanged,
NSAppKitDefinedMask = 1 << NSAppKitDefined,
NSSystemDefinedMask = 1 << NSSystemDefined,
NSApplicationDefinedMask = 1 << NSApplicationDefined,
NSPeriodicMask = 1 << NSPeriodic,
NSCursorUpdateMask = 1 << NSCursorUpdate,
NSAnyEventMask = 0xffffffffU
NSKeyDownMask |
NSKeyUpMask |
NSFlagsChangedMask |
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
NSEventMaskGesture |
NSEventMaskMagnify |
NSEventMaskSwipe |
NSEventMaskRotate |
NSEventMaskBeginGesture |
NSEventMaskEndGesture |
#endif
0;
}
if ( cat | (~wxEVT_CATEGORY_USER_INPUT) )
{
mask |=
NSAppKitDefinedMask |
NSSystemDefinedMask |
NSApplicationDefinedMask |
NSPeriodicMask |
NSCursorUpdateMask;
}
return mask;
}
*/
wxGUIEventLoop::wxGUIEventLoop()
{
m_modalSession = nil;
m_dummyWindow = nil;
}
wxGUIEventLoop::~wxGUIEventLoop()
{
wxASSERT( m_modalSession == nil );
wxASSERT( m_dummyWindow == nil );
}
//-----------------------------------------------------------------------------
@ -156,18 +187,48 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
{
wxMacAutoreleasePool autoreleasepool;
NSEvent *event = [NSApp
nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000]
inMode:NSDefaultRunLoopMode
dequeue: YES];
if ( event == nil )
return -1;
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
nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000]
inMode:NSDefaultRunLoopMode
dequeue: YES];
if ( event == nil )
return -1;
[NSApp sendEvent: event];
[NSApp sendEvent: event];
return 1;
return 1;
}
}
void wxGUIEventLoop::DoRun()
@ -240,3 +301,112 @@ void wxModalEventLoop::DoStop()
[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;
}