]> icculus.org git repositories - btb/d2x.git/blob - arch/win32/mouse.c
move old per-file change logs into new file ChangeLog-old
[btb/d2x.git] / arch / win32 / mouse.c
1 /* $Id: mouse.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14 /*
15  *
16  * Functions to access Mouse and Cyberman...
17  *
18  */
19
20 #define WIN32_LEAN_AND_MEAN
21 #include <dinput.h>
22
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "error.h"
29 #include "fix.h"
30 #include "mouse.h"
31 #include "mono.h"
32 #include "timer.h"
33 #include "args.h"
34
35 // These are to kludge up a bit my slightly broken GCC directx port.
36 #ifndef E_FAIL
37 #define E_FAIL (HRESULT)0x80004005L
38 #endif
39 #ifndef SUCCEEDED
40 #define SUCCEEDED(a) ((HRESULT)(a) >= 0)
41 #endif
42 #ifndef S_OK
43 #define S_OK 0
44 #define S_FALSE 1
45 #endif
46 #ifndef SEVERITY_SUCCESS
47 #define SEVERITY_SUCCESS    0
48 #define SEVERITY_ERROR      1
49 #endif
50 #ifndef FACILITY_WIN32
51 #define FACILITY_WIN32                   7
52 #endif
53 #ifndef FIELD_OFFSET
54 #define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
55 #endif
56
57 #define ME_CURSOR_MOVED (1<<0)
58 #define ME_LB_P                 (1<<1)
59 #define ME_LB_R                 (1<<2)
60 #define ME_RB_P                 (1<<3)
61 #define ME_RB_R                 (1<<4)
62 #define ME_MB_P                 (1<<5)
63 #define ME_MB_R                 (1<<6)
64 #define ME_OB_P                 (1<<7)
65 #define ME_OB_R                 (1<<8)
66 #define ME_X_C                  (1<<9)
67 #define ME_Y_C                  (1<<10)
68 #define ME_Z_C                  (1<<11)
69 #define ME_P_C                  (1<<12)
70 #define ME_B_C                  (1<<13)
71 #define ME_H_C                  (1<<14)
72 #define ME_O_C                  (1<<15)
73
74 typedef struct event_info {
75         short x;
76         short y;
77         short z;
78         short pitch;
79         short bank;
80         short heading;
81         ushort button_status;
82         ushort device_dependant;
83 } event_info;
84
85 typedef struct mouse_info {
86         fix             ctime;
87         ubyte   cyberman;
88         int             num_buttons;
89         ubyte   pressed[MOUSE_MAX_BUTTONS];
90         fix             time_went_down[MOUSE_MAX_BUTTONS];
91         fix             time_held_down[MOUSE_MAX_BUTTONS];
92         uint    num_downs[MOUSE_MAX_BUTTONS];
93         uint    num_ups[MOUSE_MAX_BUTTONS];
94         //      ubyte   went_down; /* Not in PC version, not needed with 'num_downs' etc */
95         event_info *x_info;
96         ushort  button_status;
97 } mouse_info;
98
99 typedef struct cyberman_info {
100         ubyte device_type;
101         ubyte major_version;
102         ubyte minor_version;
103         ubyte x_descriptor;
104         ubyte y_descriptor;
105         ubyte z_descriptor;
106         ubyte pitch_descriptor;
107         ubyte roll_descriptor;
108         ubyte yaw_descriptor;
109         ubyte reserved;
110 } cyberman_info;
111
112 static mouse_info Mouse;
113
114 static int Mouse_installed = 0;
115
116 int WMMouse_Handler_Ready = 0;
117 int mouse_wparam, mouse_lparam, mouse_msg;
118
119
120 //GGI data:
121 //extern  ggi_visual_t          visual;
122 //extern  ggi_directbuffer_t            dbuf;   // GGI direct acces to screen memory
123 //extern  ggi_pixellinearbuffer *plb;
124
125 //Mouse globals
126 static double mouse_x, mouse_y;
127 static double mouse_saved_x, mouse_saved_y; //used when hiding/unhiding to reset the real (displayed) postion
128 double mouse_accel=1.0;
129
130 void DrawMouse(void);
131 void EraseMouse(void);
132 void MoveMouse(/*int button,*/ int x, int y);
133
134 #define WIN_WIDTH 640
135 #define WIN_HEIGHT 480
136 #define SCR_WIDTH 640
137 #define SCR_HEIGHT 480
138
139 LPDIRECTINPUT g_lpdi = NULL;
140 LPDIRECTINPUTDEVICE g_lpdidMouse = NULL;
141 extern HWND g_hWnd;
142
143
144 HRESULT ReadMouse (DIDEVICEOBJECTDATA *pdidod)
145 {
146         DWORD cElements = 1;
147         HRESULT hr;
148
149         if (g_lpdidMouse == NULL)
150                 return E_FAIL;
151
152         hr = IDirectInputDevice_GetDeviceData (
153                 g_lpdidMouse,
154                 sizeof (*pdidod),
155                 pdidod,
156                 &cElements,
157                 0);
158
159         if (hr == DIERR_INPUTLOST)
160         {
161                 hr = IDirectInputDevice_Acquire (g_lpdidMouse);
162                 if (SUCCEEDED (hr))
163                 {
164                         hr = IDirectInputDevice_GetDeviceData (
165                                 g_lpdidMouse,
166                                 sizeof (*pdidod),
167                                 pdidod,
168                                 &cElements,
169                                 0);
170                 }
171         }
172
173         if (SUCCEEDED (hr) && cElements != 1)
174                 hr = E_FAIL;
175
176         return hr;
177 }
178
179
180 void UpdateMouseState (DIDEVICEOBJECTDATA *pdidod)
181 {
182 //        fix timeNow = timer_get_fixed_seconds ();
183
184         ULONG iEvt = pdidod->dwOfs;
185         switch (iEvt)
186         {
187                 case DIMOFS_BUTTON0:
188                 case DIMOFS_BUTTON1:
189                 case DIMOFS_BUTTON2:
190                 case DIMOFS_BUTTON3:
191                 {
192                         BOOL bPressed = pdidod->dwData & 0x80;
193                         ULONG iButton = (iEvt - DIMOFS_BUTTON0) + MB_LEFT;
194                         if (bPressed)
195                         {
196                                 if (!Mouse.pressed [iButton])
197                                 {
198                                         Mouse.pressed [iButton] = 1;
199                                         Mouse.time_went_down [iButton] = Mouse.ctime;
200                                         Mouse.num_downs [iButton]++;
201                                         //                      Mouse.went_down = 1;
202                                 }
203                                 Mouse.num_downs [iButton] ++;
204                         }
205                         else
206                         {
207                                 if (Mouse.pressed [iButton])
208                                 {
209                                         Mouse.pressed [iButton] = 0;
210                                         Mouse.time_held_down [iButton] += Mouse.ctime - Mouse.time_went_down [iButton];
211                                         Mouse.num_ups [iButton]++;
212                                         //                      Mouse.went_down = 0;
213                                 }
214                         }
215                         break;
216                 }
217                 case DIMOFS_X:
218                         mouse_x += (double) ((LONG) pdidod->dwData);
219                         break;
220
221                 case DIMOFS_Y:
222                         mouse_y += (double) ((LONG) pdidod->dwData);
223                         break;
224                 case DIMOFS_Z:
225                         break;//hm, handle this?
226                 default:
227                         mprintf((0,"unknown mouse event %i\n",iEvt));
228 //                      exit (iEvt);//not happy.
229                         break;
230         }
231 }
232
233 void mouse_handler()
234 {
235         DIDEVICEOBJECTDATA didod;
236
237         Mouse.ctime = timer_get_fixed_seconds();
238
239         while (SUCCEEDED (ReadMouse (&didod)))
240         {
241                 UpdateMouseState (&didod);
242         }
243 }
244
245 void mouse_flush()
246 {
247         int i;
248         fix CurTime;
249         
250         if (!Mouse_installed)
251                 return;
252
253         mouse_handler();
254         //      _disable();
255         CurTime = timer_get_fixed_seconds();
256         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
257                 Mouse.pressed[i] = 0;
258                 Mouse.time_went_down[i] = CurTime;
259                 Mouse.time_held_down[i] = 0;
260                 Mouse.num_downs[i] = 0;
261                 Mouse.num_ups[i] = 0;
262         }
263         //      Mouse.went_down = 0; /* mac only */
264         //      _enable();
265
266         {
267                 DWORD cElements = INFINITE;
268 //                HRESULT hr =
269                 IDirectInputDevice_GetDeviceData (
270                         g_lpdidMouse,
271                         sizeof (DIDEVICEOBJECTDATA),
272                         NULL,
273                         &cElements,
274                         0);
275         }
276 }
277
278
279 void mouse_close(void)
280 {
281         //      if (Mouse_installed)   // DPH: Unnecessary...
282         WMMouse_Handler_Ready=Mouse_installed = 0;
283
284         if (g_lpdidMouse != NULL)
285         {
286                 IDirectInputDevice_Unacquire (g_lpdidMouse);
287                 IDirectInputDevice_Release (g_lpdidMouse);
288                 g_lpdidMouse = NULL;
289         }
290         if (g_lpdi != NULL)
291         {
292                 IDirectInput_Release (g_lpdi);
293                 g_lpdi = NULL;
294         }
295 }
296
297
298
299 int mouse_init(int unused)
300 {
301         if (FindArg("-nomouse"))
302                 return 0;
303         if (Mouse_installed)
304                 return Mouse.num_buttons;
305         
306         {
307                 HRESULT hr;
308
309                 if (SUCCEEDED (hr = DirectInputCreate (GetModuleHandle (NULL), DIRECTINPUT_VERSION, &g_lpdi, NULL)))
310                 {
311                         if (SUCCEEDED (hr = IDirectInput_CreateDevice (g_lpdi,(void *) &GUID_SysMouse, &g_lpdidMouse, NULL)))
312                         {
313                                 DIPROPDWORD dipdw;
314                                 dipdw.diph.dwSize = sizeof (DIPROPDWORD);
315                                 dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER);
316                                 dipdw.diph.dwObj = 0;
317                                 dipdw.diph.dwHow = DIPH_DEVICE;
318                                 dipdw.dwData = 40;
319
320                                 if (SUCCEEDED (hr = IDirectInputDevice_SetDataFormat (g_lpdidMouse, &c_dfDIMouse)) &&
321                                         //changed on 9/4/99 by Victor Rachels NONEX -> Exclusive
322                                         SUCCEEDED (hr = IDirectInputDevice_SetCooperativeLevel (g_lpdidMouse, g_hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)) &&
323                                         //end this section edit -VR
324                                         SUCCEEDED (hr = IDirectInputDevice_SetProperty (g_lpdidMouse, DIPROP_BUFFERSIZE, &dipdw.diph)) &&
325                                         SUCCEEDED (hr = IDirectInputDevice_Acquire (g_lpdidMouse)))
326                                 {
327                                 }
328                                 else
329                                 {
330                                         IDirectInputDevice_Release (g_lpdidMouse);
331                                         g_lpdidMouse = NULL;
332                                         return 0;
333                                 }
334                         }
335                 }
336         }
337         Mouse.num_buttons = 3;
338         
339         WMMouse_Handler_Ready=Mouse_installed = 1;
340         atexit(mouse_close);
341         mouse_flush();
342         //      mouse_set_center();
343         
344         return Mouse.num_buttons;
345 }
346
347 //WHS: added this
348 void mouse_center() {
349         mouse_x=mouse_saved_x=WIN_WIDTH/2;
350         mouse_y=mouse_saved_y=WIN_HEIGHT/2;
351 }
352
353 void mouse_get_pos( int *x, int *y)
354 {
355         mouse_handler(); //temp
356         
357         *x=(int) mouse_x;
358         *y=(int) mouse_y;
359 }
360
361 void mouse_get_delta( int *dx, int *dy )
362 {
363         if (!Mouse_installed) {
364                 *dx = *dy = 0;
365                 return;
366         }
367         mouse_handler(); //temp
368         
369         *dx = (int) mouse_x - WIN_WIDTH/2;
370         *dy = (int) mouse_y - WIN_HEIGHT/2;
371         
372         //Now reset the mouse position to the center of the screen
373         mouse_x = (double) WIN_WIDTH/2;
374         mouse_y = (double) WIN_HEIGHT/2;
375 }
376
377 void mouse_get_delta_no_reset( int *dx, int *dy )
378 {
379         if (!Mouse_installed) {
380                 *dx = *dy = 0;
381                 return;
382         }
383         mouse_handler(); //temp
384         
385         *dx = (int) mouse_x - WIN_WIDTH/2;
386         *dy = (int) mouse_y - WIN_HEIGHT/2;
387 }
388
389 int mouse_get_btns()
390 {
391         int  i;
392         uint flag=1;
393         int  status = 0;
394         
395         if (!Mouse_installed)
396                 return 0;
397
398         mouse_handler(); //temp
399         
400         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
401                 if (Mouse.pressed[i])
402                         status |= flag;
403                 flag <<= 1;
404         }
405         return status;
406 }
407
408 /* This should be replaced with mouse_button_down_count(int button)     */
409 int mouse_went_down(int button)
410 {
411         int count;
412         
413         if (!Mouse_installed)
414                 return 0;
415
416         mouse_handler(); //temp
417         
418         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
419                 return 0;
420         
421         //      _disable();             
422         count = Mouse.num_downs[button];
423         Mouse.num_downs[button] = 0;
424         
425         //      _enable();
426         return count;
427 }
428
429 // Returns how many times this button has went down since last call.
430 int mouse_button_down_count(int button) 
431 {
432         int count;
433         
434         if (!Mouse_installed)
435                 return 0;
436         
437         mouse_handler(); //temp
438         
439         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
440                 return 0;
441         
442         //      _disable();
443         count = Mouse.num_downs[button];
444         Mouse.num_downs[button] = 0;
445         //      _enable();
446         return count;
447 }
448
449 // Returns 1 if this button is currently down
450 int mouse_button_state(int button)
451 {
452         int state;
453         
454         if (!Mouse_installed)
455                 return 0;
456         
457         mouse_handler(); //temp
458         
459         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
460                 return 0;
461         
462         //      _disable();
463         state = Mouse.pressed[button];
464         //      _enable();
465         return state;
466 }
467
468 // Returns how long this button has been down since last call.
469 fix mouse_button_down_time(int button)  
470 {
471         fix time_down, time;
472         
473         if (!Mouse_installed)
474                 return 0;
475
476         mouse_handler(); //temp
477         
478         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
479                 return 0;
480         
481         //      _disable();
482         if (!Mouse.pressed[button]) {
483                 time_down = Mouse.time_held_down[button];
484                 Mouse.time_held_down[button] = 0;
485         } else {
486                 time = timer_get_fixed_seconds();
487                 time_down = time - Mouse.time_held_down[button];
488                 Mouse.time_held_down[button] = 0;
489         }
490         //      _enable();
491         
492         return time_down;
493 }
494
495 void mouse_get_cyberman_pos( int *x, int *y )
496 {
497 }
498
499
500
501 //WHS: I made this :)
502 void hide_cursor()
503 {
504         ShowCursor(FALSE);
505 }
506
507 void show_cursor()
508 {
509         ShowCursor(TRUE);
510 }
511
512
513 /* New mouse pointer stuff for GGI/DGA */
514 //#include "cursor.h" /* cursor and mask */
515
516 typedef struct Sprite {
517         ushort width;
518         ushort height;
519         byte *pixels;
520         byte *mask;
521 } Sprite;
522
523 //Sprite mouse_sprite = { cursor_width, cursor_height, cursor_bits, cursor_mask_bits};
524
525 //byte *behind_mouse;
526 //byte behind_mouse[cursor_width*cursor_height];
527
528
529 void DrawMouse(void)
530 {
531 }
532
533
534 void EraseMouse(void)
535 {
536 }
537
538 //Should add a mode, relative, absolute
539 #define MOVE_REL 0
540 #define MOVE_ABS 1
541 //void MoveMouse(int mode, int x, int y) {
542
543 void MoveMouse(int x, int y)
544 {
545 }