Implement css3 syntax for url() values of cursor with optional hotspot coordinates. b=286303 r=biesi sr=bzbarsky a=asa

This commit is contained in:
dbaron%dbaron.org 2005-07-01 04:29:42 +00:00
parent e7d4b17335
commit 22c8c10292
22 changed files with 257 additions and 135 deletions

View File

@ -53,9 +53,11 @@ class imgIContainer;
/*
* Event state manager interface.
*/
// {5D47ACA5-B50B-479b-A1C6-2A90C0B8095F}
// 2270e188-6743-441e-b6e1-af83f1047a53
#define NS_IEVENTSTATEMANAGER_IID \
{ 0x5d47aca5, 0xb50b, 0x479b, { 0xa1, 0xc6, 0x2a, 0x90, 0xc0, 0xb8, 0x9, 0x5f } };
{ 0x2270e188, 0x6743, 0x441e, \
{ 0xb6, 0xe1, 0xaf, 0x83, 0xf1, 0x04, 0x7a, 0x53 } }
#define NS_EVENT_NEEDS_FRAME(event) (!NS_IS_FOCUS_EVENT(event))
@ -126,7 +128,9 @@ public:
NS_IMETHOD RegisterAccessKey(nsIContent* aContent, PRUint32 aKey) = 0;
NS_IMETHOD UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey) = 0;
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer, nsIWidget* aWidget, PRBool aLockCursor) = 0;
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor) = 0;
//Method for centralized distribution of new DOM events
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool* aDefaultActionEnabled) = 0;

View File

@ -122,6 +122,8 @@
#include "nsContentUtils.h"
#include "imgIContainer.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#if defined (XP_MAC) || defined(XP_MACOSX)
#include <Events.h>
@ -2312,6 +2314,8 @@ nsEventStateManager::UpdateCursor(nsPresContext* aPresContext,
{
PRInt32 cursor = NS_STYLE_CURSOR_DEFAULT;
imgIContainer* container = nsnull;
PRBool haveHotspot = PR_FALSE;
float hotspotX = 0.0f, hotspotY = 0.0f;
//If cursor is locked just use the locked one
if (mLockCursor) {
@ -2324,6 +2328,9 @@ nsEventStateManager::UpdateCursor(nsPresContext* aPresContext,
return; // don't update the cursor if we failed to get it from the frame see bug 118877
cursor = framecursor.mCursor;
container = framecursor.mContainer;
haveHotspot = framecursor.mHaveHotspot;
hotspotX = framecursor.mHotspotX;
hotspotY = framecursor.mHotspotY;
}
// Check whether or not to show the busy cursor
@ -2343,7 +2350,8 @@ nsEventStateManager::UpdateCursor(nsPresContext* aPresContext,
}
if (aTargetFrame) {
SetCursor(cursor, container, aTargetFrame->GetWindow(), PR_FALSE);
SetCursor(cursor, container, haveHotspot, hotspotX, hotspotY,
aTargetFrame->GetWindow(), PR_FALSE);
}
if (mLockCursor || NS_STYLE_CURSOR_AUTO != cursor) {
@ -2353,6 +2361,8 @@ nsEventStateManager::UpdateCursor(nsPresContext* aPresContext,
NS_IMETHODIMP
nsEventStateManager::SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
PRBool aHaveHotspot,
float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor)
{
nsCursor c;
@ -2476,8 +2486,37 @@ nsEventStateManager::SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
// First, try the imgIContainer, if non-null
nsresult rv = NS_ERROR_FAILURE;
if (aContainer)
rv = aWidget->SetCursor(aContainer);
if (aContainer) {
PRUint32 hotspotX, hotspotY;
// css3-ui says to use the CSS-specified hotspot if present,
// otherwise use the intrinsic hotspot, otherwise use the top left
// corner.
if (aHaveHotspot) {
// XXX NSToUintRound?
hotspotX = aHotspotX > 0.0f
? PRUint32(aHotspotX + ROUND_CONST_FLOAT) : PRUint32(0);
hotspotY = aHotspotY > 0.0f
? PRUint32(aHotspotY + ROUND_CONST_FLOAT) : PRUint32(0);
} else {
hotspotX = 0;
hotspotY = 0;
nsCOMPtr<nsIProperties> props(do_QueryInterface(aContainer));
if (props) {
nsCOMPtr<nsISupportsPRUint32> hotspotXWrap, hotspotYWrap;
props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotXWrap));
props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotYWrap));
if (hotspotXWrap)
hotspotXWrap->GetData(&hotspotX);
if (hotspotYWrap)
hotspotYWrap->GetData(&hotspotY);
}
}
rv = aWidget->SetCursor(aContainer, hotspotX, hotspotY);
}
if (NS_FAILED(rv))
aWidget->SetCursor(c);

View File

@ -130,7 +130,9 @@ public:
NS_IMETHOD RegisterAccessKey(nsIContent* aContent, PRUint32 aKey);
NS_IMETHOD UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey);
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer, nsIWidget* aWidget, PRBool aLockCursor);
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor);
//Method for centralized distribution of new DOM events
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aDefaultActionEnabled);

