From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_com_client.c | 19 ++++++++++++++++ dlls/uiautomationcore/uia_event.c | 30 ++++++++++++++++++++++++++ dlls/uiautomationcore/uia_private.h | 2 ++ 3 files changed, 51 insertions(+)
diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index 19540b19dc0..0980b2d0b37 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -958,6 +958,13 @@ struct uia_com_event { struct uia_event_handler_map_entry *handler_map; };
+static HRESULT uia_com_win_event_callback(DWORD event_id, HWND hwnd, LONG obj_id, LONG child_id, DWORD thread_id, + DWORD event_time) +{ + FIXME("%ld, %p, %ld, %ld, %ld, %ld: stub\n", event_id, hwnd, obj_id, child_id, thread_id, event_time); + return S_OK; +} + static HRESULT uia_event_handlers_add_handler(IUnknown *handler_iface, SAFEARRAY *runtime_id, int event_id, struct uia_com_event *event) { @@ -998,6 +1005,14 @@ static HRESULT uia_event_handlers_add_handler(IUnknown *handler_iface, SAFEARRAY
list_add_tail(&event_map->handlers_list, &event->event_handler_map_list_entry); event->handler_map = event_map; + + /* + * Add our WinEvent callback function to the event thread upon adding the + * first COM event handler. + */ + if (!com_event_handlers.handler_count) + uia_event_thread_set_win_event_callback(uia_com_win_event_callback); + com_event_handlers.handler_count++;
exit: @@ -1042,6 +1057,10 @@ static void uia_event_handlers_remove_handlers(IUnknown *handler_iface, SAFEARRA if (com_event_handlers.handler_count && (rb_entry = rb_get(&com_event_handlers.handler_map, &event_ident))) uia_event_handler_map_entry_destroy(RB_ENTRY_VALUE(rb_entry, struct uia_event_handler_map_entry, entry));
+ /* No more COM event handlers registered, remove our WinEvent callback. */ + if (!com_event_handlers.handler_count) + uia_event_thread_set_win_event_callback(NULL); + LeaveCriticalSection(&com_event_handlers_cs); }
diff --git a/dlls/uiautomationcore/uia_event.c b/dlls/uiautomationcore/uia_event.c index 395b20e0537..cf1a38a0f02 100644 --- a/dlls/uiautomationcore/uia_event.c +++ b/dlls/uiautomationcore/uia_event.c @@ -488,6 +488,7 @@ struct uia_event_thread HWND hwnd; LONG ref;
+ UiaWineWinEventCallback *win_event_callback; struct list *event_queue; HWINEVENTHOOK hook; }; @@ -843,6 +844,19 @@ static void uia_event_thread_process_queue(struct list *event_queue) case QUEUE_EVENT_TYPE_WIN_EVENT: { struct uia_queue_win_event *win_event = (struct uia_queue_win_event *)event; + UiaWineWinEventCallback *win_event_callback; + + EnterCriticalSection(&event_thread_cs); + win_event_callback = event_thread.win_event_callback; + LeaveCriticalSection(&event_thread_cs); + + if (win_event_callback) + { + hr = win_event_callback(win_event->event_id, win_event->hwnd, win_event->obj_id, win_event->child_id, + win_event->thread_id, win_event->event_time); + if (FAILED(hr)) + WARN("win_event_callback failed with hr %#lx\n", hr); + }
hr = uia_event_for_each(win_event_to_uia_event_id(win_event->event_id), uia_win_event_for_each_callback, (void *)win_event, TRUE); @@ -998,6 +1012,22 @@ static BOOL uia_clientside_event_start_event_thread(struct uia_event *event) return event->u.clientside.event_thread_started; }
+void uia_event_thread_set_win_event_callback(UiaWineWinEventCallback *cback) +{ + if (cback && !uia_start_event_thread()) + { + WARN("Failed to start UIA event thread\n"); + return; + } + + EnterCriticalSection(&event_thread_cs); + event_thread.win_event_callback = cback; + LeaveCriticalSection(&event_thread_cs); + + if (!cback) + uia_stop_event_thread(); +} + /* * IWineUiaEvent interface. */ diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 8a750bf3ae1..4e6aec9cffa 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -158,6 +158,7 @@ struct uia_event };
typedef HRESULT UiaWineEventCallback(struct uia_event *, struct uia_event_args *, SAFEARRAY *, BSTR); +typedef HRESULT UiaWineWinEventCallback(DWORD, HWND, LONG, LONG, DWORD, DWORD);
static inline void variant_init_bool(VARIANT *v, BOOL val) { @@ -227,6 +228,7 @@ HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8) DECLSPEC_HIDDEN;
/* uia_event.c */ HRESULT uia_event_add_win_event_hwnd(struct uia_event *event, HWND hwnd) DECLSPEC_HIDDEN; +void uia_event_thread_set_win_event_callback(UiaWineWinEventCallback *cback) DECLSPEC_HIDDEN; HRESULT create_serverside_uia_event(struct uia_event **out_event, LONG process_id, LONG event_cookie) DECLSPEC_HIDDEN; HRESULT uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents *advise_events, struct uia_event *event) DECLSPEC_HIDDEN;