00001 #include "lapi.h"
00002 #include "hapi.h"
00003
00004
00005 #define eSuspend 1
00006 #define eUnSuspend 2
00007 #define eCleanup 3
00008
00009
00010 #define SPI_GETMOUSESPEED 112
00011
00012 typedef struct MouseData {
00013 int X, Y;
00014 int dx, dy;
00015 int suspended;
00016 HBITMAP cachebitmap, cursorbitmap;
00017 int hx, hy, cx, cy;
00018 int tx, ty;
00019 int wx, wy, ww, wh;
00020 HDC cache, cursor;
00021 SIZE theSize;
00022 } MouseData;
00023
00024 MouseData *micedata = NULL;
00025 int nummice = -1;
00026
00027 HANDLE child = NULL;
00028 volatile int mousecount;
00029 volatile HWND mousewindow;
00030 DWORD dwThreadId;
00031 HANDLE datamutex = NULL;
00032 HANDLE canvas = NULL;
00033 HANDLE mutex = NULL;
00034 HANDLE event = NULL;
00035 HANDLE reply = NULL;
00036
00037 int lastsuspended, lastunsuspended, lastmoved;
00038
00039 unsigned int events;
00040 volatile int call, parameter;
00041
00042 int accel[3];
00043 int speed;
00044 int rx, ry;
00045
00046 HDC tmp = NULL;
00047
00048 #ifdef HMONITOR
00049 HMONITOR monitor = NULL;
00050 MONITORINFO minfo;
00051 #endif
00052 int mleft, mright, mtop, mbottom;
00053 HDC screen;
00054
00055 #define abs(x) (max((x),-(x)))
00056
00057 void __cdecl thehCallback(int number, signed int dx, signed int dy, unsigned int buttons, int suspended) {
00058 int x, y;
00059 x = y = 1;
00060 if (suspended)
00061 lastsuspended = number;
00062 else
00063 lastunsuspended = number;
00064 lastmoved = number;
00065 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00066 if (events & ACCELERATE) {
00067 if (accel[2]) {
00068 if (abs(dx) > accel[0])
00069 x *= 2;
00070 if (abs(dy) > accel[0])
00071 y *= 2;
00072 if (accel[2] == 2) {
00073 if (abs(dx) > accel[1])
00074 x *= 2;
00075 if (abs(dy) > accel[1])
00076 y *= 2;
00077 }
00078 }
00079 dx *= x;
00080 dy *= y;
00081
00082 if (speed >= 10) {
00083 dx *= (speed - 6); dy *= (speed - 6);
00084 dx += rx; dy += ry;
00085 rx = dx % 4; ry = ry % 4;
00086 dx /= 4; dy /= 4;
00087 } else {
00088 switch (speed) {
00089 case 0:
00090 case 1:
00091 dx += rx; dy += ry;
00092 rx = dx % 32; ry = dy % 32;
00093 dx /= 32; dy /= 32;
00094 break;
00095 case 2:
00096 case 3:
00097 dx += rx; dy += ry;
00098 rx = dx % 16; ry = dy % 16;
00099 dx /= 16; dy /= 16;
00100 break;
00101 case 4:
00102 case 5:
00103 dx += rx; dy += ry;
00104 rx = dx % 4; ry = dy % 4;
00105 dx /= 4; dy /= 4;
00106 break;
00107 case 6:
00108 case 7:
00109 dx += rx; dy += ry;
00110 rx = dx % 2; ry = dy % 2;
00111 dx /= 2; dy /= 2;
00112 break;
00113 case 8:
00114 case 9:
00115 dx *= 3; dy *= 3;
00116 dx += rx; dy += ry;
00117 rx = dx % 4; ry = dy % 4;
00118 dx /= 4; dy /= 4;
00119 break;
00120 }
00121 }
00122 }
00123
00124 if ((number <= nummice) && (number > 0)) {
00125 micedata[number - 1].X += dx;
00126 micedata[number - 1].Y += dy;
00127 if (events & CLIP) {
00128 micedata[number - 1].X = max(mleft, min(mright, micedata[number - 1].X));
00129 micedata[number - 1].Y = max(mtop, min(mbottom, micedata[number - 1].Y));
00130 }
00131 micedata[number - 1].dx += dx;
00132 micedata[number - 1].dy += dy;
00133 }
00134
00135 ReleaseMutex(datamutex);
00136 if (mousewindow != NULL) {
00137 WPARAM w = MAKEWPARAM(buttons, ((number & 0xff) << 8) | (((unsigned int) suspended) & 0xff));
00138 LPARAM l = MAKELPARAM(dx, dy);
00139 if (((l && (events & MOVEMENT)) || (buttons && (events & BUTTON))) &&
00140 ((events & SUSPEND) || (!suspended)))
00141 PostMessage(mousewindow, WM_USER + 1001, w, l);
00142 }
00143 hUpdateCursors(TRUE);
00144 }
00145
00146 void __cdecl hLockCanvas() {
00147 while (WaitForSingleObjectEx(canvas, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00148 }
00149
00150 void __cdecl hUpdateCursors(int useCache) {
00151 if (datamutex == NULL) return;
00152 if (events & CURSOR) {
00153 int i;
00154 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00155 if (useCache) {
00156 if (WaitForSingleObjectEx(canvas, 0, TRUE) != WAIT_OBJECT_0) {
00157 ReleaseMutex(datamutex);
00158 return;
00159 }
00160 } else
00161 while (WaitForSingleObjectEx(canvas, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00162
00163
00164 for (i = 0; i < nummice; ++i) {
00165 micedata[i].tx = micedata[i].X;
00166 micedata[i].ty = micedata[i].Y;
00167 if ((micedata[i].cursor)) {
00168 if (useCache) {
00169 micedata[i].wx = min(micedata[i].cx, micedata[i].tx) - micedata[i].hx;
00170 micedata[i].wy = min(micedata[i].cy, micedata[i].ty) - micedata[i].hy;
00171 micedata[i].ww = abs(micedata[i].cx - micedata[i].tx) + micedata[i].theSize.cx;
00172 micedata[i].wh = abs(micedata[i].cy - micedata[i].ty) + micedata[i].theSize.cy;
00173 } else {
00174 micedata[i].wx = micedata[i].tx - micedata[i].hx;
00175 micedata[i].wy = micedata[i].ty - micedata[i].hy;
00176 micedata[i].ww = micedata[i].theSize.cx;
00177 micedata[i].wh = micedata[i].theSize.cy;
00178 }
00179 BitBlt(tmp, micedata[i].wx, micedata[i].wy, micedata[i].ww, micedata[i].wh, screen, micedata[i].wx, micedata[i].wy, SRCCOPY);
00180 }
00181 }
00182
00183 if (useCache)
00184 for (i = 0; i < nummice; ++i)
00185 BitBlt(tmp, micedata[i].cx - micedata[i].hx, micedata[i].cy - micedata[i].hy, micedata[i].theSize.cx, micedata[i].theSize.cy, micedata[i].cache, 0, 0, SRCCOPY);
00186
00187 for (i = 0; i < nummice; ++i)
00188 BitBlt(micedata[i].cache, 0, 0, micedata[i].theSize.cx, micedata[i].theSize.cy, tmp, micedata[i].tx - micedata[i].hx, micedata[i].ty - micedata[i].hy, SRCCOPY);
00189
00190 for (i = 0; i < nummice; ++i) {
00191 if (!micedata[i].suspended) {
00192 if (micedata[i].cursor)
00193 TransparentBlt(tmp, micedata[i].tx - micedata[i].hx, micedata[i].ty - micedata[i].hy, micedata[i].theSize.cx, micedata[i].theSize.cy, micedata[i].cursor, 0, 0, micedata[i].theSize.cx, micedata[i].theSize.cy, RGB(255, 0, 205));
00194 BitBlt(screen, micedata[i].wx, micedata[i].wy, micedata[i].ww, micedata[i].wh, tmp, micedata[i].wx, micedata[i].wy, SRCCOPY);
00195 micedata[i].cx = micedata[i].tx;
00196 micedata[i].cy = micedata[i].ty;
00197 }
00198 }
00199 ReleaseMutex(canvas);
00200 ReleaseMutex(datamutex);
00201 }
00202 }
00203
00204
00205 DWORD WINAPI MainThread(LPVOID lpParameter) {
00206 int loop = TRUE;
00207 lRegisterCallback(thehCallback);
00208 parameter = lGetMice(mousecount);
00209 SetEvent(reply);
00210 while (loop) {
00211 if (WaitForSingleObjectEx(event, INFINITE, TRUE) == WAIT_OBJECT_0) {
00212 switch (call) {
00213 case eSuspend:
00214 lSuspendMouse(parameter);
00215 break;
00216 case eUnSuspend:
00217 lUnSuspendMouse(parameter);
00218 break;
00219 case eCleanup:
00220 lUnGetAllMice();
00221 lUnRegisterCallback();
00222 loop = FALSE;
00223 default: ;
00224 }
00225 ResetEvent(event);
00226 SetEvent(reply);
00227 }
00228 #if 0
00229 hUpdateCursors(TRUE);
00230 #endif
00231 }
00232 return 0;
00233 }
00234
00235
00236
00237 int __cdecl hInitialise(int count, HWND window, HDC getscreen, unsigned int getevents) {
00238 int i;
00239 if (event == NULL) {
00240 event = CreateEvent(NULL, TRUE, FALSE, NULL);
00241 reply = CreateEvent(NULL, TRUE, FALSE, NULL);
00242 }
00243 if (datamutex == NULL) {
00244 datamutex = CreateMutex(NULL, TRUE, NULL);
00245 }
00246 if (mutex == NULL) {
00247 mutex = CreateMutex(NULL, TRUE, NULL);
00248 canvas = CreateMutex(NULL, FALSE, NULL);
00249 }
00250 if (child == NULL) {
00251 mousecount = count;
00252 mousewindow = window;
00253 child = CreateThread(NULL, 0, MainThread, NULL, 0, &dwThreadId);
00254 }
00255 if (child == NULL) {
00256 MessageBox(window, "Could not create mouse thread!", "Error!", MB_OK | MB_ICONEXCLAMATION);
00257 ReleaseMutex(mutex);
00258 return 0;
00259 }
00260
00261
00262 SetThreadPriority(child, 5);
00263 events = getevents;
00264
00265
00266 SystemParametersInfo(SPI_GETMOUSE, 0, accel, 0);
00267 #ifdef SPI_GETMOUSESPEED
00268 SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0);
00269 #else
00270 speed = 10;
00271 #endif
00272 rx = ry = 0;
00273
00274
00275 if (events & CURSOR) {
00276 if (getscreen)
00277 screen = getscreen;
00278 else
00279 screen = CreateDC("DISPLAY", NULL, NULL, NULL);
00280 #ifdef HMONITOR
00281 monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
00282 minfo.cbSize = sizeof(MONITORINFO);
00283 GetMonitorInfo(monitor, &minfo);
00284 mleft = minfo.rcMonitor.left;
00285 mright = minfo.rcMonitor.right;
00286 mtop = minfo.rcMonitor.top;
00287 mbottom = minfo.rcMonitor.bottom;
00288 #else
00289 mleft = 0;
00290 mtop = 0;
00291 mright = GetDeviceCaps(screen, HORZRES);
00292 mbottom = GetDeviceCaps(screen, VERTRES);
00293 #endif
00294 } else
00295 events &= (~CLIP);
00296
00297 while (WaitForSingleObjectEx(reply, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00298 nummice = count = parameter;
00299 if (micedata != NULL) free(micedata);
00300 micedata = malloc(sizeof(MouseData) * nummice);
00301 for (i = 0; i < nummice; ++i) {
00302 micedata[i].X = micedata[i].Y = micedata[i].dx = micedata[i].dy =
00303 micedata[i].hx = micedata[i].hy = micedata[i].suspended = 0;
00304 micedata[i].cursor = 0;
00305 micedata[i].cache = 0;
00306 }
00307 ReleaseMutex(datamutex);
00308 ResetEvent(reply);
00309 ReleaseMutex(mutex);
00310 return count;
00311 }
00312
00313 void __cdecl hSuspendMouse(int number) {
00314 if (mutex == NULL) return;
00315 while (WaitForSingleObjectEx(mutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00316 lastsuspended = lastmoved = number;
00317 lastunsuspended = -1;
00318 if ((child != NULL) && (number <= nummice) && (number > 0)) {
00319 micedata[number - 1].suspended = 1;
00320 parameter = number;
00321 call = eSuspend;
00322 SetEvent(event);
00323 while (WaitForSingleObjectEx(reply, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00324 ResetEvent(reply);
00325 }
00326 ReleaseMutex(mutex);
00327 }
00328
00329 void __cdecl hUnSuspendMouse(int number) {
00330 if (mutex == NULL) return;
00331 lastunsuspended = lastmoved = number;
00332 lastsuspended = -1;
00333 while (WaitForSingleObjectEx(mutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00334 if ((child != NULL) && (number <= nummice) && (number > 0)) {
00335 micedata[number - 1].suspended = 0;
00336 parameter = number;
00337 call = eUnSuspend;
00338 SetEvent(event);
00339 while (WaitForSingleObjectEx(reply, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00340 ResetEvent(reply);
00341 }
00342 ReleaseMutex(mutex);
00343 }
00344
00345 void __cdecl hCleanup(void) {
00346 if (mutex == NULL) return;
00347 while (WaitForSingleObjectEx(mutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00348 if (child != NULL) {
00349 call = eCleanup;
00350 SetEvent(event);
00351 while (WaitForSingleObjectEx(reply, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00352 ResetEvent(reply);
00353
00354 CloseHandle(child); child = NULL;
00355 }
00356 ReleaseMutex(mutex);
00357 }
00358
00359 void __cdecl hGetRelativePosition(int number, hPOINT* p) {
00360 if ((datamutex == NULL) || (p == NULL)) return;
00361 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00362 if ((number <= nummice) && (number > 0)) {
00363 p->x = micedata[number - 1].dx;
00364 p->y = micedata[number - 1].dy;
00365 micedata[number - 1].dx -= p->x;
00366 micedata[number - 1].dy -= p->y;
00367 }
00368 ReleaseMutex(datamutex);
00369 }
00370
00371 void __cdecl hGetAbsolutePosition(int number, hPOINT* p) {
00372 if ((datamutex == NULL) || (p == NULL)) return;
00373 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00374 if ((number <= nummice) && (number > 0))
00375 p->x = micedata[number - 1].X;
00376 p->y = micedata[number - 1].Y;
00377 ReleaseMutex(datamutex);
00378 }
00379
00380 void __cdecl hSetAbsolutePosition(int number, hPOINT p) {
00381 if (datamutex == NULL) return;
00382 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00383 if ((number <= nummice) && (number > 0)) {
00384 micedata[number - 1].X = max(mleft, min(mright, p.x));
00385 micedata[number - 1].Y = max(mtop, min(mbottom, p.y));
00386 }
00387 ReleaseMutex(datamutex);
00388 }
00389
00390 void __cdecl hSetCursor(int number, hPOINT p, HBITMAP cursor, BYTE r, BYTE g, BYTE b) {
00391 while (WaitForSingleObjectEx(datamutex, INFINITE, TRUE) != WAIT_OBJECT_0) ;
00392 if ((number <= nummice) && (number > 0)) {
00393 if (micedata[number - 1].cursor) {
00394 DeleteDC(micedata[number - 1].cursor);
00395 DeleteObject(micedata[number - 1].cursorbitmap);
00396 micedata[number - 1].cursor = NULL;
00397 micedata[number - 1].cursorbitmap = NULL;
00398 hUpdateCursors(TRUE);
00399 DeleteDC(micedata[number - 1].cache);
00400 DeleteObject(micedata[number - 1].cachebitmap);
00401 micedata[number - 1].cache = NULL;
00402 micedata[number - 1].cachebitmap = NULL;
00403 }
00404 micedata[number - 1].hx = p.x;
00405 micedata[number - 1].hy = p.y;
00406 if (cursor) {
00407 micedata[number - 1].cursor = CreateCompatibleDC(screen);
00408 micedata[number - 1].cache = CreateCompatibleDC(screen);
00409 if (tmp == NULL) {
00410 tmp = CreateCompatibleDC(screen);
00411 SelectObject(tmp, CreateCompatibleBitmap(screen, GetDeviceCaps(screen, HORZRES), GetDeviceCaps(screen, VERTRES)));
00412 }
00413 micedata[number - 1].theSize.cx = 18;
00414 micedata[number - 1].theSize.cy = 18;
00415
00416
00417 micedata[number - 1].cursorbitmap = CreateCompatibleBitmap(screen, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy);
00418 micedata[number - 1].cachebitmap = CreateCompatibleBitmap(screen, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy);
00419
00420 SelectObject(micedata[number - 1].cursor, cursor);
00421 SelectObject(micedata[number - 1].cache, micedata[number - 1].cachebitmap);
00422
00423 BitBlt(micedata[number - 1].cache, 0, 0, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy, micedata[number - 1].cursor, 0, 0, SRCCOPY);
00424 SelectObject(micedata[number - 1].cursor, micedata[number - 1].cursorbitmap);
00425
00426 FillRgn(micedata[number - 1].cursor, CreateRectRgn(0, 0, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy), CreateSolidBrush(RGB(r, g, b)));
00427 TransparentBlt(micedata[number - 1].cursor, 0, 0, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy, micedata[number - 1].cache, 0, 0, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy, RGB(255, 0, 204));
00428
00429 BitBlt(micedata[number - 1].cache, 0, 0, micedata[number - 1].theSize.cx, micedata[number - 1].theSize.cy, screen, 0, 0, WHITENESS);
00430 micedata[number - 1].cx = -10 - micedata[number - 1].theSize.cx - p.x;
00431 micedata[number - 1].cy = -10 - micedata[number - 1].theSize.cy - p.y;
00432 }
00433 }
00434 hUpdateCursors(TRUE);
00435 ReleaseMutex(datamutex);
00436 }
00437
00438 int __cdecl hGetLastSuspended(void) {
00439 int i = lastsuspended;
00440 lastsuspended = -1;
00441 return i;
00442 }
00443
00444 int __cdecl hGetLastUnSuspended(void) {
00445 int i = lastunsuspended;
00446 lastunsuspended = -1;
00447 return i;
00448 }
00449
00450 int __cdecl hGetLastMoved(void) {
00451 int i = lastmoved;
00452 lastmoved = -1;
00453 return i;
00454 }
00455