alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (awt_Robot.cpp)

This example Java source code file (awt_Robot.cpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awtcomponent\:\:masks, awtrobot\:\:getrobot, catch_bad_alloc, dassert, jni_version_1_2, jnicall, jnienv, jniexport, jnu_getenv, null, rgbquad, spif_sendchange, systemparametersinfo, try

The awt_Robot.cpp Java example source code

/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"
#include "awt_Toolkit.h"
#include "awt_Component.h"
#include "awt_Robot.h"
#include "sun_awt_windows_WRobotPeer.h"
#include "java_awt_event_InputEvent.h"
#include <winuser.h>

AwtRobot::AwtRobot( jobject peer )
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    m_peerObject = env->NewWeakGlobalRef(peer);
    JNI_SET_PDATA(peer, this);
}

AwtRobot::~AwtRobot()
{
}

#ifndef SPI_GETMOUSESPEED
#define SPI_GETMOUSESPEED 112
#endif

#ifndef SPI_SETMOUSESPEED
#define SPI_SETMOUSESPEED 113
#endif

void AwtRobot::MouseMove( jint x, jint y)
{
    // Fix for Bug 4288230. See Q193003 from MSDN.
      int oldAccel[3], newAccel[3];
      INT_PTR oldSpeed, newSpeed;
      BOOL bResult;

   // The following values set mouse ballistics to 1 mickey/pixel.
      newAccel[0] = 0;
      newAccel[1] = 0;
      newAccel[2] = 0;
      newSpeed = 10;

      // Save the Current Mouse Acceleration Constants
      bResult = SystemParametersInfo(SPI_GETMOUSE,0,oldAccel,0);
      bResult = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &oldSpeed,0);
      // Set the new Mouse Acceleration Constants (Disabled).
      bResult = SystemParametersInfo(SPI_SETMOUSE,0,newAccel,SPIF_SENDCHANGE);
      bResult = SystemParametersInfo(SPI_SETMOUSESPEED, 0,
                // 4504963: Though the third argument to SystemParameterInfo is
                // declared as a PVOID, as of Windows 2000 it is apparently
                // interpreted as an int.  (The MSDN docs for SPI_SETMOUSESPEED
                // say that it's an integer between 1 and 20, the default being
                // 10).  Instead of passing the @ of the desired value, the
                // value itself is now passed, cast as a PVOID so as to
                // compile.  -bchristi 10/02/2001
                                     (PVOID)newSpeed,
                                     SPIF_SENDCHANGE);

      POINT curPos;
      ::GetCursorPos(&curPos);
      x -= curPos.x;
      y -= curPos.y;

      mouse_event(MOUSEEVENTF_MOVE,x,y,0,0);
      // Move the cursor to the desired coordinates.

      // Restore the old Mouse Acceleration Constants.
      bResult = SystemParametersInfo(SPI_SETMOUSE,0, oldAccel, SPIF_SENDCHANGE);
      bResult = SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)oldSpeed,
                                     SPIF_SENDCHANGE);
}

void AwtRobot::MousePress( jint buttonMask )
{
    DWORD dwFlags = 0L;
    // According to MSDN: Software Driving Software
    // application should consider SM_SWAPBUTTON to correctly emulate user with
    // left handed mouse setup
    BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON);

    if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
        buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK)
    {
        dwFlags |= !bSwap ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
    }

    if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
         buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK)
    {
        dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN;
    }

    if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
         buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK)
    {
        dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
    }

    INPUT mouseInput = {0};
    mouseInput.type = INPUT_MOUSE;
    mouseInput.mi.time = 0;
    mouseInput.mi.dwFlags = dwFlags;
    if ( buttonMask & AwtComponent::masks[3] ) {
        mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN;
        mouseInput.mi.mouseData = XBUTTON1;
    }

    if ( buttonMask & AwtComponent::masks[4] ) {
        mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN;
        mouseInput.mi.mouseData = XBUTTON2;
    }
    ::SendInput(1, &mouseInput, sizeof(mouseInput));
}

