1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ui/compositor/test/test_compositor_host.h" 6 7#import <AppKit/NSApplication.h> 8#import <AppKit/NSOpenGL.h> 9#import <AppKit/NSView.h> 10#import <AppKit/NSWindow.h> 11#import <Foundation/NSAutoreleasePool.h> 12 13#include "base/compiler_specific.h" 14#include "base/mac/scoped_nsobject.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/thread_task_runner_handle.h" 17#include "ui/compositor/compositor.h" 18#include "ui/gfx/rect.h" 19 20// AcceleratedTestView provides an NSView class that delegates drawing to a 21// ui::Compositor delegate, setting up the NSOpenGLContext as required. 22@interface AcceleratedTestView : NSView { 23 ui::Compositor* compositor_; 24} 25// Designated initializer. 26-(id)init; 27-(void)setCompositor:(ui::Compositor*)compositor; 28@end 29 30@implementation AcceleratedTestView 31-(id)init { 32 // The frame will be resized when reparented into the window's view hierarchy. 33 self = [super initWithFrame:NSZeroRect]; 34 return self; 35} 36 37-(void)setCompositor:(ui::Compositor*)compositor { 38 compositor_ = compositor; 39} 40 41- (void)drawRect:(NSRect)rect { 42 DCHECK(compositor_) << "Drawing with no compositor set."; 43 compositor_->Draw(); 44} 45@end 46 47namespace ui { 48 49// Tests that use Objective-C memory semantics need to have a top-level 50// NSAutoreleasePool set up and initialized prior to execution and drained upon 51// exit. The tests will leak otherwise. 52class FoundationHost { 53 protected: 54 FoundationHost() { 55 pool_ = [[NSAutoreleasePool alloc] init]; 56 } 57 virtual ~FoundationHost() { 58 [pool_ drain]; 59 } 60 61 private: 62 NSAutoreleasePool* pool_; 63 DISALLOW_COPY_AND_ASSIGN(FoundationHost); 64}; 65 66// Tests that use the AppKit framework need to have the NSApplication 67// initialized prior to doing anything with display objects such as windows, 68// views, or controls. 69class AppKitHost : public FoundationHost { 70 protected: 71 AppKitHost() { 72 [NSApplication sharedApplication]; 73 } 74 virtual ~AppKitHost() { 75 } 76 private: 77 DISALLOW_COPY_AND_ASSIGN(AppKitHost); 78}; 79 80// TestCompositorHostMac provides a window surface and a coordinated compositor 81// for use in the compositor unit tests. 82class TestCompositorHostMac : public TestCompositorHost, 83 public AppKitHost { 84 public: 85 TestCompositorHostMac(const gfx::Rect& bounds, 86 ui::ContextFactory* context_factory); 87 virtual ~TestCompositorHostMac(); 88 89 private: 90 // TestCompositorHost: 91 virtual void Show() OVERRIDE; 92 virtual ui::Compositor* GetCompositor() OVERRIDE; 93 94 gfx::Rect bounds_; 95 96 ui::ContextFactory* context_factory_; 97 98 scoped_ptr<ui::Compositor> compositor_; 99 100 // Owned. Released when window is closed. 101 NSWindow* window_; 102 103 DISALLOW_COPY_AND_ASSIGN(TestCompositorHostMac); 104}; 105 106TestCompositorHostMac::TestCompositorHostMac( 107 const gfx::Rect& bounds, 108 ui::ContextFactory* context_factory) 109 : bounds_(bounds), context_factory_(context_factory), window_(nil) { 110} 111 112TestCompositorHostMac::~TestCompositorHostMac() { 113 // Release reference to |compositor_|. Important because the |compositor_| 114 // holds |this| as its delegate, so that reference must be removed here. 115 [[window_ contentView] setCompositor:NULL]; 116 [window_ setContentView:nil]; 117 118 [window_ orderOut:nil]; 119 [window_ close]; 120} 121 122void TestCompositorHostMac::Show() { 123 DCHECK(!window_); 124 window_ = [[NSWindow alloc] 125 initWithContentRect:NSMakeRect(bounds_.x(), 126 bounds_.y(), 127 bounds_.width(), 128 bounds_.height()) 129 styleMask:NSBorderlessWindowMask 130 backing:NSBackingStoreBuffered 131 defer:NO]; 132 base::scoped_nsobject<AcceleratedTestView> view( 133 [[AcceleratedTestView alloc] init]); 134 compositor_.reset(new ui::Compositor(view, 135 context_factory_, 136 base::ThreadTaskRunnerHandle::Get())); 137 compositor_->SetScaleAndSize(1.0f, bounds_.size()); 138 [view setCompositor:compositor_.get()]; 139 [window_ setContentView:view]; 140 [window_ orderFront:nil]; 141} 142 143ui::Compositor* TestCompositorHostMac::GetCompositor() { 144 return compositor_.get(); 145} 146 147// static 148TestCompositorHost* TestCompositorHost::Create( 149 const gfx::Rect& bounds, 150 ui::ContextFactory* context_factory) { 151 return new TestCompositorHostMac(bounds, context_factory); 152} 153 154} // namespace ui 155