/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "video/win32/win32_input.hh"
#include "error/error.hh"
#include "device/keys.hh"
#include "device/event.hh"
#include "main/win_main.hh"
#include "device/kernel.hh"
#include "video/win32/resource.h"
#include "memory/malloc.hh"
i4_bool win32_input_class::class_registered=i4_F;
static win32_input_class *win32_current_input=0;
HWND current_window_handle;
HANDLE myPid;
int i4_default_warning(const char *st);
int i4_default_error(const char *st);
// int i4_win32_error(const char *st)
// {
// if (current_window_handle)
// {
// MessageBox(current_window_handle, st, "Error!", MB_OK | MB_APPLMODAL);
// exit(0);
// }
// else
// i4_default_error(st);
// return 1;
// }
i4_bool win32_input_class::process_events()
{
i4_bool ret=i4_F;
MSG msg;
w32 size=20;
// //check the DirectInput key device if it exists
// if(lpdiKey)
// lpdiKey->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keyData, &size, 0);
// w32 size=20;
//check the DirectInput key device if it exists
/*
if(lpdiKey)
{
ret=lpdiKey->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keyData, &size, DIGDD_PEEK);
if(ret==DI_OK || ret==DI_BUFFEROVERFLOW)
{
for(int i=0;iget_window_handle(), 0,0);
if (msg.message != WM_USER)
input->message_que.que(msg);
}
thread_running=i4_F;
}
*/
void win32_input_class::get_window_area(int &x, int &y, int &w, int &h)
{
RECT r;
GetClientRect(whandle, &r);
w=r.right-r.left;
h=r.bottom-r.top;
NONCLIENTMETRICS cl;
cl.cbSize=sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS),
&cl,
0);
x=r.left + cl.iBorderWidth;
y=r.top + cl.iCaptionHeight;
}
i4_bool win32_input_class::create_window(sw32 x, sw32 y, w32 w, w32 h,
i4_display_class *display_responsible_for_close,
i4_bool takeup_fullscreen)
{
if (!class_registered)
{
WNDCLASS window_class;
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.lpfnWndProc = WindowProc;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = i4_win32_instance;
window_class.hIcon = LoadIcon( i4_win32_instance, MAKEINTRESOURCE(103));
// window_class.hIcon = LoadIcon( i4_win32_instance, "102");
// window_class.hIcon = (HICON)LoadImage( i4_win32_instance, MAKEINTRESOURCE(IDI_GOLGOTHA), IMAGE_ICON,0,0,LR_LOADTRANSPARENT);
window_class.hCursor = LoadCursor( NULL, IDC_ARROW );
window_class.hbrBackground = GetStockObject(WHITE_BRUSH);
window_class.lpszMenuName = window_name();
window_class.lpszClassName = class_name();
RegisterClass( &window_class );
class_registered=i4_T;
}
if (takeup_fullscreen)
whandle = CreateWindowEx(0,
class_name(),
window_name(),
WS_POPUP | WS_EX_TOPMOST,
0,0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
i4_win32_instance,
NULL );
else
whandle = CreateWindowEx(0,
class_name(),
window_name(),
WS_POPUP | WS_EX_TOPMOST,
// WS_OVERLAPPEDWINDOW,
x, y, w, h,
NULL,
NULL,
i4_win32_instance,
NULL );
if (whandle)
{
have_window=i4_T;
current_window_handle=whandle;
i4_kernel.add_device(this);
win32_current_input=this;
display=display_responsible_for_close;
ShowCursor(FALSE);
DragAcceptFiles(whandle, i4_T);
}
else
i4_error("failed to create window");
if (!i4_win32_window_handle)
i4_win32_window_handle=whandle;
//myPid=GetCurrentProcess();
//SetPriorityClass(myPid, HIGH_PRIORITY_CLASS);
if (takeup_fullscreen)
{
confine.on=i4_T;
confine.x1=0;
confine.y1=0;
confine.x2=w-1;
confine.y2=h-1;
ShowWindow(whandle, SW_SHOWNORMAL);
/*
SetWindowPos(whandle,
HWND_TOPMOST,
0,0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SWP_SHOWWINDOW);
*/
}
else
ShowWindow(whandle, SW_SHOW);
UpdateWindow(whandle);
return i4_T;
}
void win32_input_class::destroy_window()
{
if (have_window)
{
PostMessage(whandle, WM_USER, 0,0); // send message to thread to unblock it
// stop_thread=i4_T;
// while (!thread_running)
// Sleep(0);
have_window=i4_F;
if (i4_win32_window_handle==whandle)
i4_win32_window_handle=0;
current_window_handle=0;
DestroyWindow(whandle);
i4_kernel.remove_device(this);
win32_current_input=0;
// if(lpdiKey) lpdiKey->Release(), lpdiKey=NULL;
// if(lpdi) lpdi->Release(), lpdi=NULL;
ShowCursor(TRUE);
}
}
long FAR PASCAL WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
if (win32_current_input)
return win32_current_input->process(hWnd, message, wParam, lParam, 0);
else
return DefWindowProc(hWnd, message, wParam, lParam);
}
win32_input_class::win32_input_class(char *extra_message)
{
mouse_locked = i4_F;
async_mouse = 0;
modifier_state = 0;
have_window = i4_F;
active = i4_F;
if (extra_message && (strlen(extra_message) < 128))
strcpy(window_message,extra_message);
else
window_message[0]=0;
}
void win32_input_class::set_async_mouse(dx_threaded_mouse_class *m)
{
if (async_mouse)
{
//dont let this mouse references us anymore
// async_mouse->input = 0;
}
async_mouse = m;
if (async_mouse)
{
// async_mouse->input = this;
// async_mouse->set_active(active);
}
}
w16 win32_input_class::translate_windows_key(w16 wkey, w32 &m)
{
w16 key;
m=0;
switch (wkey)
{
case VK_BACK : key=I4_BACKSPACE; break;
case VK_TAB : key=I4_TAB; break;
case VK_RETURN : key=I4_ENTER; break;
case VK_ESCAPE : key=I4_ESC; break;
case VK_SPACE : key=I4_SPACE; break;
case VK_UP : key=I4_UP; break;
case VK_DOWN : key=I4_DOWN; break;
case VK_LEFT : key=I4_LEFT; break;
case VK_RIGHT : key=I4_RIGHT; break;
case VK_CONTROL :
case VK_LCONTROL : key=I4_CTRL_L; m=I4_MODIFIER_CTRL_L; break;
case VK_RCONTROL : key=I4_CTRL_R; m=I4_MODIFIER_CTRL_R; break;
case VK_MENU :
case VK_LMENU : key=I4_ALT_L; m=I4_MODIFIER_ALT_L; break;
case VK_RMENU : key=I4_ALT_R; m=I4_MODIFIER_ALT_R; break;
case VK_SHIFT :
case VK_LSHIFT : key=I4_SHIFT_L; m=I4_MODIFIER_SHIFT_L; break;
case VK_RSHIFT : key=I4_SHIFT_R; m=I4_MODIFIER_SHIFT_R; break;
case VK_CAPITAL : key=I4_CAPS; break;
case VK_NUMLOCK : key=I4_NUM_LOCK; break;
case VK_HOME : key=I4_HOME; break;
case VK_END : key=I4_END; break;
case VK_DELETE : key=I4_DEL; break;
case VK_F1 : key=I4_F1; break;
case VK_F2 : key=I4_F2; break;
case VK_F3 : key=I4_F3; break;
case VK_F4 : key=I4_F4; break;
case VK_F5 : key=I4_F5; break;
case VK_F6 : key=I4_F6; break;
case VK_F7 : key=I4_F7; break;
case VK_F8 : key=I4_F8; break;
case VK_F9 : key=I4_F9; break;
case VK_F10 : key=I4_F10; break;
case VK_F11 : key=I4_F11; break;
case VK_F12 : key=I4_F12; break;
case VK_F13 : key=I4_F13; break;
case VK_F14 : key=I4_F14; break;
case VK_F15 : key=I4_F15; break;
case VK_INSERT : key=I4_INSERT; break;
case VK_PRIOR : key=I4_PAGEUP; break;
case VK_NEXT : key=I4_PAGEDOWN; break;
case VK_NUMPAD0 : key=I4_KP0; break;
case VK_NUMPAD1 : key=I4_KP1; break;
case VK_NUMPAD2 : key=I4_KP2; break;
case VK_NUMPAD3 : key=I4_KP3; break;
case VK_NUMPAD4 : key=I4_KP4; break;
case VK_NUMPAD5 : key=I4_KP5; break;
case VK_NUMPAD6 : key=I4_KP6; break;
case VK_NUMPAD7 : key=I4_KP7; break;
case VK_NUMPAD8 : key=I4_KP8; break;
case VK_NUMPAD9 : key=I4_KP9; break;
case VK_DIVIDE : key=I4_KPSLASH; break;
case VK_MULTIPLY : key=I4_KPSTAR; break;
case VK_SUBTRACT : key=I4_KPMINUS; break;
case VK_ADD : key=I4_KPPLUS; break;
case VK_DECIMAL : key=I4_KPPERIOD; break;
case 0xc0 : key='`'; break;
case 0xba : key=';'; break;
case 0xbb : key='='; break;
case 0xbc : key=','; break;
case 0xbd : key='-'; break;
case 0xbe : key='.'; break;
case 0xbf : key='/'; break;
case 0xdb : key='['; break;
case 0xdc : key='\\'; break;
case 0xdd : key=']'; break;
case 0xde : key='\''; break;
default :
if ((wkey>='A' && wkey<='Z') || (wkey>='0' && wkey<='9'))
key = wkey;
else
key = 0;
break;
}
return key;
}
i4_bool win32_input_class::lock_mouse_in_place(i4_bool yes_no)
{
//if (async_mouse)
// async_mouse->lock_position(yes_no);
mouse_locked=yes_no;
return i4_T;
}
void win32_input_class::update_mouse_movement(sw32 new_x, sw32 new_y)
{
if (!active)
return;
i4_mouse_move_event_class ev(mouse_x, mouse_y, new_x, new_y);
int mx,my;
mx = new_x;
my = new_y;
if (confine.on)
{
if (mxconfine.x2)
{
mx=confine.x2;
SetCursorPos(mx, my);
}
if (mouse_y>confine.y2)
{
my=confine.y2;
SetCursorPos(mx, my);
}
}
send_event_to_agents(&ev,i4_device_class::FLAG_MOUSE_MOVE);
if (mouse_locked)
{
if (mx!=mouse_x || my!=mouse_y)
SetCursorPos(mouse_x, mouse_y);
}
else
{
mouse_x=mx;
mouse_y=my;
}
}
void win32_input_class::update_mouse_buttons(i4_mouse_button_event_class::btype type,
mouse_button_state state)
{
if (!active)
return;
i4_time_class now;
if (state==UP)
{
i4_mouse_button_up_event_class ev_up(type, mouse_x, mouse_y, now, last_up[type]);
send_event_to_agents(&ev_up,i4_device_class::FLAG_MOUSE_BUTTON_UP);
last_up[type]=now;
}
else
if (state==DOWN)
{
i4_mouse_button_down_event_class ev_down(type, mouse_x, mouse_y, now, last_down[type]);
send_event_to_agents(&ev_down,i4_device_class::FLAG_MOUSE_BUTTON_DOWN);
last_down[type]=now;
}
}
sw32 win32_input_class::process(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD time)
{
PAINTSTRUCT ps;
HDC hdc;
if (!have_window)
return DefWindowProc(hWnd, message, wParam, lParam);
switch( message )
{
case WM_DROPFILES :
{
HANDLE drop=(HANDLE) wParam;
POINT point;
DragQueryPoint(drop, &point);
i4_window_got_drop_class de(0);
int t=DragQueryFile(drop, 0xffffffff, 0,0);
de.drag_info.t_filenames=t;
de.drag_info.filenames=(i4_str **)i4_malloc(sizeof(i4_str *) * t, "");
de.drag_info.drag_object_type=i4_drag_info_struct::FILENAMES;
de.drag_info.x=point.x;
de.drag_info.y=point.y;
for (int i=0; iremove_cursor())
{
ShowCursor(FALSE);
return TRUE;
}
} break;
#endif
case WM_SIZE :
resize(LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOVE :
move(LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOUSEMOVE :
{
if (!async_mouse)
update_mouse_movement(LOWORD(lParam),HIWORD(lParam));
} break;
case WM_LBUTTONDOWN :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::LEFT, DOWN);
} break;
case WM_LBUTTONUP :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::LEFT, UP);
} break;
case WM_RBUTTONDOWN :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::RIGHT, DOWN);
} break;
case WM_RBUTTONUP :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::RIGHT, UP);
} break;
case WM_MBUTTONDOWN :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::CENTER, DOWN);
} break;
case WM_MBUTTONUP :
{
if (!async_mouse)
update_mouse_buttons(i4_mouse_button_event_class::CENTER, UP);
} break;
case WM_SETFOCUS:
set_active(i4_T);
// if (async_mouse)
// async_mouse->set_active(i4_T);
break;
case WM_KILLFOCUS:
set_active(i4_F);
// if (async_mouse)
// async_mouse->set_active(i4_F);
break;
case WM_ACTIVATEAPP :
set_active((i4_bool)wParam);
// if (async_mouse)
// async_mouse->set_active((i4_bool)wParam);
break;
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_CLOSE:
i4_display_close_event_class dc(display);
send_event_to_agents(&dc, i4_device_class::FLAG_DISPLAY_CLOSE);
close_event();
return 0;
}
}
case WM_DESTROY:
{
} return 0;
case WM_SYSKEYDOWN :
case WM_KEYDOWN :
{
w32 m;
w16 key_code=translate_windows_key(wParam, m);
modifier_state|=m;
w16 key=i4_key_translate(key_code, 1, modifier_state);
i4_time_class t(time);
i4_key_press_event_class ev(key,key_code, modifier_state, t);
send_event_to_agents(&ev,i4_device_class::FLAG_KEY_PRESS);
} break;
case WM_SYSKEYUP :
case WM_KEYUP :
{
w32 m;
w16 key_code=translate_windows_key(wParam,m);
modifier_state&=~m;
w16 key=i4_key_translate(key_code, 0, modifier_state);
i4_time_class t(time);
i4_key_release_event_class ev(key,key_code, modifier_state, t);
send_event_to_agents(&ev,i4_device_class::FLAG_KEY_RELEASE);
} break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// BOOL win32_input_class::CreateKeyboard(GUID &guid, LPDIRECTINPUTDEVICE& lpdiKey, DWORD dwAccess)
// {
/* HRESULT err=lpdi->CreateDevice(guid, &lpdiKey, NULL);
if(err!=DI_OK)
{
i4_warning("Unable to create DirectInput keyboard device!\n\0");
goto fail;
}
// Tell DirectInput that we want to receive data in keyboard format
err=lpdiKey->SetDataFormat(&c_dfDIKeyboard);
if(err!=DI_OK)
{
i4_warning("Unable to access DirectInput device as a keyboard!\n\0");
goto fail;
}
// set desired access mode
err=lpdiKey->SetCooperativeLevel(current_window_handle, dwAccess);
if(err != DI_OK)
{
i4_warning("Unable to set DirectInput keyboard cooperativity level!\n\0");
goto fail;
}
return TRUE;
fail:
if(lpdiKey) lpdiKey->Release(), lpdiKey=0; */
// return FALSE;
//}
/*BOOL win32_input_class::InitDInput(void)
{
HRESULT err;
GUID guid=GUID_SysKeyboard;
err=DirectInputCreate(i4_win32_instance, DIRECTINPUT_VERSION, &lpdi, NULL);
if(err!=DI_OK)
{
i4_warning("Unable to create DirectInput object!\n\0");
return FALSE;
}
i4_warning("DirectInput object initialized...\n\0");
// Create a keyboard obj
if(CreateKeyboard(guid, lpdiKey, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND))
{
lpdiKey->Acquire();
i4_warning("Keyboard found and acquired...\n\0");
return TRUE;
}
if(lpdiKey) lpdiKey->Release(), lpdiKey=NULL;
if(lpdi) lpdi->Release(), lpdi=NULL;
return FALSE;
} */