source: trunk/src/gui/dialogs/qnspanelproxy_mac.mm

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 9.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qdialogbuttonbox.h>
43#if defined(Q_WS_MAC)
44#include <private/qt_mac_p.h>
45#import <AppKit/AppKit.h>
46#import <Foundation/Foundation.h>
47#import <objc/objc-class.h>
48
49QT_BEGIN_NAMESPACE
50static QWidget *currentWindow = 0;
51QT_END_NAMESPACE
52
53QT_USE_NAMESPACE
54
55@class QT_MANGLE_NAMESPACE(QNSPanelProxy);
56
57@interface QT_MANGLE_NAMESPACE(QNSPanelProxy) : NSWindow {
58}
59- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
60 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation;
61- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
62 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation screen:(NSScreen *)screen;
63- (id)qt_fakeInitWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
64 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation;
65- (id)qt_fakeInitWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
66 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation screen:(NSScreen *)screen;
67@end
68
69@implementation QT_MANGLE_NAMESPACE(QNSPanelProxy)
70- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
71 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation
72{
73 // remove evil flag
74 windowStyle &= ~NSUtilityWindowMask;
75 self = [self qt_fakeInitWithContentRect:contentRect styleMask:windowStyle
76 backing:bufferingType defer:deferCreation];
77 return self;
78}
79
80- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
81 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation screen:(NSScreen *)screen
82{
83 // remove evil flag
84 windowStyle &= ~NSUtilityWindowMask;
85 return [self qt_fakeInitWithContentRect:contentRect styleMask:windowStyle
86 backing:bufferingType defer:deferCreation screen:screen];
87}
88
89- (id)qt_fakeInitWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
90 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation
91{
92 Q_UNUSED(contentRect);
93 Q_UNUSED(windowStyle);
94 Q_UNUSED(bufferingType);
95 Q_UNUSED(deferCreation);
96 return nil;
97}
98
99- (id)qt_fakeInitWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle
100 backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation screen:(NSScreen *)screen
101{
102 Q_UNUSED(contentRect);
103 Q_UNUSED(windowStyle);
104 Q_UNUSED(bufferingType);
105 Q_UNUSED(deferCreation);
106 Q_UNUSED(screen);
107 return nil;
108}
109@end
110
111@class QT_MANGLE_NAMESPACE(QNSWindowProxy);
112
113@interface QT_MANGLE_NAMESPACE(QNSWindowProxy) : NSWindow {
114}
115- (void)setTitle:(NSString *)title;
116- (void)qt_fakeSetTitle:(NSString *)title;
117@end
118
119@implementation QT_MANGLE_NAMESPACE(QNSWindowProxy)
120- (void)setTitle:(NSString *)title
121{
122 QCFString cftitle(currentWindow->windowTitle());
123
124 // evil reverse engineering
125 if ([title isEqualToString:@"Print"]
126 || [title isEqualToString:@"Page Setup"]
127 || [[self className] isEqualToString:@"PMPrintingWindow"])
128 title = (NSString *)(static_cast<CFStringRef>(cftitle));
129 return [self qt_fakeSetTitle:title];
130}
131
132- (void)qt_fakeSetTitle:(NSString *)title
133{
134 Q_UNUSED(title);
135}
136@end
137
138QT_BEGIN_NAMESPACE
139
140void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class proxyClass)
141{
142#ifndef QT_MAC_USE_COCOA
143 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
144#endif
145 {
146#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
147 // The following code replaces the _implementation_ for the selector we want to hack
148 // (originalSel) with the implementation found in proxyClass. Then it creates
149 // a new 'backup' method inside baseClass containing the old, original,
150 // implementation (fakeSel). You can let the proxy implementation of originalSel
151 // call fakeSel if needed (similar approach to calling a super class implementation).
152 // fakeSel must also be implemented in proxyClass, as the signature is used
153 // as template for the method one we add into baseClass.
154 // NB: You will typically never create any instances of proxyClass; we use it
155 // only for stealing its contents and put it into baseClass.
156 Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
157 Method newMethod = class_getInstanceMethod(proxyClass, originalSel);
158 Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel);
159
160 IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod));
161 class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod));
162#endif
163 }
164}
165
166void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* proxyClass */)
167{
168#ifndef QT_MAC_USE_COCOA
169 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
170#endif
171 {
172#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
173 Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
174 Method fakeMethodInBaseClass = class_getInstanceMethod(baseClass, fakeSel);
175 method_setImplementation(originalMethod, method_getImplementation(fakeMethodInBaseClass));
176#endif
177 }
178}
179
180/*
181 Intercept the NSColorPanel constructor if the shared
182 color panel doesn't exist yet. What's going on here is
183 quite wacky, because we want to override the NSPanel
184 constructor and at the same time call the old NSPanel
185 constructor. So what we do is we effectively rename the
186 old NSPanel constructor qt_fakeInitWithContentRect:...
187 and have the new one call the old one.
188*/
189void macStartInterceptNSPanelCtor()
190{
191 macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:),
192 @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:),
193 [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
194 macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:),
195 @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:),
196 [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
197}
198
199/*
200 Restore things as they were.
201*/
202void macStopInterceptNSPanelCtor()
203{
204 macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:),
205 @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:),
206 [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
207 macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:),
208 @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:),
209 [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
210}
211
212/*
213 Intercept the NSPrintPanel and NSPageLayout setTitle: calls. The
214 hack is similar as for NSColorPanel above.
215*/
216void macStartInterceptWindowTitle(QWidget *window)
217{
218 currentWindow = window;
219 macStartIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:),
220 [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]);
221}
222
223/*
224 Restore things as they were.
225*/
226void macStopInterceptWindowTitle()
227{
228 currentWindow = 0;
229 macStopIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:),
230 [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]);
231}
232
233/*
234 Doesn't really belong in here.
235*/
236NSButton *macCreateButton(const char *text, NSView *superview)
237{
238 static const NSRect buttonFrameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
239
240 NSButton *button = [[NSButton alloc] initWithFrame:buttonFrameRect];
241 [button setButtonType:NSMomentaryLightButton];
242 [button setBezelStyle:NSRoundedBezelStyle];
243 [button setTitle:(NSString*)(CFStringRef)QCFString(QDialogButtonBox::tr(text)
244 .remove(QLatin1Char('&')))];
245 [[button cell] setFont:[NSFont systemFontOfSize:
246 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
247 [superview addSubview:button];
248 return button;
249}
250
251QT_END_NAMESPACE
252
253#endif
Note: See TracBrowser for help on using the repository browser.