mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 485121. Support getting native geometry data from the test plugin on Mac and GTK2/X11. r=joshmoz,karl
--HG-- rename : layout/generic/test/test_character_movement.html => layout/generic/test/test_movement_by_characters.html rename : layout/generic/test/test_word_movement.html => layout/generic/test/test_movement_by_words.html
This commit is contained in:
parent
97ea54af4c
commit
3ff534b70e
@ -44,10 +44,18 @@ relativesrcdir = layout/generic/test
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = test_bug288789.html \
|
||||
# in the list below, we make sure that the tests that require focus
|
||||
# run before test_plugin_clipping, which can steal focus for its window.
|
||||
_TEST_FILES = \
|
||||
bug344830_testembed.svg \
|
||||
frame_selection_underline.xhtml \
|
||||
frame_selection_underline-ref.xhtml \
|
||||
frame_selection_underline.css \
|
||||
plugin_clipping_helper.xhtml \
|
||||
test_backspace_delete.xul \
|
||||
test_bug288789.html \
|
||||
test_bug323656.html \
|
||||
test_bug344830.html \
|
||||
bug344830_testembed.svg \
|
||||
test_bug382429.html \
|
||||
test_bug384527.html \
|
||||
test_bug385751.html \
|
||||
@ -67,13 +75,11 @@ _TEST_FILES = test_bug288789.html \
|
||||
test_bug468167.html \
|
||||
test_bug469613.xul \
|
||||
test_bug470212.html \
|
||||
test_character_movement.html \
|
||||
test_word_movement.html \
|
||||
test_backspace_delete.xul \
|
||||
test_movement_by_characters.html \
|
||||
test_movement_by_words.html \
|
||||
test_plugin_clipping.xhtml \
|
||||
test_plugin_position.xhtml \
|
||||
test_selection_underline.html \
|
||||
frame_selection_underline.xhtml \
|
||||
frame_selection_underline-ref.xhtml \
|
||||
frame_selection_underline.css \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
223
layout/generic/test/plugin_clipping_helper.xhtml
Normal file
223
layout/generic/test/plugin_clipping_helper.xhtml
Normal file
@ -0,0 +1,223 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" title="Test Plugin Clipping">
|
||||
<head>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<style>
|
||||
embed { width:200px; height:200px; display:block; }
|
||||
iframe { border:none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Use a XUL element here so we can get its boxObject.screenX/Y -->
|
||||
<hbox style="height:10px; position:absolute; left:0; top:0; z-index:-100;" id="h1"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox style="width:100px;"></hbox><hbox id="h2"/>
|
||||
</hbox>
|
||||
|
||||
<!-- Non-clipped plugin -->
|
||||
<embed id="p1" type="application/x-test" wmode="window"
|
||||
style="position:absolute; left:300px; top:0"></embed>
|
||||
<!-- Clipped to the top and left by the viewport -->
|
||||
<embed id="p2" type="application/x-test" wmode="window"
|
||||
style="position:absolute; left:-100px; top:-100px;"></embed>
|
||||
<!-- Clipped by a scrollable DIV -->
|
||||
<div style="overflow:auto; width:200px; height:200px;
|
||||
position:absolute; left:100px; top:0;">
|
||||
<div style="position:relative; left:-100px; top:-100px;">
|
||||
<embed id="p3" type="application/x-test" wmode="window"></embed>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Clipped by a scrollable DIV *and* to the viewport -->
|
||||
<div style="overflow:auto; width:200px; height:200px; position:absolute; top:100px; left:-100px;">
|
||||
<div style="position:relative; top:-100px;">
|
||||
<embed id="p4" type="application/x-test" wmode="window"></embed>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Clipped by an iframe -->
|
||||
<iframe id="f1" style="position:absolute; left:200px; top:200px; width:200px; height:200px;"></iframe>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
var windowFrameX, windowFrameY;
|
||||
|
||||
var f1 = document.getElementById("f1");
|
||||
f1.src = "data:text/html," +
|
||||
"<embed style='position:absolute; left:-100px; top:-100px; width:200px; height:200px;'" +
|
||||
"id='p5' type='application/x-test' wmode='window'></embed>";
|
||||
|
||||
// Import test API
|
||||
var is = window.opener.is;
|
||||
var ok = window.opener.ok;
|
||||
var todo = window.opener.todo;
|
||||
var SimpleTest = window.opener.SimpleTest;
|
||||
|
||||
function dumpRegion(rects) {
|
||||
var s = [];
|
||||
for (var i = 0; i < rects.length; ++i) {
|
||||
var r = rects[i];
|
||||
s.push("{" + r.join(",") + "}");
|
||||
}
|
||||
return s.join(", ");
|
||||
}
|
||||
|
||||
function generateSpan(coords) {
|
||||
coords.sort(function(a,b) { return a - b; });
|
||||
var result = [coords[0]];
|
||||
for (var i = 1; i < coords.length; ++i) {
|
||||
if (coords[i] != coords[i - 1]) {
|
||||
result.push(coords[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function containsRect(r1, r2) {
|
||||
return r1[0] <= r2[0] && r1[2] >= r2[2] &&
|
||||
r1[1] <= r2[1] && r1[3] >= r2[3];
|
||||
}
|
||||
|
||||
function subtractRect(r1, r2, rlist) {
|
||||
var spanX = generateSpan([r1[0], r1[2], r2[0], r2[2]]);
|
||||
var spanY = generateSpan([r1[1], r1[3], r2[1], r2[3]]);
|
||||
for (var i = 1; i < spanX.length; ++i) {
|
||||
for (var j = 1; j < spanY.length; ++j) {
|
||||
var subrect = [spanX[i - 1], spanY[j - 1], spanX[i], spanY[j]];
|
||||
if (containsRect(r1, subrect) && !containsRect(r2, subrect)) {
|
||||
rlist.push(subrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function regionContainsRect(rs, r) {
|
||||
var rectList = [r];
|
||||
for (var i = 0; i < rs.length; ++i) {
|
||||
var newList = [];
|
||||
for (var j = 0; j < rectList.length; ++j) {
|
||||
subtractRect(rs[i], rectList[j], newList);
|
||||
}
|
||||
if (newList.length == 0)
|
||||
return true;
|
||||
rectList = newList;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function regionContains(r1s, r2s) {
|
||||
for (var i = 0; i < r2s.length; ++i) {
|
||||
if (!regionContainsRect(r1s, r2s[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function equalRegions(r1s, r2s) {
|
||||
return regionContains(r1s, r2s) && regionContains(r2s, r1s);
|
||||
}
|
||||
|
||||
// Checks that a plugin's clip region equals the specified rectangle list.
|
||||
// The rectangles are given relative to the plugin's top-left. They are in
|
||||
// [left, top, right, bottom] format.
|
||||
function checkClipRegionWithDoc(doc, offsetX, offsetY, id, rects) {
|
||||
var p = doc.getElementById(id);
|
||||
var pX = p.getEdge(0);
|
||||
var pY = p.getEdge(1);
|
||||
var pWidth = p.getEdge(2) - pX;
|
||||
var pHeight = p.getEdge(3) - pY;
|
||||
var bounds = p.getBoundingClientRect();
|
||||
|
||||
// First, check regular area
|
||||
is(pX, windowFrameX + bounds.left + offsetX, id + " plugin X");
|
||||
is(pY, windowFrameY + bounds.top + offsetY, id + " plugin Y");
|
||||
is(pWidth, bounds.width, id + " plugin width");
|
||||
is(pHeight, bounds.height, id + " plugin height");
|
||||
|
||||
// Now check clip region. 'rects' is relative to the plugin's top-left.
|
||||
var clipRects = [];
|
||||
var n = p.getClipRegionRectCount();
|
||||
for (var i = 0; i < n; ++i) {
|
||||
// Convert the clip rect to be relative to the plugin's top-left.
|
||||
clipRects[i] = [
|
||||
p.getClipRegionRectEdge(i, 0) - pX,
|
||||
p.getClipRegionRectEdge(i, 1) - pY,
|
||||
p.getClipRegionRectEdge(i, 2) - pX,
|
||||
p.getClipRegionRectEdge(i, 3) - pY
|
||||
];
|
||||
}
|
||||
|
||||
ok(equalRegions(clipRects, rects), "Matching regions: expected " +
|
||||
dumpRegion(rects) + ", got " + dumpRegion(clipRects));
|
||||
}
|
||||
|
||||
function checkClipRegion(id, rects) {
|
||||
checkClipRegionWithDoc(document, 0, 0, id, rects);
|
||||
}
|
||||
|
||||
function checkClipRegionForFrame(fid, id, rects) {
|
||||
var f = document.getElementById(fid);
|
||||
var bounds = f.getBoundingClientRect();
|
||||
checkClipRegionWithDoc(f.contentDocument, bounds.left, bounds.top, id, rects);
|
||||
}
|
||||
|
||||
function runTests2() {
|
||||
var p = document.getElementById("p1");
|
||||
if (p.getClipRegionRectEdge(0, 0) == p.getClipRegionRectEdge(0, 2)) {
|
||||
// plugin hasn't been updated yet. wait.
|
||||
setTimeout(runTests2, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
checkClipRegion("p1", [[0, 0, 200, 200]]);
|
||||
checkClipRegion("p2", [[100, 100, 200, 200]]);
|
||||
checkClipRegion("p3", [[100, 100, 200, 200]]);
|
||||
checkClipRegion("p4", [[100, 100, 200, 200]]);
|
||||
checkClipRegionForFrame("f1", "p5", [[100, 100, 200, 200]]);
|
||||
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var h1 = document.getElementById("h1");
|
||||
var h2 = document.getElementById("h2");
|
||||
var hwidth = h2.boxObject.screenX - h1.boxObject.screenX;
|
||||
if (hwidth != 100) {
|
||||
// Maybe it's a DPI issue
|
||||
todo(false, "Unexpected DPI?");
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!document.getElementById("p1").identifierToStringTest) {
|
||||
todo(false, "Test plugin not available");
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
todo(false, "Windows does not support windowed plugins (yet)");
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = h1.getBoundingClientRect();
|
||||
windowFrameX = h1.boxObject.screenX - bounds.left - window.screenX;
|
||||
windowFrameY = h1.boxObject.screenY - bounds.top - window.screenY;
|
||||
|
||||
runTests2();
|
||||
}
|
||||
|
||||
window.addEventListener("load", runTests, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
24
layout/generic/test/test_plugin_clipping.xhtml
Normal file
24
layout/generic/test/test_plugin_clipping.xhtml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" title="Test Plugin Clipping">
|
||||
<head>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function runTests() {
|
||||
window.open("plugin_clipping_helper.xhtml", "", "width=620,height=320");
|
||||
}
|
||||
|
||||
addLoadEvent(runTests);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
75
layout/generic/test/test_plugin_position.xhtml
Normal file
75
layout/generic/test/test_plugin_position.xhtml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" title="Test Plugin Positioning">
|
||||
<head>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Use a XUL element here so we can get its boxObject.screenX/Y -->
|
||||
<hbox style="height:10px; position:absolute; left:0; top:0; z-index:-100;" id="h1"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox style="width:100px;"></hbox><hbox id="h2"/>
|
||||
</hbox>
|
||||
|
||||
<embed id="p" type="application/x-test" width="200" height="200" wmode="window"></embed>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
var windowFrameX, windowFrameY;
|
||||
|
||||
function checkGeometry(id) {
|
||||
var p = document.getElementById(id);
|
||||
var pX = p.getEdge(0);
|
||||
var pY = p.getEdge(1);
|
||||
var pWidth = p.getEdge(2) - pX;
|
||||
var pHeight = p.getEdge(3) - pY;
|
||||
var bounds = p.getBoundingClientRect();
|
||||
|
||||
is(pX, windowFrameX + bounds.left, id + " plugin X");
|
||||
is(pY, windowFrameY + bounds.top, id + " plugin Y");
|
||||
is(pWidth, bounds.width, id + " plugin width");
|
||||
is(pHeight, bounds.height, id + " plugin height");
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var h1 = document.getElementById("h1");
|
||||
var h2 = document.getElementById("h2");
|
||||
var hwidth = h2.boxObject.screenX - h1.boxObject.screenX;
|
||||
if (hwidth != 100) {
|
||||
// Maybe it's a DPI issue
|
||||
todo(false, "Unexpected DPI?");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!document.getElementById("p").identifierToStringTest) {
|
||||
todo(false, "Test plugin not available");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
todo(false, "Windows does not support windowed plugins (yet)");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = h1.getBoundingClientRect();
|
||||
windowFrameX = h1.boxObject.screenX - bounds.left - window.screenX;
|
||||
windowFrameY = h1.boxObject.screenY - bounds.top - window.screenY;
|
||||
|
||||
checkGeometry("p");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addLoadEvent(runTests);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -52,3 +52,46 @@ The test plugin object supports the following scriptable method:
|
||||
* hasWidget()
|
||||
Returns true if the plugin has an associated widget. This will return true if
|
||||
wmode="window" was specified and the platform supports windowed plugins.
|
||||
|
||||
== Plugin geometry ==
|
||||
|
||||
The test plugin supports the following scriptable methods:
|
||||
|
||||
* getEdge(edge)
|
||||
Returns the integer screen pixel coordinate of an edge of the plugin's
|
||||
area:
|
||||
-- edge=0: returns left edge coordinate
|
||||
-- edge=1: returns top edge coordinate
|
||||
-- edge=2: returns right edge coordinate
|
||||
-- edge=3: returns bottom edge coordinate
|
||||
The coordinates are relative to the top-left corner of the top-level window
|
||||
containing the plugin, including the window decorations. Therefore:
|
||||
-- On Mac, they're relative to the top-left corner of the toplevel Cocoa
|
||||
window.
|
||||
-- On Windows, they're relative to the top-left corner of the toplevel HWND's
|
||||
non-client area.
|
||||
-- On GTK2, they're relative to the top-left corner of the toplevel window's
|
||||
window manager frame.
|
||||
This means they can be added to Gecko's window.screenX/screenY (if DPI is set
|
||||
to 96) to get screen coordinates.
|
||||
On the platforms that support window-mode plugins (Windows/GTK2), this only
|
||||
works for window-mode plugins. It will throw an error for windowless plugins.
|
||||
|
||||
* getClipRegionRectCount()
|
||||
Returns the number of rectangles in the plugin's clip region.
|
||||
For plugins with widgets, the clip region is computed as the intersection of the
|
||||
clip region for the widget (if the platform does not support clip regions
|
||||
on native widgets, this would just be the widget's rectangle) with the
|
||||
clip regions of all ancestor widgets which would clip this widget.
|
||||
On the platforms that support window-mode plugins (Windows/GTK2), this only
|
||||
works for window-mode plugins. It will throw an error for windowless plugins.
|
||||
On Mac, all plugins have a clip region containing just a single clip
|
||||
rectangle only. So if you request wmode="window" but the plugin reports
|
||||
!hasWidget, you can assume that complex clip regions are not supported.
|
||||
|
||||
* getClipRegionRectEdge(i, edge)
|
||||
Returns the integer screen pixel coordinate of an edge of a rectangle from the
|
||||
plugin's clip region. If i is less than zero or greater than or equal to
|
||||
getClipRegionRectCount(), this will throw an error. The coordinates are
|
||||
the same as for getEdge. See getClipRegionRectCount() above for
|
||||
notes on platform plugin limitations.
|
||||
|
@ -44,6 +44,8 @@
|
||||
#define PLUGIN_DESCRIPTION "Plug-in for testing purposes."
|
||||
#define PLUGIN_VERSION "1.0.0.0"
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
//
|
||||
// static data
|
||||
//
|
||||
@ -55,12 +57,6 @@ static NPClass sNPClass;
|
||||
// identifiers
|
||||
//
|
||||
|
||||
#define IDENTIFIER_TO_STRING_TEST_METHOD 0
|
||||
#define QUERY_PRIVATE_MODE_STATE_METHOD 1
|
||||
#define LAST_REPORTED_PRIVATE_MODE_STATE_METHOD 2
|
||||
#define HAS_WIDGET_METHOD 3
|
||||
#define NUM_METHOD_IDENTIFIERS 4
|
||||
|
||||
typedef bool (* ScriptableFunction)
|
||||
(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
|
||||
@ -68,19 +64,28 @@ static bool identifierToStringTest(NPObject* npobj, const NPVariant* args, uint3
|
||||
static bool queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
|
||||
static NPIdentifier sPluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
|
||||
static const NPUTF8* sPluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
|
||||
static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||
"identifierToStringTest",
|
||||
"queryPrivateModeState",
|
||||
"lastReportedPrivateModeState",
|
||||
"hasWidget",
|
||||
"getEdge",
|
||||
"getClipRegionRectCount",
|
||||
"getClipRegionRectEdge",
|
||||
};
|
||||
static const ScriptableFunction sPluginMethodFunctions[NUM_METHOD_IDENTIFIERS] = {
|
||||
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
|
||||
static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = {
|
||||
identifierToStringTest,
|
||||
queryPrivateModeState,
|
||||
lastReportedPrivateModeState,
|
||||
hasWidget,
|
||||
getEdge,
|
||||
getClipRegionRectCount,
|
||||
getClipRegionRectEdge,
|
||||
};
|
||||
|
||||
static bool sIdentifiersInitialized = false;
|
||||
@ -88,14 +93,16 @@ static bool sIdentifiersInitialized = false;
|
||||
static void initializeIdentifiers()
|
||||
{
|
||||
if (!sIdentifiersInitialized) {
|
||||
NPN_GetStringIdentifiers(sPluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, sPluginMethodIdentifiers);
|
||||
NPN_GetStringIdentifiers(sPluginMethodIdentifierNames,
|
||||
ARRAY_LENGTH(sPluginMethodIdentifierNames), sPluginMethodIdentifiers);
|
||||
sIdentifiersInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void clearIdentifiers()
|
||||
{
|
||||
memset(sPluginMethodIdentifierNames, 0, NUM_METHOD_IDENTIFIERS * sizeof(NPIdentifier));
|
||||
memset(sPluginMethodIdentifiers, 0,
|
||||
ARRAY_LENGTH(sPluginMethodIdentifiers) * sizeof(NPIdentifier));
|
||||
sIdentifiersInitialized = false;
|
||||
}
|
||||
|
||||
@ -325,7 +332,7 @@ NPP_SetWindow(NPP instance, NPWindow* window)
|
||||
{
|
||||
InstanceData* instanceData = (InstanceData*)(instance->pdata);
|
||||
void* oldWindow = instanceData->window.window;
|
||||
instanceData->window = *window;
|
||||
pluginDoSetWindow(instanceData, window);
|
||||
if (instanceData->hasWidget && oldWindow != instanceData->window.window) {
|
||||
pluginWidgetInit(instanceData, oldWindow);
|
||||
}
|
||||
@ -403,7 +410,7 @@ NPP_SetValue(NPP instance, NPNVariable variable, void* value)
|
||||
{
|
||||
if (variable == NPNVprivateModeBool) {
|
||||
InstanceData* instanceData = (InstanceData*)(instance->pdata);
|
||||
instanceData->lastReportedPrivateModeState = *static_cast<NPBool*>(value);
|
||||
instanceData->lastReportedPrivateModeState = bool(*static_cast<NPBool*>(value));
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
return NPERR_GENERIC_ERROR;
|
||||
@ -531,7 +538,7 @@ scriptableInvalidate(NPObject* npobj)
|
||||
bool
|
||||
scriptableHasMethod(NPObject* npobj, NPIdentifier name)
|
||||
{
|
||||
for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) {
|
||||
if (name == sPluginMethodIdentifiers[i])
|
||||
return true;
|
||||
}
|
||||
@ -541,7 +548,7 @@ scriptableHasMethod(NPObject* npobj, NPIdentifier name)
|
||||
bool
|
||||
scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) {
|
||||
if (name == sPluginMethodIdentifiers[i])
|
||||
return sPluginMethodFunctions[i](npobj, args, argCount, result);
|
||||
}
|
||||
@ -602,6 +609,7 @@ identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount
|
||||
NPIdentifier identifier = variantToIdentifier(args[0]);
|
||||
if (!identifier)
|
||||
return false;
|
||||
|
||||
NPUTF8* utf8String = NPN_UTF8FromIdentifier(identifier);
|
||||
if (!utf8String)
|
||||
return false;
|
||||
@ -612,6 +620,9 @@ identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount
|
||||
static bool
|
||||
queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 0)
|
||||
return false;
|
||||
|
||||
NPBool pms = false;
|
||||
NPN_GetValue(static_cast<TestNPObject*>(npobj)->npp, NPNVprivateModeBool, &pms);
|
||||
BOOLEAN_TO_NPVARIANT(pms, *result);
|
||||
@ -621,6 +632,9 @@ queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||
static bool
|
||||
lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 0)
|
||||
return false;
|
||||
|
||||
InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
|
||||
BOOLEAN_TO_NPVARIANT(id->lastReportedPrivateModeState, *result);
|
||||
return true;
|
||||
@ -629,7 +643,67 @@ lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t ar
|
||||
static bool
|
||||
hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 0)
|
||||
return false;
|
||||
|
||||
InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
|
||||
BOOLEAN_TO_NPVARIANT(id->hasWidget, *result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 1)
|
||||
return false;
|
||||
if (!NPVARIANT_IS_INT32(args[0]))
|
||||
return false;
|
||||
int32_t edge = NPVARIANT_TO_INT32(args[0]);
|
||||
if (edge < EDGE_LEFT || edge > EDGE_BOTTOM)
|
||||
return false;
|
||||
|
||||
InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
|
||||
int32_t r = pluginGetEdge(id, RectEdge(edge));
|
||||
if (r == NPTEST_INT32_ERROR)
|
||||
return false;
|
||||
INT32_TO_NPVARIANT(r, *result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 0)
|
||||
return false;
|
||||
|
||||
InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
|
||||
int32_t r = pluginGetClipRegionRectCount(id);
|
||||
if (r == NPTEST_INT32_ERROR)
|
||||
return false;
|
||||
INT32_TO_NPVARIANT(r, *result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
|
||||
{
|
||||
if (argCount != 2)
|
||||
return false;
|
||||
if (!NPVARIANT_IS_INT32(args[0]))
|
||||
return false;
|
||||
int32_t rectIndex = NPVARIANT_TO_INT32(args[0]);
|
||||
if (rectIndex < 0)
|
||||
return false;
|
||||
if (!NPVARIANT_IS_INT32(args[1]))
|
||||
return false;
|
||||
int32_t edge = NPVARIANT_TO_INT32(args[1]);
|
||||
if (edge < EDGE_LEFT || edge > EDGE_BOTTOM)
|
||||
return false;
|
||||
|
||||
InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
|
||||
int32_t r = pluginGetClipRegionRectEdge(id, rectIndex, RectEdge(edge));
|
||||
if (r == NPTEST_INT32_ERROR)
|
||||
return false;
|
||||
INT32_TO_NPVARIANT(r, *result);
|
||||
return true;
|
||||
}
|
||||
|
@ -40,6 +40,14 @@
|
||||
#endif
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* XXX In various places in this file we use GDK APIs to inspect the
|
||||
* window ancestors of the plugin. These APIs will not work properly if
|
||||
* this plugin is used in a browser that does not use GDK for all its
|
||||
* widgets. They would also fail for out-of-process plugins. These should
|
||||
* be fixed to use raw X APIs instead.
|
||||
*/
|
||||
|
||||
bool
|
||||
pluginSupportsWindowMode()
|
||||
{
|
||||
@ -124,6 +132,8 @@ pluginDrawWindow(InstanceData* instanceData, GdkDrawable* gdkWindow)
|
||||
return;
|
||||
|
||||
GdkGC* gdkContext = gdk_gc_new(gdkWindow);
|
||||
if (!gdkContext)
|
||||
return;
|
||||
|
||||
// draw a grey background for the plugin frame
|
||||
GdkColor grey;
|
||||
@ -159,6 +169,12 @@ ExposeWidget(GtkWidget* widget, GdkEventExpose* event,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
instanceData->window = *newWindow;
|
||||
}
|
||||
|
||||
void
|
||||
pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
|
||||
{
|
||||
@ -208,3 +224,105 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
|
||||
{
|
||||
if (!instanceData->hasWidget)
|
||||
return NPTEST_INT32_ERROR;
|
||||
GtkWidget* plug = static_cast<GtkWidget*>(instanceData->platformData);
|
||||
if (!plug)
|
||||
return NPTEST_INT32_ERROR;
|
||||
GdkWindow* plugWnd = plug->window;
|
||||
if (!plugWnd)
|
||||
return NPTEST_INT32_ERROR;
|
||||
// XXX This only works because Gecko uses GdkWindows everywhere!
|
||||
GdkWindow* toplevelWnd = gdk_window_get_toplevel(plugWnd);
|
||||
if (!toplevelWnd)
|
||||
return NPTEST_INT32_ERROR;
|
||||
|
||||
gint plugScreenX, plugScreenY;
|
||||
gdk_window_get_origin(plugWnd, &plugScreenX, &plugScreenY);
|
||||
gint toplevelFrameX, toplevelFrameY;
|
||||
gdk_window_get_root_origin(toplevelWnd, &toplevelFrameX, &toplevelFrameY);
|
||||
gint width, height;
|
||||
gdk_drawable_get_size(GDK_DRAWABLE(plugWnd), &width, &height);
|
||||
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return plugScreenX - toplevelFrameX;
|
||||
case EDGE_TOP:
|
||||
return plugScreenY - toplevelFrameY;
|
||||
case EDGE_RIGHT:
|
||||
return plugScreenX + width - toplevelFrameX;
|
||||
case EDGE_BOTTOM:
|
||||
return plugScreenY + height - toplevelFrameY;
|
||||
}
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
|
||||
{
|
||||
if (!instanceData->hasWidget)
|
||||
return NPTEST_INT32_ERROR;
|
||||
// XXX later we'll want to support XShape and be able to return a
|
||||
// complex region here
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge)
|
||||
{
|
||||
if (!instanceData->hasWidget)
|
||||
return NPTEST_INT32_ERROR;
|
||||
|
||||
GtkWidget* plug = static_cast<GtkWidget*>(instanceData->platformData);
|
||||
if (!plug)
|
||||
return NPTEST_INT32_ERROR;
|
||||
GdkWindow* plugWnd = plug->window;
|
||||
if (!plugWnd)
|
||||
return NPTEST_INT32_ERROR;
|
||||
// XXX This only works because Gecko uses GdkWindows everywhere!
|
||||
GdkWindow* toplevelWnd = gdk_window_get_toplevel(plugWnd);
|
||||
if (!toplevelWnd)
|
||||
return NPTEST_INT32_ERROR;
|
||||
|
||||
gint width, height;
|
||||
gdk_drawable_get_size(GDK_DRAWABLE(plugWnd), &width, &height);
|
||||
|
||||
GdkRectangle rect = { 0, 0, width, height };
|
||||
GdkWindow* wnd = plugWnd;
|
||||
while (wnd != toplevelWnd) {
|
||||
gint x, y;
|
||||
gdk_window_get_position(wnd, &x, &y);
|
||||
rect.x += x;
|
||||
rect.y += y;
|
||||
|
||||
// XXX This only works because Gecko uses GdkWindows everywhere!
|
||||
GdkWindow* parent = gdk_window_get_parent(wnd);
|
||||
gint parentWidth, parentHeight;
|
||||
gdk_drawable_get_size(GDK_DRAWABLE(parent), &parentWidth, &parentHeight);
|
||||
GdkRectangle parentRect = { 0, 0, parentWidth, parentHeight };
|
||||
gdk_rectangle_intersect(&rect, &parentRect, &rect);
|
||||
wnd = parent;
|
||||
}
|
||||
|
||||
gint toplevelFrameX, toplevelFrameY;
|
||||
gdk_window_get_root_origin(toplevelWnd, &toplevelFrameX, &toplevelFrameY);
|
||||
gint toplevelOriginX, toplevelOriginY;
|
||||
gdk_window_get_origin(toplevelWnd, &toplevelOriginX, &toplevelOriginY);
|
||||
|
||||
rect.x += toplevelOriginX - toplevelFrameX;
|
||||
rect.y += toplevelOriginY - toplevelFrameY;
|
||||
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return rect.x;
|
||||
case EDGE_TOP:
|
||||
return rect.y;
|
||||
case EDGE_RIGHT:
|
||||
return rect.x + rect.width;
|
||||
case EDGE_BOTTOM:
|
||||
return rect.y + rect.height;
|
||||
}
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
@ -66,6 +66,30 @@ pluginInstanceShutdown(InstanceData* instanceData)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
RectEquals(const NPRect& r1, const NPRect& r2)
|
||||
{
|
||||
return r1.left == r2.left && r1.top == r2.top &&
|
||||
r1.right == r2.right && r1.bottom == r2.bottom;
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
// Ugh. Due to a terrible Gecko bug, we have to ignore position changes
|
||||
// when the clip rect doesn't change; the position can be wrong
|
||||
// when set by a path other than nsObjectFrame::FixUpPluginWindow.
|
||||
int32_t oldX = instanceData->window.x;
|
||||
int32_t oldY = instanceData->window.y;
|
||||
bool clipChanged =
|
||||
!RectEquals(instanceData->window.clipRect, newWindow->clipRect);
|
||||
instanceData->window = *newWindow;
|
||||
if (!clipChanged) {
|
||||
instanceData->window.x = oldX;
|
||||
instanceData->window.y = oldY;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
|
||||
{
|
||||
@ -219,3 +243,48 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
|
||||
{
|
||||
NPWindow* w = &instanceData->window;
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return w->x;
|
||||
case EDGE_TOP:
|
||||
return w->y;
|
||||
case EDGE_RIGHT:
|
||||
return w->x + w->width;
|
||||
case EDGE_BOTTOM:
|
||||
return w->y + w->height;
|
||||
}
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge)
|
||||
{
|
||||
if (rectIndex != 0)
|
||||
return NPTEST_INT32_ERROR;
|
||||
|
||||
// We have to add the Cocoa titlebar height here since the clip rect
|
||||
// is being returned relative to that
|
||||
static const int COCOA_TITLEBAR_HEIGHT = 22;
|
||||
|
||||
NPWindow* w = &instanceData->window;
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return w->clipRect.left;
|
||||
case EDGE_TOP:
|
||||
return w->clipRect.top + COCOA_TITLEBAR_HEIGHT;
|
||||
case EDGE_RIGHT:
|
||||
return w->clipRect.right;
|
||||
case EDGE_BOTTOM:
|
||||
return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT;
|
||||
}
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
@ -59,6 +59,11 @@ NPError pluginInstanceInit(InstanceData* instanceData);
|
||||
*/
|
||||
void pluginInstanceShutdown(InstanceData* instanceData);
|
||||
|
||||
/**
|
||||
* Set the instanceData's window to newWindow.
|
||||
*/
|
||||
void pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow);
|
||||
|
||||
/**
|
||||
* Initialize the window for a windowed plugin. oldWindow is the old
|
||||
* native window value. This will never be called for windowless plugins.
|
||||
@ -71,4 +76,41 @@ void pluginWidgetInit(InstanceData* instanceData, void* oldWindow);
|
||||
*/
|
||||
int16_t pluginHandleEvent(InstanceData* instanceData, void* event);
|
||||
|
||||
enum RectEdge {
|
||||
EDGE_LEFT = 0,
|
||||
EDGE_TOP = 1,
|
||||
EDGE_RIGHT = 2,
|
||||
EDGE_BOTTOM = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
NPTEST_INT32_ERROR = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the coordinate of the given edge of the plugin's area, relative
|
||||
* to the top-left corner of the toplevel window containing the plugin,
|
||||
* including window decorations. Only works for window-mode plugins
|
||||
* and Mac plugins.
|
||||
* Returns NPTEST_ERROR on error.
|
||||
*/
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge);
|
||||
|
||||
/**
|
||||
* Return the number of rectangles in the plugin's clip region. Only
|
||||
* works for window-mode plugins and Mac plugins.
|
||||
* Returns NPTEST_ERROR on error.
|
||||
*/
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData);
|
||||
|
||||
/**
|
||||
* Return the coordinate of the given edge of a rectangle in the plugin's
|
||||
* clip region, relative to the top-left corner of the toplevel window
|
||||
* containing the plugin, including window decorations. Only works for
|
||||
* window-mode plugins and Mac plugins.
|
||||
* Returns NPTEST_ERROR on error.
|
||||
*/
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge);
|
||||
|
||||
#endif // nptest_platform_h_
|
||||
|
@ -64,6 +64,12 @@ pluginInstanceShutdown(InstanceData* instanceData)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
instanceData->window = *newWindow;
|
||||
}
|
||||
|
||||
void
|
||||
pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
|
||||
{
|
||||
@ -186,3 +192,22 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user