1/* 2 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com 3 * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> 4 * Copyright (C) 2010-2012 Igalia S.L. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "CursorGtk.h" 31#include "GtkVersioning.h" 32 33#include "Image.h" 34#include "IntPoint.h" 35#include "RefPtrCairo.h" 36#include <gdk/gdk.h> 37#include <gtk/gtk.h> 38#include <wtf/Assertions.h> 39 40namespace WebCore { 41 42static GRefPtr<GdkCursor> createNamedCursor(CustomCursorType cursorType) 43{ 44 CustomCursor cursor = CustomCursors[cursorType]; 45 GRefPtr<GdkCursor> c = adoptGRef(gdk_cursor_new_from_name(gdk_display_get_default(), cursor.name)); 46 if (c) 47 return c; 48 49 RefPtr<cairo_surface_t> source = adoptRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.bits), CAIRO_FORMAT_A1, 32, 32, 4)); 50 RefPtr<cairo_surface_t> mask = adoptRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.mask_bits), CAIRO_FORMAT_A1, 32, 32, 4)); 51 RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_A1, 32, 32)); 52 RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get())); 53 54 cairo_set_source_surface(cr.get(), source.get(), 0, 0); 55 cairo_mask_surface(cr.get(), mask.get(), 0, 0); 56 57 GRefPtr<GdkPixbuf> pixbuf = adoptGRef(gdk_pixbuf_get_from_surface(surface.get(), 0, 0, 32, 32)); 58 return adoptGRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), cursor.hot_x, cursor.hot_y)); 59} 60 61static GRefPtr<GdkCursor> createCustomCursor(Image* image, const IntPoint& hotSpot) 62{ 63 IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); 64 GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->getGdkPixbuf()); 65 return adoptGRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), effectiveHotSpot.x(), effectiveHotSpot.y())); 66} 67 68void Cursor::ensurePlatformCursor() const 69{ 70 if (m_platformCursor || m_type == Cursor::Pointer) 71 return; 72 73 switch (m_type) { 74 case Cursor::Pointer: 75 // A null GdkCursor is the default cursor for the window. 76 m_platformCursor = 0; 77 break; 78 case Cursor::Cross: 79 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_CROSS)); 80 break; 81 case Cursor::Hand: 82 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_HAND2)); 83 break; 84 case Cursor::IBeam: 85 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_XTERM)); 86 break; 87 case Cursor::Wait: 88 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_WATCH)); 89 break; 90 case Cursor::Help: 91 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_QUESTION_ARROW)); 92 break; 93 case Cursor::Move: 94 case Cursor::MiddlePanning: 95 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_FLEUR)); 96 break; 97 case Cursor::EastResize: 98 case Cursor::EastPanning: 99 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_RIGHT_SIDE)); 100 break; 101 case Cursor::NorthResize: 102 case Cursor::NorthPanning: 103 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_SIDE)); 104 break; 105 case Cursor::NorthEastResize: 106 case Cursor::NorthEastPanning: 107 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_RIGHT_CORNER)); 108 break; 109 case Cursor::NorthWestResize: 110 case Cursor::NorthWestPanning: 111 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_LEFT_CORNER)); 112 break; 113 case Cursor::SouthResize: 114 case Cursor::SouthPanning: 115 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_SIDE)); 116 break; 117 case Cursor::SouthEastResize: 118 case Cursor::SouthEastPanning: 119 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER)); 120 break; 121 case Cursor::SouthWestResize: 122 case Cursor::SouthWestPanning: 123 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER)); 124 break; 125 case Cursor::WestResize: 126 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_LEFT_SIDE)); 127 break; 128 case Cursor::NorthSouthResize: 129 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_TEE)); 130 break; 131 case Cursor::EastWestResize: 132 case Cursor::WestPanning: 133 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_LEFT_SIDE)); 134 break; 135 case Cursor::NorthEastSouthWestResize: 136 case Cursor::NorthWestSouthEastResize: 137 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SIZING)); 138 break; 139 case Cursor::ColumnResize: 140 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW)); 141 break; 142 case Cursor::RowResize: 143 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW)); 144 break; 145 case Cursor::VerticalText: 146 m_platformCursor = createNamedCursor(CustomCursorVerticalText); 147 break; 148 case Cursor::Cell: 149 m_platformCursor = adoptGRef(gdk_cursor_new(GDK_PLUS)); 150 break; 151 case Cursor::ContextMenu: 152 m_platformCursor = createNamedCursor(CustomCursorContextMenu); 153 break; 154 case Cursor::Alias: 155 m_platformCursor = createNamedCursor(CustomCursorAlias); 156 break; 157 case Cursor::Progress: 158 m_platformCursor = createNamedCursor(CustomCursorProgress); 159 break; 160 case Cursor::NoDrop: 161 case Cursor::NotAllowed: 162 m_platformCursor = createNamedCursor(CustomCursorNoDrop); 163 break; 164 case Cursor::Copy: 165 m_platformCursor = createNamedCursor(CustomCursorCopy); 166 break; 167 case Cursor::None: 168 m_platformCursor = createNamedCursor(CustomCursorNone); 169 break; 170 case Cursor::ZoomIn: 171 m_platformCursor = createNamedCursor(CustomCursorZoomIn); 172 break; 173 case Cursor::ZoomOut: 174 m_platformCursor = createNamedCursor(CustomCursorZoomOut); 175 break; 176 case Cursor::Grab: 177 m_platformCursor = createNamedCursor(CustomCursorGrab); 178 break; 179 case Cursor::Grabbing: 180 m_platformCursor = createNamedCursor(CustomCursorGrabbing); 181 break; 182 case Cursor::Custom: 183 m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot); 184 break; 185 } 186} 187 188Cursor::Cursor(const Cursor& other) 189 : m_type(other.m_type) 190 , m_image(other.m_image) 191 , m_hotSpot(other.m_hotSpot) 192 , m_platformCursor(other.m_platformCursor) 193{ 194} 195 196Cursor& Cursor::operator=(const Cursor& other) 197{ 198 m_type = other.m_type; 199 m_image = other.m_image; 200 m_hotSpot = other.m_hotSpot; 201 m_platformCursor = other.m_platformCursor; 202 return *this; 203} 204 205Cursor::~Cursor() 206{ 207} 208 209} 210