test_compositor_host_mac.mm revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/memory/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 CompositorDelegate,
83                              public AppKitHost {
84 public:
85  TestCompositorHostMac(const gfx::Rect& bounds);
86  virtual ~TestCompositorHostMac();
87
88 private:
89  // TestCompositorHost:
90  virtual void Show() OVERRIDE;
91  virtual ui::Compositor* GetCompositor() OVERRIDE;
92
93  // CompositorDelegate:
94  virtual void ScheduleDraw() OVERRIDE;
95
96  gfx::Rect bounds_;
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(const gfx::Rect& bounds)
106    : bounds_(bounds), window_(nil) {
107}
108
109TestCompositorHostMac::~TestCompositorHostMac() {
110  // Release reference to |compositor_|.  Important because the |compositor_|
111  // holds |this| as its delegate, so that reference must be removed here.
112  [[window_ contentView] setCompositor:NULL];
113  [window_ setContentView:nil];
114
115  [window_ orderOut:nil];
116  [window_ close];
117}
118
119void TestCompositorHostMac::Show() {
120  DCHECK(!window_);
121  window_ = [[NSWindow alloc]
122                initWithContentRect:NSMakeRect(bounds_.x(),
123                                               bounds_.y(),
124                                               bounds_.width(),
125                                               bounds_.height())
126                          styleMask:NSBorderlessWindowMask
127                            backing:NSBackingStoreBuffered
128                              defer:NO];
129  scoped_nsobject<AcceleratedTestView> view([[AcceleratedTestView alloc] init]);
130  compositor_.reset(new ui::Compositor(this, view, bounds_.size()));
131  [view setCompositor:compositor_.get()];
132  [window_ setContentView:view];
133  [window_ orderFront:nil];
134}
135
136ui::Compositor* TestCompositorHostMac::GetCompositor() {
137  return compositor_.get();
138}
139
140void TestCompositorHostMac::ScheduleDraw() {
141  DCHECK(!ui::Compositor::WasInitializedWithThread());
142  if (!compositor_.get())
143    return;
144
145  // Force display now.
146  [window_ display];
147}
148
149// static
150TestCompositorHost* TestCompositorHost::Create(const gfx::Rect& bounds) {
151  return new TestCompositorHostMac(bounds);
152}
153
154}  // namespace ui
155