mouse.pp 6.9 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 and e.buttons<>LasthandlerMouseEvent.Buttons) then
  43. e.Action:=MouseActionUp
  44. else
  45. e.Action:=MouseActionDown;
  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. LastMouseEvent:=e;
  71. LeaveCriticalSection(ChangeMouseEvents);
  72. end;
  73. procedure SysInitMouse;
  74. var
  75. mode : dword;
  76. begin
  77. // enable mouse events
  78. GetConsoleMode(StdInputHandle,@mode);
  79. mode:=mode or ENABLE_MOUSE_INPUT;
  80. SetConsoleMode(StdInputHandle,mode);
  81. PendingMouseHead:=@PendingMouseEvent;
  82. PendingMouseTail:=@PendingMouseEvent;
  83. PendingMouseEvents:=0;
  84. FillChar(LastMouseEvent,sizeof(TMouseEvent),0);
  85. InitializeCriticalSection(ChangeMouseEvents);
  86. SetMouseEventHandler(@MouseEventHandler);
  87. ShowMouse;
  88. end;
  89. procedure SysDoneMouse;
  90. var
  91. mode : dword;
  92. begin
  93. HideMouse;
  94. // disable mouse events
  95. GetConsoleMode(StdInputHandle,@mode);
  96. mode:=mode and (not ENABLE_MOUSE_INPUT);
  97. SetConsoleMode(StdInputHandle,mode);
  98. SetMouseEventHandler(nil);
  99. DeleteCriticalSection(ChangeMouseEvents);
  100. end;
  101. function SysDetectMouse:byte;
  102. var
  103. num : dword;
  104. begin
  105. GetNumberOfConsoleMouseButtons(@num);
  106. SysDetectMouse:=num;
  107. end;
  108. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  109. var
  110. b : byte;
  111. begin
  112. repeat
  113. EnterCriticalSection(ChangeMouseEvents);
  114. b:=PendingMouseEvents;
  115. LeaveCriticalSection(ChangeMouseEvents);
  116. if b>0 then
  117. break
  118. else
  119. sleep(50);
  120. until false;
  121. EnterCriticalSection(ChangeMouseEvents);
  122. MouseEvent:=PendingMouseHead^;
  123. inc(PendingMouseHead);
  124. if longint(PendingMouseHead)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  125. PendingMouseHead:=@PendingMouseEvent;
  126. dec(PendingMouseEvents);
  127. if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
  128. MouseEvent.Action:=MouseActionMove;
  129. if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
  130. begin
  131. if (LastMouseEvent.Buttons and MouseEvent.buttons<>LastMouseEvent.Buttons) then
  132. MouseEvent.Action:=MouseActionUp
  133. else
  134. MouseEvent.Action:=MouseActionDown;
  135. end;
  136. if MouseEvent.action=0 then MousEevent.action:=MouseActionMove; // can sometimes happen due to compression of events.
  137. LastMouseEvent:=MouseEvent;
  138. LeaveCriticalSection(ChangeMouseEvents);
  139. end;
  140. function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  141. begin
  142. EnterCriticalSection(ChangeMouseEvents);
  143. if PendingMouseEvents>0 then
  144. begin
  145. MouseEvent:=PendingMouseHead^;
  146. SysPollMouseEvent:=true;
  147. end
  148. else
  149. SysPollMouseEvent:=false;
  150. LeaveCriticalSection(ChangeMouseEvents);
  151. end;
  152. procedure SysPutMouseEvent(const MouseEvent: TMouseEvent);
  153. begin
  154. if PendingMouseEvents<MouseEventBufSize then
  155. begin
  156. PendingMouseTail^:=MouseEvent;
  157. inc(PendingMouseTail);
  158. if longint(PendingMouseTail)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  159. PendingMouseTail:=@PendingMouseEvent;
  160. { why isn't this done here ?
  161. so the win32 version do this by hand:}
  162. inc(PendingMouseEvents);
  163. end;
  164. end;
  165. function SysGetMouseX:word;
  166. begin
  167. EnterCriticalSection(ChangeMouseEvents);
  168. SysGetMouseX:=LastMouseEvent.x;
  169. LeaveCriticalSection(ChangeMouseEvents);
  170. end;
  171. function SysGetMouseY:word;
  172. begin
  173. EnterCriticalSection(ChangeMouseEvents);
  174. SysGetMouseY:=LastMouseEvent.y;
  175. LeaveCriticalSection(ChangeMouseEvents);
  176. end;
  177. function SysGetMouseButtons:word;
  178. begin
  179. EnterCriticalSection(ChangeMouseEvents);
  180. SysGetMouseButtons:=LastMouseEvent.Buttons;
  181. LeaveCriticalSection(ChangeMouseEvents);
  182. end;
  183. Const
  184. SysMouseDriver : TMouseDriver = (
  185. UseDefaultQueue : False;
  186. InitDriver : @SysInitMouse;
  187. DoneDriver : @SysDoneMouse;
  188. DetectMouse : @SysDetectMouse;
  189. ShowMouse : Nil;
  190. HideMouse : Nil;
  191. GetMouseX : @SysGetMouseX;
  192. GetMouseY : @SysGetMouseY;
  193. GetMouseButtons : @SysGetMouseButtons;
  194. SetMouseXY : Nil;
  195. GetMouseEvent : @SysGetMouseEvent;
  196. PollMouseEvent : @SysPollMouseEvent;
  197. PutMouseEvent : @SysPutMouseEvent;
  198. );
  199. Begin
  200. SetMouseDriver(SysMouseDriver);
  201. end.
  202. {
  203. $Log$
  204. Revision 1.11 2005-03-31 14:43:03 marco
  205. * fix to lastmouseevent update
  206. Revision 1.10 2005/02/14 17:13:32 peter
  207. * truncate log
  208. Revision 1.9 2005/01/12 10:25:48 armin
  209. * Patch for bug 3548 from Peter
  210. }