1// Copyright (c) 2009 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#if !defined(__LP64__)
6
7#include <Carbon/Carbon.h>
8
9#include "content/plugin/plugin_interpose_util_mac.h"
10#include "ui/gfx/rect.h"
11#include "webkit/plugins/npapi/carbon_plugin_window_tracker_mac.h"
12
13#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
14
15// Returns true if the given window is modal.
16static bool IsModalWindow(WindowRef window) {
17  WindowModality modality = kWindowModalityNone;
18  WindowRef modal_target = NULL;
19  OSStatus status = GetWindowModality(window, &modality, &modal_target);
20  return (status == noErr) && (modality != kWindowModalityNone);
21}
22
23static bool IsContainingWindowActive(const OpaquePluginRef delegate) {
24  return mac_plugin_interposing::GetPluginWindowHasFocus(delegate);
25}
26
27static CGRect CGRectForWindow(WindowRef window) {
28  CGRect bounds = { { 0, 0 }, { 0, 0 } };
29  HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
30                    &bounds);
31  return bounds;
32}
33
34struct WindowInfo {
35  uint32 window_id;
36  CGRect bounds;
37  WindowInfo(WindowRef window) {
38    window_id = HIWindowGetCGWindowID(window);
39    bounds = CGRectForWindow(window);
40  }
41};
42
43static void OnPluginWindowClosed(const WindowInfo& window_info) {
44  mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
45                                                          window_info.bounds);
46}
47
48static void OnPluginWindowShown(WindowRef window) {
49  mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
50      HIWindowGetCGWindowID(window), CGRectForWindow(window),
51      IsModalWindow(window));
52}
53
54static void OnPluginWindowSelected(WindowRef window) {
55  mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow(
56      HIWindowGetCGWindowID(window), CGRectForWindow(window),
57      IsModalWindow(window));
58}
59
60#pragma mark -
61
62static Boolean ChromePluginIsWindowActive(WindowRef window) {
63  const OpaquePluginRef delegate =
64      webkit::npapi::CarbonPluginWindowTracker::SharedInstance()->
65          GetDelegateForDummyWindow(window);
66  return delegate ? IsContainingWindowActive(delegate)
67                  : IsWindowActive(window);
68}
69
70static Boolean ChromePluginIsWindowHilited(WindowRef window) {
71  const OpaquePluginRef delegate =
72      webkit::npapi::CarbonPluginWindowTracker::SharedInstance()->
73          GetDelegateForDummyWindow(window);
74  return delegate ? IsContainingWindowActive(delegate)
75                  : IsWindowHilited(window);
76}
77
78static void ChromePluginSelectWindow(WindowRef window) {
79  mac_plugin_interposing::SwitchToPluginProcess();
80  SelectWindow(window);
81  OnPluginWindowSelected(window);
82}
83
84static void ChromePluginShowWindow(WindowRef window) {
85  mac_plugin_interposing::SwitchToPluginProcess();
86  ShowWindow(window);
87  OnPluginWindowShown(window);
88}
89
90static void ChromePluginDisposeWindow(WindowRef window) {
91  WindowInfo window_info(window);
92  DisposeWindow(window);
93  OnPluginWindowClosed(window_info);
94}
95
96static void ChromePluginHideWindow(WindowRef window) {
97  WindowInfo window_info(window);
98  HideWindow(window);
99  OnPluginWindowClosed(window_info);
100}
101
102static void ChromePluginShowHide(WindowRef window, Boolean show) {
103  if (show) {
104    mac_plugin_interposing::SwitchToPluginProcess();
105    ShowHide(window, show);
106    OnPluginWindowShown(window);
107  } else {
108    WindowInfo window_info(window);
109    ShowHide(window, show);
110    OnPluginWindowClosed(window_info);
111  }
112}
113
114static void ChromePluginReleaseWindow(WindowRef window) {
115  WindowInfo window_info(window);
116  ReleaseWindow(window);
117  OnPluginWindowClosed(window_info);
118}
119
120static void ChromePluginDisposeDialog(DialogRef dialog) {
121  WindowRef window = GetDialogWindow(dialog);
122  WindowInfo window_info(window);
123  DisposeDialog(dialog);
124  OnPluginWindowClosed(window_info);
125}
126
127static WindowPartCode ChromePluginFindWindow(Point point, WindowRef* window) {
128  OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate();
129  webkit::npapi::CarbonPluginWindowTracker* tracker =
130      webkit::npapi::CarbonPluginWindowTracker::SharedInstance();
131  WindowRef plugin_window = tracker->GetDummyWindowForDelegate(delegate);
132  if (plugin_window) {
133    // If plugin_window is non-NULL, then we are in the middle of routing an
134    // event to the plugin, so we know it's destined for this window already,
135    // so we don't have to worry that we'll be stealing an event meant for an
136    // overlapping window.
137    Rect window_bounds;
138    GetWindowBounds(plugin_window, kWindowContentRgn, &window_bounds);
139    if (PtInRect(point, &window_bounds)) {
140      if (window)
141        *window = plugin_window;
142      return inContent;
143    }
144  }
145  return FindWindow(point, window);
146}
147
148static OSStatus ChromePluginSetThemeCursor(ThemeCursor cursor) {
149  OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate();
150  if (delegate) {
151    mac_plugin_interposing::NotifyPluginOfSetThemeCursor(delegate, cursor);
152    return noErr;
153  }
154  return SetThemeCursor(cursor);
155}
156
157static void ChromePluginSetCursor(const Cursor* cursor) {
158  OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate();
159  if (delegate) {
160    mac_plugin_interposing::NotifyPluginOfSetCursor(delegate, cursor);
161    return;
162  }
163  return SetCursor(cursor);
164}
165
166#pragma mark -
167
168struct interpose_substitution {
169  const void* replacement;
170  const void* original;
171};
172
173#define INTERPOSE_FUNCTION(function) \
174    { reinterpret_cast<const void*>(ChromePlugin##function), \
175      reinterpret_cast<const void*>(function) }
176
177__attribute__((used)) static const interpose_substitution substitutions[]
178    __attribute__((section("__DATA, __interpose"))) = {
179  INTERPOSE_FUNCTION(IsWindowActive),
180  INTERPOSE_FUNCTION(IsWindowHilited),
181  INTERPOSE_FUNCTION(SelectWindow),
182  INTERPOSE_FUNCTION(ShowWindow),
183  INTERPOSE_FUNCTION(ShowHide),
184  INTERPOSE_FUNCTION(DisposeWindow),
185  INTERPOSE_FUNCTION(HideWindow),
186  INTERPOSE_FUNCTION(ReleaseWindow),
187  INTERPOSE_FUNCTION(DisposeDialog),
188  INTERPOSE_FUNCTION(FindWindow),
189  INTERPOSE_FUNCTION(SetThemeCursor),
190  INTERPOSE_FUNCTION(SetCursor),
191};
192
193#endif  // !__LP64__
194