mouse.pp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Mouse unit for linux
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit Mouse;
  14. interface
  15. {$i mouseh.inc}
  16. implementation
  17. uses
  18. windows,dos,Winevent;
  19. {$i mouse.inc}
  20. var
  21. ChangeMouseEvents : TCriticalSection;
  22. LastHandlerMouseEvent : TMouseEvent;
  23. procedure MouseEventHandler(var ir:INPUT_RECORD);
  24. var
  25. e : TMouseEvent;
  26. begin
  27. EnterCriticalSection(ChangeMouseEvents);
  28. e.x:=ir.Event.MouseEvent.dwMousePosition.x;
  29. e.y:=ir.Event.MouseEvent.dwMousePosition.y;
  30. e.buttons:=0;
  31. e.action:=0;
  32. if (ir.Event.MouseEvent.dwButtonState and FROM_LEFT_1ST_BUTTON_PRESSED<>0) then
  33. e.buttons:=e.buttons or MouseLeftButton;
  34. if (ir.Event.MouseEvent.dwButtonState and FROM_LEFT_2ND_BUTTON_PRESSED<>0) then
  35. e.buttons:=e.buttons or MouseMiddleButton;
  36. if (ir.Event.MouseEvent.dwButtonState and RIGHTMOST_BUTTON_PRESSED<>0) then
  37. e.buttons:=e.buttons or MouseRightButton;
  38. if (Lasthandlermouseevent.x<>e.x) or (LasthandlerMouseEvent.y<>e.y) then
  39. e.Action:=MouseActionMove;
  40. if (LastHandlerMouseEvent.Buttons<>e.Buttons) then
  41. begin
  42. if (LasthandlerMouseEvent.Buttons=0) then
  43. e.Action:=MouseActionDown
  44. else
  45. e.Action:=MouseActionUp;
  46. end;
  47. //
  48. // The mouse event compression here was flawed and could lead
  49. // to "zero" mouse actions if the new (x,y) was the same as the
  50. // previous one. (bug 2312)
  51. //
  52. { can we compress the events? }
  53. if (PendingMouseEvents>0) and
  54. (e.buttons=PendingMouseTail^.buttons) and
  55. (e.action=PendingMouseTail^.action) then
  56. begin
  57. PendingMouseTail^.x:=e.x;
  58. PendingMouseTail^.y:=e.y;
  59. end
  60. else
  61. begin
  62. if e.action<>0 then
  63. begin
  64. LastHandlermouseEvent:=e;
  65. PutMouseEvent(e);
  66. end;
  67. // this should be done in PutMouseEvent, now it is PM
  68. // inc(PendingMouseEvents);
  69. end;
  70. LeaveCriticalSection(ChangeMouseEvents);
  71. end;
  72. procedure SysInitMouse;
  73. var
  74. mode : dword;
  75. begin
  76. // enable mouse events
  77. GetConsoleMode(StdInputHandle,@mode);
  78. mode:=mode or ENABLE_MOUSE_INPUT;
  79. SetConsoleMode(StdInputHandle,mode);
  80. PendingMouseHead:=@PendingMouseEvent;
  81. PendingMouseTail:=@PendingMouseEvent;
  82. PendingMouseEvents:=0;
  83. FillChar(LastMouseEvent,sizeof(TMouseEvent),0);
  84. InitializeCriticalSection(ChangeMouseEvents);
  85. SetMouseEventHandler(@MouseEventHandler);
  86. ShowMouse;
  87. end;
  88. procedure SysDoneMouse;
  89. var
  90. mode : dword;
  91. begin
  92. HideMouse;
  93. // disable mouse events
  94. GetConsoleMode(StdInputHandle,@mode);
  95. mode:=mode and (not ENABLE_MOUSE_INPUT);
  96. SetConsoleMode(StdInputHandle,mode);
  97. SetMouseEventHandler(nil);
  98. DeleteCriticalSection(ChangeMouseEvents);
  99. end;
  100. function SysDetectMouse:byte;
  101. var
  102. num : dword;
  103. begin
  104. GetNumberOfConsoleMouseButtons(@num);
  105. SysDetectMouse:=num;
  106. end;
  107. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  108. var
  109. b : byte;
  110. begin
  111. repeat
  112. EnterCriticalSection(ChangeMouseEvents);
  113. b:=PendingMouseEvents;
  114. LeaveCriticalSection(ChangeMouseEvents);
  115. if b>0 then
  116. break
  117. else
  118. sleep(50);
  119. until false;
  120. EnterCriticalSection(ChangeMouseEvents);
  121. MouseEvent:=PendingMouseHead^;
  122. inc(PendingMouseHead);
  123. if longint(PendingMouseHead)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  124. PendingMouseHead:=@PendingMouseEvent;
  125. dec(PendingMouseEvents);
  126. if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
  127. MouseEvent.Action:=MouseActionMove;
  128. if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
  129. begin
  130. if (LastMouseEvent.Buttons=0) then
  131. MouseEvent.Action:=MouseActionDown
  132. else
  133. MouseEvent.Action:=MouseActionUp;
  134. end;
  135. if MouseEvent.action=0 then MousEevent.action:=MouseActionMove; // can sometimes happen due to compression of events.
  136. LastMouseEvent:=MouseEvent;
  137. LeaveCriticalSection(ChangeMouseEvents);
  138. end;
  139. function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  140. begin
  141. EnterCriticalSection(ChangeMouseEvents);
  142. if PendingMouseEvents>0 then
  143. begin
  144. MouseEvent:=PendingMouseHead^;
  145. SysPollMouseEvent:=true;
  146. end
  147. else
  148. SysPollMouseEvent:=false;
  149. LeaveCriticalSection(ChangeMouseEvents);
  150. end;
  151. procedure SysPutMouseEvent(const MouseEvent: TMouseEvent);
  152. begin
  153. if PendingMouseEvents<MouseEventBufSize then
  154. begin
  155. PendingMouseTail^:=MouseEvent;
  156. inc(PendingMouseTail);
  157. if longint(PendingMouseTail)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  158. PendingMouseTail:=@PendingMouseEvent;
  159. { why isn't this done here ?
  160. so the win32 version do this by hand:}
  161. inc(PendingMouseEvents);
  162. end;
  163. end;
  164. function SysGetMouseX:word;
  165. begin
  166. EnterCriticalSection(ChangeMouseEvents);
  167. SysGetMouseX:=LastMouseEvent.x;
  168. LeaveCriticalSection(ChangeMouseEvents);
  169. end;
  170. function SysGetMouseY:word;
  171. begin
  172. EnterCriticalSection(ChangeMouseEvents);
  173. SysGetMouseY:=LastMouseEvent.y;
  174. LeaveCriticalSection(ChangeMouseEvents);
  175. end;
  176. function SysGetMouseButtons:word;
  177. begin
  178. EnterCriticalSection(ChangeMouseEvents);
  179. SysGetMouseButtons:=LastMouseEvent.Buttons;
  180. LeaveCriticalSection(ChangeMouseEvents);
  181. end;
  182. Const
  183. SysMouseDriver : TMouseDriver = (
  184. UseDefaultQueue : False;
  185. InitDriver : @SysInitMouse;
  186. DoneDriver : @SysDoneMouse;
  187. DetectMouse : @SysDetectMouse;
  188. ShowMouse : Nil;
  189. HideMouse : Nil;
  190. GetMouseX : @SysGetMouseX;
  191. GetMouseY : @SysGetMouseY;
  192. GetMouseButtons : @SysGetMouseButtons;
  193. SetMouseXY : Nil;
  194. GetMouseEvent : @SysGetMouseEvent;
  195. PollMouseEvent : @SysPollMouseEvent;
  196. PutMouseEvent : @SysPutMouseEvent;
  197. );
  198. Begin
  199. SetMouseDriver(SysMouseDriver);
  200. end.
  201. {
  202. $Log$
  203. Revision 1.8 2004-11-21 15:24:35 marco
  204. * fix for bug 2246, zero events surpressed by moving compression into handler
  205. Revision 1.7 2004/11/04 10:21:07 peter
  206. GetMouse[X,Y,Buttons] based on LastMouseEvent
  207. Revision 1.6 2002/09/07 16:01:29 peter
  208. * old logs removed and tabs fixed
  209. }