+ xwindow = (Window) calloc (1, sizeof(*xwindow));
+ xwindow->type = WINDOW;
+ xwindow->window.view = self;
+ CFRetain (xwindow->window.view); // needed for garbage collection?
+
+#ifdef BACKBUFFER_OPENGL
+ CGSize new_backbuffer_size;
+
+ {
+# ifndef USE_IPHONE
+ if (!ogl_ctx) {
+
+ pixfmt = [self getGLPixelFormat];
+ [pixfmt retain];
+
+ NSAssert (pixfmt, @"unable to create NSOpenGLPixelFormat");
+
+ // Fun: On OS X 10.7, the second time an OpenGL context is created, after
+ // the preferences dialog is launched in SaverTester, the context only
+ // lasts until the first full GC. Then it turns black. Solution is to
+ // reuse the OpenGL context after this point.
+ // "Analyze" says that both pixfmt and ogl_ctx are leaked.
+ ogl_ctx = [[NSOpenGLContext alloc] initWithFormat:pixfmt
+ shareContext:nil];
+
+ // Sync refreshes to the vertical blanking interval
+ GLint r = 1;
+ [ogl_ctx setValues:&r forParameter:NSOpenGLCPSwapInterval];
+// check_gl_error ("NSOpenGLCPSwapInterval"); // SEGV sometimes. Too early?
+ }
+
+ [ogl_ctx makeCurrentContext];
+ check_gl_error ("makeCurrentContext");
+
+ // NSOpenGLContext logs an 'invalid drawable' when this is called
+ // from initWithFrame.
+ [ogl_ctx setView:self];
+
+ // Get device pixels instead of points.
+ self.wantsBestResolutionOpenGLSurface = YES;
+
+ // This may not be necessary if there's FBO support.
+# ifdef JWXYZ_GL
+ xwindow->window.pixfmt = pixfmt;
+ CFRetain (xwindow->window.pixfmt);
+ xwindow->window.virtual_screen = [ogl_ctx currentVirtualScreen];
+ xwindow->window.current_drawable = xwindow;
+ NSAssert (ogl_ctx, @"no CGContext");
+# endif
+
+ // Clear frame buffer ASAP, else there are bits left over from other apps.
+ glClearColor (0, 0, 0, 1);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+// glFinish ();
+// glXSwapBuffers (mi->dpy, mi->window);
+
+
+ // Enable multi-threading, if possible. This runs most OpenGL commands
+ // and GPU management on a second CPU.
+ {
+# ifndef kCGLCEMPEngine
+# define kCGLCEMPEngine 313 // Added in MacOS 10.4.8 + XCode 2.4.
+# endif
+ CGLContextObj cctx = CGLGetCurrentContext();
+ CGLError err = CGLEnable (cctx, kCGLCEMPEngine);
+ if (err != kCGLNoError) {
+ NSLog (@"enabling multi-threaded OpenGL failed: %d", err);
+ }
+ }
+
+ new_backbuffer_size = NSSizeToCGSize ([self bounds].size);
+
+ // Scale factor for desktop retina displays
+ double s = [self hackedContentScaleFactor];
+ new_backbuffer_size.width *= s;
+ new_backbuffer_size.height *= s;
+
+# else // USE_IPHONE
+ if (!ogl_ctx) {
+ CAEAGLLayer *eagl_layer = (CAEAGLLayer *) self.layer;
+ eagl_layer.opaque = TRUE;
+ eagl_layer.drawableProperties = [self getGLProperties];
+
+ // Without this, the GL frame buffer is half the screen resolution!
+ eagl_layer.contentsScale = [UIScreen mainScreen].scale;
+
+ ogl_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+# ifdef JWXYZ_GL
+ ogl_ctx_pixmap = [[EAGLContext alloc]
+ initWithAPI:kEAGLRenderingAPIOpenGLES1
+ sharegroup:ogl_ctx.sharegroup];
+# endif // JWXYZ_GL
+
+ eagl_layer.contentsGravity = [self getCAGravity];
+ }
+
+# ifdef JWXYZ_GL
+ xwindow->window.ogl_ctx_pixmap = ogl_ctx_pixmap;
+# endif // JWXYZ_GL
+
+ [EAGLContext setCurrentContext: ogl_ctx];
+
+ [self resizeGL];
+
+ double s = [self hackedContentScaleFactor];
+ new_backbuffer_size = self.bounds.size;
+ new_backbuffer_size.width *= s;
+ new_backbuffer_size.height *= s;
+
+# endif // USE_IPHONE
+
+# ifdef JWXYZ_GL
+ xwindow->ogl_ctx = ogl_ctx;
+# ifndef USE_IPHONE
+ CFRetain (xwindow->ogl_ctx);
+# endif // USE_IPHONE
+# endif // JWXYZ_GL
+
+ check_gl_error ("startAnimation");
+
+// NSLog (@"%s / %s / %s\n", glGetString (GL_VENDOR),
+// glGetString (GL_RENDERER), glGetString (GL_VERSION));
+
+ [self enableBackbuffer:new_backbuffer_size];
+ }
+#endif // BACKBUFFER_OPENGL
+
+ [self setViewport];
+ [self createBackbuffer:new_backbuffer_size];
+
+# ifdef USE_TOUCHBAR
+ static BOOL created_touchbar = NO;
+
+ if (!touchbar_view &&
+ //#### !self.isPreview &&
+ self.window.screen == [[NSScreen screens] objectAtIndex: 0] &&
+ !created_touchbar) {
+
+ // Figure out which NSScreen has the touchbar on it;
+ // find its bounds; create a saver there.
+
+ created_touchbar = YES;
+ NSScreen *tbs = [[NSScreen screens] lastObject]; // #### write me
+ NSRect rect = [tbs visibleFrame];
+
+ // #### debugging
+ rect.origin.x += 40;
+ rect.origin.x += 40;
+ rect.size.width /= 4;
+ rect.size.height /= 4;
+ NSLog(@"## TB %.0f, %.0f %.0f x %.0f",
+ rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+
+ touchbar_view = [[[self class] alloc]
+ initWithFrame:rect
+ saverName:[NSString stringWithCString:xsft->progclass
+ encoding:NSISOLatin1StringEncoding]
+ isPreview:self.isPreview];
+ [touchbar_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+
+ touchbar_window = [[NSWindow alloc]
+ initWithContentRect:rect
+ styleMask: (NSTitledWindowMask|NSResizableWindowMask)
+ backing:NSBackingStoreBuffered
+ defer:YES
+ screen:tbs];
+ [touchbar_window setTitle: @"XScreenSaver Touchbar"];
+ [[touchbar_window contentView] addSubview: touchbar_view];
+ [touchbar_window makeKeyAndOrderFront:touchbar_window];
+ }
+
+ if (touchbar_view) [touchbar_view startAnimation];
+# endif // USE_TOUCHBAR
+}