xref: /haiku/src/add-ons/accelerants/via/Cursor.c (revision 3e216965baa8d58a67bf7372e2bfa13d999f5a9d)
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-9/2005
8 */
9 
10 #define MODULE_BIT 0x20000000
11 
12 #include "acc_std.h"
13 
14 status_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 */
44 void 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 	/* set up minimum amount to scroll */
59 	if (si->dm.flags & DUALHEAD_BITS)
60 	{
61 		//fixme for VIA...
62 		switch(si->dm.space)
63 		{
64 		case B_RGB16_LITTLE:
65 			h_adjust = 0x1f;
66 			break;
67 		case B_RGB32_LITTLE:
68 			h_adjust = 0x0f;
69 			break;
70 		default:
71 			h_adjust = 0x1f;
72 			break;
73 		}
74 	}
75 	else
76 	{
77 		switch(si->dm.space)
78 		{
79 		case B_CMAP8:
80 			h_adjust = 0x07;
81 			break;
82 		case B_RGB15_LITTLE:case B_RGB16_LITTLE:
83 			h_adjust = 0x03;
84 			break;
85 		case B_RGB32_LITTLE:
86 			h_adjust = 0x01;
87 			break;
88 		default:
89 			h_adjust = 0x07;
90 			break;
91 		}
92 	}
93 
94 	/* adjust h/v_display_start to move cursor onto screen */
95 	switch (si->dm.flags & DUALHEAD_BITS)
96 	{
97 	case DUALHEAD_ON:
98 	case DUALHEAD_SWITCH:
99 		if (x >= ((si->dm.timing.h_display * 2) + hds))
100 		{
101 			hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
102 			/* make sure we stay within the display! */
103 			if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
104 				hds -= (h_adjust + 1);
105 		}
106 		else if (x < hds)
107 			hds = x & ~h_adjust;
108 		break;
109 	default:
110 		if (x >= (si->dm.timing.h_display + hds))
111 		{
112 			hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
113 			/* make sure we stay within the display! */
114 			if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
115 				hds -= (h_adjust + 1);
116 		}
117 		else if (x < hds)
118 			hds = x & ~h_adjust;
119 		break;
120 	}
121 
122 	if (y >= (si->dm.timing.v_display + vds))
123 		vds = y - si->dm.timing.v_display + 1;
124 	else if (y < vds)
125 		vds = y;
126 
127 	/* reposition the desktop _and_ the overlay on the display if required */
128 	if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
129 	{
130 		MOVE_DISPLAY(hds,vds);
131 		eng_bes_move_overlay();
132 	}
133 
134 	/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
135 	if (x > (hds + si->cursor.hot_x)) x -= (hds + si->cursor.hot_x);
136 	else x = 0;
137 	if (y > (vds + si->cursor.hot_y)) y -= (vds + si->cursor.hot_y);
138 	else y = 0;
139 
140 	/* position the cursor on the display */
141 	switch (si->dm.flags & DUALHEAD_BITS)
142 	{
143 	case DUALHEAD_CLONE:
144 		head1_cursor_position(x,y);
145 		head2_cursor_position(x,y);
146 		break;
147 	case DUALHEAD_ON:
148 	case DUALHEAD_SWITCH:
149 		if (x < si->dm.timing.h_display)
150 		{
151 			if (si->cursor.dh_right)
152 			{
153 				LOG(4,("MOVE_CURSOR: now on left side\n"));
154 				head2_cursor_hide();
155 				head1_cursor_show();
156 				si->cursor.dh_right = false;
157 			}
158 			head1_cursor_position(x, y);
159 		}
160 		else
161 		{
162 			if (!si->cursor.dh_right)
163 			{
164 				LOG(4,("MOVE_CURSOR: now on right side\n"));
165 				head1_cursor_hide();
166 				head2_cursor_show();
167 				si->cursor.dh_right = true;
168 			}
169 			head2_cursor_position((x - si->dm.timing.h_display), y);
170 		}
171 		break;
172 	default: /* singlehead mode */
173 		head1_cursor_position(x,y);
174 		break;
175 	}
176 }
177 
178 void SHOW_CURSOR(bool is_visible)
179 {
180 	/* record for our info */
181 	si->cursor.is_visible = is_visible;
182 
183 	switch (si->dm.flags & DUALHEAD_BITS)
184 	{
185 	case DUALHEAD_CLONE:
186 		if (is_visible)
187 		{
188 			head1_cursor_show();
189 			head2_cursor_show();
190 		}
191 		else
192 		{
193 			head1_cursor_hide();
194 			head2_cursor_hide();
195 		}
196 		break;
197 	case DUALHEAD_ON:
198 	case DUALHEAD_SWITCH:
199 		if (is_visible)
200 		{
201 			if (!si->cursor.dh_right)
202 			{
203 				head1_cursor_show();
204 			}
205 			else
206 			{
207 				head2_cursor_show();
208 			}
209 		}
210 		else
211 		{
212 			head1_cursor_hide();
213 			head2_cursor_hide();
214 		}
215 		break;
216 	default: /* singlehead mode */
217 		if (is_visible)
218 		{
219 			head1_cursor_show();
220 		}
221 		else
222 		{
223 			head1_cursor_hide();
224 		}
225 		break;
226 	}
227 }
228