View File

@ -6396,8 +6396,9 @@ nsGlobalChromeWindow::SetCursor(const nsAString& aCursor)
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
// Call esm and set cursor.
rv = presContext->EventStateManager()->SetCursor(cursor, nsnull, widget,
PR_TRUE);
rv = presContext->EventStateManager()->SetCursor(cursor, nsnull,
PR_FALSE, 0.0f, 0.0f,
widget, PR_TRUE);
}
return rv;

View File

@ -4734,14 +4734,20 @@ void nsFrame::FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
nsIFrame::Cursor& aCursor)
{
aCursor.mCursor = ui->mCursor;
aCursor.mHaveHotspot = PR_FALSE;
aCursor.mHotspotX = aCursor.mHotspotY = 0.0f;
PRInt32 count = ui->mCursorArray.Count();
for (int i = 0; i < count; i++) {
for (nsCursorImage *item = ui->mCursorArray,
*item_end = ui->mCursorArray + ui->mCursorArrayLength;
item < item_end; ++item) {
PRUint32 status;
nsresult rv = ui->mCursorArray[i]->GetImageStatus(&status);
nsresult rv = item->mImage->GetImageStatus(&status);
if (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_FRAME_COMPLETE)) {
// This is the one we want
ui->mCursorArray[i]->GetImage(getter_AddRefs(aCursor.mContainer));
item->mImage->GetImage(getter_AddRefs(aCursor.mContainer));
aCursor.mHaveHotspot = item->mHaveHotspot;
aCursor.mHotspotX = item->mHotspotX;
aCursor.mHotspotY = item->mHotspotY;
break;
}
}

View File

@ -94,9 +94,10 @@ struct nsMargin;
typedef class nsIFrame nsIBox;
// IID for the nsIFrame interface
// 715842c9-8d33-41e9-8d71-78c81850c882
// 2fb5effc-5eeb-4ccb-b9fa-325f8642200f
#define NS_IFRAME_IID \
{ 0x715842c9, 0x8d33, 0x41e9, { 0x8d, 0x71, 0x78, 0xc8, 0x18, 0x50, 0xc8, 0x82 } }
{ 0x2fb5effc, 0x5eeb, 0x4ccb, \
{ 0xb9, 0xfa, 0x32, 0x5f, 0x86, 0x42, 0x20, 0x0f } }
/**
* Indication of how the frame can be split. This is used when doing runaround
@ -765,6 +766,8 @@ public:
struct Cursor {
nsCOMPtr<imgIContainer> mContainer;
PRInt32 mCursor;
PRBool mHaveHotspot;
float mHotspotX, mHotspotY;
};
/**
* Get the cursor for a given frame.

View File

@ -243,13 +243,19 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
} break;
case eCSSType_ValueList:
if (iProp == eCSSProperty_content ||
iProp == eCSSProperty_cursor) {
if (iProp == eCSSProperty_content) {
for (nsCSSValueList* l = ValueListAtCursor(cursor);
l; l = l->mNext)
if (l->mValue.GetUnit() == eCSSUnit_URL)
l->mValue.StartImageLoad(
aRuleData->mPresContext->GetDocument());
} else if (iProp == eCSSProperty_cursor) {
for (nsCSSValueList* l = ValueListAtCursor(cursor);
l; l = l->mNext)
if (l->mValue.GetUnit() == eCSSUnit_Array)
l->mValue.GetArrayValue()->Item(0).
StartImageLoad(
aRuleData->mPresContext->GetDocument());
}
// fall through
case eCSSType_CounterData:

View File

@ -232,6 +232,12 @@ PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString&
AppendCSSValueToString(aProperty, val->mValue, aResult);
val = val->mNext;
if (val) {
if (aProperty == eCSSProperty_cursor
#ifdef MOZ_SVG
|| aProperty == eCSSProperty_stroke_dasharray
#endif
)
aResult.Append(PRUnichar(','));
aResult.Append(PRUnichar(' '));
}
} while (val);

View File

@ -3572,6 +3572,7 @@ PRBool CSSParserImpl::ParsePositiveVariant(nsresult& aErrorCode,
return PR_FALSE;
}
// Assigns to aValue iff it returns PR_TRUE.
PRBool CSSParserImpl::ParseVariant(nsresult& aErrorCode, nsCSSValue& aValue,
PRInt32 aVariantMask,
const PRInt32 aKeywordTable[])
@ -5325,30 +5326,48 @@ PRBool CSSParserImpl::ParseCursor(nsresult& aErrorCode)
cur = *curp = new nsCSSValueList();
if (!cur) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
delete list;
return PR_FALSE;
break;
}
if (!ParseVariant(aErrorCode, cur->mValue,
(cur == list) ? VARIANT_AHUK : VARIANT_AUK,
nsCSSProps::kCursorKTable)) {
delete list;
return PR_FALSE;
}
if (cur->mValue.GetUnit() != eCSSUnit_URL)
break;
}
if (cur->mValue.GetUnit() != eCSSUnit_URL) {
if (!ExpectEndProperty(aErrorCode, PR_TRUE)) {
break;
}
// Only success case here, since having the failure case at the
// end allows more sharing of code.
mTempData.SetPropertyBit(eCSSProperty_cursor);
mTempData.mUserInterface.mCursor = list;
aErrorCode = NS_OK;
return PR_TRUE;
}
// We have a URL, so make a value array with three values.
nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(3);
if (!val) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
break;
}
val->Item(0) = cur->mValue;
cur->mValue.SetArrayValue(val, eCSSUnit_Array);
// Parse optional x and y position of cursor hotspot (css3-ui).
if (ParseVariant(aErrorCode, val->Item(1), VARIANT_NUMBER, nsnull)) {
// If we have one number, we must have two.
if (!ParseVariant(aErrorCode, val->Item(2), VARIANT_NUMBER, nsnull)) {
break;
}
}
if (!ExpectSymbol(aErrorCode, ',', PR_TRUE)) {
delete list;
return PR_FALSE;
break;
}
}
if (!ExpectEndProperty(aErrorCode, PR_TRUE)) {
delete list;
return PR_FALSE;
}
mTempData.SetPropertyBit(eCSSProperty_cursor);
mTempData.mUserInterface.mCursor = list;
aErrorCode = NS_OK;
return PR_TRUE;
// Have failure case at the end so we can |break| to get to it.
delete list;
return PR_FALSE;
}

View File

@ -2127,21 +2127,43 @@ nsComputedDOMStyle::GetCursor(nsIFrame *aFrame,
GetStyleData(eStyleStruct_UserInterface, (const nsStyleStruct*&)ui, aFrame);
if (ui) {
PRInt32 count = ui->mCursorArray.Count();
for (PRInt32 i = 0; i < count; i++) {
for (nsCursorImage *item = ui->mCursorArray,
*item_end = ui->mCursorArray + ui->mCursorArrayLength;
item < item_end; ++item) {
nsDOMCSSValueList *itemList = GetROCSSValueList(PR_FALSE);
if (!itemList || !valueList->AppendCSSValue(itemList)) {
delete itemList;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIURI> uri;
ui->mCursorArray[i]->GetURI(getter_AddRefs(uri));
item->mImage->GetURI(getter_AddRefs(uri));
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
if (!val) {
if (!val || !itemList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
val->SetURI(uri);
if (!valueList->AppendCSSValue(val)) {
delete valueList;
delete val;
return NS_ERROR_OUT_OF_MEMORY;
if (item->mHaveHotspot) {
nsROCSSPrimitiveValue *valX = GetROCSSPrimitiveValue();
if (!valX || !itemList->AppendCSSValue(valX)) {
delete valX;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
nsROCSSPrimitiveValue *valY = GetROCSSPrimitiveValue();
if (!valY || !itemList->AppendCSSValue(valY)) {
delete valY;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
valX->SetNumber(item->mHotspotX);
valY->SetNumber(item->mHotspotY);
}
}

View File

@ -2437,20 +2437,45 @@ nsRuleNode::ComputeUserInterfaceData(nsStyleStruct* aStartData,
// cursor: enum, auto, url, inherit
nsCSSValueList* list = uiData.mCursor;
if (nsnull != list) {
ui->mCursorArray.Clear();
delete [] ui->mCursorArray;
ui->mCursorArray = nsnull;
ui->mCursorArrayLength = 0;
if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
inherited = PR_TRUE;
ui->mCursor = parentUI->mCursor;
ui->mCursorArray.AppendObjects(parentUI->mCursorArray);
ui->CopyCursorArrayFrom(*parentUI);
}
else {
// The parser will never create a list that is *all* URL values --
// that's invalid.
while (list->mValue.GetUnit() == eCSSUnit_Image) {
imgIRequest* req = list->mValue.GetImageValue();
if (req)
ui->mCursorArray.AppendObject(req);
list = list->mNext;
PRUint32 arrayLength = 0;
for (nsCSSValueList *list2 = list;
list2->mValue.GetUnit() == eCSSUnit_Array; list2 = list2->mNext)
if (list2->mValue.GetArrayValue()->Item(0).GetImageValue())
++arrayLength;
if (arrayLength != 0) {
ui->mCursorArray = new nsCursorImage[arrayLength];
if (ui->mCursorArray) {
ui->mCursorArrayLength = arrayLength;
for (nsCursorImage *item = ui->mCursorArray;
list->mValue.GetUnit() == eCSSUnit_Array;
list = list->mNext) {
nsCSSValue::Array *arr = list->mValue.GetArrayValue();
imgIRequest *req = arr->Item(0).GetImageValue();
if (req) {
item->mImage = req;
if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
item->mHaveHotspot = PR_TRUE;
item->mHotspotX = arr->Item(1).GetFloatValue(),
item->mHotspotY = arr->Item(2).GetFloatValue();
}
++item;
}
}
}
}
if (eCSSUnit_Enumerated == list->mValue.GetUnit()) {

View File

@ -1618,6 +1618,13 @@ nsChangeHint nsStyleText::MaxDifference()
// nsStyleUserInterface
//
nsCursorImage::nsCursorImage()
: mHaveHotspot(PR_FALSE)
, mHotspotX(0.0f)
, mHotspotY(0.0f)
{
}
nsStyleUserInterface::nsStyleUserInterface(void)
{
mUserInput = NS_STYLE_USER_INPUT_AUTO;
@ -1625,19 +1632,23 @@ nsStyleUserInterface::nsStyleUserInterface(void)
mUserFocus = NS_STYLE_USER_FOCUS_NONE;
mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
mCursorArrayLength = 0;
mCursorArray = nsnull;
}
nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
mUserInput(aSource.mUserInput),
mUserModify(aSource.mUserModify),
mUserFocus(aSource.mUserFocus),
mCursor(aSource.mCursor),
mCursorArray(aSource.mCursorArray)
mCursor(aSource.mCursor)
{
CopyCursorArrayFrom(aSource);
}
nsStyleUserInterface::~nsStyleUserInterface(void)
{
delete [] mCursorArray;
}
nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
@ -1648,7 +1659,7 @@ nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aO
// We could do better. But it wouldn't be worth it, URL-specified cursors are
// rare.
if (mCursorArray.Count() > 0 || aOther.mCursorArray.Count() > 0)
if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
if (mUserModify != aOther.mUserModify)
@ -1673,6 +1684,21 @@ nsChangeHint nsStyleUserInterface::MaxDifference()
}
#endif
void
nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
{
mCursorArray = nsnull;
mCursorArrayLength = 0;
if (aSource.mCursorArrayLength) {
mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
if (mCursorArray) {
mCursorArrayLength = aSource.mCursorArrayLength;
for (PRUint32 i = 0; i < mCursorArrayLength; ++i)
mCursorArray[i] = aSource.mCursorArray[i];
}
}
}
//-----------------------
// nsStyleUIReset
//

View File

@ -1147,6 +1147,14 @@ struct nsStyleUIReset: public nsStyleStruct {
PRUint8 mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
};
struct nsCursorImage {
nsCOMPtr<imgIRequest> mImage;
PRBool mHaveHotspot;
float mHotspotX, mHotspotY;
nsCursorImage();
};
struct nsStyleUserInterface: public nsStyleStruct {
nsStyleUserInterface(void);
nsStyleUserInterface(const nsStyleUserInterface& aOther);
@ -1172,12 +1180,16 @@ struct nsStyleUserInterface: public nsStyleStruct {
PRUint8 mUserFocus; // [inherited] (auto-select)
PRUint8 mCursor; // [inherited] See nsStyleConsts.h
nsCOMArray<imgIRequest> mCursorArray; // [inherited] The specified URL values. Takes precedence over mCursor.
// NOTE: Using nsCOMArray here means that copying this struct is slower (and
// takes more memory) than it could be if we used nsISupportsArray, because
// we have to append all objects to the new array. However, since these
// properties are rarely set, they are usually cached, and thus this is not
// much of a problem.
PRUint32 mCursorArrayLength;
nsCursorImage *mCursorArray;// [inherited] The specified URL values
// and coordinates. Takes precedence over
// mCursor. Zero-length array is represented
// by null pointer.
// Does not free mCursorArray; the caller is responsible for calling
// |delete [] mCursorArray| first if it is needed.
void CopyCursorArrayFrom(const nsStyleUserInterface& aSource);
};
struct nsStyleXUL : public nsStyleStruct {

View File

@ -92,10 +92,10 @@ typedef nsEventStatus (*PR_CALLBACK EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_SCREEN 9
#define NS_NATIVE_SHELLWIDGET 10 // Get the shell GtkWidget
// {18032AD5-B265-11d1-AA2A-000000000000}
// e7f09105-d21b-406a-89d5-e6b731b8f665
#define NS_IWIDGET_IID \
{ 0x18032ad5, 0xb265, 0x11d1, \
{ 0xaa, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
{ 0xe7f09105, 0xd21b, 0x406a, \
{ 0x89, 0xd5, 0xe6, 0xb7, 0x31, 0xb8, 0xf6, 0x65 } }
// Hide the native window systems real window type so as to avoid
@ -651,10 +651,13 @@ class nsIWidget : public nsISupports {
* Sets an image as the cursor for this widget.
*
* @param aCursor the cursor to set
* @param aX the X coordinate of the hotspot (from left).
* @param aY the Y coordinate of the hotspot (from top).
* @retval NS_ERROR_NOT_IMPLEMENTED if setting images as cursors is not
* supported
*/
NS_IMETHOD SetCursor(imgIContainer* aCursor) = 0;
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY) = 0;
/**
* Get the window type of this widget

View File

@ -89,8 +89,6 @@ static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsIGdkPixbufImage.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#include "nsIInterfaceRequestorUtils.h"
/* utility functions */
@ -789,7 +787,8 @@ nsWindow::SetCursor(nsCursor aCursor)
NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer* aCursor)
nsWindow::SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY)
{
// if we're not the toplevel window pass up the cursor request to
// the toplevel window to handle it.
@ -797,7 +796,7 @@ nsWindow::SetCursor(imgIContainer* aCursor)
GtkWidget *widget =
get_gtk_widget_for_gdk_window(mDrawingarea->inner_window);
nsWindow *window = get_window_for_gtk_widget(widget);
return window->SetCursor(aCursor);
return window->SetCursor(aCursor, aHotspotX, aHotspotY);
}
if (!sPixbufCursorChecked) {
@ -831,21 +830,6 @@ nsWindow::SetCursor(imgIContainer* aCursor)
if (!pixbuf)
return NS_ERROR_NOT_AVAILABLE;
// Get the hotspot
PRUint32 hX = 0, hY = 0;
nsCOMPtr<nsIProperties> props(do_QueryInterface(aCursor));
if (props) {
nsCOMPtr<nsISupportsPRUint32> hXWrap, hYWrap;
props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hXWrap));
props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hYWrap));
if (hXWrap)
hXWrap->GetData(&hX);
if (hYWrap)
hYWrap->GetData(&hY);
}
// Looks like all cursors need an alpha channel (tested on Gtk 2.4.4). This
// is of course not documented anywhere...
// So add one if there isn't one yet
@ -861,7 +845,7 @@ nsWindow::SetCursor(imgIContainer* aCursor)
// Now create the cursor
GdkCursor* cursor = _gdk_cursor_new_from_pixbuf(_gdk_display_get_default(),
pixbuf,
hX, hY);
aHotspotX, aHotspotY);
gdk_pixbuf_unref(pixbuf);
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
if (cursor) {

View File

@ -107,7 +107,8 @@ public:
virtual nsIFontMetrics* GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD Validate();
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect &aRect,

View File

@ -80,14 +80,11 @@
#include "nsXPIDLString.h"
#include "nsIFile.h"
#include "nsISupportsPrimitives.h"
#include "nsOS2Uni.h"
#include "nsPaletteOS2.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIProperties.h"
#include <stdlib.h>
#include <ctype.h>
@ -1840,7 +1837,8 @@ NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
// substantially modified to accommodate platform differences and to
// improve efficiency
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY)
{
// if this is the same image as last time, reuse the saved hptr;
@ -1874,29 +1872,6 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
format != gfxIFormats::BGR)
return NS_ERROR_UNEXPECTED;
// get the hotspot; if it doesn't have one, put it in the
// upper-left corner of the image (per CSS standards);
// PM will scale its location when it rescales the image
PRUint32 hotspotX = (PRUint32)-1, hotspotY = (PRUint32)-1;
nsCOMPtr<nsIProperties> props(do_QueryInterface(aCursor));
if (props) {
nsCOMPtr<nsISupportsPRUint32> hotspotXWrap, hotspotYWrap;
props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotXWrap));
props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotYWrap));
if (hotspotXWrap)
hotspotXWrap->GetData(&hotspotX);
if (hotspotYWrap)
hotspotYWrap->GetData(&hotspotY);
}
if (hotspotX == (PRUint32)-1)
hotspotX = 0;
if (hotspotY == (PRUint32)-1)
hotspotY = height;
else
hotspotY = height - hotspotY - 1;
frame->LockImageData();
PRUint32 dataLen;
PRUint8* data;
@ -1946,8 +1921,8 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
POINTERINFO info = {0};
info.fPointer = TRUE;
info.xHotspot = hotspotX;
info.yHotspot = hotspotY;
info.xHotspot = aHotspotX;
info.yHotspot = height - aHotspotY - 1;
info.hbmPointer = hAlpha;
info.hbmColor = hBmp;

