Home | History | Annotate | Download | only in browser
      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