OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_pump_mac.h" | 5 #import "base/message_pump_mac.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/time.h" | 13 #include "base/time.h" |
14 | 14 |
15 namespace { | 15 namespace { |
16 | 16 |
17 void NoOp(void* info) { | 17 void NoOp(void* info) { |
18 } | 18 } |
19 | 19 |
20 const CFTimeInterval kCFTimeIntervalMax = | 20 const CFTimeInterval kCFTimeIntervalMax = |
21 std::numeric_limits<CFTimeInterval>::max(); | 21 std::numeric_limits<CFTimeInterval>::max(); |
22 | 22 |
| 23 // Set to true if MessagePumpMac::Create() is called before NSApp is |
| 24 // initialized. Only accessed from the main thread. |
| 25 bool not_using_crapp = false; |
| 26 |
23 } // namespace | 27 } // namespace |
24 | 28 |
25 namespace base { | 29 namespace base { |
26 | 30 |
27 // A scoper for autorelease pools created from message pump run loops. | 31 // A scoper for autorelease pools created from message pump run loops. |
28 // Avoids dirtying up the ScopedNSAutoreleasePool interface for the rare | 32 // Avoids dirtying up the ScopedNSAutoreleasePool interface for the rare |
29 // case where an autorelease pool needs to be passed in. | 33 // case where an autorelease pool needs to be passed in. |
30 class MessagePumpScopedAutoreleasePool { | 34 class MessagePumpScopedAutoreleasePool { |
31 public: | 35 public: |
32 explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : | 36 explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 modifierFlags:0 | 588 modifierFlags:0 |
585 timestamp:0 | 589 timestamp:0 |
586 windowNumber:0 | 590 windowNumber:0 |
587 context:NULL | 591 context:NULL |
588 subtype:0 | 592 subtype:0 |
589 data1:0 | 593 data1:0 |
590 data2:0] | 594 data2:0] |
591 atStart:NO]; | 595 atStart:NO]; |
592 } | 596 } |
593 | 597 |
| 598 MessagePumpCrApplication::MessagePumpCrApplication() { |
| 599 } |
| 600 |
594 // Prevents an autorelease pool from being created if the app is in the midst of | 601 // Prevents an autorelease pool from being created if the app is in the midst of |
595 // handling a UI event because various parts of AppKit depend on objects that | 602 // handling a UI event because various parts of AppKit depend on objects that |
596 // are created while handling a UI event to be autoreleased in the event loop. | 603 // are created while handling a UI event to be autoreleased in the event loop. |
597 // An example of this is NSWindowController. When a window with a window | 604 // An example of this is NSWindowController. When a window with a window |
598 // controller is closed it goes through a stack like this: | 605 // controller is closed it goes through a stack like this: |
599 // (Several stack frames elided for clarity) | 606 // (Several stack frames elided for clarity) |
600 // | 607 // |
601 // #0 [NSWindowController autorelease] | 608 // #0 [NSWindowController autorelease] |
602 // #1 DoAClose | 609 // #1 DoAClose |
603 // #2 MessagePumpCFRunLoopBase::DoWork() | 610 // #2 MessagePumpCFRunLoopBase::DoWork() |
(...skipping 11 matching lines...) Expand all Loading... |
615 // window in frame #5. When the stack is unwound to frame #5, the window would | 622 // window in frame #5. When the stack is unwound to frame #5, the window would |
616 // no longer exists and crashes may occur. Apple gets around this by never | 623 // no longer exists and crashes may occur. Apple gets around this by never |
617 // releasing the pool it creates in frame #4, and letting frame #7 clean it up | 624 // releasing the pool it creates in frame #4, and letting frame #7 clean it up |
618 // when it cleans up the pool that wraps frame #7. When an autorelease pool is | 625 // when it cleans up the pool that wraps frame #7. When an autorelease pool is |
619 // released it releases all other pools that were created after it on the | 626 // released it releases all other pools that were created after it on the |
620 // autorelease pool stack. | 627 // autorelease pool stack. |
621 // | 628 // |
622 // CrApplication is responsible for setting handlingSendEvent to true just | 629 // CrApplication is responsible for setting handlingSendEvent to true just |
623 // before it sends the event through the event handling mechanism, and | 630 // before it sends the event through the event handling mechanism, and |
624 // returning it to its previous value once the event has been sent. | 631 // returning it to its previous value once the event has been sent. |
625 NSAutoreleasePool* MessagePumpNSApplication::CreateAutoreleasePool() { | 632 NSAutoreleasePool* MessagePumpCrApplication::CreateAutoreleasePool() { |
626 NSAutoreleasePool* pool = nil; | 633 if (MessagePumpMac::IsHandlingSendEvent()) |
627 DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); | 634 return nil; |
628 if (![NSApp isHandlingSendEvent]) { | 635 return MessagePumpNSApplication::CreateAutoreleasePool(); |
629 pool = MessagePumpCFRunLoopBase::CreateAutoreleasePool(); | |
630 } | |
631 return pool; | |
632 } | 636 } |
633 | 637 |
634 // static | 638 // static |
635 MessagePump* MessagePumpMac::Create() { | 639 MessagePump* MessagePumpMac::Create() { |
636 if ([NSThread isMainThread]) { | 640 if ([NSThread isMainThread]) { |
| 641 if ([NSApp conformsToProtocol:@protocol(CrAppProtocol)]) |
| 642 return new MessagePumpCrApplication; |
| 643 |
| 644 // The main-thread MessagePump implementations REQUIRE an NSApp. |
| 645 // Executables which have specific requirements for their |
| 646 // NSApplication subclass should initialize appropriately before |
| 647 // creating an event loop. |
| 648 [NSApplication sharedApplication]; |
| 649 not_using_crapp = true; |
637 return new MessagePumpNSApplication; | 650 return new MessagePumpNSApplication; |
638 } | 651 } |
639 | 652 |
640 return new MessagePumpNSRunLoop; | 653 return new MessagePumpNSRunLoop; |
641 } | 654 } |
642 | 655 |
| 656 // static |
| 657 bool MessagePumpMac::UsingCrApp() { |
| 658 DCHECK([NSThread isMainThread]); |
| 659 |
| 660 // If NSApp is still not initialized, then the subclass used cannot |
| 661 // be determined. |
| 662 DCHECK(NSApp); |
| 663 |
| 664 // The pump was created using MessagePumpNSApplication. |
| 665 if (not_using_crapp) |
| 666 return false; |
| 667 |
| 668 return [NSApp conformsToProtocol:@protocol(CrAppProtocol)]; |
| 669 } |
| 670 |
| 671 // static |
| 672 bool MessagePumpMac::IsHandlingSendEvent() { |
| 673 DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); |
| 674 NSObject<CrAppProtocol>* app = static_cast<NSObject<CrAppProtocol>*>(NSApp); |
| 675 return [app isHandlingSendEvent]; |
| 676 } |
| 677 |
643 } // namespace base | 678 } // namespace base |
OLD | NEW |