View File

@ -167,7 +167,8 @@ class nsWindow : public nsBaseWidget,
NS_IMETHOD SetFont( const nsFont &aFont);
NS_IMETHOD SetColorMap( nsColorMap *aColorMap);
NS_IMETHOD SetCursor( nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD HideWindowChrome(PRBool aShouldHide);
NS_IMETHOD SetTitle( const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec);

View File

@ -74,8 +74,6 @@
#include "nsIEventQueue.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#include "nsNativeCharsetUtils.h"
#include <windows.h>
@ -2735,7 +2733,8 @@ HBITMAP nsWindow::CreateOpaqueAlphaChannel(PRUint32 aWidth, PRUint32 aHeight)
SM_CXCURSOR, SM_CYCURSOR (::GetSystemMetrics). However, ::CreateIconIndirect
returns null when the size is not correct.
*/
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY)
{
if (gCursorImgContainer == aCursor && gHCursor) {
::SetCursor(gHCursor);
@ -2752,21 +2751,6 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
frame->GetWidth(&width);
frame->GetHeight(&height);
PRUint32 hotspotX = 0, hotspotY = 0;
nsCOMPtr<nsIProperties> props(do_QueryInterface(aCursor));
if (props) {
nsCOMPtr<nsISupportsPRUint32> hotspotXWrap, hotspotYWrap;
props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotXWrap));
props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32), getter_AddRefs(hotspotYWrap));
if (hotspotXWrap)
hotspotXWrap->GetData(&hotspotX);
if (hotspotYWrap)
hotspotYWrap->GetData(&hotspotY);
}
gfx_format format;
nsresult rv = frame->GetFormat(&format);
if (NS_FAILED(rv))
@ -2866,8 +2850,8 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor)
ICONINFO info = {0};
info.fIcon = FALSE;
info.xHotspot = hotspotX;
info.yHotspot = hotspotY;
info.xHotspot = aHotspotX;
info.yHotspot = aHotspotY;
info.hbmMask = hAlpha;
info.hbmColor = hBMP;

View File

@ -344,7 +344,8 @@ public:
virtual nsIFontMetrics* GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD HideWindowChrome(PRBool aShouldHide);
NS_IMETHOD Validate();
NS_IMETHOD Invalidate(PRBool aIsSynchronous);

View File

@ -490,7 +490,8 @@ NS_METHOD nsBaseWidget::SetCursor(nsCursor aCursor)
return NS_OK;
}
NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor)
NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -96,7 +96,8 @@ public:
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
virtual nsCursor GetCursor();
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD GetWindowType(nsWindowType& aWindowType);
NS_IMETHOD SetWindowType(nsWindowType aWindowType);
NS_IMETHOD SetWindowTranslucency(PRBool aTranslucent);