251 } 252 if (buttons & (1 << 4)) { 253 mouseInput.mi.dwFlags |= MOUSEEVENTF_XUP; 254 mouseInput.mi.mouseData = XBUTTON2; 255 } 256 257 ::SendInput(1, &mouseInput, sizeof(mouseInput)); 258 } 259 260 /* 261 * Class: com_sun_glass_ui_win_WinRobot 262 * Method: _mouseWheel 263 * Signature: (I)V 264 */ 265 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinRobot__1mouseWheel 266 (JNIEnv *env, jobject jrobot, jint wheelAmt) 267 { 268 ::mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheelAmt * -1 * WHEEL_DELTA, 0); 269 } 270 271 void GetScreenCapture(jint x, jint y, jint devw, jint devh, 272 jint *pixelData, jint retw, jint reth); 273 274 /* 275 * Class: com_sun_glass_ui_win_WinRobot 276 * Method: _getPixelColor 277 * Signature: (II)I 278 */ 279 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinRobot__1getPixelColor 280 (JNIEnv *env, jobject jrobot, jint x, jint y) 281 { 282 jfloat fx = (jfloat) x + 0.5f; 283 jfloat fy = (jfloat) y + 0.5f; 284 GlassScreen::FX2Win(&fx, &fy); 285 jint dx = (jint) fx; 286 jint dy = (jint) fy; 287 288 jint val = 0; 289 //NOTE: we don't use the ::GetPixel() on the screen DC because it's not capable of 290 // getting the correct colors when non-opaque windows are present 291 GetScreenCapture(dx, dy, 1, 1, &val, 1, 1); 292 return val; 293 } 294 295 /* 296 * Class: com_sun_glass_ui_win_WinRobot 297 * Method: _getScreenCapture 298 * Signature: (IIII[I;)V 299 */ 300 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinRobot__1getScreenCapture 301 (JNIEnv *env, jobject jrobot, jint x, jint y, jint width, jint height, jintArray pixelArray) 302 { 303 int numPixels = width * height; 304 int pixelDataSize = sizeof(jint) * numPixels; 305 ASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0); 306 307 jint * pixelData = (jint *)(new BYTE[pixelDataSize]); 308 309 if (pixelData) { 310 GetScreenCapture(x, y, width, height, pixelData, width, height); 311 312 // copy pixels into Java array 313 env->SetIntArrayRegion(pixelArray, 0, numPixels, pixelData); 314 delete[] pixelData; 315 } 316 } 317 318 void GetScreenCapture(jint x, jint y, jint devw, jint devh, 319 jint *pixelData, jint retw, jint reth) 320 { 321 HDC hdcScreen = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 322 HDC hdcMem = ::CreateCompatibleDC(hdcScreen); 323 HBITMAP hbitmap; 324 HBITMAP hOldBitmap; 325 HPALETTE hOldPalette = NULL; 326 327 // create an offscreen bitmap 328 hbitmap = ::CreateCompatibleBitmap(hdcScreen, retw, reth); 329 if (hbitmap == NULL) { 330 //TODO: OOM might be better? 331 //throw std::bad_alloc(); 332 } 333 hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hbitmap); 334 335 /* TODO: check this out 336 // REMIND: not multimon-friendly... 337 int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 338 hOldPalette = 339 AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex); 340 AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex); 341 */ 342 343 // copy screen image to offscreen bitmap 344 // CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents 345 // correctly on Win2K/XP 346 static const DWORD dwRop = SRCCOPY|CAPTUREBLT; 347 if (retw == devw && reth == devh) { 348 ::BitBlt(hdcMem, 0, 0, retw, reth, hdcScreen, x, y, dwRop); 349 } else { 350 ::StretchBlt(hdcMem, 0, 0, retw, reth, hdcScreen, x, y, devw, devh, dwRop); 351 } 352 353 static const int BITS_PER_PIXEL = 32; 354 355 struct { 356 BITMAPINFOHEADER bmiHeader; 357 RGBQUAD bmiColors[3]; 358 } BitmapInfo; 359 360 // prepare BITMAPINFO for a 32-bit RGB bitmap 361 ::memset(&BitmapInfo, 0, sizeof(BitmapInfo)); 362 BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 363 BitmapInfo.bmiHeader.biWidth = retw; 364 BitmapInfo.bmiHeader.biHeight = -reth; // negative height means a top-down DIB 365 BitmapInfo.bmiHeader.biPlanes = 1; 366 BitmapInfo.bmiHeader.biBitCount = BITS_PER_PIXEL; 367 BitmapInfo.bmiHeader.biCompression = BI_BITFIELDS; 368 369 // Setup up color masks 370 static const RGBQUAD redMask = {0, 0, 0xFF, 0}; 371 static const RGBQUAD greenMask = {0, 0xFF, 0, 0}; 372 static const RGBQUAD blueMask = {0xFF, 0, 0, 0}; 373 374 BitmapInfo.bmiColors[0] = redMask; 375 BitmapInfo.bmiColors[1] = greenMask; 376 BitmapInfo.bmiColors[2] = blueMask; 377 378 // Get the bitmap data in device-independent, 32-bit packed pixel format 379 ::GetDIBits(hdcMem, hbitmap, 0, reth, pixelData, (BITMAPINFO *)&BitmapInfo, DIB_RGB_COLORS); 380 381 // convert Win32 pixel format (BGRX) to Java format (ARGB) 382 ASSERT(sizeof(jint) == sizeof(RGBQUAD)); 383 jint numPixels = retw * reth; 384 jint *pPixel = pixelData; 385 for(int nPixel = 0; nPixel < numPixels; nPixel++) { 386 RGBQUAD * prgbq = (RGBQUAD *) pPixel; 387 *pPixel++ = WinToJavaPixel(prgbq->rgbRed, prgbq->rgbGreen, prgbq->rgbBlue); 388 } 389 390 // free all the GDI objects we made 391 ::SelectObject(hdcMem, hOldBitmap); 392 if (hOldPalette != NULL) { 393 ::SelectPalette(hdcMem, hOldPalette, FALSE); 394 } 395 ::DeleteObject(hbitmap); 396 ::DeleteDC(hdcMem); 397 ::DeleteDC(hdcScreen); 398 } 399 400 } 401 | 251 } 252 if (buttons & (1 << 4)) { 253 mouseInput.mi.dwFlags |= MOUSEEVENTF_XUP; 254 mouseInput.mi.mouseData = XBUTTON2; 255 } 256 257 ::SendInput(1, &mouseInput, sizeof(mouseInput)); 258 } 259 260 /* 261 * Class: com_sun_glass_ui_win_WinRobot 262 * Method: _mouseWheel 263 * Signature: (I)V 264 */ 265 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinRobot__1mouseWheel 266 (JNIEnv *env, jobject jrobot, jint wheelAmt) 267 { 268 ::mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheelAmt * -1 * WHEEL_DELTA, 0); 269 } 270 271 void GetScreenCapture(jint x, jint y, jint width, jint height, jint *pixelData); 272 273 /* 274 * Class: com_sun_glass_ui_win_WinRobot 275 * Method: _getPixelColor 276 * Signature: (II)I 277 */ 278 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinRobot__1getPixelColor 279 (JNIEnv *env, jobject jrobot, jint x, jint y) 280 { 281 jfloat fx = (jfloat) x + 0.5f; 282 jfloat fy = (jfloat) y + 0.5f; 283 GlassScreen::FX2Win(&fx, &fy); 284 jint dx = (jint) fx; 285 jint dy = (jint) fy; 286 287 jint val = 0; 288 //NOTE: we don't use the ::GetPixel() on the screen DC because it's not capable of 289 // getting the correct colors when non-opaque windows are present 290 GetScreenCapture(dx, dy, 1, 1, &val); 291 return val; 292 } 293 294 /* 295 * Class: com_sun_glass_ui_win_WinRobot 296 * Method: _getScreenCapture 297 * Signature: (IIII[I;)V 298 */ 299 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinRobot__1getScreenCapture 300 (JNIEnv *env, jobject jrobot, jint x, jint y, jint width, jint height, jintArray pixelArray) 301 { 302 int numPixels = width * height; 303 int pixelDataSize = sizeof(jint) * numPixels; 304 ASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0); 305 306 jint * pixelData = (jint *)(new BYTE[pixelDataSize]); 307 308 if (pixelData) { 309 GetScreenCapture(x, y, width, height, pixelData); 310 311 // copy pixels into Java array 312 env->SetIntArrayRegion(pixelArray, 0, numPixels, pixelData); 313 delete[] pixelData; 314 } 315 } 316 317 void GetScreenCapture(jint x, jint y, jint width, jint height, jint *pixelData) 318 { 319 HDC hdcScreen = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 320 HDC hdcMem = ::CreateCompatibleDC(hdcScreen); 321 HBITMAP hbitmap; 322 HBITMAP hOldBitmap; 323 HPALETTE hOldPalette = NULL; 324 325 // create an offscreen bitmap 326 hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height); 327 if (hbitmap == NULL) { 328 //TODO: OOM might be better? 329 //throw std::bad_alloc(); 330 } 331 hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hbitmap); 332 333 /* TODO: check this out 334 // REMIND: not multimon-friendly... 335 int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 336 hOldPalette = 337 AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex); 338 AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex); 339 */ 340 341 // copy screen image to offscreen bitmap 342 // CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents 343 // correctly on Win2K/XP 344 static const DWORD dwRop = SRCCOPY|CAPTUREBLT; 345 ::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y, dwRop); 346 347 static const int BITS_PER_PIXEL = 32; 348 349 struct { 350 BITMAPINFOHEADER bmiHeader; 351 RGBQUAD bmiColors[3]; 352 } BitmapInfo; 353 354 // prepare BITMAPINFO for a 32-bit RGB bitmap 355 ::memset(&BitmapInfo, 0, sizeof(BitmapInfo)); 356 BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 357 BitmapInfo.bmiHeader.biWidth = width; 358 BitmapInfo.bmiHeader.biHeight = -height; // negative height means a top-down DIB 359 BitmapInfo.bmiHeader.biPlanes = 1; 360 BitmapInfo.bmiHeader.biBitCount = BITS_PER_PIXEL; 361 BitmapInfo.bmiHeader.biCompression = BI_BITFIELDS; 362 363 // Setup up color masks 364 static const RGBQUAD redMask = {0, 0, 0xFF, 0}; 365 static const RGBQUAD greenMask = {0, 0xFF, 0, 0}; 366 static const RGBQUAD blueMask = {0xFF, 0, 0, 0}; 367 368 BitmapInfo.bmiColors[0] = redMask; 369 BitmapInfo.bmiColors[1] = greenMask; 370 BitmapInfo.bmiColors[2] = blueMask; 371 372 // Get the bitmap data in device-independent, 32-bit packed pixel format 373 ::GetDIBits(hdcMem, hbitmap, 0, height, pixelData, (BITMAPINFO *)&BitmapInfo, DIB_RGB_COLORS); 374 375 // convert Win32 pixel format (BGRX) to Java format (ARGB) 376 ASSERT(sizeof(jint) == sizeof(RGBQUAD)); 377 jint numPixels = width * height; 378 jint *pPixel = pixelData; 379 for(int nPixel = 0; nPixel < numPixels; nPixel++) { 380 RGBQUAD * prgbq = (RGBQUAD *) pPixel; 381 *pPixel++ = WinToJavaPixel(prgbq->rgbRed, prgbq->rgbGreen, prgbq->rgbBlue); 382 } 383 384 // free all the GDI objects we made 385 ::SelectObject(hdcMem, hOldBitmap); 386 if (hOldPalette != NULL) { 387 ::SelectPalette(hdcMem, hOldPalette, FALSE); 388 } 389 ::DeleteObject(hbitmap); 390 ::DeleteDC(hdcMem); 391 ::DeleteDC(hdcScreen); 392 } 393 394 } 395 |