Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/dialogs/qfontdialog_mac.mm

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5959#endif
    6060
     61QT_BEGIN_NAMESPACE
     62
     63extern void macStartInterceptNSPanelCtor();
     64extern void macStopInterceptNSPanelCtor();
     65extern NSButton *macCreateButton(const char *text, NSView *superview);
     66extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
     67
     68QT_END_NAMESPACE
    6169QT_USE_NAMESPACE
    6270
     
    7583const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
    7684
    77 @class QCocoaFontPanelDelegate;
     85@class QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate);
    7886
    7987
     
    8694#endif
    8795
    88 @interface QCocoaFontPanelDelegate : NSObject <NSWindowDelegate> {
     96@interface QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) : NSObject <NSWindowDelegate> {
    8997    NSFontPanel *mFontPanel;
    9098    NSView *mStolenContentView;
     
    96104    CGFloat mDialogExtraWidth;
    97105    CGFloat mDialogExtraHeight;
    98     NSModalSession mModalSession;
     106    int mReturnCode;
     107    BOOL mAppModal;
    99108}
    100109- (id)initWithFontPanel:(NSFontPanel *)panel
     
    105114             extraWidth:(CGFloat)extraWidth
    106115            extraHeight:(CGFloat)extraHeight;
     116- (void)showModelessPanel;
     117- (void)showWindowModalSheet:(QWidget *)docWidget;
     118- (void)runApplicationModalPanel;
     119- (BOOL)isAppModal;
    107120- (void)changeFont:(id)sender;
    108121- (void)changeAttributes:(id)sender;
    109 - (void)setModalSession:(NSModalSession)session;
    110122- (BOOL)windowShouldClose:(id)window;
    111123- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
     
    121133- (void)finishOffWithCode:(NSInteger)result;
    122134- (void)cleanUpAfterMyself;
     135- (void)setSubwindowStacking;
    123136@end
    124137
     
    146159}
    147160
    148 @implementation QCocoaFontPanelDelegate
     161@implementation QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate)
    149162- (id)initWithFontPanel:(NSFontPanel *)panel
    150163       stolenContentView:(NSView *)stolenContentView
     
    164177    mDialogExtraWidth = extraWidth;
    165178    mDialogExtraHeight = extraHeight;
    166     mModalSession = 0;
     179    mReturnCode = -1;
     180    mAppModal = false;
    167181
    168182    if (mPanelHackedWithButtons) {
     
    175189        [cancelButton setTarget:self];
    176190    }
     191
    177192    mQtFont = new QFont();
    178193    return self;
    179194}
    180195
     196- (void)setSubwindowStacking
     197{
     198#ifdef QT_MAC_USE_COCOA
     199    // Stack the native dialog in front of its parent, if any:
     200    QFontDialog *q = mPriv->fontDialog();
     201    if (!qt_mac_is_macsheet(q)) {
     202        if (QWidget *parent = q->parentWidget()) {
     203            if (parent->isWindow()) {
     204                [qt_mac_window_for(parent)
     205                    addChildWindow:[mStolenContentView window] ordered:NSWindowAbove];
     206            }
     207        }
     208    }
     209#endif
     210}
     211
    181212- (void)dealloc
    182213{
    183214    delete mQtFont;
    184215    [super dealloc];
     216}
     217
     218- (void)showModelessPanel
     219{
     220    mAppModal = false;
     221    NSWindow *ourPanel = [mStolenContentView window];
     222    [ourPanel makeKeyAndOrderFront:self];
     223}
     224
     225- (void)runApplicationModalPanel
     226{
     227    QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
     228    mAppModal = true;
     229    NSWindow *ourPanel = [mStolenContentView window];
     230    [ourPanel setReleasedWhenClosed:NO];
     231    [NSApp runModalForWindow:ourPanel];
     232    QAbstractEventDispatcher::instance()->interrupt();
     233
     234    if (mReturnCode == NSOKButton)
     235        mPriv->fontDialog()->accept();
     236    else
     237        mPriv->fontDialog()->reject();
     238}
     239
     240- (BOOL)isAppModal
     241{
     242    return mAppModal;
     243}
     244
     245- (void)showWindowModalSheet:(QWidget *)docWidget
     246{
     247#ifdef QT_MAC_USE_COCOA
     248    NSWindow *window = qt_mac_window_for(docWidget);
     249#else
     250    WindowRef hiwindowRef = qt_mac_window_for(docWidget);
     251    NSWindow *window = [[NSWindow alloc] initWithWindowRef:hiwindowRef];
     252    CFRetain(hiwindowRef);
     253#endif
     254
     255    mAppModal = false;
     256    NSWindow *ourPanel = [mStolenContentView window];
     257    [NSApp beginSheet:ourPanel
     258        modalForWindow:window
     259        modalDelegate:0
     260        didEndSelector:0
     261        contextInfo:0 ];
     262
     263#ifndef QT_MAC_USE_COCOA
     264    CFRelease(hiwindowRef);
     265#endif
    185266}
    186267
     
    215296    if (mPriv)
    216297        mPriv->updateSampleFont(*mQtFont);
    217 }
    218 
    219 - (void)setModalSession:(NSModalSession)session
    220 {
    221     Q_ASSERT(!mModalSession);
    222     mModalSession = session;
    223298}
    224299
     
    283358
    284359    const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
    285                                           qMax(okSizeHint.width, cancelSizeHint.width)),
    286                                      CGFloat((frameSize.width - 2.0 * ButtonSideMargin
    287                                               - ButtonSpacing) * 0.5));
     360                qMax(okSizeHint.width, cancelSizeHint.width)),
     361            CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
    288362    const CGFloat ButtonHeight = qMax(ButtonMinHeight,
    289363                                     qMax(okSizeHint.height, cancelSizeHint.height));
     
    318392    [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
    319393                                      *mQtFont)];
    320     [[mStolenContentView window] close];
    321394    [self finishOffWithCode:NSOKButton];
    322395}
     
    325398{
    326399    Q_ASSERT(mPanelHackedWithButtons);
    327     [[mStolenContentView window] close];
    328400    [self finishOffWithCode:NSCancelButton];
    329401}
     
    369441- (void)finishOffWithCode:(NSInteger)code
    370442{
    371     if (mPriv) {
    372         if (mModalSession) {
    373             [NSApp endModalSession:mModalSession];
    374             mModalSession = 0;
     443#ifdef QT_MAC_USE_COCOA
     444    QFontDialog *q = mPriv->fontDialog();
     445    if (QWidget *parent = q->parentWidget()) {
     446        if (parent->isWindow()) {
     447            [qt_mac_window_for(parent) removeChildWindow:[mStolenContentView window]];
    375448        }
    376         // Hack alert!
    377         // Since this code path was never intended to be followed when starting from exec
    378         // we need to force the dialog to communicate the new font, otherwise the signal
    379         // won't get emitted.
    380         if(code == NSOKButton)
    381             mPriv->sampleEdit->setFont([self qtFont]);
    382         mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
     449    }
     450#endif
     451
     452    if(code == NSOKButton)
     453        mPriv->sampleEdit->setFont([self qtFont]);
     454
     455    if (mAppModal) {
     456        mReturnCode = code;
     457        [NSApp stopModalWithCode:code];
    383458    } else {
    384         [NSApp stopModalWithCode:code];
     459        if (code == NSOKButton)
     460            mPriv->fontDialog()->accept();
     461        else
     462            mPriv->fontDialog()->reject();
    385463    }
    386464}
     
    409487QT_BEGIN_NAMESPACE
    410488
    411 extern void macStartInterceptNSPanelCtor();
    412 extern void macStopInterceptNSPanelCtor();
    413 extern NSButton *macCreateButton(const char *text, NSView *superview);
    414 
    415 void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial,
    416         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options,
    417         QFontDialogPrivate *priv)
    418 {
    419     Q_UNUSED(parent);   // we would use the parent if only NSFontPanel could be a sheet
     489void QFontDialogPrivate::closeCocoaFontPanel()
     490{
    420491    QMacCocoaAutoReleasePool pool;
    421 
    422     /*
    423         The standard Cocoa font panel has no OK or Cancel button and
    424         is created as a utility window. For strange reasons (which seem
    425         to stem from the fact that the font panel is based on a NIB
    426         file), the approach we use for the color panel doesn't work for
    427         the font panel (and, inversely, the approach we use here doesn't
    428         quite work for color panel, and crashed last time I tried). So
    429         instead, we take the following steps:
    430 
    431          1. Constructs a plain NSPanel that looks the way we want it
    432             to look. Specifically, if the NoButtons option is off, we
    433             construct a panel without the NSUtilityWindowMask flag
    434             and with buttons (OK and Cancel).
    435 
    436          2. Steal the content view from the shared NSFontPanel and
    437             put it inside our new NSPanel's content view, together
    438             with the OK and Cancel buttons.
    439 
    440          3. Lay out the original content view and the buttons when
    441             the font panel is shown and whenever it is resized.
    442 
    443          4. Clean up after ourselves.
    444 
    445          PS. Some customization is also done in QCocoaApplication
    446          validModesForFontPanel:.
    447     */
    448 
    449     Qt::WindowModality modality = Qt::ApplicationModal;
    450     if (priv)
    451         modality = priv->fontDialog()->windowModality();
    452 
    453     bool needButtons = !(options & QFontDialog::NoButtons);
    454     // don't need our own panel if the title bar isn't visible anyway (in a sheet)
    455     bool needOwnPanel = (needButtons && modality != Qt::WindowModal);
    456 
    457     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
    458     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
    459     [sharedFontPanel setHidesOnDeactivate:false];
    460 
    461     // hack to ensure that QCocoaApplication's validModesForFontPanel:
    462     // implementation is honored
    463     if (!sharedFontPanelExisted && needOwnPanel) {
    464         [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
    465         [sharedFontPanel close];
    466     }
    467 
    468     NSPanel *ourPanel = 0;
    469     NSView *stolenContentView = 0;
    470     NSButton *okButton = 0;
    471     NSButton *cancelButton = 0;
    472 
    473     CGFloat dialogExtraWidth = 0.0;
    474     CGFloat dialogExtraHeight = 0.0;
    475 
    476     if (!needOwnPanel) {
    477         // we can reuse the NSFontPanel unchanged
    478         ourPanel = sharedFontPanel;
    479     } else {
    480         // compute dialogExtra{Width,Height}
    481         dialogExtraWidth = 2.0 * DialogSideMargin;
    482         dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
    483                             + ButtonBottomMargin;
    484 
    485         // compute initial contents rectangle
    486         NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
    487         contentRect.size.width += dialogExtraWidth;
    488         contentRect.size.height += dialogExtraHeight;
    489 
    490         // create the new panel
    491         ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
    492                                               styleMask:StyleMask
    493                                                 backing:NSBackingStoreBuffered
    494                                                   defer:YES];
    495         [ourPanel setReleasedWhenClosed:YES];
    496     }
    497 
    498     stolenContentView = [sharedFontPanel contentView];
    499 
    500     if (needButtons) {
    501         // steal the font panel's contents view
    502         [stolenContentView retain];
    503         [sharedFontPanel setContentView:0];
    504 
    505         // create a new content view and add the stolen one as a subview
    506         NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
    507         NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
    508         [ourContentView addSubview:stolenContentView];
    509 
    510         // create OK and Cancel buttons and add these as subviews
    511         okButton = macCreateButton("&OK", ourContentView);
    512         cancelButton = macCreateButton("Cancel", ourContentView);
    513 
    514         [ourPanel setContentView:ourContentView];
    515         [ourPanel setDefaultButtonCell:[okButton cell]];
    516     }
    517 
    518     // create a delegate and set it
    519     QCocoaFontPanelDelegate *delegate =
    520             [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
    521                                              stolenContentView:stolenContentView
    522                                                       okButton:okButton
    523                                                   cancelButton:cancelButton
    524                                                           priv:priv
    525                                                     extraWidth:dialogExtraWidth
    526                                                    extraHeight:dialogExtraHeight];
    527     [ourPanel setDelegate:delegate];
    528     [[NSFontManager sharedFontManager] setDelegate:delegate];
    529 #ifdef QT_MAC_USE_COCOA
    530     [[NSFontManager sharedFontManager] setTarget:delegate];
    531 #endif
    532     setFont(delegate, initial);
    533 
    534     // hack to get correct initial layout
    535     NSRect frameRect = [ourPanel frame];
    536     frameRect.size.width += 1.0;
    537     [ourPanel setFrame:frameRect display:NO];
    538     frameRect.size.width -= 1.0;
    539     frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
    540     [ourPanel setFrame:frameRect display:NO];
    541     [ourPanel center];
    542 
    543     [ourPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
    544 
    545     if (priv) {
    546         switch (modality) {
    547         case Qt::WindowModal:
    548             if (parent) {
    549 #ifndef QT_MAC_USE_COCOA
    550                 WindowRef hiwindowRef = qt_mac_window_for(parent);
    551                 NSWindow *window =
    552                     [[NSWindow alloc] initWithWindowRef:hiwindowRef];
    553                 // Cocoa docs say I should retain the Carbon ref.
    554                 CFRetain(hiwindowRef);
    555 #else
    556                 NSWindow *window = qt_mac_window_for(parent);
    557 #endif
    558                 [NSApp beginSheet:ourPanel
    559                    modalForWindow:window
    560                     modalDelegate:0
    561                    didEndSelector:0
    562                       contextInfo:0];
    563 #ifndef QT_MAC_USE_COCOA
    564                 [window release];
    565 #endif
    566                 break;
    567             }
    568             // fallthrough
    569         case Qt::ApplicationModal:
    570             [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
    571             break;
    572         default:
    573             [ourPanel makeKeyAndOrderFront:ourPanel];
    574         }
    575     }
    576     return delegate;
    577 }
    578 
    579 void QFontDialogPrivate::closeCocoaFontPanel(void *delegate)
    580 {
    581     QMacCocoaAutoReleasePool pool;
    582     QCocoaFontPanelDelegate *theDelegate = static_cast<QCocoaFontPanelDelegate *>(delegate);
     492    QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *theDelegate = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
    583493    NSWindow *ourPanel = [theDelegate actualPanel];
    584494    [ourPanel close];
     495    if ([theDelegate isAppModal])
     496        [ourPanel release];
    585497    [theDelegate cleanUpAfterMyself];
    586     [theDelegate autorelease];
    587 }
    588 
    589 QFont QFontDialogPrivate::execCocoaFontPanel(bool *ok, const QFont &initial,
    590         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options)
    591 {
    592     QMacCocoaAutoReleasePool pool;
    593     QCocoaFontPanelDelegate *delegate =
    594             static_cast<QCocoaFontPanelDelegate *>(
    595                 openCocoaFontPanel(initial, parent, title, options));
    596     NSWindow *ourPanel = [delegate actualPanel];
    597     [ourPanel retain];
    598     int rval = [NSApp runModalForWindow:ourPanel];
    599     QFont font([delegate qtFont]);
    600     [ourPanel release];
    601     [delegate cleanUpAfterMyself];
    602     [delegate release];
    603     bool isOk = ((options & QFontDialog::NoButtons) || rval == NSOKButton);
    604     if (ok)
    605         *ok = isOk;
    606     if (isOk) {
    607         return font;
    608     } else {
    609         return initial;
    610     }
     498    [theDelegate release];
     499    this->delegate = 0;
     500    sharedFontPanelAvailable = true;
    611501}
    612502
     
    643533
    644534    [mgr setSelectedFont:nsFont isMultiple:NO];
    645     [static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font];
    646 }
    647 
    648 void *QFontDialogPrivate::_q_constructNativePanel()
    649 {
     535    [static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate) setQtFont:font];
     536}
     537
     538void QFontDialogPrivate::createNSFontPanelDelegate()
     539{
     540    if (delegate)
     541        return;
     542
     543    sharedFontPanelAvailable = false;
    650544    QMacCocoaAutoReleasePool pool;
    651 
    652545    bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
    653546    NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
     
    671564    // compute dialogExtra{Width,Height}
    672565    dialogExtraWidth = 2.0 * DialogSideMargin;
    673     dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
    674                         + ButtonBottomMargin;
     566    dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + ButtonBottomMargin;
    675567
    676568    // compute initial contents rectangle
     
    685577                        defer:YES];
    686578    [ourPanel setReleasedWhenClosed:YES];
    687 
    688579    stolenContentView = [sharedFontPanel contentView];
    689580
     
    705596        [ourPanel setDefaultButtonCell:[okButton cell]];
    706597    }
    707     // create a delegate and set it
    708     QCocoaFontPanelDelegate *delegate =
    709             [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
     598
     599    // create the delegate and set it
     600    QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = [[QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) alloc] initWithFontPanel:sharedFontPanel
    710601                                             stolenContentView:stolenContentView
    711602                                                      okButton:okButton
     
    714605                                                    extraWidth:dialogExtraWidth
    715606                                                   extraHeight:dialogExtraHeight];
    716     [ourPanel setDelegate:delegate];
    717     [[NSFontManager sharedFontManager] setDelegate:delegate];
     607    delegate = del;
     608    [ourPanel setDelegate:del];
     609
     610    [[NSFontManager sharedFontManager] setDelegate:del];
    718611#ifdef QT_MAC_USE_COCOA
    719     [[NSFontManager sharedFontManager] setTarget:delegate];
    720 #endif
    721     setFont(delegate, QApplication::font());
     612    [[NSFontManager sharedFontManager] setTarget:del];
     613#endif
     614    setFont(del, q_func()->currentFont());
    722615
    723616    {
     
    727620        [ourPanel setFrame:frameRect display:NO];
    728621        frameRect.size.width -= 1.0;
    729         frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
     622        frameRect.size = [del windowWillResize:ourPanel toSize:frameRect.size];
    730623        [ourPanel setFrame:frameRect display:NO];
    731624        [ourPanel center];
    732625    }
     626    [del setSubwindowStacking];
    733627    NSString *title = @"Select font";
    734628    [ourPanel setTitle:title];
    735 
    736     [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
    737     return delegate;
    738629}
    739630
     
    760651void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
    761652{
    762     QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
     653    createNSFontPanelDelegate();
     654    QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
     655    [del runApplicationModalPanel];
     656}
     657
     658bool QFontDialogPrivate::showCocoaFontPanel()
     659{
     660    if (!sharedFontPanelAvailable)
     661        return false;
     662
    763663    Q_Q(QFontDialog);
    764     QCocoaFontPanelDelegate *delegate = (QCocoaFontPanelDelegate *)_q_constructNativePanel();
    765     NSWindow *ourPanel = [delegate actualPanel];
    766     [ourPanel retain];
    767     int rval = [NSApp runModalForWindow:ourPanel];
    768     QAbstractEventDispatcher::instance()->interrupt();
    769     [ourPanel release];
    770     [delegate cleanUpAfterMyself];
    771     [delegate release];
    772     bool isOk = (rval == NSOKButton);
    773     if(isOk)
    774         rescode = QDialog::Accepted;
     664    QMacCocoaAutoReleasePool pool;
     665    createNSFontPanelDelegate();
     666    QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
     667    if (qt_mac_is_macsheet(q))
     668        [del showWindowModalSheet:q->parentWidget()];
    775669    else
    776         rescode = QDialog::Rejected;
    777 }
    778 
     670        [del showModelessPanel];
     671    return true;
     672}
     673
     674bool QFontDialogPrivate::hideCocoaFontPanel()
     675{
     676    if (!delegate){
     677        // Nothing to do. We return false to leave the question
     678        // open regarding whether or not to go native:
     679        return false;
     680    } else {
     681        closeCocoaFontPanel();
     682        // Even when we hide it, we are still using a
     683        // native dialog, so return true:
     684        return true;
     685    }
     686}
    779687bool QFontDialogPrivate::setVisible_sys(bool visible)
    780688{
     
    782690    if (!visible == q->isHidden())
    783691        return false;
    784     return visible;
     692
     693    return visible ? showCocoaFontPanel() : hideCocoaFontPanel();
    785694}
    786695
Note: See TracChangeset for help on using the changeset viewer.