Home | History | Annotate | Download | only in npapi
      1 // Copyright (c) 2010 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 #import <AppKit/AppKit.h>
      6 
      7 #include "base/logging.h"
      8 #include "build/build_config.h"
      9 #include "content/child/npapi/plugin_instance.h"
     10 
     11 // When C++ exceptions are disabled, the C++ library defines |try| and
     12 // |catch| so as to allow exception-expecting C++ code to build properly when
     13 // language support for exceptions is not present.  These macros interfere
     14 // with the use of |@try| and |@catch| in Objective-C files such as this one.
     15 // Undefine these macros here, after everything has been #included, since
     16 // there will be no C++ uses and only Objective-C uses from this point on.
     17 #undef try
     18 #undef catch
     19 
     20 namespace content {
     21 
     22 namespace {
     23 
     24 // Returns an autoreleased NSEvent constructed from the given np_event,
     25 // targeting the given window.
     26 NSEvent* NSEventForNPCocoaEvent(NPCocoaEvent* np_event, NSWindow* window) {
     27   bool mouse_down = 1;
     28   switch (np_event->type) {
     29     case NPCocoaEventMouseDown:
     30       mouse_down = 1;
     31       break;
     32     case NPCocoaEventMouseUp:
     33       mouse_down = 0;
     34       break;
     35     default:
     36       // If plugins start bringing up context menus for things other than
     37       // clicks, this will need more plumbing; for now just log it and proceed
     38       // as if it were a mouse down.
     39       NOTREACHED();
     40   }
     41   NSEventType event_type = NSLeftMouseDown;
     42   switch (np_event->data.mouse.buttonNumber) {
     43     case 0:
     44       event_type = mouse_down ? NSLeftMouseDown : NSLeftMouseUp;
     45       break;
     46     case 1:
     47       event_type = mouse_down ? NSRightMouseDown : NSRightMouseUp;
     48       break;
     49     default:
     50       event_type = mouse_down ? NSOtherMouseDown : NSOtherMouseUp;
     51       break;
     52   }
     53 
     54   NSInteger click_count = np_event->data.mouse.clickCount;
     55   NSInteger modifiers = np_event->data.mouse.modifierFlags;
     56   // NPCocoaEvent doesn't have a timestamp, so just use the current time.
     57   NSEvent* event =
     58       [NSEvent mouseEventWithType:event_type
     59                          location:NSZeroPoint
     60                     modifierFlags:modifiers
     61                         timestamp:[[NSApp currentEvent] timestamp]
     62                      windowNumber:[window windowNumber]
     63                           context:[NSGraphicsContext currentContext]
     64                       eventNumber:0
     65                        clickCount:click_count
     66                          pressure:1.0];
     67   return event;
     68 }
     69 
     70 }  // namespace
     71 
     72 NPError PluginInstance::PopUpContextMenu(NPMenu* menu) {
     73   if (!currently_handled_event_)
     74     return NPERR_GENERIC_ERROR;
     75 
     76   CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID());
     77   NSPoint screen_point = NSMakePoint(
     78       plugin_origin_.x() + currently_handled_event_->data.mouse.pluginX,
     79       plugin_origin_.y() + currently_handled_event_->data.mouse.pluginY);
     80   // Plugin offsets are upper-left based, so flip vertically for Cocoa.
     81   screen_point.y = main_display_bounds.size.height - screen_point.y;
     82 
     83   NSMenu* nsmenu = reinterpret_cast<NSMenu*>(menu);
     84   NPError return_val = NPERR_NO_ERROR;
     85   @try {
     86     [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
     87   }
     88   @catch (NSException* e) {
     89     NSLog(@"Caught exception while handling PopUpContextMenu: %@", e);
     90     return_val = NPERR_GENERIC_ERROR;
     91   }
     92 
     93   return return_val;
     94 }
     95 
     96 ScopedCurrentPluginEvent::ScopedCurrentPluginEvent(PluginInstance* instance,
     97                                                    NPCocoaEvent* event)
     98     : instance_(instance) {
     99   instance_->set_currently_handled_event(event);
    100 }
    101 
    102 ScopedCurrentPluginEvent::~ScopedCurrentPluginEvent() {
    103   instance_->set_currently_handled_event(NULL);
    104 }
    105 
    106 }  // namespace content
    107