1/*
2	Copyright 1999, Be Incorporated.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4
5	Other authors:
6	Mark Watson,
7	Rudolf Cornelissen 4/2003-5/2004
8*/
9
10#define MODULE_BIT 0x20000000
11
12#include "acc_std.h"
13
14status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask)
15{
16	LOG(4,("SET_CURSOR_SHAPE: width %d, height %d, hot_x %d, hot_y %d\n",
17		width, height, hot_x, hot_y));
18
19	if ((width != 16) || (height != 16))
20	{
21		return B_ERROR;
22	}
23	else if ((hot_x >= width) || (hot_y >= height))
24	{
25		return B_ERROR;
26	}
27	else
28	{
29		head1_cursor_define(andMask,xorMask);
30		if ((si->dm.flags & DUALHEAD_BITS) != DUALHEAD_OFF)
31			head2_cursor_define(andMask,xorMask);
32
33		/* Update cursor variables appropriately. */
34		si->cursor.width = width;
35		si->cursor.height = height;
36		si->cursor.hot_x = hot_x;
37		si->cursor.hot_y = hot_y;
38	}
39
40	return B_OK;
41}
42
43/* Move the cursor to the specified position on the desktop, taking account of virtual/dual issues */
44void MOVE_CURSOR(uint16 x, uint16 y)
45{
46	uint16 hds = si->dm.h_display_start;	/* the current horizontal starting pixel */
47	uint16 vds = si->dm.v_display_start;	/* the current vertical starting line */
48	uint16 h_adjust;
49
50	/* clamp cursor to display */
51	if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1;
52	if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1;
53
54	/* store, for our info */
55	si->cursor.x = x;
56	si->cursor.y = y;
57
58	/* setting up minimum amount to scroll not needed:
59	 * Nvidia cards can always do pixelprecise panning on both heads */
60	h_adjust = 0x00;
61
62	/* adjust h/v_display_start to move cursor onto screen */
63	switch (si->dm.flags & DUALHEAD_BITS)
64	{
65	case DUALHEAD_ON:
66	case DUALHEAD_SWITCH:
67		if (x >= ((si->dm.timing.h_display * 2) + hds))
68		{
69			hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
70			/* make sure we stay within the display! */
71			if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
72				hds -= (h_adjust + 1);
73		}
74		else if (x < hds)
75			hds = x & ~h_adjust;
76		break;
77	default:
78		if (x >= (si->dm.timing.h_display + hds))
79		{
80			hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
81			/* make sure we stay within the display! */
82			if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
83				hds -= (h_adjust + 1);
84		}
85		else if (x < hds)
86			hds = x & ~h_adjust;
87		break;
88	}
89
90	if (y >= (si->dm.timing.v_display + vds))
91		vds = y - si->dm.timing.v_display + 1;
92	else if (y < vds)
93		vds = y;
94
95	/* reposition the desktop _and_ the overlay on the display if required */
96	if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
97	{
98		MOVE_DISPLAY(hds,vds);
99		eng_bes_move_overlay();
100	}
101
102	/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
103	if (x > (hds + si->cursor.hot_x)) x -= (hds + si->cursor.hot_x);
104	else x = 0;
105	if (y > (vds + si->cursor.hot_y)) y -= (vds + si->cursor.hot_y);
106	else y = 0;
107
108	/* position the cursor on the display */
109	switch (si->dm.flags & DUALHEAD_BITS)
110	{
111	case DUALHEAD_CLONE:
112		head1_cursor_position(x,y);
113		head2_cursor_position(x,y);
114		break;
115	case DUALHEAD_ON:
116	case DUALHEAD_SWITCH:
117		if (x < si->dm.timing.h_display)
118		{
119			if (si->cursor.dh_right)
120			{
121				LOG(4,("MOVE_CURSOR: now on left side\n"));
122				head2_cursor_hide();
123				head1_cursor_show();
124				si->cursor.dh_right = false;
125			}
126			head1_cursor_position(x, y);
127		}
128		else
129		{
130			if (!si->cursor.dh_right)
131			{
132				LOG(4,("MOVE_CURSOR: now on right side\n"));
133				head1_cursor_hide();
134				head2_cursor_show();
135				si->cursor.dh_right = true;
136			}
137			head2_cursor_position((x - si->dm.timing.h_display), y);
138		}
139		break;
140	default: /* singlehead mode */
141		head1_cursor_position(x,y);
142		break;
143	}
144}
145
146void SHOW_CURSOR(bool is_visible)
147{
148	/* record for our info */
149	si->cursor.is_visible = is_visible;
150
151	switch (si->dm.flags & DUALHEAD_BITS)
152	{
153	case DUALHEAD_CLONE:
154		if (is_visible)
155		{
156			head1_cursor_show();
157			head2_cursor_show();
158		}
159		else
160		{
161			head1_cursor_hide();
162			head2_cursor_hide();
163		}
164		break;
165	case DUALHEAD_ON:
166	case DUALHEAD_SWITCH:
167		if (is_visible)
168		{
169			if (!si->cursor.dh_right)
170			{
171				head1_cursor_show();
172			}
173			else
174			{
175				head2_cursor_show();
176			}
177		}
178		else
179		{
180			head1_cursor_hide();
181			head2_cursor_hide();
182		}
183		break;
184	default: /* singlehead mode */
185		if (is_visible)
186		{
187			head1_cursor_show();
188		}
189		else
190		{
191			head1_cursor_hide();
192		}
193		break;
194	}
195}
196