Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
26fb3d4a
Commit
26fb3d4a
authored
Aug 16, 2012
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winex11: Add a critical section to protect the keyboard mapping tables.
parent
c970621d
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
79 additions
and
85 deletions
+79
-85
keyboard.c
dlls/winex11.drv/keyboard.c
+79
-85
No files found.
dlls/winex11.drv/keyboard.c
View file @
26fb3d4a
...
...
@@ -66,6 +66,15 @@ static WORD keyc2vkey[256], keyc2scan[256];
static
int
NumLockMask
,
ScrollLockMask
,
AltGrMask
;
/* mask in the XKeyEvent state */
static
CRITICAL_SECTION
kbd_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
kbd_section
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": kbd_section"
)
}
};
static
CRITICAL_SECTION
kbd_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
char
KEYBOARD_MapDeadKeysym
(
KeySym
keysym
);
/* Keyboard translation tables */
...
...
@@ -1111,7 +1120,7 @@ static inline KeySym keycode_to_keysym( Display *display, KeyCode keycode, int i
}
/* Returns the Windows virtual key code associated with the X event <e> */
/*
x11 lock
must be held */
/*
kbd_section
must be held */
static
WORD
EVENT_event_to_vkey
(
XIC
xic
,
XKeyEvent
*
e
)
{
KeySym
keysym
=
0
;
...
...
@@ -1229,6 +1238,8 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
memset
(
modifiers
,
0
,
sizeof
(
modifiers
));
EnterCriticalSection
(
&
kbd_section
);
/* the minimum keycode is always greater or equal to 8, so we can
* skip the first 8 values, hence start at 1
*/
...
...
@@ -1270,6 +1281,7 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
}
}
LeaveCriticalSection
(
&
kbd_section
);
if
(
!
changed
)
return
;
update_key_state
(
keystate
,
VK_CONTROL
,
(
keystate
[
VK_LCONTROL
]
|
keystate
[
VK_RCONTROL
])
&
0x80
);
...
...
@@ -1341,7 +1353,6 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
if
(
event
->
type
==
KeyPress
)
update_user_time
(
event
->
time
);
wine_tsx11_lock
();
/* Clients should pass only KeyPress events to XmbLookupString */
if
(
xic
&&
event
->
type
==
KeyPress
)
{
...
...
@@ -1353,7 +1364,6 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
if
(
Str
==
NULL
)
{
ERR_
(
key
)(
"Failed to allocate memory!
\n
"
);
wine_tsx11_unlock
();
return
;
}
ascii_chars
=
XmbLookupString
(
xic
,
event
,
Str
,
ascii_chars
,
&
keysym
,
&
status
);
...
...
@@ -1361,7 +1371,6 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
}
else
ascii_chars
=
XLookupString
(
event
,
buf
,
sizeof
(
buf
),
&
keysym
,
NULL
);
wine_tsx11_unlock
();
TRACE_
(
key
)(
"nbyte = %d, status %d
\n
"
,
ascii_chars
,
status
);
...
...
@@ -1373,6 +1382,8 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return
;
}
EnterCriticalSection
(
&
kbd_section
);
/* If XKB extensions are used, the state mask for AltGr will use the group
index instead of the modifier mask. The group index is set in bits
13-14 of the state field in the XKeyEvent structure. So if AltGr is
...
...
@@ -1398,27 +1409,26 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
if
(
buf
!=
Str
)
HeapFree
(
GetProcessHeap
(),
0
,
Str
);
wine_tsx11_lock
();
vkey
=
EVENT_event_to_vkey
(
xic
,
event
);
/* X returns keycode 0 for composed characters */
if
(
!
vkey
&&
ascii_chars
)
vkey
=
VK_NONAME
;
wine_tsx11_unlock
();
TRACE_
(
key
)(
"keycode %u converted to vkey 0x%X
\n
"
,
event
->
keycode
,
vkey
);
bScan
=
keyc2scan
[
event
->
keycode
]
&
0xFF
;
if
(
!
vkey
)
return
;
TRACE_
(
key
)(
"keycode %u converted to vkey 0x%X scan %02x
\n
"
,
event
->
keycode
,
vkey
,
bScan
);
if
(
vkey
)
{
dwFlags
=
0
;
if
(
event
->
type
==
KeyRelease
)
dwFlags
|=
KEYEVENTF_KEYUP
;
if
(
vkey
&
0x100
)
dwFlags
|=
KEYEVENTF_EXTENDEDKEY
;
update_lock_state
(
hwnd
,
vkey
,
event
->
state
,
event_time
);
bScan
=
keyc2scan
[
event
->
keycode
]
&
0xFF
;
TRACE_
(
key
)(
"bScan = 0x%02x.
\n
"
,
bScan
);
X11DRV_send_keyboard_input
(
hwnd
,
vkey
&
0xff
,
bScan
,
dwFlags
,
event_time
);
}
LeaveCriticalSection
(
&
kbd_section
);
}
/**********************************************************************
...
...
@@ -1427,7 +1437,7 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
* Called from X11DRV_InitKeyboard
* This routine walks through the defined keyboard layouts and selects
* whichever matches most closely.
*
X11 lock
must be held.
*
kbd_section
must be held.
*/
static
void
X11DRV_KEYBOARD_DetectLayout
(
Display
*
display
)
...
...
@@ -1641,7 +1651,7 @@ void X11DRV_InitKeyboard( Display *display )
set_kbd_layout_preload_key
();
wine_tsx11_lock
(
);
EnterCriticalSection
(
&
kbd_section
);
XDisplayKeycodes
(
display
,
&
min_keycode
,
&
max_keycode
);
if
(
key_mapping
)
XFree
(
key_mapping
);
key_mapping
=
XGetKeyboardMapping
(
display
,
min_keycode
,
...
...
@@ -1878,7 +1888,7 @@ void X11DRV_InitKeyboard( Display *display )
keyc2scan
[
keyc
]
=
scan
++
;
}
wine_tsx11_unlock
(
);
LeaveCriticalSection
(
&
kbd_section
);
}
static
BOOL
match_x11_keyboard_layout
(
HKL
hkl
)
...
...
@@ -2012,7 +2022,7 @@ SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
Display
*
display
=
thread_init_display
();
KeyCode
keycode
;
KeySym
keysym
;
int
i
,
i
ndex
;
int
index
;
CHAR
cChar
;
SHORT
ret
;
...
...
@@ -2031,7 +2041,6 @@ SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
keysym
=
(
unsigned
char
)
cChar
;
/* (!) cChar is signed */
if
(
keysym
<=
27
)
keysym
+=
0xFF00
;
/* special chars : return, backspace... */
wine_tsx11_lock
();
keycode
=
XKeysymToKeycode
(
display
,
keysym
);
/* keysym -> keycode */
if
(
!
keycode
)
{
...
...
@@ -2039,49 +2048,41 @@ SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
{
ret
=
0x0240
+
cChar
;
/* 0x0200 indicates a control character */
TRACE
(
" ... returning ctrl char %#.2x
\n
"
,
ret
);
wine_tsx11_unlock
();
return
ret
;
}
/* It didn't work ... let's try with deadchar code. */
TRACE
(
"retrying with | 0xFE00
\n
"
);
keycode
=
XKeysymToKeycode
(
display
,
keysym
|
0xFE00
);
}
wine_tsx11_unlock
();
TRACE
(
"'%c'(%lx): got keycode %u
\n
"
,
cChar
,
keysym
,
keycode
);
if
(
!
keycode
)
return
-
1
;
EnterCriticalSection
(
&
kbd_section
);
/* keycode -> (keyc2vkey) vkey */
ret
=
keyc2vkey
[
keycode
];
if
(
!
keycode
||
!
ret
)
if
(
!
ret
)
{
LeaveCriticalSection
(
&
kbd_section
);
TRACE
(
"keycode for '%c' not found, returning -1
\n
"
,
cChar
);
return
-
1
;
}
index
=
-
1
;
wine_tsx11_lock
();
for
(
i
=
0
;
i
<
4
;
i
++
)
/* find shift state */
{
if
(
keycode_to_keysym
(
display
,
keycode
,
i
)
==
keysym
)
{
index
=
i
;
break
;
}
}
wine_tsx11_unlock
();
for
(
index
=
0
;
index
<
4
;
index
++
)
/* find shift state */
if
(
keycode_to_keysym
(
display
,
keycode
,
index
)
==
keysym
)
break
;
LeaveCriticalSection
(
&
kbd_section
);
switch
(
index
)
{
default:
case
-
1
:
WARN
(
"Keysym %lx not found while parsing the keycode table
\n
"
,
keysym
);
return
-
1
;
case
0
:
break
;
case
1
:
ret
+=
0x0100
;
break
;
case
2
:
ret
+=
0x0600
;
break
;
case
3
:
ret
+=
0x0700
;
break
;
default:
WARN
(
"Keysym %lx not found while parsing the keycode table
\n
"
,
keysym
);
return
-
1
;
}
/*
index : 0 adds 0x0000
...
...
@@ -2100,21 +2101,20 @@ SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
*/
UINT
CDECL
X11DRV_MapVirtualKeyEx
(
UINT
wCode
,
UINT
wMapType
,
HKL
hkl
)
{
UINT
ret
=
0
;
int
keyc
;
Display
*
display
=
thread_init_display
();
#define returnMVK(value) do { TRACE("returning 0x%x.\n",value); return value; } while(0)
TRACE
(
"wCode=0x%x, wMapType=%d, hkl %p
\n
"
,
wCode
,
wMapType
,
hkl
);
if
(
!
match_x11_keyboard_layout
(
hkl
))
FIXME
(
"keyboard layout %p is not supported
\n
"
,
hkl
);
EnterCriticalSection
(
&
kbd_section
);
switch
(
wMapType
)
{
case
MAPVK_VK_TO_VSC
:
/* vkey-code to scan-code */
case
MAPVK_VK_TO_VSC_EX
:
{
int
keyc
;
switch
(
wCode
)
{
case
VK_SHIFT
:
wCode
=
VK_LSHIFT
;
break
;
...
...
@@ -2124,54 +2124,45 @@ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
/* let's do vkey -> keycode -> scan */
for
(
keyc
=
min_keycode
;
keyc
<=
max_keycode
;
keyc
++
)
if
((
keyc2vkey
[
keyc
]
&
0xFF
)
==
wCode
)
break
;
if
(
keyc
>
max_keycode
)
{
TRACE
(
"returning no scan-code.
\n
"
);
return
0
;
if
((
keyc2vkey
[
keyc
]
&
0xFF
)
==
wCode
)
{
ret
=
keyc2scan
[
keyc
]
&
0xFF
;
break
;
}
returnMVK
(
keyc2scan
[
keyc
]
&
0xFF
);
}
break
;
case
MAPVK_VSC_TO_VK
:
/* scan-code to vkey-code */
case
MAPVK_VSC_TO_VK_EX
:
{
int
keyc
;
UINT
vkey
=
0
;
/* let's do scan -> keycode -> vkey */
for
(
keyc
=
min_keycode
;
keyc
<=
max_keycode
;
keyc
++
)
if
((
keyc2scan
[
keyc
]
&
0xFF
)
==
(
wCode
&
0xFF
))
{
vkey
=
keyc2vkey
[
keyc
]
&
0xFF
;
ret
=
keyc2vkey
[
keyc
]
&
0xFF
;
/* Only stop if it's not a numpad vkey; otherwise keep
looking for a potential better vkey. */
if
(
vkey
&&
(
vkey
<
VK_NUMPAD0
||
VK_DIVIDE
<
vkey
))
if
(
ret
&&
(
ret
<
VK_NUMPAD0
||
VK_DIVIDE
<
ret
))
break
;
}
if
(
vkey
==
0
)
{
TRACE
(
"returning no vkey-code.
\n
"
);
return
0
;
}
if
(
wMapType
==
MAPVK_VSC_TO_VK
)
switch
(
vkey
)
switch
(
ret
)
{
case
VK_LSHIFT
:
case
VK_RSHIFT
:
vkey
=
VK_SHIFT
;
break
;
ret
=
VK_SHIFT
;
break
;
case
VK_LCONTROL
:
case
VK_RCONTROL
:
vkey
=
VK_CONTROL
;
break
;
ret
=
VK_CONTROL
;
break
;
case
VK_LMENU
:
case
VK_RMENU
:
vkey
=
VK_MENU
;
break
;
ret
=
VK_MENU
;
break
;
}
returnMVK
(
vkey
)
;
}
break
;
case
MAPVK_VK_TO_CHAR
:
/* vkey-code to unshifted ANSI code */
{
/* we still don't know what "unshifted" means. in windows VK_W (0x57)
...
...
@@ -2183,7 +2174,7 @@ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
/* let's do vkey -> keycode -> (XLookupString) ansi char */
XKeyEvent
e
;
KeySym
keysym
;
int
keyc
,
len
;
int
len
;
char
s
[
10
];
e
.
display
=
display
;
...
...
@@ -2191,8 +2182,6 @@ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
e
.
keycode
=
0
;
e
.
type
=
KeyPress
;
wine_tsx11_lock
();
/* We exit on the first keycode found, to speed up the thing. */
for
(
keyc
=
min_keycode
;
(
keyc
<=
max_keycode
)
&&
(
!
e
.
keycode
)
;
keyc
++
)
{
/* Find a keycode that could have generated this virtual key */
...
...
@@ -2223,28 +2212,27 @@ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
if
(
!
e
.
keycode
)
{
WARN
(
"Unknown virtual key %X !!!
\n
"
,
wCode
);
wine_tsx11_unlock
();
return
0
;
/* whatever */
break
;
}
TRACE
(
"Found keycode %u
\n
"
,
e
.
keycode
);
len
=
XLookupString
(
&
e
,
s
,
sizeof
(
s
),
&
keysym
,
NULL
);
wine_tsx11_unlock
();
if
(
len
)
{
WCHAR
wch
;
if
(
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
s
,
len
,
&
wch
,
1
))
returnMVK
(
toupperW
(
wch
));
if
(
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
s
,
len
,
&
wch
,
1
))
ret
=
toupperW
(
wch
);
}
TRACE
(
"returning no ANSI.
\n
"
);
return
0
;
break
;
}
default:
/* reserved */
FIXME
(
"Unknown wMapType %d !
\n
"
,
wMapType
);
return
0
;
break
;
}
return
0
;
LeaveCriticalSection
(
&
kbd_section
);
TRACE
(
"returning 0x%x.
\n
"
,
ret
);
return
ret
;
}
/***********************************************************************
...
...
@@ -2319,6 +2307,8 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
/* let's do scancode -> keycode -> keysym -> String */
EnterCriticalSection
(
&
kbd_section
);
for
(
keyi
=
min_keycode
;
keyi
<=
max_keycode
;
keyi
++
)
if
((
keyc2scan
[
keyi
])
==
scanCode
)
break
;
...
...
@@ -2326,17 +2316,16 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
{
INT
rc
;
wine_tsx11_lock
();
keyc
=
(
KeyCode
)
keyi
;
keys
=
keycode_to_keysym
(
display
,
keyc
,
0
);
name
=
XKeysymToString
(
keys
);
wine_tsx11_unlock
();
if
(
name
&&
(
vkey
==
VK_SHIFT
||
vkey
==
VK_CONTROL
||
vkey
==
VK_MENU
))
{
char
*
idx
=
strrchr
(
name
,
'_'
);
if
(
idx
&&
(
strcasecmp
(
idx
,
"_r"
)
==
0
||
strcasecmp
(
idx
,
"_l"
)
==
0
))
{
LeaveCriticalSection
(
&
kbd_section
);
TRACE
(
"found scan=%04x keyc=%u keysym=%lx modified_string=%s
\n
"
,
scanCode
,
keyc
,
keys
,
debugstr_an
(
name
,
idx
-
name
));
rc
=
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
name
,
idx
-
name
+
1
,
lpBuffer
,
nSize
);
...
...
@@ -2348,6 +2337,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
if
(
name
)
{
LeaveCriticalSection
(
&
kbd_section
);
TRACE
(
"found scan=%04x keyc=%u keysym=%04x vkey=%04x string=%s
\n
"
,
scanCode
,
keyc
,
(
int
)
keys
,
vkey
,
debugstr_a
(
name
));
rc
=
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
name
,
-
1
,
lpBuffer
,
nSize
);
...
...
@@ -2359,6 +2349,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
/* Finally issue WARN for unknown keys */
LeaveCriticalSection
(
&
kbd_section
);
WARN
(
"(%08x,%p,%d): unsupported key, vkey=%04X, ansi=%04x
\n
"
,
lParam
,
lpBuffer
,
nSize
,
vkey
,
ansi
);
*
lpBuffer
=
0
;
return
0
;
...
...
@@ -2504,6 +2495,8 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
e
.
window
=
X11DRV_get_whole_window
(
focus
);
xic
=
X11DRV_get_ic
(
focus
);
EnterCriticalSection
(
&
kbd_section
);
if
(
lpKeyState
[
VK_SHIFT
]
&
0x80
)
{
TRACE_
(
key
)(
"ShiftMask = %04x
\n
"
,
ShiftMask
);
...
...
@@ -2531,7 +2524,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
TRACE_
(
key
)(
"(%04X, %04X) : faked state = 0x%04x
\n
"
,
virtKey
,
scanCode
,
e
.
state
);
wine_tsx11_lock
();
/* We exit on the first keycode found, to speed up the thing. */
for
(
keyc
=
min_keycode
;
(
keyc
<=
max_keycode
)
&&
(
!
e
.
keycode
)
;
keyc
++
)
{
/* Find a keycode that could have generated this virtual key */
...
...
@@ -2565,7 +2558,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
if
(
!
e
.
keycode
&&
virtKey
!=
VK_NONAME
)
{
WARN_
(
key
)(
"Unknown virtual key %X !!!
\n
"
,
virtKey
);
wine_tsx11_unlock
(
);
LeaveCriticalSection
(
&
kbd_section
);
return
0
;
}
else
TRACE_
(
key
)(
"Found keycode %u
\n
"
,
e
.
keycode
);
...
...
@@ -2586,7 +2579,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
if
(
lpChar
==
NULL
)
{
ERR_
(
key
)(
"Failed to allocate memory!
\n
"
);
wine_tsx11_unlock
(
);
LeaveCriticalSection
(
&
kbd_section
);
return
0
;
}
ret
=
XmbLookupString
(
xic
,
&
e
,
lpChar
,
ret
,
&
keysym
,
&
status
);
...
...
@@ -2594,7 +2587,6 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
}
else
ret
=
XLookupString
(
&
e
,
buf
,
sizeof
(
buf
),
&
keysym
,
NULL
);
wine_tsx11_unlock
();
TRACE_
(
key
)(
"nbyte = %d, status 0x%x
\n
"
,
ret
,
status
);
...
...
@@ -2731,6 +2723,8 @@ found:
if
(
buf
!=
lpChar
)
HeapFree
(
GetProcessHeap
(),
0
,
lpChar
);
LeaveCriticalSection
(
&
kbd_section
);
/* Null-terminate the buffer, if there's room. MSDN clearly states that the
caller must not assume this is done, but some programs (e.g. Audiosurf) do. */
if
(
1
<=
ret
&&
ret
<
bufW_size
)
...
...
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