bf8b88a0c988535f4900904d9544c641917bcf99
[profile/ivi/qtbase.git] / src / widgets / dialogs / qfontdialog_mac.mm
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qfontdialog_p.h"
43 #if !defined(QT_NO_FONTDIALOG) && defined(Q_WS_MAC)
44 #include <qapplication.h>
45 #include <qdialogbuttonbox.h>
46 #include <qlineedit.h>
47 #include <private/qapplication_p.h>
48 #include <private/qfont_p.h>
49 #include <private/qfontengine_p.h>
50 #include <private/qt_cocoa_helpers_mac_p.h>
51 #include <private/qt_mac_p.h>
52 #include <qabstracteventdispatcher.h>
53 #include <qdebug.h>
54 #include <private/qfontengine_coretext_p.h>
55 #import <AppKit/AppKit.h>
56 #import <Foundation/Foundation.h>
57
58 #if !CGFLOAT_DEFINED
59 typedef float CGFloat;  // Should only not be defined on 32-bit platforms
60 #endif
61
62 QT_BEGIN_NAMESPACE
63
64 extern void macStartInterceptNSPanelCtor();
65 extern void macStopInterceptNSPanelCtor();
66 extern NSButton *macCreateButton(const char *text, NSView *superview);
67 extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
68
69 QT_END_NAMESPACE
70 QT_USE_NAMESPACE
71
72 // should a priori be kept in sync with qcolordialog_mac.mm
73 const CGFloat ButtonMinWidth = 78.0;
74 const CGFloat ButtonMinHeight = 32.0;
75 const CGFloat ButtonSpacing = 0.0;
76 const CGFloat ButtonTopMargin = 0.0;
77 const CGFloat ButtonBottomMargin = 7.0;
78 const CGFloat ButtonSideMargin = 9.0;
79
80 // looks better with some margins
81 const CGFloat DialogTopMargin = 7.0;
82 const CGFloat DialogSideMargin = 9.0;
83
84 const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
85
86 @class QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate);
87
88
89 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
90
91 @protocol NSWindowDelegate <NSObject>
92 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
93 @end
94
95 #endif
96
97 @interface QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) : NSObject <NSWindowDelegate> {
98     NSFontPanel *mFontPanel;
99     NSView *mStolenContentView;
100     NSButton *mOkButton;
101     NSButton *mCancelButton;
102     QFontDialogPrivate *mPriv;
103     QFont *mQtFont;
104     BOOL mPanelHackedWithButtons;
105     CGFloat mDialogExtraWidth;
106     CGFloat mDialogExtraHeight;
107     int mReturnCode;
108     BOOL mAppModal;
109 }
110 - (id)initWithFontPanel:(NSFontPanel *)panel
111       stolenContentView:(NSView *)stolenContentView
112                okButton:(NSButton *)okButton
113            cancelButton:(NSButton *)cancelButton
114                    priv:(QFontDialogPrivate *)priv
115              extraWidth:(CGFloat)extraWidth
116             extraHeight:(CGFloat)extraHeight;
117 - (void)showModelessPanel;
118 - (void)showWindowModalSheet:(QWidget *)docWidget;
119 - (void)runApplicationModalPanel;
120 - (BOOL)isAppModal;
121 - (void)changeFont:(id)sender;
122 - (void)changeAttributes:(id)sender;
123 - (BOOL)windowShouldClose:(id)window;
124 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
125 - (void)relayout;
126 - (void)relayoutToContentSize:(NSSize)frameSize;
127 - (void)onOkClicked;
128 - (void)onCancelClicked;
129 - (NSFontPanel *)fontPanel;
130 - (NSWindow *)actualPanel;
131 - (NSSize)dialogExtraSize;
132 - (void)setQtFont:(const QFont &)newFont;
133 - (QFont)qtFont;
134 - (void)finishOffWithCode:(NSInteger)result;
135 - (void)cleanUpAfterMyself;
136 - (void)setSubwindowStacking;
137 @end
138
139 static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
140 {
141     QFont newFont;
142     if (cocoaFont) {
143         int pSize = qRound([cocoaFont pointSize]);
144         QString family(qt_mac_NSStringToQString([cocoaFont familyName]));
145         QString typeface(qt_mac_NSStringToQString([cocoaFont fontName]));
146
147         int hyphenPos = typeface.indexOf(QLatin1Char('-'));
148         if (hyphenPos != -1) {
149             typeface.remove(0, hyphenPos + 1);
150         } else {
151             typeface = QLatin1String("Normal");
152         }
153
154         newFont = QFontDatabase().font(family, typeface, pSize);
155         newFont.setUnderline(resolveFont.underline());
156         newFont.setStrikeOut(resolveFont.strikeOut());
157
158     }
159     return newFont;
160 }
161
162 @implementation QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate)
163 - (id)initWithFontPanel:(NSFontPanel *)panel
164        stolenContentView:(NSView *)stolenContentView
165                 okButton:(NSButton *)okButton
166             cancelButton:(NSButton *)cancelButton
167                     priv:(QFontDialogPrivate *)priv
168               extraWidth:(CGFloat)extraWidth
169              extraHeight:(CGFloat)extraHeight
170 {
171     self = [super init];
172     mFontPanel = panel;
173     mStolenContentView = stolenContentView;
174     mOkButton = okButton;
175     mCancelButton = cancelButton;
176     mPriv = priv;
177     mPanelHackedWithButtons = (okButton != 0);
178     mDialogExtraWidth = extraWidth;
179     mDialogExtraHeight = extraHeight;
180     mReturnCode = -1;
181     mAppModal = false;
182
183     if (mPanelHackedWithButtons) {
184         [self relayout];
185
186         [okButton setAction:@selector(onOkClicked)];
187         [okButton setTarget:self];
188
189         [cancelButton setAction:@selector(onCancelClicked)];
190         [cancelButton setTarget:self];
191     }
192
193     mQtFont = new QFont();
194     return self;
195 }
196
197 - (void)setSubwindowStacking
198 {
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 }
210
211 - (void)dealloc
212 {
213     delete mQtFont;
214     [super dealloc];
215 }
216
217 - (void)showModelessPanel
218 {
219     mAppModal = false;
220     NSWindow *ourPanel = [mStolenContentView window];
221     [ourPanel makeKeyAndOrderFront:self];
222 }
223
224 - (void)runApplicationModalPanel
225 {
226     QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
227     mAppModal = true;
228     NSWindow *ourPanel = [mStolenContentView window];
229     [ourPanel setReleasedWhenClosed:NO];
230     [NSApp runModalForWindow:ourPanel];
231     QAbstractEventDispatcher::instance()->interrupt();
232
233     if (mReturnCode == NSOKButton)
234         mPriv->fontDialog()->accept();
235     else
236         mPriv->fontDialog()->reject();
237 }
238
239 - (BOOL)isAppModal
240 {
241     return mAppModal;
242 }
243
244 - (void)showWindowModalSheet:(QWidget *)docWidget
245 {
246     NSWindow *window = qt_mac_window_for(docWidget);
247
248     mAppModal = false;
249     NSWindow *ourPanel = [mStolenContentView window];
250     [NSApp beginSheet:ourPanel
251         modalForWindow:window
252         modalDelegate:0
253         didEndSelector:0
254         contextInfo:0 ];
255
256 }
257
258 - (void)changeFont:(id)sender
259 {
260     NSFont *dummyFont = [NSFont userFontOfSize:12.0];
261     [self setQtFont:qfontForCocoaFont([sender convertFont:dummyFont], *mQtFont)];
262     if (mPriv)
263         mPriv->updateSampleFont(*mQtFont);
264 }
265
266 - (void)changeAttributes:(id)sender
267 {
268     NSDictionary *dummyAttribs = [NSDictionary dictionary];
269     NSDictionary *attribs = [sender convertAttributes:dummyAttribs];
270
271     for (id key in attribs) {
272         NSNumber *number = static_cast<NSNumber *>([attribs objectForKey:key]);
273         if ([key isEqual:NSUnderlineStyleAttributeName]) {
274             mQtFont->setUnderline([number intValue] != NSUnderlineStyleNone);
275         } else if ([key isEqual:NSStrikethroughStyleAttributeName]) {
276             mQtFont->setStrikeOut([number intValue] != NSUnderlineStyleNone);
277         }
278     }
279
280     if (mPriv)
281         mPriv->updateSampleFont(*mQtFont);
282 }
283
284 - (BOOL)windowShouldClose:(id)window
285 {
286     Q_UNUSED(window);
287     if (mPanelHackedWithButtons) {
288         [self onCancelClicked];
289     } else {
290         [self finishOffWithCode:NSCancelButton];
291     }
292     return true;
293 }
294
295 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
296 {
297     if (mFontPanel == window) {
298         proposedFrameSize = [static_cast<id <NSWindowDelegate> >(mFontPanel) windowWillResize:mFontPanel toSize:proposedFrameSize];
299     } else {
300         /*
301             Ugly hack: NSFontPanel rearranges the layout of its main
302             component in windowWillResize:toSize:. So we temporarily
303             restore the stolen content view to its rightful owner,
304             call windowWillResize:toSize:, and steal the content view
305             again.
306         */
307         [mStolenContentView removeFromSuperview];
308         [mFontPanel setContentView:mStolenContentView];
309         NSSize extraSize = [self dialogExtraSize];
310         proposedFrameSize.width -= extraSize.width;
311         proposedFrameSize.height -= extraSize.height;
312         proposedFrameSize = [static_cast<id <NSWindowDelegate> >(mFontPanel) windowWillResize:mFontPanel toSize:proposedFrameSize];
313         NSRect frameRect = { { 0.0, 0.0 }, proposedFrameSize };
314         [mFontPanel setFrame:frameRect display:NO];
315         [mFontPanel setContentView:0];
316         [[window contentView] addSubview:mStolenContentView];
317         proposedFrameSize.width += extraSize.width;
318         proposedFrameSize.height += extraSize.height;
319     }
320     if (mPanelHackedWithButtons) {
321         NSRect frameRect = { { 0.0, 0.0 }, proposedFrameSize };
322         NSRect contentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:[window styleMask]];
323         [self relayoutToContentSize:contentRect.size];
324     }
325     return proposedFrameSize;
326 }
327
328 - (void)relayout
329 {
330     [self relayoutToContentSize:[[mStolenContentView superview] frame].size];
331 }
332
333 - (void)relayoutToContentSize:(NSSize)frameSize
334 {
335     Q_ASSERT(mPanelHackedWithButtons);
336
337     [mOkButton sizeToFit];
338     NSSize okSizeHint = [mOkButton frame].size;
339
340     [mCancelButton sizeToFit];
341     NSSize cancelSizeHint = [mCancelButton frame].size;
342
343     const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
344                 qMax(okSizeHint.width, cancelSizeHint.width)),
345             CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
346     const CGFloat ButtonHeight = qMax(ButtonMinHeight,
347                                      qMax(okSizeHint.height, cancelSizeHint.height));
348
349     const CGFloat X = DialogSideMargin;
350     const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin;
351
352     NSRect okRect = { { frameSize.width - ButtonSideMargin - ButtonWidth,
353                         ButtonBottomMargin },
354                       { ButtonWidth, ButtonHeight } };
355     [mOkButton setFrame:okRect];
356     [mOkButton setNeedsDisplay:YES];
357
358     NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - ButtonWidth,
359                             ButtonBottomMargin },
360                             { ButtonWidth, ButtonHeight } };
361     [mCancelButton setFrame:cancelRect];
362     [mCancelButton setNeedsDisplay:YES];
363
364     NSRect stolenCVRect = { { X, Y },
365                             { frameSize.width - X - X, frameSize.height - Y - DialogTopMargin } };
366     [mStolenContentView setFrame:stolenCVRect];
367     [mStolenContentView setNeedsDisplay:YES];
368
369     [[mStolenContentView superview] setNeedsDisplay:YES];
370 }
371
372 - (void)onOkClicked
373 {
374     Q_ASSERT(mPanelHackedWithButtons);
375     NSFontManager *fontManager = [NSFontManager sharedFontManager];
376     [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
377                                       *mQtFont)];
378     [self finishOffWithCode:NSOKButton];
379 }
380
381 - (void)onCancelClicked
382 {
383     Q_ASSERT(mPanelHackedWithButtons);
384     [self finishOffWithCode:NSCancelButton];
385 }
386
387 - (NSFontPanel *)fontPanel
388 {
389     return mFontPanel;
390 }
391
392 - (NSWindow *)actualPanel
393 {
394     return [mStolenContentView window];
395 }
396
397 - (NSSize)dialogExtraSize
398 {
399     // this must be recomputed each time, because sometimes the
400     // NSFontPanel has the NSDocModalWindowMask flag set, and sometimes
401     // not -- which affects the frame rect vs. content rect measurements
402
403     // take the different frame rectangles into account for dialogExtra{Width,Height}
404     NSRect someRect = { { 0.0, 0.0 }, { 100000.0, 100000.0 } };
405     NSRect sharedFontPanelContentRect = [mFontPanel contentRectForFrameRect:someRect];
406     NSRect ourPanelContentRect = [NSWindow contentRectForFrameRect:someRect styleMask:StyleMask];
407
408     NSSize result = { mDialogExtraWidth, mDialogExtraHeight };
409     result.width -= ourPanelContentRect.size.width - sharedFontPanelContentRect.size.width;
410     result.height -= ourPanelContentRect.size.height - sharedFontPanelContentRect.size.height;
411     return result;
412 }
413
414 - (void)setQtFont:(const QFont &)newFont
415 {
416     delete mQtFont;
417     mQtFont = new QFont(newFont);
418 }
419
420 - (QFont)qtFont
421 {
422     return *mQtFont;
423 }
424
425 - (void)finishOffWithCode:(NSInteger)code
426 {
427     QFontDialog *q = mPriv->fontDialog();
428     if (QWidget *parent = q->parentWidget()) {
429         if (parent->isWindow()) {
430             [qt_mac_window_for(parent) removeChildWindow:[mStolenContentView window]];
431         }
432     }
433
434     if(code == NSOKButton)
435         mPriv->sampleEdit->setFont([self qtFont]);
436
437     if (mAppModal) {
438         mReturnCode = code;
439         [NSApp stopModalWithCode:code];
440     } else {
441         if (code == NSOKButton)
442             mPriv->fontDialog()->accept();
443         else
444             mPriv->fontDialog()->reject();
445     }
446 }
447
448 - (void)cleanUpAfterMyself
449 {
450     if (mPanelHackedWithButtons) {
451         NSView *ourContentView = [mFontPanel contentView];
452
453         // return stolen stuff to its rightful owner
454         [mStolenContentView removeFromSuperview];
455         [mFontPanel setContentView:mStolenContentView];
456
457         [mOkButton release];
458         [mCancelButton release];
459         [ourContentView release];
460     }
461     [mFontPanel setDelegate:nil];
462     [[NSFontManager sharedFontManager] setDelegate:nil];
463     [[NSFontManager sharedFontManager] setTarget:nil];
464 }
465 @end
466
467 QT_BEGIN_NAMESPACE
468
469 void QFontDialogPrivate::closeCocoaFontPanel()
470 {
471     QMacCocoaAutoReleasePool pool;
472     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *theDelegate = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
473     NSWindow *ourPanel = [theDelegate actualPanel];
474     [ourPanel close];
475     if ([theDelegate isAppModal])
476         [ourPanel release];
477     [theDelegate cleanUpAfterMyself];
478     [theDelegate release];
479     this->delegate = 0;
480     sharedFontPanelAvailable = true;
481 }
482
483 void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
484 {
485     QMacCocoaAutoReleasePool pool;
486     QFontEngine *fe = font.d->engineForScript(QUnicodeTables::Common);
487     NSFontManager *mgr = [NSFontManager sharedFontManager];
488     const NSFont *nsFont = 0;
489
490 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
491     if (qstrcmp(fe->name(), "CoreText") == 0) {
492         nsFont = reinterpret_cast<const NSFont *>(static_cast<QCoreTextFontEngineMulti *>(fe)->ctfont);
493     } else
494 #endif
495     {
496         int weight = 5;
497         NSFontTraitMask mask = 0;
498         if (font.style() == QFont::StyleItalic) {
499             mask |= NSItalicFontMask;
500         }
501         if (font.weight() == QFont::Bold) {
502             weight = 9;
503             mask |= NSBoldFontMask;
504         }
505
506         NSFontManager *mgr = [NSFontManager sharedFontManager];
507         QFontInfo fontInfo(font);
508         nsFont = [mgr fontWithFamily:qt_mac_QStringToNSString(fontInfo.family())
509             traits:mask
510             weight:weight
511             size:fontInfo.pointSize()];
512     }
513
514     [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO];
515     [static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate) setQtFont:font];
516 }
517
518 void QFontDialogPrivate::createNSFontPanelDelegate()
519 {
520     if (delegate)
521         return;
522
523     sharedFontPanelAvailable = false;
524     QMacCocoaAutoReleasePool pool;
525     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
526     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
527     [sharedFontPanel setHidesOnDeactivate:false];
528
529     // hack to ensure that QCocoaApplication's validModesForFontPanel:
530     // implementation is honored
531     if (!sharedFontPanelExisted) {
532         [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
533         [sharedFontPanel close];
534     }
535
536     NSPanel *ourPanel = 0;
537     NSView *stolenContentView = 0;
538     NSButton *okButton = 0;
539     NSButton *cancelButton = 0;
540
541     CGFloat dialogExtraWidth = 0.0;
542     CGFloat dialogExtraHeight = 0.0;
543
544     // compute dialogExtra{Width,Height}
545     dialogExtraWidth = 2.0 * DialogSideMargin;
546     dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + ButtonBottomMargin;
547
548     // compute initial contents rectangle
549     NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
550     contentRect.size.width += dialogExtraWidth;
551     contentRect.size.height += dialogExtraHeight;
552
553     // create the new panel
554     ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
555                 styleMask:StyleMask
556                     backing:NSBackingStoreBuffered
557                         defer:YES];
558     [ourPanel setReleasedWhenClosed:YES];
559     stolenContentView = [sharedFontPanel contentView];
560
561     // steal the font panel's contents view
562     [stolenContentView retain];
563     [sharedFontPanel setContentView:0];
564
565     {
566         // create a new content view and add the stolen one as a subview
567         NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
568         NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
569         [ourContentView addSubview:stolenContentView];
570
571         // create OK and Cancel buttons and add these as subviews
572         okButton = macCreateButton("&OK", ourContentView);
573         cancelButton = macCreateButton("Cancel", ourContentView);
574
575         [ourPanel setContentView:ourContentView];
576         [ourPanel setDefaultButtonCell:[okButton cell]];
577     }
578
579     // create the delegate and set it
580     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = [[QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) alloc] initWithFontPanel:sharedFontPanel
581                                              stolenContentView:stolenContentView
582                                                       okButton:okButton
583                                                   cancelButton:cancelButton
584                                                           priv:this
585                                                     extraWidth:dialogExtraWidth
586                                                    extraHeight:dialogExtraHeight];
587     delegate = del;
588     [ourPanel setDelegate:del];
589
590     [[NSFontManager sharedFontManager] setDelegate:del];
591     [[NSFontManager sharedFontManager] setTarget:del];
592     setFont(del, q_func()->currentFont());
593
594     {
595         // hack to get correct initial layout
596         NSRect frameRect = [ourPanel frame];
597         frameRect.size.width += 1.0;
598         [ourPanel setFrame:frameRect display:NO];
599         frameRect.size.width -= 1.0;
600         frameRect.size = [del windowWillResize:ourPanel toSize:frameRect.size];
601         [ourPanel setFrame:frameRect display:NO];
602         [ourPanel center];
603     }
604     [del setSubwindowStacking];
605     NSString *title = @"Select font";
606     [ourPanel setTitle:title];
607 }
608
609 void QFontDialogPrivate::mac_nativeDialogModalHelp()
610 {
611     // Copied from QFileDialogPrivate
612     // Do a queued meta-call to open the native modal dialog so it opens after the new
613     // event loop has started to execute (in QDialog::exec). Using a timer rather than
614     // a queued meta call is intentional to ensure that the call is only delivered when
615     // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
616     // running (which is the case if e.g a top-most QEventLoop has been
617     // interrupted, and the second-most event loop has not yet been reactivated (regardless
618     // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
619     if (nativeDialogInUse) {
620         Q_Q(QFontDialog);
621         QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
622     }
623 }
624
625 // The problem with the native font dialog is that OS X does not
626 // offer a proper dialog, but a panel (i.e. without Ok and Cancel buttons).
627 // This means we need to "construct" a native dialog by taking the panel
628 // and "adding" the buttons.
629 void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
630 {
631     createNSFontPanelDelegate();
632     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
633     [del runApplicationModalPanel];
634 }
635
636 bool QFontDialogPrivate::showCocoaFontPanel()
637 {
638     if (!sharedFontPanelAvailable)
639         return false;
640
641     Q_Q(QFontDialog);
642     QMacCocoaAutoReleasePool pool;
643     createNSFontPanelDelegate();
644     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
645     if (qt_mac_is_macsheet(q))
646         [del showWindowModalSheet:q->parentWidget()];
647     else
648         [del showModelessPanel];
649     return true;
650 }
651
652 bool QFontDialogPrivate::hideCocoaFontPanel()
653 {
654     if (!delegate){
655         // Nothing to do. We return false to leave the question
656         // open regarding whether or not to go native:
657         return false;
658     } else {
659         closeCocoaFontPanel();
660         // Even when we hide it, we are still using a
661         // native dialog, so return true:
662         return true;
663     }
664 }
665 bool QFontDialogPrivate::setVisible_sys(bool visible)
666 {
667     Q_Q(QFontDialog);
668     if (!visible == q->isHidden())
669         return false;
670
671     return visible ? showCocoaFontPanel() : hideCocoaFontPanel();
672 }
673
674 QT_END_NAMESPACE
675
676 #endif