void AwtRobot::MouseRelease( jint buttonMask )
{
    DWORD dwFlags = 0L;
    // According to MSDN: Software Driving Software
    // application should consider SM_SWAPBUTTON to correctly emulate user with
    // left handed mouse setup
    BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON);

    if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
        buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK)
    {
        dwFlags |= !bSwap ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
    }

    if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
         buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK)
    {
        dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP;
    }

    if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
        buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK)
    {
        dwFlags |= MOUSEEVENTF_MIDDLEUP;
    }

    INPUT mouseInput = {0};
    mouseInput.type = INPUT_MOUSE;
    mouseInput.mi.time = 0;
    mouseInput.mi.dwFlags = dwFlags;

    if ( buttonMask & AwtComponent::masks[3] ) {
        mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP;
        mouseInput.mi.mouseData = XBUTTON1;
    }

    if ( buttonMask & AwtComponent::masks[4] ) {
        mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP;
        mouseInput.mi.mouseData = XBUTTON2;
    }
    ::SendInput(1, &mouseInput, sizeof(mouseInput));
}

void AwtRobot::MouseWheel (jint wheelAmt) {
    mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheelAmt * -1 * WHEEL_DELTA, 0);
}

inline jint AwtRobot::WinToJavaPixel(USHORT r, USHORT g, USHORT b)
{
    jint value =
            0xFF << 24 | // alpha channel is always turned all the way up
            r << 16 |
            g << 8  |
            b << 0;
    return value;
}

void AwtRobot::GetRGBPixels(jint x, jint y, jint width, jint height, jintArray pixelArray)
{
    DASSERT(width > 0 && height > 0);

    HDC hdcScreen = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
    HDC hdcMem = ::CreateCompatibleDC(hdcScreen);
    HBITMAP hbitmap;
    HBITMAP hOldBitmap;
    HPALETTE hOldPalette = NULL;
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    // create an offscreen bitmap
    hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height);
    if (hbitmap == NULL) {
        throw std::bad_alloc();
    }
    hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hbitmap);

    // REMIND: not multimon-friendly...
    int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
    hOldPalette =
        AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex);
    AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex);

    // copy screen image to offscreen bitmap
    // CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents
    // correctly on Win2K/XP
    VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
                                                SRCCOPY|CAPTUREBLT) != 0);

    static const int BITS_PER_PIXEL = 32;
    static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8;

    if (!IS_SAFE_SIZE_MUL(width, height)) throw std::bad_alloc();
    int numPixels = width*height;
    if (!IS_SAFE_SIZE_MUL(BYTES_PER_PIXEL, numPixels)) throw std::bad_alloc();
    int pixelDataSize = BYTES_PER_PIXEL*numPixels;
    DASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0);
    // allocate memory for BITMAPINFO + pixel data
    // 4620932: When using BI_BITFIELDS, GetDIBits expects an array of 3
    // RGBQUADS to follow the BITMAPINFOHEADER, but we were only allocating the
    // 1 that is included in BITMAPINFO.  Thus, GetDIBits was writing off the
    // end of our block of memory.  Now we allocate sufficient memory.
    // See MSDN docs for BITMAPINFOHEADER -bchristi

    if (!IS_SAFE_SIZE_ADD(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), pixelDataSize)) {
        throw std::bad_alloc();
    }
    BITMAPINFO * pinfo = (BITMAPINFO *)(new BYTE[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD) + pixelDataSize]);

    // pixel data starts after 3 RGBQUADS for color masks
    RGBQUAD *pixelData = &pinfo->bmiColors[3];

    // prepare BITMAPINFO for a 32-bit RGB bitmap
    ::memset(pinfo, 0, sizeof(*pinfo));
    pinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pinfo->bmiHeader.biWidth = width;
    pinfo->bmiHeader.biHeight = -height; // negative height means a top-down DIB
    pinfo->bmiHeader.biPlanes = 1;
    pinfo->bmiHeader.biBitCount = BITS_PER_PIXEL;
    pinfo->bmiHeader.biCompression = BI_BITFIELDS;

    // Setup up color masks
    static const RGBQUAD redMask =   {0, 0, 0xFF, 0};
    static const RGBQUAD greenMask = {0, 0xFF, 0, 0};
    static const RGBQUAD blueMask =  {0xFF, 0, 0, 0};

    pinfo->bmiColors[0] = redMask;
    pinfo->bmiColors[1] = greenMask;
    pinfo->bmiColors[2] = blueMask;

    // Get the bitmap data in device-independent, 32-bit packed pixel format
    ::GetDIBits(hdcMem, hbitmap, 0, height, pixelData, pinfo, DIB_RGB_COLORS);

    // convert Win32 pixel format (BGRX) to Java format (ARGB)
    DASSERT(sizeof(jint) == sizeof(RGBQUAD));
    for(int nPixel = 0; nPixel < numPixels; nPixel++) {
        RGBQUAD * prgbq = &pixelData[nPixel];
        jint jpixel = WinToJavaPixel(prgbq->rgbRed, prgbq->rgbGreen, prgbq->rgbBlue);
        // stuff the 32-bit pixel back into the 32-bit RGBQUAD
        *prgbq = *( (RGBQUAD *)(&jpixel) );
    }

    // copy pixels into Java array
    env->SetIntArrayRegion(pixelArray, 0, numPixels, (jint *)pixelData);
    delete pinfo;

    // free all the GDI objects we made
    ::SelectObject(hdcMem, hOldBitmap);
    if (hOldPalette != NULL) {
        ::SelectPalette(hdcMem, hOldPalette, FALSE);
    }
    ::DeleteObject(hbitmap);
    ::DeleteDC(hdcMem);
    ::DeleteDC(hdcScreen);
}

