1/*
2 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
3 * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "CursorGtk.h"
30
31#include "Image.h"
32#include "IntPoint.h"
33
34#include <wtf/Assertions.h>
35
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
38
39namespace WebCore {
40
41static GdkCursor* customCursorNew(CustomCursorType cursorType)
42{
43    CustomCursor cursor = CustomCursors[cursorType];
44    GdkCursor* c = gdk_cursor_new_from_name(gdk_display_get_default(), cursor.name);
45    if (!c) {
46        const GdkColor fg = { 0, 0, 0, 0 };
47        const GdkColor bg = { 65535, 65535, 65535, 65535 };
48
49        GdkPixmap* source = gdk_bitmap_create_from_data(NULL, cursor.bits, 32, 32);
50        GdkPixmap* mask = gdk_bitmap_create_from_data(NULL, cursor.mask_bits, 32, 32);
51        c = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, cursor.hot_x, cursor.hot_y);
52        g_object_unref(source);
53        g_object_unref(mask);
54    }
55    return c;
56}
57
58
59Cursor::Cursor(const Cursor& other)
60    : m_impl(other.m_impl)
61{
62    if (m_impl)
63        gdk_cursor_ref(m_impl);
64}
65
66Cursor::Cursor(Image* image, const IntPoint& hotSpot)
67{
68    GdkPixbuf* pixbuf = image->getGdkPixbuf();
69    m_impl = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, hotSpot.x(), hotSpot.y());
70    g_object_unref(pixbuf);
71}
72
73Cursor::~Cursor()
74{
75    if (m_impl)
76        gdk_cursor_unref(m_impl);
77}
78
79Cursor& Cursor::operator=(const Cursor& other)
80{
81    gdk_cursor_ref(other.m_impl);
82    gdk_cursor_unref(m_impl);
83    m_impl = other.m_impl;
84    return *this;
85}
86
87Cursor::Cursor(GdkCursor* c)
88    : m_impl(c)
89{
90    m_impl = c;
91    ASSERT(c);
92    gdk_cursor_ref(c);
93}
94
95const Cursor& pointerCursor()
96{
97    static Cursor c = gdk_cursor_new(GDK_LEFT_PTR);
98    return c;
99}
100
101const Cursor& crossCursor()
102{
103    static Cursor c = gdk_cursor_new(GDK_CROSS);
104    return c;
105}
106
107const Cursor& handCursor()
108{
109    static Cursor c = gdk_cursor_new(GDK_HAND2);
110    return c;
111}
112
113const Cursor& moveCursor()
114{
115    static Cursor c = gdk_cursor_new(GDK_FLEUR);
116    return c;
117}
118
119const Cursor& iBeamCursor()
120{
121    static Cursor c = gdk_cursor_new(GDK_XTERM);
122    return c;
123}
124
125const Cursor& waitCursor()
126{
127    static Cursor c = gdk_cursor_new(GDK_WATCH);
128    return c;
129}
130
131const Cursor& helpCursor()
132{
133    static Cursor c = gdk_cursor_new(GDK_QUESTION_ARROW);
134    return c;
135}
136
137const Cursor& eastResizeCursor()
138{
139    static Cursor c = gdk_cursor_new(GDK_RIGHT_SIDE);
140    return c;
141}
142
143const Cursor& northResizeCursor()
144{
145    static Cursor c = gdk_cursor_new(GDK_TOP_SIDE);
146    return c;
147}
148
149const Cursor& northEastResizeCursor()
150{
151    static Cursor c = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
152    return c;
153}
154
155const Cursor& northWestResizeCursor()
156{
157    static Cursor c = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
158    return c;
159}
160
161const Cursor& southResizeCursor()
162{
163    static Cursor c = gdk_cursor_new(GDK_BOTTOM_SIDE);
164    return c;
165}
166
167const Cursor& southEastResizeCursor()
168{
169    static Cursor c = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
170    return c;
171}
172
173const Cursor& southWestResizeCursor()
174{
175    static Cursor c = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
176    return c;
177}
178
179const Cursor& westResizeCursor()
180{
181    static Cursor c = gdk_cursor_new(GDK_LEFT_SIDE);
182    return c;
183}
184
185const Cursor& northSouthResizeCursor()
186{
187    static Cursor c = gdk_cursor_new(GDK_TOP_TEE);
188    return c;
189}
190
191const Cursor& eastWestResizeCursor()
192{
193    static Cursor c = gdk_cursor_new(GDK_LEFT_SIDE);
194    return c;
195}
196
197const Cursor& northEastSouthWestResizeCursor()
198{
199    static Cursor c = gdk_cursor_new(GDK_SIZING);
200    return c;
201}
202
203const Cursor& northWestSouthEastResizeCursor()
204{
205    static Cursor c = gdk_cursor_new(GDK_SIZING);
206    return c;
207}
208
209const Cursor& columnResizeCursor()
210{
211    static Cursor c = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
212    return c;
213}
214
215const Cursor& rowResizeCursor()
216{
217    static Cursor c = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
218    return c;
219}
220
221const Cursor& middlePanningCursor()
222{
223    return moveCursor();
224}
225
226const Cursor& eastPanningCursor()
227{
228    return eastResizeCursor();
229}
230
231const Cursor& northPanningCursor()
232{
233    return northResizeCursor();
234}
235
236const Cursor& northEastPanningCursor()
237{
238    return northEastResizeCursor();
239}
240
241const Cursor& northWestPanningCursor()
242{
243    return northWestResizeCursor();
244}
245
246const Cursor& southPanningCursor()
247{
248    return southResizeCursor();
249}
250
251const Cursor& southEastPanningCursor()
252{
253    return southEastResizeCursor();
254}
255
256const Cursor& southWestPanningCursor()
257{
258    return southWestResizeCursor();
259}
260
261const Cursor& westPanningCursor()
262{
263    return westResizeCursor();
264}
265
266
267const Cursor& verticalTextCursor()
268{
269    static Cursor c = customCursorNew(CustomCursorVerticalText);
270    return c;
271}
272
273const Cursor& cellCursor()
274{
275    static Cursor c = gdk_cursor_new(GDK_PLUS);
276    return c;
277}
278
279const Cursor& contextMenuCursor()
280{
281    static Cursor c = customCursorNew(CustomCursorContextMenu);
282    return c;
283}
284
285const Cursor& noDropCursor()
286{
287    static Cursor c = customCursorNew(CustomCursorNoDrop);
288    return c;
289}
290
291const Cursor& copyCursor()
292{
293    static Cursor c = customCursorNew(CustomCursorCopy);
294    return c;
295}
296
297const Cursor& progressCursor()
298{
299    static Cursor c = customCursorNew(CustomCursorProgress);
300    return c;
301}
302
303const Cursor& aliasCursor()
304{
305    static Cursor c = customCursorNew(CustomCursorAlias);
306    return c;
307}
308
309const Cursor& noneCursor()
310{
311    static Cursor c = customCursorNew(CustomCursorNone);
312    return c;
313}
314
315const Cursor& notAllowedCursor()
316{
317    return noDropCursor();
318}
319
320const Cursor& zoomInCursor()
321{
322    static Cursor c = customCursorNew(CustomCursorZoomIn);
323    return c;
324}
325
326const Cursor& zoomOutCursor()
327{
328    static Cursor c = customCursorNew(CustomCursorZoomOut);
329    return c;
330}
331
332const Cursor& grabCursor()
333{
334    static Cursor c = customCursorNew(CustomCursorGrab);
335    return c;
336}
337
338const Cursor& grabbingCursor()
339{
340    static Cursor c = customCursorNew(CustomCursorGrabbing);
341    return c;
342}
343
344}
345