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