Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3bc30c37
Commit
3bc30c37
authored
Nov 27, 2022
by
Rémi Bernon
Committed by
Alexandre Julliard
Nov 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
joy.cpl: Draw xinput controller state with gdi32.
parent
3f4a7990
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
258 additions
and
2 deletions
+258
-2
Makefile.in
dlls/joy.cpl/Makefile.in
+1
-1
joy_private.h
dlls/joy.cpl/joy_private.h
+1
-0
main.c
dlls/joy.cpl/main.c
+19
-0
xinput.c
dlls/joy.cpl/xinput.c
+237
-1
No files found.
dlls/joy.cpl/Makefile.in
View file @
3bc30c37
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
...
...
dlls/joy.cpl/joy_private.h
View file @
3bc30c37
...
...
@@ -29,5 +29,6 @@
#include "resource.h"
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 */
dlls/joy.cpl/main.c
View file @
3bc30c37
...
...
@@ -1015,6 +1015,23 @@ static void display_cpl_sheets( HWND parent, struct JoystickData *data )
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.@)
*
...
...
@@ -1041,6 +1058,7 @@ LONG CALLBACK CPlApplet(HWND hwnd, UINT command, LPARAM lParam1, LPARAM lParam2)
{
HRESULT
hr
;
register_window_class
();
device_state_event
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
/* Initialize dinput */
...
...
@@ -1082,6 +1100,7 @@ LONG CALLBACK CPlApplet(HWND hwnd, UINT command, LPARAM lParam1, LPARAM lParam2)
IDirectInput8_Release
(
data
.
di
);
CloseHandle
(
device_state_event
);
unregister_window_class
();
break
;
}
...
...
dlls/joy.cpl/xinput.c
View file @
3bc30c37
...
...
@@ -19,10 +19,12 @@
#include <stdarg.h>
#include <stddef.h>
#include <math.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "xinput.h"
...
...
@@ -96,12 +98,240 @@ static DWORD WINAPI input_thread_proc( void *param )
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
)
{
HWND
parent
;
HINSTANCE
instance
=
(
HINSTANCE
)
GetWindowLongPtrW
(
hwnd
,
GWLP_HINSTANCE
);
HWND
parent
,
view
;
LONG
margin
;
RECT
rect
;
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
);
}
...
...
@@ -117,6 +347,12 @@ static void update_user_view( HWND hwnd, DWORD index )
parent
=
GetDlgItem
(
hwnd
,
IDC_XI_USER_0
+
index
);
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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment