]> git.saurik.com Git - wxWidgets.git/commitdiff
support wxWindowDisabler on osx_cocoa
authorStefan Csomor <csomor@advancedconcepts.ch>
Sat, 5 Mar 2011 12:21:20 +0000 (12:21 +0000)
committerStefan Csomor <csomor@advancedconcepts.ch>
Sat, 5 Mar 2011 12:21:20 +0000 (12:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67129 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/osx/cocoa/evtloop.h
include/wx/utils.h
src/common/utilscmn.cpp
src/osx/cocoa/evtloop.mm

index afccc7a92daa4a7c69029bc724e3f48026f2c6fd..c8b5d9e66641ad03054810a326e220cfb9da3ca3 100644 (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_
index 0906fa834c95fdad275ad0380337635ac4d4abcd..b539373de9217c8d101425cc4b0b9db37b5960eb 100644 (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;
 
index 6037037de0c253fbf6f635ba7ef42ccad2246983..15908b65e78968a2d8ad40aa26bd9783006d98ad 100644 (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)
index 89957cd2bd7672e073352c8ef469c97c107777e1..e558a54e255f58bd6e49db7b1ad3c1c952068429 100644 (file)
 // wxEventLoop implementation
 // ============================================================================
 
-/*
-static int 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,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
-       NSTabletPointMask               = 1 << NSTabletPoint,
-       NSTabletProximityMask           = 1 << NSTabletProximity,
-#endif
-       NSOtherMouseDownMask            = 1 << NSOtherMouseDown,
-       NSOtherMouseUpMask              = 1 << NSOtherMouseUp,
-       NSOtherMouseDraggedMask         = 1 << NSOtherMouseDragged,
-
 
+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;
 
-       NSKeyDownMask                   = 1 << NSKeyDown,
-       NSKeyUpMask                     = 1 << NSKeyUp,
-       NSFlagsChangedMask              = 1 << NSFlagsChanged,
+    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 |
+            NSTabletProximityMask |
+#endif
+            NSOtherMouseDownMask |
+            NSOtherMouseUpMask |
+            NSOtherMouseDraggedMask |
+
+            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;
+}
 
-       NSAppKitDefinedMask             = 1 << NSAppKitDefined,
-       NSSystemDefinedMask             = 1 << NSSystemDefined,
-       NSApplicationDefinedMask        = 1 << NSApplicationDefined,
-       NSPeriodicMask                  = 1 << NSPeriodic,
-       NSCursorUpdateMask              = 1 << NSCursorUpdate,
 
-       NSAnyEventMask                  = 0xffffffffU
+wxGUIEventLoop::wxGUIEventLoop()
+{
+    m_modalSession = nil;
+    m_dummyWindow = nil;
 }
-*/
 
-wxGUIEventLoop::wxGUIEventLoop()
+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;
+}
+