Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | // vim:set ts=2 sts=2 sw=2 et cin: |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "nsPluginUtilsOSX.h" |
michael@0 | 8 | |
michael@0 | 9 | #import <Cocoa/Cocoa.h> |
michael@0 | 10 | #import <QuartzCore/QuartzCore.h> |
michael@0 | 11 | #include "nsObjCExceptions.h" |
michael@0 | 12 | |
michael@0 | 13 | #ifndef __LP64__ |
michael@0 | 14 | void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect) |
michael@0 | 15 | { |
michael@0 | 16 | if (!aWindow) |
michael@0 | 17 | return; |
michael@0 | 18 | |
michael@0 | 19 | Rect windowRect; |
michael@0 | 20 | ::GetWindowBounds(aWindow, kWindowStructureRgn, &windowRect); |
michael@0 | 21 | outRect.x = windowRect.left; |
michael@0 | 22 | outRect.y = windowRect.top; |
michael@0 | 23 | outRect.width = windowRect.right - windowRect.left; |
michael@0 | 24 | outRect.height = windowRect.bottom - windowRect.top; |
michael@0 | 25 | } |
michael@0 | 26 | #endif |
michael@0 | 27 | |
michael@0 | 28 | void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect) |
michael@0 | 29 | { |
michael@0 | 30 | NS_OBJC_BEGIN_TRY_ABORT_BLOCK; |
michael@0 | 31 | |
michael@0 | 32 | if (!aWindow) |
michael@0 | 33 | return; |
michael@0 | 34 | |
michael@0 | 35 | NSWindow* window = (NSWindow*)aWindow; |
michael@0 | 36 | |
michael@0 | 37 | float menubarScreenHeight; |
michael@0 | 38 | NSArray* allScreens = [NSScreen screens]; |
michael@0 | 39 | if ([allScreens count]) |
michael@0 | 40 | menubarScreenHeight = [[allScreens objectAtIndex:0] frame].size.height; |
michael@0 | 41 | else |
michael@0 | 42 | return; // If there are no screens, there's not much we can say. |
michael@0 | 43 | |
michael@0 | 44 | NSRect frame = [window frame]; |
michael@0 | 45 | outRect.x = (nscoord)frame.origin.x; |
michael@0 | 46 | outRect.y = (nscoord)(menubarScreenHeight - (frame.origin.y + frame.size.height)); |
michael@0 | 47 | outRect.width = (nscoord)frame.size.width; |
michael@0 | 48 | outRect.height = (nscoord)frame.size.height; |
michael@0 | 49 | |
michael@0 | 50 | NS_OBJC_END_TRY_ABORT_BLOCK; |
michael@0 | 51 | } |
michael@0 | 52 | |
michael@0 | 53 | bool NS_NPAPI_CocoaWindowIsMain(void* aWindow) |
michael@0 | 54 | { |
michael@0 | 55 | NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; |
michael@0 | 56 | |
michael@0 | 57 | if (!aWindow) |
michael@0 | 58 | return true; |
michael@0 | 59 | |
michael@0 | 60 | NSWindow* window = (NSWindow*)aWindow; |
michael@0 | 61 | |
michael@0 | 62 | return (bool)[window isMainWindow]; |
michael@0 | 63 | |
michael@0 | 64 | NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(true); |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event) |
michael@0 | 68 | { |
michael@0 | 69 | NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; |
michael@0 | 70 | |
michael@0 | 71 | if (!menu || !widget || !event) |
michael@0 | 72 | return NPERR_GENERIC_ERROR; |
michael@0 | 73 | |
michael@0 | 74 | NSMenu* cocoaMenu = (NSMenu*)menu; |
michael@0 | 75 | NSView* cocoaView = (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET); |
michael@0 | 76 | |
michael@0 | 77 | NSEventType cocoaEventType = NSRightMouseDown; |
michael@0 | 78 | unsigned int cocoaModifierFlags = 0; |
michael@0 | 79 | double x = 0.0; // Coordinates for the context menu in plugin terms, top-left origin. |
michael@0 | 80 | double y = 0.0; |
michael@0 | 81 | |
michael@0 | 82 | NPCocoaEventType eventType = event->type; |
michael@0 | 83 | if (eventType == NPCocoaEventMouseDown || |
michael@0 | 84 | eventType == NPCocoaEventMouseUp || |
michael@0 | 85 | eventType == NPCocoaEventMouseMoved || |
michael@0 | 86 | eventType == NPCocoaEventMouseEntered || |
michael@0 | 87 | eventType == NPCocoaEventMouseExited || |
michael@0 | 88 | eventType == NPCocoaEventMouseDragged) { |
michael@0 | 89 | x = event->data.mouse.pluginX; |
michael@0 | 90 | y = event->data.mouse.pluginY; |
michael@0 | 91 | if ((x < 0.0) || (y < 0.0)) |
michael@0 | 92 | return NPERR_GENERIC_ERROR; |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | // Flip the coords to bottom-left origin. |
michael@0 | 96 | NSRect viewFrame = [cocoaView frame]; |
michael@0 | 97 | double shiftedX = x; |
michael@0 | 98 | double shiftedY = viewFrame.size.height - y; |
michael@0 | 99 | // Shift to window coords. |
michael@0 | 100 | shiftedX += viewFrame.origin.x; |
michael@0 | 101 | shiftedY += [cocoaView convertPoint:NSMakePoint(0,0) toView:nil].y - viewFrame.size.height; |
michael@0 | 102 | |
michael@0 | 103 | // Create an NSEvent we can use to show the context menu. Only the location |
michael@0 | 104 | // is important here so just simulate a right mouse down. The coordinates |
michael@0 | 105 | // must be in top-level window terms. |
michael@0 | 106 | NSEvent* cocoaEvent = [NSEvent mouseEventWithType:cocoaEventType |
michael@0 | 107 | location:NSMakePoint(shiftedX, shiftedY) |
michael@0 | 108 | modifierFlags:cocoaModifierFlags |
michael@0 | 109 | timestamp:0 |
michael@0 | 110 | windowNumber:[[cocoaView window] windowNumber] |
michael@0 | 111 | context:nil |
michael@0 | 112 | eventNumber:0 |
michael@0 | 113 | clickCount:1 |
michael@0 | 114 | pressure:0.0]; |
michael@0 | 115 | |
michael@0 | 116 | [NSMenu popUpContextMenu:cocoaMenu withEvent:cocoaEvent forView:cocoaView]; |
michael@0 | 117 | |
michael@0 | 118 | return NPERR_NO_ERROR; |
michael@0 | 119 | |
michael@0 | 120 | NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR); |
michael@0 | 121 | } |
michael@0 | 122 | |
michael@0 | 123 | NPBool NS_NPAPI_ConvertPointCocoa(void* inView, |
michael@0 | 124 | double sourceX, double sourceY, NPCoordinateSpace sourceSpace, |
michael@0 | 125 | double *destX, double *destY, NPCoordinateSpace destSpace) |
michael@0 | 126 | { |
michael@0 | 127 | // Plugins don't always have a view/frame. It would be odd to ask for a point conversion |
michael@0 | 128 | // without a view, so we'll warn about it, but it's technically OK. |
michael@0 | 129 | if (!inView) { |
michael@0 | 130 | NS_WARNING("Must have a native view to convert coordinates."); |
michael@0 | 131 | return false; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | // Caller has to want a result. |
michael@0 | 135 | if (!destX && !destY) |
michael@0 | 136 | return false; |
michael@0 | 137 | |
michael@0 | 138 | if (sourceSpace == destSpace) { |
michael@0 | 139 | if (destX) |
michael@0 | 140 | *destX = sourceX; |
michael@0 | 141 | if (destY) |
michael@0 | 142 | *destY = sourceY; |
michael@0 | 143 | return true; |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | NSView* view = (NSView*)inView; |
michael@0 | 147 | NSWindow* window = [view window]; |
michael@0 | 148 | NSPoint sourcePoint = NSMakePoint(sourceX, sourceY); |
michael@0 | 149 | |
michael@0 | 150 | // Convert to screen space. |
michael@0 | 151 | NSPoint screenPoint; |
michael@0 | 152 | switch (sourceSpace) { |
michael@0 | 153 | case NPCoordinateSpacePlugin: |
michael@0 | 154 | screenPoint = [view convertPoint:sourcePoint toView:nil]; |
michael@0 | 155 | screenPoint = [window convertBaseToScreen:screenPoint]; |
michael@0 | 156 | break; |
michael@0 | 157 | case NPCoordinateSpaceWindow: |
michael@0 | 158 | screenPoint = [window convertBaseToScreen:sourcePoint]; |
michael@0 | 159 | break; |
michael@0 | 160 | case NPCoordinateSpaceFlippedWindow: |
michael@0 | 161 | sourcePoint.y = [window frame].size.height - sourcePoint.y; |
michael@0 | 162 | screenPoint = [window convertBaseToScreen:sourcePoint]; |
michael@0 | 163 | break; |
michael@0 | 164 | case NPCoordinateSpaceScreen: |
michael@0 | 165 | screenPoint = sourcePoint; |
michael@0 | 166 | break; |
michael@0 | 167 | case NPCoordinateSpaceFlippedScreen: |
michael@0 | 168 | sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y; |
michael@0 | 169 | screenPoint = sourcePoint; |
michael@0 | 170 | break; |
michael@0 | 171 | default: |
michael@0 | 172 | return false; |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | // Convert from screen to dest space. |
michael@0 | 176 | NSPoint destPoint; |
michael@0 | 177 | switch (destSpace) { |
michael@0 | 178 | case NPCoordinateSpacePlugin: |
michael@0 | 179 | destPoint = [window convertScreenToBase:screenPoint]; |
michael@0 | 180 | destPoint = [view convertPoint:destPoint fromView:nil]; |
michael@0 | 181 | break; |
michael@0 | 182 | case NPCoordinateSpaceWindow: |
michael@0 | 183 | destPoint = [window convertScreenToBase:screenPoint]; |
michael@0 | 184 | break; |
michael@0 | 185 | case NPCoordinateSpaceFlippedWindow: |
michael@0 | 186 | destPoint = [window convertScreenToBase:screenPoint]; |
michael@0 | 187 | destPoint.y = [window frame].size.height - destPoint.y; |
michael@0 | 188 | break; |
michael@0 | 189 | case NPCoordinateSpaceScreen: |
michael@0 | 190 | destPoint = screenPoint; |
michael@0 | 191 | break; |
michael@0 | 192 | case NPCoordinateSpaceFlippedScreen: |
michael@0 | 193 | destPoint = screenPoint; |
michael@0 | 194 | destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y; |
michael@0 | 195 | break; |
michael@0 | 196 | default: |
michael@0 | 197 | return false; |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | if (destX) |
michael@0 | 201 | *destX = destPoint.x; |
michael@0 | 202 | if (destY) |
michael@0 | 203 | *destY = destPoint.y; |
michael@0 | 204 | |
michael@0 | 205 | return true; |
michael@0 | 206 | } |
michael@0 | 207 |