Bug 38447 implement imgIContainer* version of SetCursor on gtk2 (>= 2.4)

r=bryner sr=roc
This commit is contained in:
cbiesinger%web.de 2005-03-15 22:24:20 +00:00
parent 55ffff862e
commit 2959b2c17b
3 changed files with 110 additions and 3 deletions

View File

@ -61,7 +61,9 @@ REQUIRES = xpcom \
uconv \
intl \
gtkxtbin \
xremoteservice
xremoteservice \
imglib2 \
$(NULL)
CSRCS = \
mozcontainer.c \

View File

@ -36,6 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "prlink.h"
#include "nsWindow.h"
#include "nsToolkit.h"
#include "nsIRenderingContext.h"
@ -57,7 +59,8 @@
#include "gtk2xtbin.h"
#include "nsIPref.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIServiceManager.h"
#include "nsGfxCIID.h"
@ -80,6 +83,16 @@ static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility"
#include "nsIFile.h"
#include "nsILocalFile.h"
/* SetCursor(imgIContainer*) */
#include <gdk/gdk.h>
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsIGdkPixbufImage.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#include "nsIInterfaceRequestorUtils.h"
/* utility functions */
static PRBool check_for_rollup(GdkWindow *aWindow,
gdouble aMouseX, gdouble aMouseY,
@ -226,6 +239,14 @@ static GtkIMContext *IM_get_input_context(MozDrawingarea *aArea);
// http://bugzilla.gnome.org/show_bug.cgi?id=88940
#endif
// needed for imgIContainer cursors
typedef GdkCursor* (*_gdk_cursor_new_from_pixbuf_fn)(GdkDisplay *display,
GdkPixbuf *pixbuf,
gint x,
gint y);
static _gdk_cursor_new_from_pixbuf_fn _gdk_cursor_new_from_pixbuf;
static PRBool sPixbufCursorChecked;
#define kWindowPositionSlop 20
// cursor cache
@ -764,6 +785,89 @@ nsWindow::SetCursor(nsCursor aCursor)
}
NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer* aCursor)
{
// if we're not the toplevel window pass up the cursor request to
// the toplevel window to handle it.
if (!mContainer && mDrawingarea) {
GtkWidget *widget =
get_gtk_widget_for_gdk_window(mDrawingarea->inner_window);
nsWindow *window = get_window_for_gtk_widget(widget);
return window->SetCursor(aCursor);
}
if (!sPixbufCursorChecked) {
PRLibrary* lib;
_gdk_cursor_new_from_pixbuf = (_gdk_cursor_new_from_pixbuf_fn)
PR_FindFunctionSymbolAndLibrary("gdk_cursor_new_from_pixbuf", &lib);
sPixbufCursorChecked = PR_TRUE;
}
if (!_gdk_cursor_new_from_pixbuf)
return NS_ERROR_NOT_IMPLEMENTED;
mCursor = nsCursor(-1);
// Get first image frame
nsCOMPtr<gfxIImageFrame> frame;
aCursor->GetFrameAt(0, getter_AddRefs(frame));
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIGdkPixbufImage> pixImg(do_GetInterface(frame));
if (!pixImg)
return NS_ERROR_NOT_AVAILABLE;
GdkPixbuf* pixbuf = pixImg->GetGdkPixbuf();
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
if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
GdkPixbuf* alphaBuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0);
gdk_pixbuf_unref(pixbuf);
if (!alphaBuf) {
return NS_ERROR_OUT_OF_MEMORY;
}
pixbuf = alphaBuf;
}
// Now create the cursor
GdkCursor* cursor = _gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
pixbuf,
hX, hY);
gdk_pixbuf_unref(pixbuf);
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
if (cursor) {
if (mContainer) {
gdk_window_set_cursor(GTK_WIDGET(mContainer)->window, cursor);
XFlush(GDK_DISPLAY());
rv = NS_OK;
}
gdk_cursor_unref(cursor);
}
return rv;
}
NS_IMETHODIMP
nsWindow::Validate()
{
@ -3906,7 +4010,7 @@ nsresult
initialize_prefs(void)
{
// check to see if we should set our raise pref
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
PRBool val = PR_TRUE;
nsresult rv;

View File

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