// SendInput.cpp : Defines the entry point for the DLL application.
//

//#include "stdafx.h"
#ifndef WINVER				// Allow use of features specific to Windows XP or later.
#define WINVER 0x0501		// Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.
#endif						

#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE			// Allow use of features specific to IE 6.0 or later.
#define _WIN32_IE 0x0600	// Change this to the appropriate value to target other versions of IE.
#endif

#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <jni.h>

/*
#include "SendInput.h"


#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif
*/

/*
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}
*/


/*********************************************************************************/
/* Sending input to the Windows event stream                                     */
/*********************************************************************************/

JNIEXPORT jint JNICALL Java_sivantoledo_win32_SendInput_keyDownUp
  (JNIEnv *env, jclass C, jchar k)
{
  INPUT in[2];

  in[0].type = INPUT_KEYBOARD;
  in[0].ki.wVk = k;
	in[0].ki.wScan = 0;
	in[0].ki.dwFlags = 0; // 0 means key down
	in[0].ki.time = 0; // system supplies time stamp
	in[0].ki.dwExtraInfo = 0;

  in[1].type = INPUT_KEYBOARD;
  in[1].ki.wVk = k;
	in[1].ki.wScan = 0;
	in[1].ki.dwFlags = KEYEVENTF_KEYUP;
	in[1].ki.time = 0; // system supplies time stamp
	in[1].ki.dwExtraInfo = 0;

	return SendInput(2,in,sizeof(INPUT));
}

JNIEXPORT jint JNICALL Java_sivantoledo_win32_SendInput_charDownUp
  (JNIEnv *env, jclass C, jchar c)
{
  INPUT in[2];

  in[0].type = INPUT_KEYBOARD;
  in[0].ki.wVk = 0;
	in[0].ki.wScan = c;
	in[0].ki.dwFlags = KEYEVENTF_UNICODE; // 0 means key down
	in[0].ki.time = 0; // system supplies time stamp
	in[0].ki.dwExtraInfo = 0;

  in[1].type = INPUT_KEYBOARD;
  in[1].ki.wVk = 0;
	in[1].ki.wScan = c;
	in[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
	in[1].ki.time = 0; // system supplies time stamp
	in[1].ki.dwExtraInfo = 0;

	return SendInput(2,in,sizeof(INPUT));
}

JNIEXPORT jint JNICALL Java_sivantoledo_win32_SendInput_mouseRelative
  (JNIEnv *env, jclass C, jint x, jint y)
{
  INPUT in[1];

  in[0].type = INPUT_MOUSE;
  in[0].mi.dx = x;
	in[0].mi.dy = y;
	in[0].mi.mouseData   = 0;
	in[0].mi.dwFlags     = MOUSEEVENTF_MOVE; // 0 means key down
	in[0].mi.time        = 0; // system supplies time stamp
	in[0].mi.dwExtraInfo = 0;

	return SendInput(1,in,sizeof(INPUT));
}

JNIEXPORT jint JNICALL Java_sivantoledo_win32_SendInput_mouseDownUp
  (JNIEnv *env, jclass C, int button)
{
  INPUT in[2];

  in[0].type = INPUT_MOUSE;
  in[0].mi.dx = 0;
	in[0].mi.dy = 0;
	in[0].mi.mouseData   = 0;
	in[0].mi.time        = 0; // system supplies time stamp
	in[0].mi.dwExtraInfo = 0;

  switch (button) {
    case 0: in[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN;   break;
    case 1: in[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_MIDDLEDOWN; break;
    case 2: in[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_RIGHTDOWN;  break;
  }

  in[1].type = INPUT_MOUSE;
  in[1].mi.dx = 0;
	in[1].mi.dy = 0;
	in[1].mi.mouseData   = 0;
	in[1].mi.time        = 0; // system supplies time stamp
	in[1].mi.dwExtraInfo = 0;

  switch (button) {
    case 0: in[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTUP;   break;
    case 1: in[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_MIDDLEUP; break;
    case 2: in[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_RIGHTUP;  break;
  }

	return SendInput(2,in,sizeof(INPUT));
}
