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.
IsModalWindow(WindowRef window)16 static 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
IsContainingWindowActive(const OpaquePluginRef delegate)23 static bool IsContainingWindowActive(const OpaquePluginRef delegate) {
24 return mac_plugin_interposing::GetPluginWindowHasFocus(delegate);
25 }
26
CGRectForWindow(WindowRef window)27 static CGRect CGRectForWindow(WindowRef window) {
28 CGRect bounds = { { 0, 0 }, { 0, 0 } };
29 HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
30 &bounds);
31 return bounds;
32 }
33
34 struct WindowInfo {
35 uint32 window_id;
36 CGRect bounds;
WindowInfoWindowInfo37 WindowInfo(WindowRef window) {
38 window_id = HIWindowGetCGWindowID(window);
39 bounds = CGRectForWindow(window);
40 }
41 };
42
OnPluginWindowClosed(const WindowInfo & window_info)43 static void OnPluginWindowClosed(const WindowInfo& window_info) {
44 mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
45 window_info.bounds);
46 }
47
OnPluginWindowShown(WindowRef window)48 static void OnPluginWindowShown(WindowRef window) {
49 mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
50 HIWindowGetCGWindowID(window), CGRectForWindow(window),
51 IsModalWindow(window));
52 }
53
OnPluginWindowSelected(WindowRef window)54 static void OnPluginWindowSelected(WindowRef window) {
55 mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow(
56 HIWindowGetCGWindowID(window), CGRectForWindow(window),
57 IsModalWindow(window));
58 }
59
60 #pragma mark -
61
ChromePluginIsWindowActive(WindowRef window)62 static 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
ChromePluginIsWindowHilited(WindowRef window)70 static 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
ChromePluginSelectWindow(WindowRef window)78 static void ChromePluginSelectWindow(WindowRef window) {
79 mac_plugin_interposing::SwitchToPluginProcess();
80 SelectWindow(window);
81 OnPluginWindowSelected(window);
82 }
83
ChromePluginShowWindow(WindowRef window)84 static void ChromePluginShowWindow(WindowRef window) {
85 mac_plugin_interposing::SwitchToPluginProcess();
86 ShowWindow(window);
87 OnPluginWindowShown(window);
88 }
89
ChromePluginDisposeWindow(WindowRef window)90 static void ChromePluginDisposeWindow(WindowRef window) {
91 WindowInfo window_info(window);
92 DisposeWindow(window);
93 OnPluginWindowClosed(window_info);
94 }
95
ChromePluginHideWindow(WindowRef window)96 static void ChromePluginHideWindow(WindowRef window) {
97 WindowInfo window_info(window);
98 HideWindow(window);
99 OnPluginWindowClosed(window_info);
100 }
101
ChromePluginShowHide(WindowRef window,Boolean show)102 static 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
ChromePluginReleaseWindow(WindowRef window)114 static void ChromePluginReleaseWindow(WindowRef window) {
115 WindowInfo window_info(window);
116 ReleaseWindow(window);
117 OnPluginWindowClosed(window_info);
118 }
119
ChromePluginDisposeDialog(DialogRef dialog)120 static void ChromePluginDisposeDialog(DialogRef dialog) {
121 WindowRef window = GetDialogWindow(dialog);
122 WindowInfo window_info(window);
123 DisposeDialog(dialog);
124 OnPluginWindowClosed(window_info);
125 }
126
ChromePluginFindWindow(Point point,WindowRef * window)127 static 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
ChromePluginSetThemeCursor(ThemeCursor cursor)148 static 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
ChromePluginSetCursor(const Cursor * cursor)157 static 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
168 struct 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