1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Stuff for BeOS.
12  *
13  *      By Jason Wilkins.
14  *
15  *      Windowed mode modifications by Peter Wang.
16  *
17  *      Cursor show/hide in windowed mode added by Angelo Mottola.
18  *
19  *      See readme.txt for copyright information.
20  */
21 
22 #include "bealleg.h"
23 #include "allegro/internal/aintern.h"
24 #include "allegro/platform/aintbeos.h"
25 
26 #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU
27 #error something is wrong with the makefile
28 #endif
29 
30 #define MOUSE_THREAD_NAME     "mouse driver"
31 #define MOUSE_THREAD_PRIORITY 60
32 #define MOUSE_THREAD_PERIOD   20000 // microseconds, 1/50th of a second
33 
34 
35 
36 #define PREFIX_I                "al-bmouse INFO: "
37 #define PREFIX_W                "al-bmouse WARNING: "
38 #define PREFIX_E                "al-bmouse ERROR: "
39 
40 static thread_id     mouse_thread_id      = -1;
41 static volatile bool mouse_thread_running = false;
42 
43 sem_id   _be_mouse_view_attached = -1;
44 BWindow *_be_mouse_window        = NULL;
45 BView   *_be_mouse_view          = NULL;
46 bool	 _be_mouse_window_mode   = false;
47 
48 static int be_mouse_x  = 0;
49 static int be_mouse_y  = 0;
50 static int be_mouse_b  = 0;
51 
52 static int be_mickey_x = 0;
53 static int be_mickey_y = 0;
54 
55 static int limit_up     = 0;
56 static int limit_down   = 0;
57 static int limit_left   = 0;
58 static int limit_right  = 0;
59 
60 static bool be_mouse_warped = false;
61 
62 
mouse_thread(void * mouse_started)63 int32 mouse_thread(void *mouse_started)
64 {
65    BPoint cursor(0, 0);
66    uint32 buttons;
67 
68    if (!_be_mouse_window_mode) {
69       set_mouse_position(320, 240);
70    }
71 
72    release_sem(*(sem_id *)mouse_started);
73 
74    for (;;) {
75       acquire_sem(_be_mouse_view_attached);
76 
77       if (mouse_thread_running == false) {
78          release_sem(_be_mouse_view_attached);
79          /* XXX commented out due to conflicting TRACE in Haiku
80          TRACE(PREFIX_I "mouse thread exited\n");
81          */
82 
83          return 0;
84       }
85 
86       if ((_be_focus_count > 0) && _be_mouse_window->Lock()) {
87          _be_mouse_view->GetMouse(&cursor, &buttons);
88 	 if (!_be_mouse_window_mode) {
89 	    int dx = (int)cursor.x - 320;
90 	    int dy = (int)cursor.y - 240;
91 
92 	    if (be_mouse_warped) {
93 	       dx = 0;
94 	       dy = 0;
95 	       be_mouse_warped = false;
96 	    }
97 	    be_mickey_x = dx;
98 	    be_mickey_y = dy;
99 	    be_mouse_x += dx;
100 	    be_mouse_y += dy;
101 
102 	    if (dx != 0 || dy != 0) {
103 	       set_mouse_position(320, 240);
104 	    }
105 	 }
106 	 else {
107 	    BRect bounds = _be_mouse_window->Bounds();
108 
109 	    if (bounds.Contains(cursor)) {
110 	       int old_x = be_mouse_x;
111 	       int old_y = be_mouse_y;
112 
113 	       _mouse_on = TRUE;
114 	       if (!be_app->IsCursorHidden()) {
115 	          be_app->HideCursor();
116 	       }
117 
118 	       be_mouse_x = (int)(cursor.x - bounds.left);
119 	       be_mouse_y = (int)(cursor.y - bounds.top);
120 	       if (!be_mouse_warped) {
121 	          be_mickey_x += (be_mouse_x - old_x);
122 	          be_mickey_y += (be_mouse_y - old_y);
123 	       }
124 	       else {
125 	          be_mouse_warped = false;
126 	          be_mickey_x = 0;
127 	          be_mickey_y = 0;
128 	       }
129 	    }
130 	    else {
131 	       buttons = 0;
132 	       _mouse_on = FALSE;
133 	       if (be_app->IsCursorHidden()) {
134 	          be_app->ShowCursor();
135 	       }
136 	    }
137 	 }
138 
139 	 _be_mouse_window->Unlock();
140 
141 	 be_mouse_x = CLAMP(limit_left, be_mouse_x, limit_right);
142 	 be_mouse_y = CLAMP(limit_up,   be_mouse_y, limit_down);
143 
144 	 be_mouse_b = 0;
145 	 be_mouse_b |= (buttons & B_PRIMARY_MOUSE_BUTTON)   ? 1 : 0;
146 	 be_mouse_b |= (buttons & B_SECONDARY_MOUSE_BUTTON) ? 2 : 0;
147 	 be_mouse_b |= (buttons & B_TERTIARY_MOUSE_BUTTON)  ? 4 : 0;
148 
149 	 _mouse_x = be_mouse_x;
150 	 _mouse_y = be_mouse_y;
151 	 _mouse_z = _be_mouse_z;
152 	 _mouse_b = be_mouse_b;
153 	 _handle_mouse_input();
154       }
155 
156       release_sem(_be_mouse_view_attached);
157 
158       snooze(MOUSE_THREAD_PERIOD);
159    }
160 }
161 
162 
163 
be_mouse_init(void)164 extern "C" int be_mouse_init(void)
165 {
166    sem_id mouse_started;
167    int32  num_buttons;
168 
169    mouse_started = create_sem(0, "starting mouse driver...");
170 
171    if (mouse_started < 0) {
172       goto cleanup;
173    }
174 
175    mouse_thread_id = spawn_thread(mouse_thread, MOUSE_THREAD_NAME,
176                         MOUSE_THREAD_PRIORITY, &mouse_started);
177 
178    if (mouse_thread_id < 0) {
179       goto cleanup;
180    }
181 
182    mouse_thread_running = true;
183    resume_thread(mouse_thread_id);
184    acquire_sem(mouse_started);
185    delete_sem(mouse_started);
186 
187    be_mickey_x = 0;
188    be_mickey_y = 0;
189 
190    be_mouse_x = 0;
191    be_mouse_y = 0;
192    be_mouse_b = 0;
193 
194    limit_up     = 0;
195    limit_down   = 0;
196    limit_left   = 0;
197    limit_right  = 0;
198 
199    get_mouse_type(&num_buttons);
200 
201    return num_buttons;
202 
203    cleanup: {
204       if (mouse_started > 0) {
205          delete_sem(mouse_started);
206       }
207 
208       be_mouse_exit();
209       return 0;
210    }
211 }
212 
213 
214 
be_mouse_exit(void)215 extern "C" void be_mouse_exit(void)
216 {
217    be_mickey_x = 0;
218    be_mickey_y = 0;
219 
220    be_mouse_x = 0;
221    be_mouse_y = 0;
222    be_mouse_b = 0;
223 
224    limit_up     = 0;
225    limit_down   = 0;
226    limit_left   = 0;
227    limit_right  = 0;
228 
229    mouse_thread_running = false;
230 
231    if (mouse_thread_id > 0) {
232       release_sem(_be_mouse_view_attached);
233       wait_for_thread(mouse_thread_id, &ignore_result);
234       acquire_sem(_be_mouse_view_attached);
235       mouse_thread_id = -1;
236    }
237 }
238 
239 
240 
be_mouse_position(int x,int y)241 extern "C" void be_mouse_position(int x, int y)
242 {
243    acquire_sem(_be_mouse_view_attached);
244    _mouse_x = be_mouse_x = CLAMP(limit_left, x, limit_right);
245    _mouse_y = be_mouse_y = CLAMP(limit_up,   y, limit_down);
246    be_mouse_warped = true;
247    if (!_be_mouse_window_mode)
248       set_mouse_position(320, 240);
249    release_sem(_be_mouse_view_attached);
250 }
251 
252 
253 
be_mouse_set_range(int x1,int y1,int x2,int y2)254 extern "C" void be_mouse_set_range(int x1, int y1, int x2, int y2)
255 {
256    acquire_sem(_be_mouse_view_attached);
257    limit_up     = y1;
258    limit_down   = y2;
259    limit_left   = x1;
260    limit_right  = x2;
261    release_sem(_be_mouse_view_attached);
262 }
263 
264 
265 
be_mouse_set_speed(int xspeed,int yspeed)266 extern "C" void be_mouse_set_speed(int xspeed, int yspeed)
267 {
268 }
269 
270 
271 
be_mouse_get_mickeys(int * mickeyx,int * mickeyy)272 extern "C" void be_mouse_get_mickeys(int *mickeyx, int *mickeyy)
273 {
274    acquire_sem(_be_mouse_view_attached);
275    if (mickeyx != NULL) {
276       *mickeyx = be_mickey_x;
277    }
278 
279    if (mickeyy != NULL) {
280       *mickeyy = be_mickey_y;
281    }
282 
283    be_mickey_x = 0;
284    be_mickey_y = 0;
285    release_sem(_be_mouse_view_attached);
286 }
287