2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: Mouse emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
16 /* PRIVATE VARIABLES **********************************************************/
18 static MOUSE_MODE Mode
, PreviousMode
;
19 static COORD Position
;
20 static ULONG WidthMm
, HeightMm
, WidthPixels
, HeightPixels
;
21 static ULONG SampleRate
;
22 static ULONG Resolution
;
23 static BOOLEAN Scaling
;
24 static BOOLEAN Reporting
;
26 static ULONG ButtonState
;
27 static SHORT HorzCounter
;
28 static SHORT VertCounter
;
29 static CHAR ScrollCounter
;
31 /* PRIVATE FUNCTIONS **********************************************************/
33 static VOID
MouseResetConfig(VOID
)
35 /* Reset the configuration to defaults */
42 static VOID
MouseResetCounters(VOID
)
44 /* Reset all flags and counters */
45 ButtonState
= HorzCounter
= VertCounter
= ScrollCounter
= 0;
48 static VOID
MouseReset(VOID
)
50 /* Reset everything */
54 /* Enter streaming mode and the reset the mouse ID */
55 Mode
= MOUSE_STREAMING_MODE
;
58 /* Send the Basic Assurance Test success code and the device ID */
59 KeyboardQueuePush(MOUSE_BAT_SUCCESS
);
60 KeyboardQueuePush(MouseId
);
64 static VOID
MouseGetPacket(PMOUSE_PACKET Packet
)
66 /* Clear the packet */
67 ZeroMemory(Packet
, sizeof(MOUSE_PACKET
));
69 Packet
->Flags
|= MOUSE_ALWAYS_SET
;
71 /* Check for horizontal overflows */
72 if ((HorzCounter
< MOUSE_MIN
) || (HorzCounter
> MOUSE_MAX
))
74 if (HorzCounter
> MOUSE_MAX
) HorzCounter
= MOUSE_MAX
;
75 if (HorzCounter
< MOUSE_MIN
) HorzCounter
= MOUSE_MIN
;
77 Packet
->Flags
|= MOUSE_X_OVERFLOW
;
80 /* Check for vertical overflows */
81 if ((VertCounter
< MOUSE_MIN
) || (VertCounter
> MOUSE_MAX
))
83 if (VertCounter
> MOUSE_MIN
) VertCounter
= MOUSE_MIN
;
84 if (VertCounter
< MOUSE_MIN
) VertCounter
= MOUSE_MIN
;
86 Packet
->Flags
|= MOUSE_Y_OVERFLOW
;
89 /* Set the sign flags */
90 if (HorzCounter
& MOUSE_SIGN_BIT
) Packet
->Flags
|= MOUSE_X_SIGN
;
91 if (HorzCounter
& MOUSE_SIGN_BIT
) Packet
->Flags
|= MOUSE_Y_SIGN
;
93 /* Set the button flags */
94 if (ButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
) Packet
->Flags
|= MOUSE_LEFT_BUTTON
;
95 if (ButtonState
& FROM_LEFT_2ND_BUTTON_PRESSED
) Packet
->Flags
|= MOUSE_MIDDLE_BUTTON
;
96 if (ButtonState
& RIGHTMOST_BUTTON_PRESSED
) Packet
->Flags
|= MOUSE_RIGHT_BUTTON
;
100 if (ButtonState
& FROM_LEFT_3RD_BUTTON_PRESSED
) Packet
->Extra
|= MOUSE_4TH_BUTTON
;
101 if (ButtonState
& FROM_LEFT_4TH_BUTTON_PRESSED
) Packet
->Extra
|= MOUSE_5TH_BUTTON
;
106 /* Set the scroll counter */
107 Packet
->Extra
|= (UCHAR
)ScrollCounter
& 0x0F;
110 /* Store the counters in the packet */
111 Packet
->HorzCounter
= LOBYTE(HorzCounter
);
112 Packet
->VertCounter
= LOBYTE(VertCounter
);
114 /* Reset the counters */
115 MouseResetCounters();
119 /* PUBLIC FUNCTIONS ***********************************************************/
121 VOID
MouseUpdatePosition(PCOORD NewPosition
)
123 /* Update the counters */
124 HorzCounter
+= ((NewPosition
->X
- Position
.X
) * WidthMm
* Resolution
) / WidthPixels
;
125 VertCounter
+= ((NewPosition
->Y
- Position
.Y
) * HeightMm
* Resolution
) / HeightPixels
;
127 /* Update the position */
128 Position
= *NewPosition
;
131 VOID
MouseUpdateButtons(ULONG NewButtonState
)
133 ButtonState
= NewButtonState
;
136 VOID
MouseScroll(LONG Direction
)
138 ScrollCounter
+= Direction
;
141 COORD
MouseGetPosition(VOID
)
146 VOID
MouseCommand(BYTE Command
)
150 /* Set 1:1 Scaling */
154 KeyboardQueuePush(MOUSE_ACK
);
158 /* Set 2:1 Scaling */
162 KeyboardQueuePush(MOUSE_ACK
);
169 // TODO: NOT IMPLEMENTED
177 // TODO: NOT IMPLEMENTED
182 /* Enter Streaming Mode */
185 MouseResetCounters();
186 Mode
= MOUSE_STREAMING_MODE
;
188 KeyboardQueuePush(MOUSE_ACK
);
195 // TODO: NOT IMPLEMENTED
200 /* Return From Wrap Mode */
203 if (Mode
== MOUSE_WRAP_MODE
)
205 /* Restore the previous mode */
206 MouseResetCounters();
208 KeyboardQueuePush(MOUSE_ACK
);
210 else KeyboardQueuePush(MOUSE_ERROR
);
215 /* Enter Wrap Mode */
218 if (Mode
!= MOUSE_WRAP_MODE
)
220 /* Save the previous mode */
224 MouseResetCounters();
225 Mode
= MOUSE_WRAP_MODE
;
227 KeyboardQueuePush(MOUSE_ACK
);
231 /* Enter Remote Mode */
234 MouseResetCounters();
235 Mode
= MOUSE_REMOTE_MODE
;
237 KeyboardQueuePush(MOUSE_ACK
);
244 KeyboardQueuePush(MOUSE_ACK
);
245 KeyboardQueuePush(MouseId
);
249 /* Set Sample Rate */
252 // TODO: NOT IMPLEMENTED
257 /* Enable Reporting */
261 KeyboardQueuePush(MOUSE_ACK
);
265 /* Disable Reporting */
269 KeyboardQueuePush(MOUSE_ACK
);
276 /* Reset the configuration and counters */
278 MouseResetCounters();
285 // TODO: NOT IMPLEMENTED
297 /* Unknown command */
300 KeyboardQueuePush(MOUSE_ERROR
);
305 BOOLEAN
MouseInit(VOID
)
310 /* Get the console window */
311 hWnd
= GetConsoleWindow();
312 if (hWnd
== NULL
) return FALSE
;
314 /* Get the console window's device context */
315 hDC
= GetWindowDC(hWnd
);
316 if (hDC
== NULL
) return FALSE
;
318 /* Get the parameters */
319 WidthMm
= (ULONG
)GetDeviceCaps(hDC
, HORZSIZE
);
320 HeightMm
= (ULONG
)GetDeviceCaps(hDC
, VERTSIZE
);
321 WidthPixels
= (ULONG
)GetDeviceCaps(hDC
, HORZRES
);
322 HeightPixels
= (ULONG
)GetDeviceCaps(hDC
, VERTRES
);
324 /* Release the device context */
325 ReleaseDC(hWnd
, hDC
);