Qt 4.8
quikitwindow.mm
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #import <QuartzCore/CAEAGLLayer.h>
43 
44 #include "quikitwindow.h"
45 
46 #include "quikitscreen.h"
47 
48 #include <QtDebug>
49 #include <QtGui/QApplication>
50 #include <QtGui/QKeyEvent>
51 #include <QtGui/QPlatformGLContext>
52 #include <QtGui/QWindowSystemInterface>
53 
54 #include <QtDebug>
55 
57 {
58  static GLint bits;
59  static bool initialized = false;
60  if (!initialized) {
61  glGetIntegerv(GL_STENCIL_BITS, &bits);
62  initialized = true;
63  }
64  return bits;
65 }
66 
67 static GLint depthBits()
68 {
69  // we can choose between GL_DEPTH24_STENCIL8_OES and GL_DEPTH_COMPONENT16
70  return stencilBits() > 0 ? 24 : 16;
71 }
72 
74 {
75 public:
77  : mView(view)
78  {
90  mFormat.setDepth(true);
91  mFormat.setRgba(true);
92  mFormat.setAlpha(true);
93  mFormat.setAccum(false);
95  mFormat.setStereo(false);
97 
98 #if defined(QT_OPENGL_ES_2)
99  EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
100 #else
101  EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
102 #endif
103  [mView setContext:aContext];
104  }
105 
107 
108  void makeCurrent()
109  {
111  [mView makeCurrent];
112  }
113 
114  void doneCurrent()
115  {
117  }
118 
119  void swapBuffers()
120  {
121  [mView presentFramebuffer];
122  }
123 
124  void* getProcAddress(const QString& ) { return 0; }
125 
127  {
128  return mFormat;
129  }
130 
131 private:
133 
135 };
136 
137 @implementation EAGLView
138 
139 @synthesize delegate;
140 
141 + (Class)layerClass
142 {
143  return [CAEAGLLayer class];
144 }
145 
146 - (id)initWithFrame:(CGRect)frame
147 {
148  if ((self = [super initWithFrame:frame])) {
149  CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
150  eaglLayer.opaque = TRUE;
151  eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
152  [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
153  kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
154  nil];
155  autocapitalizationType = UITextAutocapitalizationTypeNone;
156  autocorrectionType = UITextAutocorrectionTypeNo;
158  keyboardAppearance = UIKeyboardAppearanceDefault;
159  keyboardType = UIKeyboardTypeDefault;
160  returnKeyType = UIReturnKeyDone;
161  secureTextEntry = NO;
162  }
163  return self;
164 }
165 
166 - (void)setContext:(EAGLContext *)newContext
167 {
168  if (mContext != newContext)
169  {
170  [self deleteFramebuffer];
171  [mContext release];
172  mContext = [newContext retain];
173  [EAGLContext setCurrentContext:nil];
174  }
175 }
176 
178 {
179  if (mContext) {
180  [EAGLContext setCurrentContext:mContext];
182  [mContext presentRenderbuffer:GL_RENDERBUFFER];
183  }
184 }
185 
187 {
188  if (mContext)
189  {
190  [EAGLContext setCurrentContext:mContext];
191  if (mFramebuffer) {
193  mFramebuffer = 0;
194  }
195  if (mColorRenderbuffer) {
197  mColorRenderbuffer = 0;
198  }
199  if (mDepthRenderbuffer) {
201  mDepthRenderbuffer = 0;
202  }
203  }
204 }
205 
207 {
208  if (mContext && !mFramebuffer)
209  {
210  [EAGLContext setCurrentContext:mContext];
213 
216  [mContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
220 
223  if (stencilBits() > 0) {
226  } else {
228  }
230 
232  NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
233  if (delegate && [delegate respondsToSelector:@selector(eaglView:usesFramebuffer:)]) {
234  [delegate eaglView:self usesFramebuffer:mFramebuffer];
235  }
236  }
237 }
238 
239 - (void)makeCurrent
240 {
241  if (mContext)
242  {
243  [EAGLContext setCurrentContext:mContext];
244  if (!mFramebuffer)
245  [self createFramebuffer];
247  glViewport(0, 0, mFramebufferWidth, mFramebufferHeight);
248  }
249 }
250 
251 - (GLint)fbo
252 {
253  return mFramebuffer;
254 }
255 
256 - (void)setWindow:(QPlatformWindow *)window
257 {
258  mWindow = window;
259 }
260 
261 - (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons
262 {
263  UITouch *touch = [touches anyObject];
264  CGPoint locationInView = [touch locationInView:self];
265  CGFloat scaleFactor = [self contentScaleFactor];
266  QPoint p(locationInView.x * scaleFactor, locationInView.y * scaleFactor);
267  // TODO handle global touch point? for status bar?
269  p, p, buttons);
270 }
271 
272 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
273 {
274  [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
275 }
276 
277 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
278 {
279  [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
280 }
281 
282 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
283 {
284  [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
285 }
286 
287 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
288 {
289  [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
290 }
291 
292 // ------- Text Input ----------
293 
294 @synthesize autocapitalizationType;
295 @synthesize autocorrectionType;
297 @synthesize keyboardAppearance;
298 @synthesize keyboardType;
299 @synthesize returnKeyType;
300 @synthesize secureTextEntry;
301 
302 - (BOOL)canBecomeFirstResponder
303 {
304  return YES;
305 }
306 
307 - (BOOL)hasText
308 {
309  return YES;
310 }
311 
312 - (void)insertText:(NSString *)text
313 {
314  QString string = QString::fromUtf8([text UTF8String]);
315  int key = 0;
316  if ([text isEqualToString:@"\n"])
317  key = (int)Qt::Key_Return;
318 
319  // Send key event to window system interface
321  0, QEvent::KeyPress, key, Qt::NoModifier, string, false, int(string.length()));
323  0, QEvent::KeyRelease, key, Qt::NoModifier, string, false, int(string.length()));
324 }
325 
326 - (void)deleteBackward
327 {
328  // Send key event to window system interface
332  0, QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
333 }
334 
335 @end
336 
338 
340  QPlatformWindow(tlw),
341  mWindow(nil),
342  mContext(0)
343 {
345  mView = [[EAGLView alloc] init];
346 }
347 
349 {
350  delete mContext; mContext = 0;
351  [mView release];
352  [mWindow release];
353 }
354 
356 {
357  // Not supported. Only a single "full screen" window is supported
359 }
360 
362 {
363  if (!mWindow) {
364  mWindow = [[UIWindow alloc] init];
366  // window
367  mWindow.screen = mScreen->uiScreen();
368  // for some reason setting the screen resets frame.origin, so we need to set the frame afterwards
369  mWindow.frame = mFrame;
370 
371  // view
373  mView.frame = CGRectMake(0, 0, mWindow.bounds.size.width, mWindow.bounds.size.height); // fill
374  [mView setContentScaleFactor:[mWindow.screen scale]];
375  [mView setMultipleTouchEnabled:YES];
376  [mView setWindow:this];
377  [mWindow addSubview:mView];
378  [mWindow setNeedsDisplay];
379  [mWindow makeKeyAndVisible];
380  }
381  return mWindow;
382 }
383 
385 {
386  if (!mWindow)
387  return;
388  mFrame = [mScreen->uiScreen() applicationFrame];
389  CGRect screen = [mScreen->uiScreen() bounds];
390  QRect geom;
391  CGFloat angle = 0;
392  switch ([[UIApplication sharedApplication] statusBarOrientation]) {
393  case UIInterfaceOrientationPortrait:
394  geom = QRect(mFrame.origin.x, mFrame.origin.y, mFrame.size.width, mFrame.size.height);
395  break;
396  case UIInterfaceOrientationPortraitUpsideDown:
397  geom = QRect(screen.size.width - mFrame.origin.x - mFrame.size.width,
398  screen.size.height - mFrame.origin.y - mFrame.size.height,
399  mFrame.size.width,
400  mFrame.size.height);
401  angle = M_PI;
402  break;
403  case UIInterfaceOrientationLandscapeLeft:
404  geom = QRect(screen.size.height - mFrame.origin.y - mFrame.size.height,
405  mFrame.origin.x,
406  mFrame.size.height,
407  mFrame.size.width);
408  angle = -M_PI/2.;
409  break;
410  case UIInterfaceOrientationLandscapeRight:
411  geom = QRect(mFrame.origin.y,
412  screen.size.width - mFrame.origin.x - mFrame.size.width,
413  mFrame.size.height,
414  mFrame.size.width);
415  angle = +M_PI/2.;
416  break;
417  }
418 
419  CGFloat scale = [mScreen->uiScreen() scale];
420  geom = QRect(geom.x() * scale, geom.y() * scale,
421  geom.width() * scale, geom.height() * scale);
422 
423  if (angle != 0) {
424  [mView layer].transform = CATransform3DMakeRotation(angle, 0, 0, 1.);
425  } else {
426  [mView layer].transform = CATransform3DIdentity;
427  }
428  [mView setNeedsDisplay];
429  widget()->setGeometry(geom);
430  widget()->update();
431 }
432 
434 {
435  if (!mContext) {
437  }
438  return mContext;
439 }
440 
EAGLPlatformContext * mContext
Definition: quikitwindow.h:131
BOOL secureTextEntry
Definition: quikitwindow.h:73
GLint fbo
Definition: quikitwindow.h:84
GLuint mDepthRenderbuffer
Definition: quikitwindow.h:63
void swapBuffers()
Reimplement in subclass to native swap buffers calls.
QPlatformWindow * mWindow
Definition: quikitwindow.h:57
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
EventRef event
#define GL_RENDERBUFFER_WIDTH
void setDepthBufferSize(int size)
Set the minimum depth buffer size to size.
UIWindow * ensureNativeWindow()
void setStereo(bool enable)
If enable is true enables stereo buffering; otherwise disables stereo buffering.
virtual void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or the window is resized.
#define GL_FRAMEBUFFER_COMPLETE
void setDirectRendering(bool enable)
If enable is true enables direct rendering; otherwise disables direct rendering.
virtual void doneCurrent()
Reimplement in subclass to release current context.
static Qt::MouseButtons buttons
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
#define glGenRenderbuffers
The QPlatformWindowFormat class specifies the display format of an OpenGL rendering context and if po...
static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString &text=QString(), bool autorep=false, ushort count=1)
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
GLuint mFramebuffer
Definition: quikitwindow.h:63
BOOL enablesReturnKeyAutomatically
Definition: quikitwindow.h:69
void setBlueBufferSize(int size)
Set the preferred blue buffer size to size.
void setStencilBufferSize(int size)
Set the preferred stencil buffer size to size.
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qwidget.h:1017
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QPlatformWindow class provides an abstraction for top-level windows.
#define glBindFramebuffer
QUIKitWindow(QWidget *tlw)
#define M_PI
Definition: qmath.h:261
#define glDeleteRenderbuffers
#define GL_RENDERBUFFER
static GLint stencilBits()
Definition: quikitwindow.mm:56
#define GL_DEPTH_ATTACHMENT
void update()
Updates the widget unless updates are disabled or the widget is hidden.
Definition: qwidget.cpp:10883
void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or the window is resized.
NSWindow * window
GLint mFramebufferWidth
Definition: quikitwindow.h:60
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define GL_DEPTH_COMPONENT16
void setAccumBufferSize(int size)
Set the preferred accumulation buffer size, where size is the bit depth for each RGBA component...
#define glCheckFramebufferStatus
UIWindow * mWindow
Definition: quikitwindow.h:128
void setAlphaBufferSize(int size)
Set the preferred alpha buffer size to size.
#define glDeleteFramebuffers
UIKeyboardType keyboardType
Definition: quikitwindow.h:71
static void handleMouseEvent(QWidget *w, const QPoint &local, const QPoint &global, Qt::MouseButtons b)
tlw == 0 means that ev is in global coords only
void * getProcAddress(const QString &)
Reimplement in subclass to native getProcAddr calls.
void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
#define glGenFramebuffers
EAGLContext * mContext
Definition: quikitwindow.h:58
GLuint mColorRenderbuffer
Definition: quikitwindow.h:63
void createFramebuffer()
static QPlatformScreen * platformScreenForWidget(const QWidget *widget)
GLint mFramebufferHeight
Definition: quikitwindow.h:61
void updateGeometryAndOrientation()
void setSamples(int numSamples)
Set the preferred number of samples per pixel when multisampling is enabled to numSamples.
EAGLView * mView
Definition: quikitwindow.h:130
virtual void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
unsigned long ulong
Definition: qglobal.h:997
#define GL_STENCIL_BITS
#define GL_FRAMEBUFFER
void setDoubleBuffer(bool enable)
If enable is true sets double buffering; otherwise sets single buffering.
#define glGetRenderbufferParameteriv
void setRgba(bool enable)
If enable is true sets RGBA mode.
#define glBindRenderbuffer
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
QUIKitScreen * mScreen
Definition: quikitwindow.h:127
struct CGRect CGRect
qreal angle(const QPointF &p1, const QPointF &p2)
UIKeyboardAppearance keyboardAppearance
Definition: quikitwindow.h:70
The QPlatformGLContext class provides an abstraction for native GL contexts.
void setAlpha(bool enable)
If enable is true enables the alpha buffer; otherwise disables the alpha buffer.
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
void setWindow:(QPlatformWindow *window)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
UIReturnKeyType returnKeyType
Definition: quikitwindow.h:72
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
void setSampleBuffers(bool enable)
If enable is true, a GL context with multisample buffer support is picked; otherwise ignored...
void setWindowApi(QPlatformWindowFormat::WindowApi api)
#define GL_STENCIL_ATTACHMENT
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
Definition: qnamespace.h:54
void setStencil(bool enable)
If enable is true enables the stencil buffer; otherwise disables the stencil buffer.
#define GL_COLOR_ATTACHMENT0
void setRedBufferSize(int size)
Set the preferred red buffer size to size.
typedef GLint
Definition: glfunctions.h:67
#define glFramebufferRenderbuffer
UIScreen * uiScreen() const
Definition: quikitscreen.mm:85
void doneCurrent()
Reimplement in subclass to release current context.
#define GL_RENDERBUFFER_HEIGHT
void presentFramebuffer()
UITextAutocapitalizationType autocapitalizationType
Definition: quikitwindow.h:67
EAGLPlatformContext(EAGLView *view)
Definition: quikitwindow.mm:76
void deleteFramebuffer()
UITextAutocorrectionType autocorrectionType
Definition: quikitwindow.h:68
void setAccum(bool enable)
If enable is true enables the accumulation buffer; otherwise disables the accumulation buffer...
QPlatformGLContext * glContext() const
Reimplement to return the glContext associated with the window.
#define glRenderbufferStorage
QPlatformWindowFormat mFormat
void setGreenBufferSize(int size)
Set the preferred green buffer size to size.
static GLint depthBits()
Definition: quikitwindow.mm:67
void setDepth(bool enable)
If enable is true enables the depth buffer; otherwise disables the depth buffer.
#define text
Definition: qobjectdefs.h:80
QPlatformWindowFormat platformWindowFormat() const
QWidget has the function qplatformWindowFormat().
QWidget * widget() const
Returnes the widget which belongs to the QPlatformWindow.
float CGFloat