Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2004, 2006, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #import "config.h"
     27 #import "Cursor.h"
     28 
     29 #import "BlockExceptions.h"
     30 #import <wtf/StdLibExtras.h>
     31 
     32 @interface WebCoreCursorBundle : NSObject { }
     33 @end
     34 
     35 @implementation WebCoreCursorBundle
     36 @end
     37 
     38 namespace WebCore {
     39 
     40 // Simple NSCursor calls shouldn't need protection,
     41 // but creating a cursor with a bad image might throw.
     42 
     43 static RetainPtr<NSCursor> createCustomCursor(Image* image, const IntPoint& hotSpot)
     44 {
     45     // FIXME: The cursor won't animate.  Not sure if that's a big deal.
     46     NSImage* nsImage = image->getNSImage();
     47     if (!nsImage)
     48         return 0;
     49     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     50     return RetainPtr<NSCursor>(AdoptNS, [[NSCursor alloc] initWithImage:nsImage hotSpot:hotSpot]);
     51     END_BLOCK_OBJC_EXCEPTIONS;
     52     return 0;
     53 }
     54 
     55 // Leak these cursors intentionally, that way we won't waste time trying to clean them
     56 // up at process exit time.
     57 static NSCursor* leakNamedCursor(const char* name, int x, int y)
     58 {
     59     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     60     NSString* resourceName = [[NSString alloc] initWithUTF8String:name];
     61     NSImage* cursorImage = [[NSImage alloc] initWithContentsOfFile:
     62         [[NSBundle bundleForClass:[WebCoreCursorBundle class]]
     63         pathForResource:resourceName ofType:@"png"]];
     64     [resourceName release];
     65     NSCursor* cursor = 0;
     66     if (cursorImage) {
     67         NSPoint hotSpotPoint = {x, y}; // workaround for 4213314
     68         cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint];
     69         [cursorImage release];
     70     }
     71     return cursor;
     72     END_BLOCK_OBJC_EXCEPTIONS;
     73     return nil;
     74 }
     75 
     76 void Cursor::ensurePlatformCursor() const
     77 {
     78     if (m_platformCursor)
     79         return;
     80 
     81     switch (m_type) {
     82     case Cursor::Pointer:
     83         m_platformCursor = [NSCursor arrowCursor];
     84         break;
     85     case Cursor::Cross:
     86         m_platformCursor = leakNamedCursor("crossHairCursor", 11, 11);
     87         break;
     88     case Cursor::Hand:
     89         m_platformCursor = leakNamedCursor("linkCursor", 6, 1);
     90         break;
     91     case Cursor::IBeam:
     92         m_platformCursor = [NSCursor IBeamCursor];
     93         break;
     94     case Cursor::Wait:
     95         m_platformCursor = leakNamedCursor("waitCursor", 7, 7);
     96         break;
     97     case Cursor::Help:
     98         m_platformCursor = leakNamedCursor("helpCursor", 8, 8);
     99         break;
    100     case Cursor::Move:
    101     case Cursor::MiddlePanning:
    102         m_platformCursor = leakNamedCursor("moveCursor", 7, 7);
    103         break;
    104     case Cursor::EastResize:
    105     case Cursor::EastPanning:
    106         m_platformCursor = leakNamedCursor("eastResizeCursor", 14, 7);
    107         break;
    108     case Cursor::NorthResize:
    109     case Cursor::NorthPanning:
    110         m_platformCursor = leakNamedCursor("northResizeCursor", 7, 1);
    111         break;
    112     case Cursor::NorthEastResize:
    113     case Cursor::NorthEastPanning:
    114         m_platformCursor = leakNamedCursor("northEastResizeCursor", 14, 1);
    115         break;
    116     case Cursor::NorthWestResize:
    117     case Cursor::NorthWestPanning:
    118         m_platformCursor = leakNamedCursor("northWestResizeCursor", 0, 0);
    119         break;
    120     case Cursor::SouthResize:
    121     case Cursor::SouthPanning:
    122         m_platformCursor = leakNamedCursor("southResizeCursor", 7, 14);
    123         break;
    124     case Cursor::SouthEastResize:
    125     case Cursor::SouthEastPanning:
    126         m_platformCursor = leakNamedCursor("southEastResizeCursor", 14, 14);
    127         break;
    128     case Cursor::SouthWestResize:
    129     case Cursor::SouthWestPanning:
    130         m_platformCursor = leakNamedCursor("southWestResizeCursor", 1, 14);
    131         break;
    132     case Cursor::WestResize:
    133         m_platformCursor = leakNamedCursor("westResizeCursor", 1, 7);
    134         break;
    135     case Cursor::NorthSouthResize:
    136         m_platformCursor = leakNamedCursor("northSouthResizeCursor", 7, 7);
    137         break;
    138     case Cursor::EastWestResize:
    139     case Cursor::WestPanning:
    140         m_platformCursor = leakNamedCursor("eastWestResizeCursor", 7, 7);
    141         break;
    142     case Cursor::NorthEastSouthWestResize:
    143         m_platformCursor = leakNamedCursor("northEastSouthWestResizeCursor", 7, 7);
    144         break;
    145     case Cursor::NorthWestSouthEastResize:
    146         m_platformCursor = leakNamedCursor("northWestSouthEastResizeCursor", 7, 7);
    147         break;
    148     case Cursor::ColumnResize:
    149         m_platformCursor = [NSCursor resizeLeftRightCursor];
    150         break;
    151     case Cursor::RowResize:
    152         m_platformCursor = [NSCursor resizeUpDownCursor];
    153         break;
    154     case Cursor::VerticalText:
    155         m_platformCursor = leakNamedCursor("verticalTextCursor", 7, 7);
    156         break;
    157     case Cursor::Cell:
    158         m_platformCursor = leakNamedCursor("cellCursor", 7, 7);
    159         break;
    160     case Cursor::ContextMenu:
    161         m_platformCursor = leakNamedCursor("contextMenuCursor", 3, 2);
    162         break;
    163     case Cursor::Alias:
    164         m_platformCursor = leakNamedCursor("aliasCursor", 11, 3);
    165         break;
    166     case Cursor::Progress:
    167         m_platformCursor = leakNamedCursor("progressCursor", 3, 2);
    168         break;
    169     case Cursor::NoDrop:
    170         m_platformCursor = leakNamedCursor("noDropCursor", 3, 1);
    171         break;
    172     case Cursor::Copy:
    173         m_platformCursor = leakNamedCursor("copyCursor", 3, 2);
    174         break;
    175     case Cursor::None:
    176         m_platformCursor = leakNamedCursor("noneCursor", 7, 7);
    177         break;
    178     case Cursor::NotAllowed:
    179         m_platformCursor = leakNamedCursor("notAllowedCursor", 11, 11);
    180         break;
    181     case Cursor::ZoomIn:
    182         m_platformCursor = leakNamedCursor("zoomInCursor", 7, 7);
    183         break;
    184     case Cursor::ZoomOut:
    185         m_platformCursor = leakNamedCursor("zoomOutCursor", 7, 7);
    186         break;
    187     case Cursor::Grab:
    188         m_platformCursor = [NSCursor openHandCursor];
    189         break;
    190     case Cursor::Grabbing:
    191         m_platformCursor = [NSCursor closedHandCursor];
    192         break;
    193     case Cursor::Custom:
    194         m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot);
    195         break;
    196     }
    197 }
    198 
    199 Cursor::Cursor(const Cursor& other)
    200     : m_type(other.m_type)
    201     , m_image(other.m_image)
    202     , m_hotSpot(other.m_hotSpot)
    203     , m_platformCursor(other.m_platformCursor)
    204 {
    205 }
    206 
    207 Cursor& Cursor::operator=(const Cursor& other)
    208 {
    209     m_type = other.m_type;
    210     m_image = other.m_image;
    211     m_hotSpot = other.m_hotSpot;
    212     m_platformCursor = other.m_platformCursor;
    213     return *this;
    214 }
    215 
    216 Cursor::~Cursor()
    217 {
    218 }
    219 
    220 NSCursor *Cursor::platformCursor() const
    221 {
    222     ensurePlatformCursor();
    223     return m_platformCursor.get();
    224 }
    225 
    226 } // namespace WebCore
    227