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
ab5063b2
Commit
ab5063b2
authored
Oct 11, 2002
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added server-side infrastructure for the thread input structure.
Reimplemented AttachThreadInput() and added GetGUIThreadInfo().
parent
ed29ffde
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
386 additions
and
97 deletions
+386
-97
message.c
dlls/user/message.c
+55
-0
user32.spec
dlls/user/user32.spec
+1
-0
server_protocol.h
include/wine/server_protocol.h
+41
-1
winuser.h
include/winuser.h
+31
-9
protocol.def
server/protocol.def
+23
-0
queue.c
server/queue.c
+196
-2
request.h
server/request.h
+4
-0
trace.c
server/trace.c
+31
-0
user.h
server/user.h
+1
-0
window.c
server/window.c
+3
-0
queue.c
windows/queue.c
+0
-85
No files found.
dlls/user/message.c
View file @
ab5063b2
...
...
@@ -2231,3 +2231,58 @@ BOOL WINAPI SetMessageQueue( INT size )
/* now obsolete the message queue will be expanded dynamically as necessary */
return
TRUE
;
}
/**********************************************************************
* AttachThreadInput (USER32.@)
*
* Attaches the input processing mechanism of one thread to that of
* another thread.
*/
BOOL
WINAPI
AttachThreadInput
(
DWORD
from
,
DWORD
to
,
BOOL
attach
)
{
BOOL
ret
;
SERVER_START_REQ
(
attach_thread_input
)
{
req
->
tid_from
=
from
;
req
->
tid_to
=
to
;
req
->
attach
=
attach
;
ret
=
!
wine_server_call_err
(
req
);
}
SERVER_END_REQ
;
return
ret
;
}
/**********************************************************************
* GetGUIThreadInfo (USER32.@)
*/
BOOL
WINAPI
GetGUIThreadInfo
(
DWORD
id
,
GUITHREADINFO
*
info
)
{
BOOL
ret
;
SERVER_START_REQ
(
get_thread_input
)
{
req
->
tid
=
id
;
if
((
ret
=
!
wine_server_call_err
(
req
)))
{
info
->
flags
=
0
;
info
->
hwndActive
=
reply
->
active
;
info
->
hwndFocus
=
reply
->
focus
;
info
->
hwndCapture
=
reply
->
capture
;
info
->
hwndMenuOwner
=
reply
->
menu_owner
;
info
->
hwndMoveSize
=
reply
->
move_size
;
info
->
hwndCaret
=
reply
->
caret
;
info
->
rcCaret
.
left
=
reply
->
rect
.
left
;
info
->
rcCaret
.
top
=
reply
->
rect
.
top
;
info
->
rcCaret
.
right
=
reply
->
rect
.
right
;
info
->
rcCaret
.
bottom
=
reply
->
rect
.
bottom
;
if
(
reply
->
menu_owner
)
info
->
flags
|=
GUI_INMENUMODE
;
if
(
reply
->
move_size
)
info
->
flags
|=
GUI_INMOVESIZE
;
if
(
reply
->
caret
)
info
->
flags
|=
GUI_CARETBLINKING
;
}
}
SERVER_END_REQ
;
return
ret
;
}
dlls/user/user32.spec
View file @
ab5063b2
...
...
@@ -244,6 +244,7 @@ init UserClientDllInitialize
@ stdcall GetDoubleClickTime() GetDoubleClickTime
@ stdcall GetFocus() GetFocus
@ stdcall GetForegroundWindow() GetForegroundWindow
@ stdcall GetGUIThreadInfo(long ptr) GetGUIThreadInfo
@ stdcall GetIconInfo(long ptr) GetIconInfo
@ stub GetInputDesktop
@ stdcall GetInputState() GetInputState
...
...
include/wine/server_protocol.h
View file @
ab5063b2
...
...
@@ -2729,6 +2729,40 @@ struct get_window_properties_reply
};
struct
attach_thread_input_request
{
struct
request_header
__header
;
thread_id_t
tid_from
;
thread_id_t
tid_to
;
int
attach
;
};
struct
attach_thread_input_reply
{
struct
reply_header
__header
;
};
struct
get_thread_input_request
{
struct
request_header
__header
;
thread_id_t
tid
;
};
struct
get_thread_input_reply
{
struct
reply_header
__header
;
user_handle_t
focus
;
user_handle_t
capture
;
user_handle_t
active
;
user_handle_t
foreground
;
user_handle_t
menu_owner
;
user_handle_t
move_size
;
user_handle_t
caret
;
rectangle_t
rect
;
};
enum
request
{
REQ_new_process
,
...
...
@@ -2887,6 +2921,8 @@ enum request
REQ_remove_window_property
,
REQ_get_window_property
,
REQ_get_window_properties
,
REQ_attach_thread_input
,
REQ_get_thread_input
,
REQ_NB_REQUESTS
};
...
...
@@ -3050,6 +3086,8 @@ union generic_request
struct
remove_window_property_request
remove_window_property_request
;
struct
get_window_property_request
get_window_property_request
;
struct
get_window_properties_request
get_window_properties_request
;
struct
attach_thread_input_request
attach_thread_input_request
;
struct
get_thread_input_request
get_thread_input_request
;
};
union
generic_reply
{
...
...
@@ -3211,8 +3249,10 @@ union generic_reply
struct
remove_window_property_reply
remove_window_property_reply
;
struct
get_window_property_reply
get_window_property_reply
;
struct
get_window_properties_reply
get_window_properties_reply
;
struct
attach_thread_input_reply
attach_thread_input_reply
;
struct
get_thread_input_reply
get_thread_input_reply
;
};
#define SERVER_PROTOCOL_VERSION 8
4
#define SERVER_PROTOCOL_VERSION 8
5
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
include/winuser.h
View file @
ab5063b2
...
...
@@ -397,6 +397,27 @@ typedef struct tagINPUT
}
INPUT
,
*
PINPUT
,
*
LPINPUT
;
typedef
struct
tagGUITHREADINFO
{
DWORD
cbSize
;
DWORD
flags
;
HWND
hwndActive
;
HWND
hwndFocus
;
HWND
hwndCapture
;
HWND
hwndMenuOwner
;
HWND
hwndMoveSize
;
HWND
hwndCaret
;
RECT
rcCaret
;
}
GUITHREADINFO
,
*
PGUITHREADINFO
,
*
LPGUITHREADINFO
;
#define GUI_CARETBLINKING 0x00000001
#define GUI_INMOVESIZE 0x00000002
#define GUI_INMENUMODE 0x00000004
#define GUI_SYSTEMMENUMODE 0x00000008
#define GUI_POPUPMENUMODE 0x00000010
#define GUI_16BITTASK 0x00000020
/***** Dialogs *****/
/* Gcc on Solaris has a version of this that we don't care about */
...
...
@@ -4079,15 +4100,16 @@ UINT WINAPI GetDlgItemInt(HWND,INT,BOOL*,BOOL);
INT
WINAPI
GetDlgItemTextA
(
HWND
,
INT
,
LPSTR
,
UINT
);
INT
WINAPI
GetDlgItemTextW
(
HWND
,
INT
,
LPWSTR
,
UINT
);
#define GetDlgItemText WINELIB_NAME_AW(GetDlgItemText)
UINT
WINAPI
GetDoubleClickTime
(
void
);
HWND
WINAPI
GetFocus
(
void
);
HWND
WINAPI
GetForegroundWindow
(
void
);
BOOL
WINAPI
GetInputState
(
void
);
UINT
WINAPI
GetInternalWindowPos
(
HWND
,
LPRECT
,
LPPOINT
);
UINT
WINAPI
GetKBCodePage
(
void
);
INT
WINAPI
GetKeyboardType
(
INT
);
INT
WINAPI
GetKeyNameTextA
(
LONG
,
LPSTR
,
INT
);
INT
WINAPI
GetKeyNameTextW
(
LONG
,
LPWSTR
,
INT
);
UINT
WINAPI
GetDoubleClickTime
(
void
);
HWND
WINAPI
GetFocus
(
void
);
HWND
WINAPI
GetForegroundWindow
(
void
);
BOOL
WINAPI
GetGUIThreadInfo
(
DWORD
,
GUITHREADINFO
*
);
BOOL
WINAPI
GetInputState
(
void
);
UINT
WINAPI
GetInternalWindowPos
(
HWND
,
LPRECT
,
LPPOINT
);
UINT
WINAPI
GetKBCodePage
(
void
);
INT
WINAPI
GetKeyboardType
(
INT
);
INT
WINAPI
GetKeyNameTextA
(
LONG
,
LPSTR
,
INT
);
INT
WINAPI
GetKeyNameTextW
(
LONG
,
LPWSTR
,
INT
);
#define GetKeyNameText WINELIB_NAME_AW(GetKeyNameText)
INT
WINAPI
GetKeyboardLayoutNameA
(
LPSTR
);
INT
WINAPI
GetKeyboardLayoutNameW
(
LPWSTR
);
...
...
server/protocol.def
View file @
ab5063b2
...
...
@@ -1908,3 +1908,26 @@ enum message_type
int total; /* total number of properties */
VARARG(props,properties); /* list of properties */
@END
/* Attach (or detach) thread inputs */
@REQ(attach_thread_input)
thread_id_t tid_from; /* thread to be attached */
thread_id_t tid_to; /* thread to which tid_from should be attached */
int attach; /* is it an attach? */
@END
/* Get input data for a given thread */
@REQ(get_thread_input)
thread_id_t tid; /* id of thread */
@REPLY
user_handle_t focus; /* handle to the focus window */
user_handle_t capture; /* handle to the capture window */
user_handle_t active; /* handle to the active window */
user_handle_t foreground; /* handle to the global foreground window */
user_handle_t menu_owner; /* handle to the menu owner */
user_handle_t move_size; /* handle to the moving/resizing window */
user_handle_t caret; /* handle to the caret window */
rectangle_t rect; /* caret rectangle */
@END
server/queue.c
View file @
ab5063b2
...
...
@@ -89,6 +89,19 @@ struct timer
unsigned
int
lparam
;
/* lparam for message */
};
struct
thread_input
{
struct
object
obj
;
/* object header */
user_handle_t
focus
;
/* focus window */
user_handle_t
capture
;
/* capture window */
user_handle_t
active
;
/* active window */
user_handle_t
menu_owner
;
/* current menu owner window */
user_handle_t
move_size
;
/* current moving/resizing window */
user_handle_t
caret
;
/* caret window */
rectangle_t
rect
;
/* caret rectangle */
unsigned
char
keystate
[
256
];
/* state of each key */
};
struct
msg_queue
{
struct
object
obj
;
/* object header */
...
...
@@ -106,6 +119,7 @@ struct msg_queue
struct
timer
*
last_timer
;
/* tail of timer list */
struct
timer
*
next_timer
;
/* next timer to expire */
struct
timeout_user
*
timeout
;
/* timeout for next timer to expire */
struct
thread_input
*
input
;
/* thread input descriptor */
};
static
void
msg_queue_dump
(
struct
object
*
obj
,
int
verbose
);
...
...
@@ -114,6 +128,8 @@ static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry
static
int
msg_queue_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
);
static
int
msg_queue_satisfied
(
struct
object
*
obj
,
struct
thread
*
thread
);
static
void
msg_queue_destroy
(
struct
object
*
obj
);
static
void
thread_input_dump
(
struct
object
*
obj
,
int
verbose
);
static
void
thread_input_destroy
(
struct
object
*
obj
);
static
void
timer_callback
(
void
*
private
);
static
const
struct
object_ops
msg_queue_ops
=
...
...
@@ -134,11 +150,55 @@ static const struct object_ops msg_queue_ops =
};
static
struct
msg_queue
*
create_msg_queue
(
struct
thread
*
thread
)
static
const
struct
object_ops
thread_input_ops
=
{
sizeof
(
struct
thread_input
),
/* size */
thread_input_dump
,
/* dump */
no_add_queue
,
/* add_queue */
NULL
,
/* remove_queue */
NULL
,
/* signaled */
NULL
,
/* satisfied */
NULL
,
/* get_poll_events */
NULL
,
/* poll_event */
no_get_fd
,
/* get_fd */
no_flush
,
/* flush */
no_get_file_info
,
/* get_file_info */
NULL
,
/* queue_async */
thread_input_destroy
/* destroy */
};
/* create a thread input object */
static
struct
thread_input
*
create_thread_input
(
void
)
{
struct
thread_input
*
input
;
if
((
input
=
alloc_object
(
&
thread_input_ops
,
-
1
)))
{
input
->
focus
=
0
;
input
->
capture
=
0
;
input
->
active
=
0
;
input
->
menu_owner
=
0
;
input
->
move_size
=
0
;
input
->
caret
=
0
;
input
->
rect
.
left
=
0
;
input
->
rect
.
top
=
0
;
input
->
rect
.
right
=
0
;
input
->
rect
.
bottom
=
0
;
memset
(
input
->
keystate
,
0
,
sizeof
(
input
->
keystate
)
);
}
return
input
;
}
/* pointer to input structure of foreground thread */
static
struct
thread_input
*
foreground_input
;
/* create a message queue object */
static
struct
msg_queue
*
create_msg_queue
(
struct
thread
*
thread
,
struct
thread_input
*
input
)
{
struct
msg_queue
*
queue
;
int
i
;
if
(
!
input
&&
!
(
input
=
create_thread_input
()))
return
NULL
;
if
((
queue
=
alloc_object
(
&
msg_queue_ops
,
-
1
)))
{
queue
->
wake_bits
=
0
;
...
...
@@ -153,6 +213,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
queue
->
last_timer
=
NULL
;
queue
->
next_timer
=
NULL
;
queue
->
timeout
=
NULL
;
queue
->
input
=
(
struct
thread_input
*
)
grab_object
(
input
);
for
(
i
=
0
;
i
<
NB_MSG_KINDS
;
i
++
)
queue
->
msg_list
[
i
].
first
=
queue
->
msg_list
[
i
].
last
=
NULL
;
...
...
@@ -160,6 +221,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
if
(
!
thread
->
process
->
queue
)
thread
->
process
->
queue
=
(
struct
msg_queue
*
)
grab_object
(
queue
);
}
release_object
(
input
);
return
queue
;
}
...
...
@@ -217,7 +279,7 @@ inline static int get_hardware_msg_bit( struct message *msg )
inline
static
struct
msg_queue
*
get_current_queue
(
void
)
{
struct
msg_queue
*
queue
=
current
->
queue
;
if
(
!
queue
)
queue
=
create_msg_queue
(
current
);
if
(
!
queue
)
queue
=
create_msg_queue
(
current
,
NULL
);
return
queue
;
}
...
...
@@ -529,8 +591,76 @@ static void msg_queue_destroy( struct object *obj )
timer
=
next
;
}
if
(
queue
->
timeout
)
remove_timeout_user
(
queue
->
timeout
);
if
(
queue
->
input
)
release_object
(
queue
->
input
);
}
static
void
thread_input_dump
(
struct
object
*
obj
,
int
verbose
)
{
struct
thread_input
*
input
=
(
struct
thread_input
*
)
obj
;
fprintf
(
stderr
,
"Thread input focus=%x capture=%x active=%x
\n
"
,
input
->
focus
,
input
->
capture
,
input
->
active
);
}
static
void
thread_input_destroy
(
struct
object
*
obj
)
{
struct
thread_input
*
input
=
(
struct
thread_input
*
)
obj
;
if
(
foreground_input
==
input
)
foreground_input
=
NULL
;
}
/* fix the thread input data when a window is destroyed */
inline
static
void
thread_input_cleanup_window
(
struct
msg_queue
*
queue
,
user_handle_t
window
)
{
struct
thread_input
*
input
=
queue
->
input
;
if
(
window
==
input
->
focus
)
input
->
focus
=
0
;
if
(
window
==
input
->
capture
)
input
->
capture
=
0
;
if
(
window
==
input
->
active
)
input
->
active
=
0
;
if
(
window
==
input
->
menu_owner
)
input
->
menu_owner
=
0
;
if
(
window
==
input
->
move_size
)
input
->
move_size
=
0
;
if
(
window
==
input
->
caret
)
input
->
caret
=
0
;
}
/* attach two thread input data structures */
int
attach_thread_input
(
struct
thread
*
thread_from
,
struct
thread
*
thread_to
)
{
struct
thread_input
*
input
;
if
(
!
thread_to
->
queue
&&
!
(
thread_to
->
queue
=
create_msg_queue
(
thread_to
,
NULL
)))
return
0
;
input
=
(
struct
thread_input
*
)
grab_object
(
thread_to
->
queue
->
input
);
if
(
thread_from
->
queue
)
{
release_object
(
thread_from
->
queue
->
input
);
thread_from
->
queue
->
input
=
input
;
}
else
{
if
(
!
(
thread_from
->
queue
=
create_msg_queue
(
thread_from
,
input
)))
return
0
;
}
memset
(
input
->
keystate
,
0
,
sizeof
(
input
->
keystate
)
);
return
1
;
}
/* detach two thread input data structures */
static
void
detach_thread_input
(
struct
thread
*
thread_from
,
struct
thread
*
thread_to
)
{
struct
thread_input
*
input
;
if
(
!
thread_from
->
queue
||
!
thread_to
->
queue
||
thread_from
->
queue
->
input
!=
thread_to
->
queue
->
input
)
{
set_error
(
STATUS_ACCESS_DENIED
);
return
;
}
if
((
input
=
create_thread_input
()))
{
release_object
(
thread_from
->
queue
->
input
);
thread_from
->
queue
->
input
=
input
;
}
}
/* set the next timer to expire */
static
void
set_next_timer
(
struct
msg_queue
*
queue
,
struct
timer
*
timer
)
{
...
...
@@ -706,6 +836,8 @@ void queue_cleanup_window( struct thread *thread, user_handle_t win )
msg
=
next
;
}
}
thread_input_cleanup_window
(
queue
,
win
);
}
/* post a message to a window; used by socket handling */
...
...
@@ -1098,3 +1230,65 @@ DECL_HANDLER(kill_win_timer)
if
(
!
queue
||
!
kill_timer
(
queue
,
get_user_full_handle
(
req
->
win
),
req
->
msg
,
req
->
id
))
set_error
(
STATUS_INVALID_PARAMETER
);
}
/* attach (or detach) thread inputs */
DECL_HANDLER
(
attach_thread_input
)
{
struct
thread
*
thread_from
=
get_thread_from_id
(
req
->
tid_from
);
struct
thread
*
thread_to
=
get_thread_from_id
(
req
->
tid_to
);
if
(
!
thread_from
||
!
thread_to
)
{
if
(
thread_from
)
release_object
(
thread_from
);
if
(
thread_to
)
release_object
(
thread_to
);
return
;
}
if
(
thread_from
!=
thread_to
)
{
if
(
req
->
attach
)
attach_thread_input
(
thread_from
,
thread_to
);
else
detach_thread_input
(
thread_from
,
thread_to
);
}
else
set_error
(
STATUS_ACCESS_DENIED
);
release_object
(
thread_from
);
release_object
(
thread_to
);
}
/* get thread input data */
DECL_HANDLER
(
get_thread_input
)
{
struct
thread
*
thread
=
NULL
;
struct
thread_input
*
input
;
if
(
req
->
tid
)
{
if
(
!
(
thread
=
get_thread_from_id
(
req
->
tid
)))
return
;
input
=
thread
->
queue
?
thread
->
queue
->
input
:
NULL
;
}
else
input
=
foreground_input
;
/* get the foreground thread info */
if
(
input
)
{
reply
->
focus
=
input
->
focus
;
reply
->
capture
=
input
->
capture
;
reply
->
active
=
input
->
active
;
reply
->
menu_owner
=
input
->
menu_owner
;
reply
->
move_size
=
input
->
move_size
;
reply
->
caret
=
input
->
caret
;
reply
->
rect
=
input
->
rect
;
}
else
{
reply
->
focus
=
0
;
reply
->
capture
=
0
;
reply
->
active
=
0
;
reply
->
menu_owner
=
0
;
reply
->
move_size
=
0
;
reply
->
caret
=
0
;
reply
->
rect
.
left
=
reply
->
rect
.
top
=
reply
->
rect
.
right
=
reply
->
rect
.
bottom
=
0
;
}
/* foreground window is active window of foreground thread */
reply
->
foreground
=
foreground_input
?
foreground_input
->
active
:
0
;
if
(
thread
)
release_object
(
thread
);
}
server/request.h
View file @
ab5063b2
...
...
@@ -259,6 +259,8 @@ DECL_HANDLER(set_window_property);
DECL_HANDLER
(
remove_window_property
);
DECL_HANDLER
(
get_window_property
);
DECL_HANDLER
(
get_window_properties
);
DECL_HANDLER
(
attach_thread_input
);
DECL_HANDLER
(
get_thread_input
);
#ifdef WANT_REQUEST_HANDLERS
...
...
@@ -421,6 +423,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_remove_window_property
,
(
req_handler
)
req_get_window_property
,
(
req_handler
)
req_get_window_properties
,
(
req_handler
)
req_attach_thread_input
,
(
req_handler
)
req_get_thread_input
,
};
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/trace.c
View file @
ab5063b2
...
...
@@ -2175,6 +2175,31 @@ static void dump_get_window_properties_reply( const struct get_window_properties
dump_varargs_properties
(
cur_size
);
}
static
void
dump_attach_thread_input_request
(
const
struct
attach_thread_input_request
*
req
)
{
fprintf
(
stderr
,
" tid_from=%08x,"
,
req
->
tid_from
);
fprintf
(
stderr
,
" tid_to=%08x,"
,
req
->
tid_to
);
fprintf
(
stderr
,
" attach=%d"
,
req
->
attach
);
}
static
void
dump_get_thread_input_request
(
const
struct
get_thread_input_request
*
req
)
{
fprintf
(
stderr
,
" tid=%08x"
,
req
->
tid
);
}
static
void
dump_get_thread_input_reply
(
const
struct
get_thread_input_reply
*
req
)
{
fprintf
(
stderr
,
" focus=%08x,"
,
req
->
focus
);
fprintf
(
stderr
,
" capture=%08x,"
,
req
->
capture
);
fprintf
(
stderr
,
" active=%08x,"
,
req
->
active
);
fprintf
(
stderr
,
" foreground=%08x,"
,
req
->
foreground
);
fprintf
(
stderr
,
" menu_owner=%08x,"
,
req
->
menu_owner
);
fprintf
(
stderr
,
" move_size=%08x,"
,
req
->
move_size
);
fprintf
(
stderr
,
" caret=%08x,"
,
req
->
caret
);
fprintf
(
stderr
,
" rect="
);
dump_rectangle
(
&
req
->
rect
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
(
dump_func
)
dump_new_process_request
,
(
dump_func
)
dump_get_new_process_info_request
,
...
...
@@ -2332,6 +2357,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_remove_window_property_request
,
(
dump_func
)
dump_get_window_property_request
,
(
dump_func
)
dump_get_window_properties_request
,
(
dump_func
)
dump_attach_thread_input_request
,
(
dump_func
)
dump_get_thread_input_request
,
};
static
const
dump_func
reply_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -2491,6 +2518,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_remove_window_property_reply
,
(
dump_func
)
dump_get_window_property_reply
,
(
dump_func
)
dump_get_window_properties_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_get_thread_input_reply
,
};
static
const
char
*
const
req_names
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -2650,6 +2679,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"remove_window_property"
,
"get_window_property"
,
"get_window_properties"
,
"attach_thread_input"
,
"get_thread_input"
,
};
/* ### make_requests end ### */
...
...
server/user.h
View file @
ab5063b2
...
...
@@ -46,6 +46,7 @@ extern void *next_user_handle( user_handle_t *handle, enum user_object type );
extern
void
free_msg_queue
(
struct
thread
*
thread
);
extern
void
inc_queue_paint_count
(
struct
thread
*
thread
,
int
incr
);
extern
void
queue_cleanup_window
(
struct
thread
*
thread
,
user_handle_t
win
);
extern
int
attach_thread_input
(
struct
thread
*
thread_from
,
struct
thread
*
thread_to
);
extern
void
post_message
(
user_handle_t
win
,
unsigned
int
message
,
unsigned
int
wparam
,
unsigned
int
lparam
);
...
...
server/window.c
View file @
ab5063b2
...
...
@@ -287,6 +287,9 @@ static struct window *create_window( struct window *parent, struct window *owner
}
else
win
->
next
=
win
->
prev
=
NULL
;
/* if parent belongs to a different thread, attach the two threads */
if
(
parent
&&
parent
->
thread
&&
parent
->
thread
!=
current
)
attach_thread_input
(
current
,
parent
->
thread
);
return
win
;
}
...
...
windows/queue.c
View file @
ab5063b2
...
...
@@ -593,88 +593,3 @@ LONG WINAPI GetMessageExtraInfo(void)
if
(
!
(
queue
=
QUEUE_Current
()))
return
0
;
return
queue
->
GetMessageExtraInfoVal
;
}
/**********************************************************************
* AttachThreadInput (USER32.@) Attaches input of 1 thread to other
*
* Attaches the input processing mechanism of one thread to that of
* another thread.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* TODO:
* 1. Reset the Key State (currenly per thread key state is not maintained)
*/
BOOL
WINAPI
AttachThreadInput
(
DWORD
idAttach
,
/* [in] Thread to attach */
DWORD
idAttachTo
,
/* [in] Thread to attach to */
BOOL
fAttach
)
/* [in] Attach or detach */
{
MESSAGEQUEUE
*
pSrcMsgQ
=
0
,
*
pTgtMsgQ
=
0
;
BOOL16
bRet
=
0
;
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* A thread cannot attach to itself */
if
(
idAttach
==
idAttachTo
)
goto
CLEANUP
;
/* According to the docs this method should fail if a
* "Journal record" hook is installed. (attaches all input queues together)
*/
if
(
HOOK_IsHooked
(
WH_JOURNALRECORD
)
)
goto
CLEANUP
;
/* Retrieve message queues corresponding to the thread id's */
pTgtMsgQ
=
QUEUE_Lock
(
GetThreadQueue16
(
idAttach
)
);
pSrcMsgQ
=
QUEUE_Lock
(
GetThreadQueue16
(
idAttachTo
)
);
/* Ensure we have message queues and that Src and Tgt threads
* are not system threads.
*/
if
(
!
pSrcMsgQ
||
!
pTgtMsgQ
||
!
pSrcMsgQ
->
pQData
||
!
pTgtMsgQ
->
pQData
)
goto
CLEANUP
;
if
(
fAttach
)
/* Attach threads */
{
/* Only attach if currently detached */
if
(
pTgtMsgQ
->
pQData
!=
pSrcMsgQ
->
pQData
)
{
/* First release the target threads perQData */
PERQDATA_Release
(
pTgtMsgQ
->
pQData
);
/* Share a reference to the source threads perQDATA */
PERQDATA_Addref
(
pSrcMsgQ
->
pQData
);
pTgtMsgQ
->
pQData
=
pSrcMsgQ
->
pQData
;
}
}
else
/* Detach threads */
{
/* Only detach if currently attached */
if
(
pTgtMsgQ
->
pQData
==
pSrcMsgQ
->
pQData
)
{
/* First release the target threads perQData */
PERQDATA_Release
(
pTgtMsgQ
->
pQData
);
/* Give the target thread its own private perQDATA once more */
pTgtMsgQ
->
pQData
=
PERQDATA_CreateInstance
();
}
}
/* TODO: Reset the Key State */
bRet
=
1
;
/* Success */
CLEANUP:
/* Unlock the queues before returning */
if
(
pSrcMsgQ
)
QUEUE_Unlock
(
pSrcMsgQ
);
if
(
pTgtMsgQ
)
QUEUE_Unlock
(
pTgtMsgQ
);
return
bRet
;
}
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