xref: /haiku/src/add-ons/accelerants/skeleton/Cursor.c (revision bc3955fea5b07e2e94a27fc05e4bb58fe6f0319b)
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 
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 	/* 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 
146 void 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