1/*
2 * Copyright 2001-2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Frans van Nispen (xlr8@tref.nl)
7 *		Gabe Yoder (gyoder@stny.rr.com)
8 *		Axel Dörfler, axeld@pinc-software.de
9 */
10
11/**	BCursor describes a view-wide or application-wide cursor. */
12
13/**
14	@note:	As BeOS only supports 16x16 monochrome cursors, and I would like
15			to see a nice shadowes one, we will need to extend this one.
16 */
17
18#include <AppDefs.h>
19#include <Cursor.h>
20
21#include <AppServerLink.h>
22#include <ServerProtocol.h>
23
24
25const BCursor *B_CURSOR_SYSTEM_DEFAULT;
26const BCursor *B_CURSOR_I_BEAM;
27	// these are initialized in BApplication::InitData()
28
29BCursor::BCursor(const void *cursorData)
30	:
31	fServerToken(-1),
32	fNeedToFree(false)
33{
34	const uint8 *data = (const uint8 *)cursorData;
35
36	if (data == B_HAND_CURSOR || data == B_I_BEAM_CURSOR) {
37		// just use the default cursors from the app_server
38		fServerToken = data == B_HAND_CURSOR ?
39			B_CURSOR_ID_SYSTEM_DEFAULT : B_CURSOR_ID_I_BEAM;
40		return;
41	}
42
43	// Create a new cursor in the app_server
44
45	if (data == NULL
46		|| data[0] != 16	// size
47		|| data[1] != 1		// depth
48		|| data[2] >= 16 || data[3] >= 16)	// hot-spot
49		return;
50
51	// Send data directly to server
52	BPrivate::AppServerLink link;
53	link.StartMessage(AS_CREATE_CURSOR);
54	link.Attach(cursorData, 68);
55
56	status_t status;
57	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
58		link.Read<int32>(&fServerToken);
59		fNeedToFree = true;
60	}
61}
62
63
64BCursor::BCursor(BCursorID id)
65	:
66	fServerToken(id),
67	fNeedToFree(false)
68{
69}
70
71
72BCursor::BCursor(const BCursor& other)
73	:
74	fServerToken(-1),
75	fNeedToFree(false)
76{
77	*this = other;
78}
79
80
81BCursor::BCursor(BMessage *data)
82{
83	// undefined on BeOS
84	fServerToken = -1;
85	fNeedToFree = false;
86}
87
88
89BCursor::~BCursor()
90{
91	_FreeCursorData();
92}
93
94
95status_t
96BCursor::Archive(BMessage *into, bool deep) const
97{
98	// not implemented on BeOS
99	return B_OK;
100}
101
102
103BArchivable	*
104BCursor::Instantiate(BMessage *data)
105{
106	// not implemented on BeOS
107	return NULL;
108}
109
110
111BCursor&
112BCursor::operator=(const BCursor& other)
113{
114	if (&other != this && other != *this) {
115		_FreeCursorData();
116
117		fServerToken = other.fServerToken;
118		fNeedToFree = other.fNeedToFree;
119
120		if (fNeedToFree) {
121			// Tell app_server that there is another reference for this
122			// cursor data!
123			BPrivate::AppServerLink link;
124			link.StartMessage(AS_REFERENCE_CURSOR);
125			link.Attach<int32>(fServerToken);
126		}
127	}
128	return *this;
129}
130
131
132bool
133BCursor::operator==(const BCursor& other) const
134{
135	return fServerToken == other.fServerToken;
136}
137
138
139bool
140BCursor::operator!=(const BCursor& other) const
141{
142	return fServerToken != other.fServerToken;
143}
144
145
146status_t
147BCursor::Perform(perform_code d, void *arg)
148{
149	return B_OK;
150}
151
152
153void BCursor::_ReservedCursor1() {}
154void BCursor::_ReservedCursor2() {}
155void BCursor::_ReservedCursor3() {}
156void BCursor::_ReservedCursor4() {}
157
158
159void
160BCursor::_FreeCursorData()
161{
162	// Notify server to deallocate server-side objects for this cursor
163	if (fNeedToFree) {
164		BPrivate::AppServerLink link;
165		link.StartMessage(AS_DELETE_CURSOR);
166		link.Attach<int32>(fServerToken);
167		link.Flush();
168	}
169}
170
171