void AwtRobot::KeyPress( jint jkey )
{
    DoKeyEvent(jkey, 0); // no flags means key down
}

void AwtRobot::KeyRelease( jint jkey )
{
    DoKeyEvent(jkey, KEYEVENTF_KEYUP);
}

void AwtRobot::DoKeyEvent( jint jkey, DWORD dwFlags )
{
    UINT        vkey;
    UINT        modifiers;
    UINT        scancode;
    JNIEnv *    env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    // convert Java key into Windows key (and modifiers too)
    AwtComponent::JavaKeyToWindowsKey(jkey, &vkey, &modifiers);
    if (vkey == 0) {
        // no equivalent Windows key found for given Java keycode
        JNU_ThrowIllegalArgumentException(env, "Invalid key code");
    } else {
        // get the scancode from the virtual key
        scancode = ::MapVirtualKey(vkey, 0);
        keybd_event(vkey, scancode, dwFlags, 0);
    }
}

//
// utility function to get the C++ object from the Java one
//
// (static)
AwtRobot * AwtRobot::GetRobot( jobject self )
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    AwtRobot * robot = (AwtRobot *)JNI_GET_PDATA(self);
    DASSERT( !::IsBadWritePtr( robot, sizeof(AwtRobot)));
    return robot;
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Native method declarations
//

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_create(
    JNIEnv * env, jobject self)
{
    TRY;

    new AwtRobot(self);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer__1dispose(
    JNIEnv *env, jobject self)
{
    TRY_NO_VERIFY;

    AwtObject::_Dispose(self);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_mouseMoveImpl(
    JNIEnv * env, jobject self, jint x, jint y)
{
    TRY;

    AwtRobot::GetRobot(self)->MouseMove(x, y);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_mousePress(
    JNIEnv * env, jobject self, jint buttons)
{
    TRY;

    AwtRobot::GetRobot(self)->MousePress(buttons);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_mouseRelease(
    JNIEnv * env, jobject self, jint buttons)
{
    TRY;

    AwtRobot::GetRobot(self)->MouseRelease(buttons);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_mouseWheel(
    JNIEnv * env, jobject self, jint wheelAmt)
{
    TRY;

    AwtRobot::GetRobot(self)->MouseWheel(wheelAmt);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_getRGBPixels(
    JNIEnv *env, jobject self, jint x, jint y, jint width, jint height, jintArray pixelArray)
{
    TRY;

    AwtRobot::GetRobot(self)->GetRGBPixels(x, y, width, height, pixelArray);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_keyPress(
  JNIEnv *, jobject self, jint javakey )
{
    TRY;

    AwtRobot::GetRobot(self)->KeyPress(javakey);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_keyRelease(
  JNIEnv *, jobject self, jint javakey )
{
    TRY;

    AwtRobot::GetRobot(self)->KeyRelease(javakey);

    CATCH_BAD_ALLOC;
}

Other Java examples (source code examples)

Here is a short list of links related to this Java awt_Robot.cpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.