Reviewed by Maciej.
authorsullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Dec 2004 00:15:02 +0000 (00:15 +0000)
committersullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Dec 2004 00:15:02 +0000 (00:15 +0000)
        - fixed <rdar://problem/3744583> Safari can not quit when a webpage has a login sheet
        that can't be cancelled.

        The proper fix for this would be to change the class of the NSPanel in the nib file.
        But since this would require a localization change, I did a run-time hack instead.
        I'll file a bug about fixing this when we're out of localization freeze.

        * Panels.subproj/WebAuthenticationPanel.m:
        (-[WebAuthenticationPanel replacePanelWithSubclassHack]):
        new method, creates a new panel that is identical to the original one except that
        it's our subclass, and moves all the subviews of the original panel into the new one.
        (-[WebAuthenticationPanel loadNib]):
        call replacePanelWithSubclassHack
        (-[NonBlockingPanel _blocksActionWhenModal:]):
        only method of new NSPanel subclass; overrides this SPI to allow the user to quit
        when one of these panels/sheets is on-screen

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8199 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Panels.subproj/WebAuthenticationPanel.m

index a53e97de72610d65354fdc1d778b0654d3ad302c..0da170a84014323848af76056cc95c5eaae639f6 100644 (file)
@@ -1,3 +1,24 @@
+2004-12-13  John Sullivan  <sullivan@apple.com>
+
+        Reviewed by Maciej.
+        
+        - fixed <rdar://problem/3744583> Safari can not quit when a webpage has a login sheet 
+        that can't be cancelled.
+        
+        The proper fix for this would be to change the class of the NSPanel in the nib file.
+        But since this would require a localization change, I did a run-time hack instead.
+        I'll file a bug about fixing this when we're out of localization freeze.
+
+        * Panels.subproj/WebAuthenticationPanel.m:
+        (-[WebAuthenticationPanel replacePanelWithSubclassHack]):
+        new method, creates a new panel that is identical to the original one except that
+        it's our subclass, and moves all the subviews of the original panel into the new one.
+        (-[WebAuthenticationPanel loadNib]):
+        call replacePanelWithSubclassHack
+        (-[NonBlockingPanel _blocksActionWhenModal:]):
+        only method of new NSPanel subclass; overrides this SPI to allow the user to quit
+        when one of these panels/sheets is on-screen
+
 2004-12-10  Richard Williamson   <rjw@apple.com>
 
        Fixed <rdar://problem/3898708> REGRESSION (8A314-8A317): World Clock's short hand not displayed (ImageIO problem with PDF?)
index 354297dd1513f1fed969cc6434cf15e8ed6c3d11..ef4f550879bfb65e807c1d6b0460e74740555c82 100644 (file)
@@ -18,6 +18,9 @@
 
 #define WebAuthenticationPanelNibName @"WebAuthenticationPanel"
 
+@interface NonBlockingPanel : NSPanel
+@end
+
 @implementation WebAuthenticationPanel
 
 -(id)initWithCallback:(id)cb selector:(SEL)sel
     }
 }
 
+-(void)replacePanelWithSubclassHack
+{
+    // This is a hack to fix 3744583 without requiring a localization change. We
+    // need to use a subclass of NSPanel so we can override _blocksActionWhenModal,
+    // but using a subclass in the nib would require re-localization. So instead
+    // we make a new panel and move all the subviews into it. This will keep the
+    // IBOutlets wired appropriately, except that we have to manually reset the
+    // IBOutlet for the panel itself.
+    NSPanel *newPanel = [[NonBlockingPanel alloc] initWithContentRect:[panel contentRectForFrameRect:[panel frame]] 
+                                                            styleMask:[panel styleMask] 
+                                                              backing:[panel backingType] 
+                                                                defer:NO];
+    [newPanel setTitle:[panel title]];
+    
+    NSView *newContentView = [newPanel contentView];
+    NSArray *subviews = [[panel contentView] subviews];
+    int subviewCount = [subviews count];
+    int index;
+    for (index = 0; index < subviewCount; ++index) {
+        NSView *subview = [subviews objectAtIndex:0];
+        [subview removeFromSuperviewWithoutNeedingDisplay];
+        [newContentView addSubview:subview];
+    }
+    
+    [panel release];
+    panel = newPanel;
+}
+
 - (BOOL)loadNib
 {
     if (!nibLoaded) {
         if ([NSBundle loadNibNamed:WebAuthenticationPanelNibName owner:self]) {
             nibLoaded = YES;
             [imageView setImage:[NSImage imageNamed:@"NSApplicationIcon"]];
+            // FIXME 3918675: remove the following hack when we're out of localization freeze
+            [self replacePanelWithSubclassHack];
         } else {
             ERROR("couldn't load nib named '%@'", WebAuthenticationPanelNibName);
             return FALSE;
 }
 
 @end
+
+@implementation NonBlockingPanel
+
+- (BOOL)_blocksActionWhenModal:(SEL)theAction
+{
+    // This override of a private AppKit method allows the user to quit when a login dialog
+    // is onscreen, which is nice in general but in particular prevents pathological cases
+    // like 3744583 from requiring a Force Quit.
+    //
+    // It would be nice to allow closing the individual window as well as quitting the app when
+    // a login sheet is up, but this _blocksActionWhenModal: mechanism doesn't support that.
+    // This override matches those in NSOpenPanel and NSToolbarConfigPanel.
+    if (theAction == @selector(terminate:)) {
+        return NO;
+    }
+    return YES;
+}
+
+@end