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. 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 23 static bool IsContainingWindowActive(const OpaquePluginRef delegate) { 24 return mac_plugin_interposing::GetPluginWindowHasFocus(delegate); 25 } 26 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; 37 WindowInfo(WindowRef window) { 38 window_id = HIWindowGetCGWindowID(window); 39 bounds = CGRectForWindow(window); 40 } 41 }; 42 43 static void OnPluginWindowClosed(const WindowInfo& window_info) { 44 mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id, 45 window_info.bounds); 46 } 47 48 static void OnPluginWindowShown(WindowRef window) { 49 mac_plugin_interposing::NotifyBrowserOfPluginShowWindow( 50 HIWindowGetCGWindowID(window), CGRectForWindow(window), 51 IsModalWindow(window)); 52 } 53 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 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 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 78 static void ChromePluginSelectWindow(WindowRef window) { 79 mac_plugin_interposing::SwitchToPluginProcess(); 80 SelectWindow(window); 81 OnPluginWindowSelected(window); 82 } 83 84 static void ChromePluginShowWindow(WindowRef window) { 85 mac_plugin_interposing::SwitchToPluginProcess(); 86 ShowWindow(window); 87 OnPluginWindowShown(window); 88 } 89 90 static void ChromePluginDisposeWindow(WindowRef window) { 91 WindowInfo window_info(window); 92 DisposeWindow(window); 93 OnPluginWindowClosed(window_info); 94 } 95 96 static void ChromePluginHideWindow(WindowRef window) { 97 WindowInfo window_info(window); 98 HideWindow(window); 99 OnPluginWindowClosed(window_info); 100 } 101 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 114 static void ChromePluginReleaseWindow(WindowRef window) { 115 WindowInfo window_info(window); 116 ReleaseWindow(window); 117 OnPluginWindowClosed(window_info); 118 } 119 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 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 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 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