mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-15 06:54:46 +00:00
joy.cpl: Draw xinput controller state with gdi32.
This commit is contained in:
parent
3f4a799089
commit
3bc30c3723
|
@ -1,5 +1,5 @@
|
||||||
MODULE = joy.cpl
|
MODULE = joy.cpl
|
||||||
IMPORTS = dxguid dinput dinput8 ole32 comctl32 user32 advapi32 xinput
|
IMPORTS = dxguid dinput dinput8 ole32 comctl32 user32 gdi32 advapi32 xinput
|
||||||
|
|
||||||
EXTRADLLFLAGS = -Wb,--prefer-native
|
EXTRADLLFLAGS = -Wb,--prefer-native
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,6 @@
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||||
|
extern LRESULT CALLBACK test_xi_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||||
|
|
||||||
#endif /* __JOY_PRIVATE_H */
|
#endif /* __JOY_PRIVATE_H */
|
||||||
|
|
|
@ -1015,6 +1015,23 @@ static void display_cpl_sheets( HWND parent, struct JoystickData *data )
|
||||||
OleUninitialize();
|
OleUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void register_window_class(void)
|
||||||
|
{
|
||||||
|
WNDCLASSW xi_class =
|
||||||
|
{
|
||||||
|
.hInstance = hcpl,
|
||||||
|
.lpfnWndProc = &test_xi_window_proc,
|
||||||
|
.lpszClassName = L"JoyCplXInput",
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterClassW( &xi_class );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unregister_window_class(void)
|
||||||
|
{
|
||||||
|
UnregisterClassW( L"JoyCplXInput", hcpl );
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* CPlApplet (joy.cpl.@)
|
* CPlApplet (joy.cpl.@)
|
||||||
*
|
*
|
||||||
|
@ -1041,6 +1058,7 @@ LONG CALLBACK CPlApplet(HWND hwnd, UINT command, LPARAM lParam1, LPARAM lParam2)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
register_window_class();
|
||||||
device_state_event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
device_state_event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||||
|
|
||||||
/* Initialize dinput */
|
/* Initialize dinput */
|
||||||
|
@ -1082,6 +1100,7 @@ LONG CALLBACK CPlApplet(HWND hwnd, UINT command, LPARAM lParam1, LPARAM lParam2)
|
||||||
IDirectInput8_Release(data.di);
|
IDirectInput8_Release(data.di);
|
||||||
|
|
||||||
CloseHandle( device_state_event );
|
CloseHandle( device_state_event );
|
||||||
|
unregister_window_class();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
|
||||||
#include "xinput.h"
|
#include "xinput.h"
|
||||||
|
|
||||||
|
@ -96,12 +98,240 @@ static DWORD WINAPI input_thread_proc( void *param )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void draw_axis_view( HDC hdc, RECT rect, SHORT dx, SHORT dy, BOOL set )
|
||||||
|
{
|
||||||
|
POINT center =
|
||||||
|
{
|
||||||
|
.x = (rect.left + rect.right) / 2,
|
||||||
|
.y = (rect.top + rect.bottom) / 2,
|
||||||
|
};
|
||||||
|
POINT pos =
|
||||||
|
{
|
||||||
|
.x = center.x + MulDiv( dx, rect.right - rect.left - 20, 0xffff ),
|
||||||
|
.y = center.y - MulDiv( dy, rect.bottom - rect.top - 20, 0xffff ),
|
||||||
|
};
|
||||||
|
|
||||||
|
FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) );
|
||||||
|
|
||||||
|
SetDCBrushColor( hdc, GetSysColor( set ? COLOR_HIGHLIGHT : COLOR_WINDOW ) );
|
||||||
|
SetDCPenColor( hdc, GetSysColor( set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWFRAME ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_BRUSH ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_PEN ) );
|
||||||
|
|
||||||
|
Ellipse( hdc, rect.left, rect.top, rect.right, rect.bottom );
|
||||||
|
|
||||||
|
MoveToEx( hdc, center.x, center.y - 3, NULL );
|
||||||
|
LineTo( hdc, center.x, center.y + 4 );
|
||||||
|
MoveToEx( hdc, center.x - 3, center.y, NULL );
|
||||||
|
LineTo( hdc, center.x + 4, center.y );
|
||||||
|
|
||||||
|
if (!set) SetDCPenColor( hdc, GetSysColor( (dx || dy) ? COLOR_HIGHLIGHT : COLOR_WINDOWFRAME ) );
|
||||||
|
|
||||||
|
MoveToEx( hdc, center.x, center.y, NULL );
|
||||||
|
LineTo( hdc, pos.x, pos.y );
|
||||||
|
|
||||||
|
Ellipse( hdc, pos.x - 4, pos.y - 4, pos.x + 4, pos.y + 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_trigger_view( HDC hdc, RECT rect, BYTE dt )
|
||||||
|
{
|
||||||
|
POINT center =
|
||||||
|
{
|
||||||
|
.x = (rect.left + rect.right) / 2,
|
||||||
|
.y = (rect.top + rect.bottom) / 2,
|
||||||
|
};
|
||||||
|
LONG w = (rect.right - rect.left + 1) / 3;
|
||||||
|
LONG y = rect.bottom - (w + 1) / 2 - MulDiv( dt, rect.bottom - rect.top - w, 0xff );
|
||||||
|
|
||||||
|
FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) );
|
||||||
|
|
||||||
|
SetDCBrushColor( hdc, GetSysColor( COLOR_WINDOW ) );
|
||||||
|
SetDCPenColor( hdc, GetSysColor( COLOR_WINDOWFRAME ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_BRUSH ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_PEN ) );
|
||||||
|
|
||||||
|
RoundRect( hdc, rect.left, rect.top, rect.right, rect.bottom, 5, 5 );
|
||||||
|
|
||||||
|
if (y > center.y)
|
||||||
|
{
|
||||||
|
MoveToEx( hdc, center.x - 3, center.y, NULL );
|
||||||
|
LineTo( hdc, center.x + 3, center.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDCBrushColor( hdc, GetSysColor( dt ? COLOR_HIGHLIGHT : COLOR_WINDOW ) );
|
||||||
|
SetDCPenColor( hdc, GetSysColor( dt ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWFRAME ) );
|
||||||
|
|
||||||
|
Rectangle( hdc, center.x - w, y, center.x + w, rect.bottom );
|
||||||
|
|
||||||
|
if (y < center.y)
|
||||||
|
{
|
||||||
|
MoveToEx( hdc, center.x - 3, center.y, NULL );
|
||||||
|
LineTo( hdc, center.x + 3, center.y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_button_view( HDC hdc, RECT rect, BOOL set, const WCHAR *name )
|
||||||
|
{
|
||||||
|
COLORREF color = SetTextColor( hdc, GetSysColor( set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT ) );
|
||||||
|
HFONT font = SelectObject( hdc, GetStockObject( ANSI_VAR_FONT ) );
|
||||||
|
INT mode = SetBkMode( hdc, TRANSPARENT );
|
||||||
|
|
||||||
|
FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) );
|
||||||
|
|
||||||
|
SetDCBrushColor( hdc, GetSysColor( set ? COLOR_HIGHLIGHT : COLOR_WINDOW ) );
|
||||||
|
SetDCPenColor( hdc, GetSysColor( set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWFRAME ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_BRUSH ) );
|
||||||
|
SelectObject( hdc, GetStockObject( DC_PEN ) );
|
||||||
|
|
||||||
|
Ellipse( hdc, rect.left, rect.top, rect.right, rect.bottom );
|
||||||
|
if (name[0] >= 'A' && name[0] <= 'Z')
|
||||||
|
DrawTextW( hdc, name, -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP );
|
||||||
|
else if (name[0] == '=')
|
||||||
|
{
|
||||||
|
RECT tmp_rect = {.right = 10, .bottom = 2};
|
||||||
|
|
||||||
|
OffsetRect( &tmp_rect, rect.left, rect.top );
|
||||||
|
OffsetRect( &tmp_rect, (rect.right - rect.left) / 2, (rect.bottom - rect.top) / 2 );
|
||||||
|
OffsetRect( &tmp_rect, (tmp_rect.left - tmp_rect.right) / 2, (tmp_rect.top - tmp_rect.bottom) / 2 );
|
||||||
|
|
||||||
|
FillRect( hdc, &tmp_rect, (HBRUSH)((UINT_PTR)(set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) + 1) );
|
||||||
|
OffsetRect( &tmp_rect, 0, 3 * (tmp_rect.top - tmp_rect.bottom) / 2 );
|
||||||
|
FillRect( hdc, &tmp_rect, (HBRUSH)((UINT_PTR)(set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) + 1) );
|
||||||
|
OffsetRect( &tmp_rect, 0, 6 * (tmp_rect.bottom - tmp_rect.top) / 2 );
|
||||||
|
FillRect( hdc, &tmp_rect, (HBRUSH)((UINT_PTR)(set ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) + 1) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGFONTW logfont =
|
||||||
|
{
|
||||||
|
.lfHeight = 16,
|
||||||
|
.lfWeight = FW_NORMAL,
|
||||||
|
.lfCharSet = SYMBOL_CHARSET,
|
||||||
|
.lfFaceName = L"Marlett",
|
||||||
|
};
|
||||||
|
WCHAR buffer[4] = {0};
|
||||||
|
HFONT font;
|
||||||
|
|
||||||
|
font = CreateFontIndirectW( &logfont );
|
||||||
|
font = (HFONT)SelectObject( hdc, font );
|
||||||
|
|
||||||
|
if (name[0] == '#') { buffer[0] = 0x32; OffsetRect( &rect, 1, 0 ); }
|
||||||
|
if (name[0] == '<') buffer[0] = 0x33;
|
||||||
|
if (name[0] == '>') buffer[0] = 0x34;
|
||||||
|
if (name[0] == '^') buffer[0] = 0x35;
|
||||||
|
if (name[0] == 'v') buffer[0] = 0x36;
|
||||||
|
if (name[0] == '@') buffer[0] = 0x6e;
|
||||||
|
DrawTextW( hdc, buffer, -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP );
|
||||||
|
|
||||||
|
font = (HFONT)SelectObject( hdc, font );
|
||||||
|
DeleteObject( font );
|
||||||
|
}
|
||||||
|
|
||||||
|
SetBkMode( hdc, mode );
|
||||||
|
SetTextColor( hdc, color );
|
||||||
|
SelectObject( hdc, font );
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK test_xi_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||||
|
{
|
||||||
|
TRACE( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam );
|
||||||
|
|
||||||
|
if (msg == WM_PAINT)
|
||||||
|
{
|
||||||
|
DWORD index = GetWindowLongW( hwnd, GWLP_USERDATA );
|
||||||
|
UINT axis_size, trigger_size, button_size, horiz_space;
|
||||||
|
struct device_state state;
|
||||||
|
RECT rect, tmp_rect;
|
||||||
|
PAINTSTRUCT paint;
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
GetClientRect( hwnd, &rect );
|
||||||
|
axis_size = rect.bottom - rect.top;
|
||||||
|
button_size = (axis_size - 1) / 3;
|
||||||
|
trigger_size = axis_size / 4;
|
||||||
|
horiz_space = (rect.right - rect.left - axis_size * 2 - trigger_size * 2 - button_size * 5) / 10;
|
||||||
|
|
||||||
|
get_device_state( index, &state );
|
||||||
|
|
||||||
|
hdc = BeginPaint( hwnd, &paint );
|
||||||
|
|
||||||
|
rect.right = rect.left + axis_size;
|
||||||
|
OffsetRect( &rect, horiz_space, 0 );
|
||||||
|
draw_axis_view( hdc, rect, state.state.Gamepad.sThumbLX, state.state.Gamepad.sThumbLY,
|
||||||
|
state.state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_axis_view( hdc, rect, state.state.Gamepad.sThumbRX, state.state.Gamepad.sThumbRY,
|
||||||
|
state.state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB );
|
||||||
|
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
rect.right = rect.left + trigger_size;
|
||||||
|
draw_trigger_view( hdc, rect, state.state.Gamepad.bLeftTrigger );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_trigger_view( hdc, rect, state.state.Gamepad.bRightTrigger );
|
||||||
|
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
rect.right = rect.left + button_size;
|
||||||
|
rect.bottom = rect.top + button_size;
|
||||||
|
tmp_rect = rect;
|
||||||
|
OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP, L"^" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER, L"L" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER, L"R" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_Y, L"Y" );
|
||||||
|
|
||||||
|
rect = tmp_rect;
|
||||||
|
OffsetRect( &rect, 0, rect.bottom - rect.top );
|
||||||
|
tmp_rect = rect;
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT, L"<" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT, L">" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & 0x0400, L"@" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_X, L"X" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_B, L"B" );
|
||||||
|
|
||||||
|
rect = tmp_rect;
|
||||||
|
OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, rect.bottom - rect.top );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN, L"v" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK, L"#" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_START, L"=" );
|
||||||
|
OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 );
|
||||||
|
draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_A, L"A" );
|
||||||
|
|
||||||
|
EndPaint( hwnd, &paint );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProcW( hwnd, msg, wparam, lparam );
|
||||||
|
}
|
||||||
|
|
||||||
static void create_user_view( HWND hwnd, DWORD index )
|
static void create_user_view( HWND hwnd, DWORD index )
|
||||||
{
|
{
|
||||||
HWND parent;
|
HINSTANCE instance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
|
||||||
|
HWND parent, view;
|
||||||
|
LONG margin;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
parent = GetDlgItem( hwnd, IDC_XI_USER_0 + index );
|
parent = GetDlgItem( hwnd, IDC_XI_USER_0 + index );
|
||||||
|
|
||||||
|
GetClientRect( parent, &rect );
|
||||||
|
rect.top += 10;
|
||||||
|
|
||||||
|
margin = (rect.bottom - rect.top) * 15 / 100;
|
||||||
|
InflateRect( &rect, -margin, -margin );
|
||||||
|
|
||||||
|
view = CreateWindowW( L"JoyCplXInput", NULL, WS_CHILD | WS_VISIBLE, rect.left, rect.top,
|
||||||
|
rect.right - rect.left, rect.bottom - rect.top, parent, NULL, NULL, instance );
|
||||||
|
SetWindowLongW( view, GWLP_USERDATA, index );
|
||||||
|
|
||||||
ShowWindow( parent, SW_HIDE );
|
ShowWindow( parent, SW_HIDE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +347,12 @@ static void update_user_view( HWND hwnd, DWORD index )
|
||||||
|
|
||||||
parent = GetDlgItem( hwnd, IDC_XI_USER_0 + index );
|
parent = GetDlgItem( hwnd, IDC_XI_USER_0 + index );
|
||||||
ShowWindow( parent, state.status ? SW_HIDE : SW_SHOW );
|
ShowWindow( parent, state.status ? SW_HIDE : SW_SHOW );
|
||||||
|
|
||||||
|
if (!state.status)
|
||||||
|
{
|
||||||
|
HWND view = FindWindowExW( parent, NULL, L"JoyCplXInput", NULL );
|
||||||
|
InvalidateRect( view, NULL, TRUE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||||
|
|
Loading…
Reference in a new issue