Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/logging.h"
      6 #include "base/pickle.h"
      7 #include "grit/webkit_resources.h"
      8 #include "third_party/skia/include/core/SkBitmap.h"
      9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
     10 #include "ui/gfx/gdi_util.h"
     11 #include "webkit/glue/webcursor.h"
     12 
     13 using WebKit::WebCursorInfo;
     14 
     15 static LPCWSTR ToCursorID(WebCursorInfo::Type type) {
     16   switch (type) {
     17     case WebCursorInfo::TypePointer:
     18       return IDC_ARROW;
     19     case WebCursorInfo::TypeCross:
     20       return IDC_CROSS;
     21     case WebCursorInfo::TypeHand:
     22       return IDC_HAND;
     23     case WebCursorInfo::TypeIBeam:
     24       return IDC_IBEAM;
     25     case WebCursorInfo::TypeWait:
     26       return IDC_WAIT;
     27     case WebCursorInfo::TypeHelp:
     28       return IDC_HELP;
     29     case WebCursorInfo::TypeEastResize:
     30       return IDC_SIZEWE;
     31     case WebCursorInfo::TypeNorthResize:
     32       return IDC_SIZENS;
     33     case WebCursorInfo::TypeNorthEastResize:
     34       return IDC_SIZENESW;
     35     case WebCursorInfo::TypeNorthWestResize:
     36       return IDC_SIZENWSE;
     37     case WebCursorInfo::TypeSouthResize:
     38       return IDC_SIZENS;
     39     case WebCursorInfo::TypeSouthEastResize:
     40       return IDC_SIZENWSE;
     41     case WebCursorInfo::TypeSouthWestResize:
     42       return IDC_SIZENESW;
     43     case WebCursorInfo::TypeWestResize:
     44       return IDC_SIZEWE;
     45     case WebCursorInfo::TypeNorthSouthResize:
     46       return IDC_SIZENS;
     47     case WebCursorInfo::TypeEastWestResize:
     48       return IDC_SIZEWE;
     49     case WebCursorInfo::TypeNorthEastSouthWestResize:
     50       return IDC_SIZENESW;
     51     case WebCursorInfo::TypeNorthWestSouthEastResize:
     52       return IDC_SIZENWSE;
     53     case WebCursorInfo::TypeColumnResize:
     54       return MAKEINTRESOURCE(IDC_COLRESIZE);
     55     case WebCursorInfo::TypeRowResize:
     56       return MAKEINTRESOURCE(IDC_ROWRESIZE);
     57     case WebCursorInfo::TypeMiddlePanning:
     58       return MAKEINTRESOURCE(IDC_PAN_MIDDLE);
     59     case WebCursorInfo::TypeEastPanning:
     60       return MAKEINTRESOURCE(IDC_PAN_EAST);
     61     case WebCursorInfo::TypeNorthPanning:
     62       return MAKEINTRESOURCE(IDC_PAN_NORTH);
     63     case WebCursorInfo::TypeNorthEastPanning:
     64       return MAKEINTRESOURCE(IDC_PAN_NORTH_EAST);
     65     case WebCursorInfo::TypeNorthWestPanning:
     66       return MAKEINTRESOURCE(IDC_PAN_NORTH_WEST);
     67     case WebCursorInfo::TypeSouthPanning:
     68       return MAKEINTRESOURCE(IDC_PAN_SOUTH);
     69     case WebCursorInfo::TypeSouthEastPanning:
     70       return MAKEINTRESOURCE(IDC_PAN_SOUTH_EAST);
     71     case WebCursorInfo::TypeSouthWestPanning:
     72       return MAKEINTRESOURCE(IDC_PAN_SOUTH_WEST);
     73     case WebCursorInfo::TypeWestPanning:
     74       return MAKEINTRESOURCE(IDC_PAN_WEST);
     75     case WebCursorInfo::TypeMove:
     76       return IDC_SIZEALL;
     77     case WebCursorInfo::TypeVerticalText:
     78       return MAKEINTRESOURCE(IDC_VERTICALTEXT);
     79     case WebCursorInfo::TypeCell:
     80       return MAKEINTRESOURCE(IDC_CELL);
     81     case WebCursorInfo::TypeContextMenu:
     82       return MAKEINTRESOURCE(IDC_ARROW);
     83     case WebCursorInfo::TypeAlias:
     84       return MAKEINTRESOURCE(IDC_ALIAS);
     85     case WebCursorInfo::TypeProgress:
     86       return IDC_APPSTARTING;
     87     case WebCursorInfo::TypeNoDrop:
     88       return IDC_NO;
     89     case WebCursorInfo::TypeCopy:
     90       return MAKEINTRESOURCE(IDC_COPYCUR);
     91     case WebCursorInfo::TypeNone:
     92       return IDC_ARROW;
     93     case WebCursorInfo::TypeNotAllowed:
     94       return IDC_NO;
     95     case WebCursorInfo::TypeZoomIn:
     96       return MAKEINTRESOURCE(IDC_ZOOMIN);
     97     case WebCursorInfo::TypeZoomOut:
     98       return MAKEINTRESOURCE(IDC_ZOOMOUT);
     99     // TODO(avi): get cursor images for grab/grabbing
    100     // http://crbug.com/74699
    101     case WebCursorInfo::TypeGrab:
    102     case WebCursorInfo::TypeGrabbing:
    103       return IDC_ARROW;
    104   }
    105   NOTREACHED();
    106   return NULL;
    107 }
    108 
    109 static bool IsSystemCursorID(LPCWSTR cursor_id) {
    110   return cursor_id >= IDC_ARROW;  // See WinUser.h
    111 }
    112 
    113 static WebCursorInfo::Type ToCursorType(HCURSOR cursor) {
    114   static struct {
    115     HCURSOR cursor;
    116     WebCursorInfo::Type type;
    117   } kStandardCursors[] = {
    118     { LoadCursor(NULL, IDC_ARROW),       WebCursorInfo::TypePointer },
    119     { LoadCursor(NULL, IDC_CROSS),       WebCursorInfo::TypeCross },
    120     { LoadCursor(NULL, IDC_HAND),        WebCursorInfo::TypeHand },
    121     { LoadCursor(NULL, IDC_IBEAM),       WebCursorInfo::TypeIBeam },
    122     { LoadCursor(NULL, IDC_WAIT),        WebCursorInfo::TypeWait },
    123     { LoadCursor(NULL, IDC_HELP),        WebCursorInfo::TypeHelp },
    124     { LoadCursor(NULL, IDC_SIZENESW),    WebCursorInfo::TypeNorthEastResize },
    125     { LoadCursor(NULL, IDC_SIZENWSE),    WebCursorInfo::TypeNorthWestResize },
    126     { LoadCursor(NULL, IDC_SIZENS),      WebCursorInfo::TypeNorthSouthResize },
    127     { LoadCursor(NULL, IDC_SIZEWE),      WebCursorInfo::TypeEastWestResize },
    128     { LoadCursor(NULL, IDC_SIZEALL),     WebCursorInfo::TypeMove },
    129     { LoadCursor(NULL, IDC_APPSTARTING), WebCursorInfo::TypeProgress },
    130     { LoadCursor(NULL, IDC_NO),          WebCursorInfo::TypeNotAllowed },
    131   };
    132   for (int i = 0; i < arraysize(kStandardCursors); i++) {
    133     if (cursor == kStandardCursors[i].cursor)
    134       return kStandardCursors[i].type;
    135   }
    136   return WebCursorInfo::TypeCustom;
    137 }
    138 
    139 HCURSOR WebCursor::GetCursor(HINSTANCE module_handle){
    140   if (!IsCustom()) {
    141     const wchar_t* cursor_id =
    142         ToCursorID(static_cast<WebCursorInfo::Type>(type_));
    143 
    144     if (IsSystemCursorID(cursor_id))
    145       module_handle = NULL;
    146 
    147     return LoadCursor(module_handle, cursor_id);
    148   }
    149 
    150   if (custom_cursor_) {
    151     DCHECK(external_cursor_ == NULL);
    152     return custom_cursor_;
    153   }
    154 
    155   if (external_cursor_)
    156     return external_cursor_;
    157 
    158   BITMAPINFO cursor_bitmap_info = {0};
    159   gfx::CreateBitmapHeader(
    160       custom_size_.width(), custom_size_.height(),
    161       reinterpret_cast<BITMAPINFOHEADER*>(&cursor_bitmap_info));
    162   HDC dc = GetDC(0);
    163   HDC workingDC = CreateCompatibleDC(dc);
    164   HBITMAP bitmap_handle = CreateDIBSection(
    165       dc, &cursor_bitmap_info, DIB_RGB_COLORS, 0, 0, 0);
    166   if (!custom_data_.empty())
    167     SetDIBits(
    168         0, bitmap_handle, 0, custom_size_.height(), &custom_data_[0],
    169         &cursor_bitmap_info, DIB_RGB_COLORS);
    170 
    171   HBITMAP old_bitmap = reinterpret_cast<HBITMAP>(
    172       SelectObject(workingDC, bitmap_handle));
    173   SetBkMode(workingDC, TRANSPARENT);
    174   SelectObject(workingDC, old_bitmap);
    175 
    176   HBITMAP mask = CreateBitmap(
    177       custom_size_.width(), custom_size_.height(), 1, 1, NULL);
    178   ICONINFO ii = {0};
    179   ii.fIcon = FALSE;
    180   ii.xHotspot = hotspot_.x();
    181   ii.yHotspot = hotspot_.y();
    182   ii.hbmMask = mask;
    183   ii.hbmColor = bitmap_handle;
    184 
    185   custom_cursor_ = CreateIconIndirect(&ii);
    186 
    187   DeleteObject(mask);
    188   DeleteObject(bitmap_handle);
    189   DeleteDC(workingDC);
    190   ReleaseDC(0, dc);
    191   return custom_cursor_;
    192 }
    193 
    194 gfx::NativeCursor WebCursor::GetNativeCursor() {
    195   return GetCursor(NULL);
    196 }
    197 
    198 void WebCursor::InitFromExternalCursor(HCURSOR cursor) {
    199   WebCursorInfo::Type cursor_type = ToCursorType(cursor);
    200 
    201   InitFromCursorInfo(WebCursorInfo(cursor_type));
    202 
    203   if (cursor_type == WebCursorInfo::TypeCustom)
    204     external_cursor_ = cursor;
    205 }
    206 
    207 void WebCursor::InitPlatformData() {
    208   external_cursor_ = NULL;
    209   custom_cursor_ = NULL;
    210 }
    211 
    212 bool WebCursor::SerializePlatformData(Pickle* pickle) const {
    213   // There are some issues with converting certain HCURSORS to bitmaps. The
    214   // HCURSOR being a user object can be marshaled as is.
    215   // HCURSORs are always 32 bits on Windows, even on 64 bit systems.
    216   return pickle->WriteUInt32(reinterpret_cast<uint32>(external_cursor_));
    217 }
    218 
    219 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
    220   return pickle->ReadUInt32(iter, reinterpret_cast<uint32*>(&external_cursor_));
    221 }
    222 
    223 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
    224   if (!IsCustom())
    225     return true;
    226 
    227   return (external_cursor_ == other.external_cursor_);
    228 }
    229 
    230 void WebCursor::CopyPlatformData(const WebCursor& other) {
    231   external_cursor_ = other.external_cursor_;
    232   // The custom_cursor_ member will be initialized to a HCURSOR the next time
    233   // the GetCursor member function is invoked on this WebCursor instance. The
    234   // cursor is created using the data in the custom_data_ vector.
    235   custom_cursor_ = NULL;
    236 }
    237 
    238 void WebCursor::CleanupPlatformData() {
    239   external_cursor_ = NULL;
    240 
    241   if (custom_cursor_) {
    242     DestroyIcon(custom_cursor_);
    243     custom_cursor_ = NULL;
    244   }
    245 }
    246