static inline BOOL find_next_hook(DWORD event, HWND hwnd, LONG object_id, LONG child_id, struct hook_info *info) { BOOL ret; SERVER_START_REQ( get_hook_info ) { req->handle = wine_server_user_handle( info->handle ); req->get_next = 1; req->event = event; req->window = wine_server_user_handle( hwnd ); req->object_id = object_id; req->child_id = child_id; wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) ); ret = !wine_server_call( req ); if (ret) { info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info->handle = wine_server_ptr_handle( reply->handle ); info->proc = wine_server_get_ptr( reply->proc ); info->tid = reply->tid; } } SERVER_END_REQ; return ret; }
/*********************************************************************** * SetShellWindowEx (USER32.@) * hwndShell = Progman[Program Manager] * |-> SHELLDLL_DefView * hwndListView = | |-> SysListView32 * | | |-> tooltips_class32 * | | * | |-> SysHeader32 * | * |-> ProxyTarget */ BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView) { BOOL ret; if (GetShellWindow()) return FALSE; if (GetWindowLongW(hwndShell, GWL_EXSTYLE) & WS_EX_TOPMOST) return FALSE; if (hwndListView != hwndShell) if (GetWindowLongW(hwndListView, GWL_EXSTYLE) & WS_EX_TOPMOST) return FALSE; if (hwndListView && hwndListView!=hwndShell) SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); SERVER_START_REQ(set_global_windows) { req->flags = SET_GLOBAL_SHELL_WINDOWS; req->shell_window = wine_server_user_handle( hwndShell ); req->shell_listview = wine_server_user_handle( hwndListView ); ret = !wine_server_call_err(req); } SERVER_END_REQ; return ret; }
/***************************************************************** * set_focus_window * * Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages */ static HWND set_focus_window( HWND hwnd ) { HWND previous = 0; BOOL ret; SERVER_START_REQ( set_focus_window ) { req->handle = wine_server_user_handle( hwnd ); if ((ret = !wine_server_call_err( req ))) previous = wine_server_ptr_handle( reply->previous ); } SERVER_END_REQ; if (!ret) return 0; if (previous == hwnd) return previous; if (previous) { SendMessageW( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 ); if (hwnd != GetFocus()) return previous; /* changed by the message */ } if (IsWindow(hwnd)) { USER_Driver->pSetFocus(hwnd); SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 ); } return previous; }
/*********************************************************************** * CallNextHookEx (USER32.@) */ LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) { struct user_thread_info *thread_info = get_user_thread_info(); struct hook_info info; ZeroMemory( &info, sizeof(info) - sizeof(info.module) ); SERVER_START_REQ( get_hook_info ) { req->handle = wine_server_user_handle( thread_info->hook ); req->get_next = 1; req->event = EVENT_MIN; wine_server_set_reply( req, info.module, sizeof(info.module)-sizeof(WCHAR) ); if (!wine_server_call_err( req )) { info.module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info.handle = wine_server_ptr_handle( reply->handle ); info.id = reply->id; info.pid = reply->pid; info.tid = reply->tid; info.proc = wine_server_get_ptr( reply->proc ); info.next_unicode = reply->unicode; } } SERVER_END_REQ; info.prev_unicode = thread_info->hook_unicode; return call_hook( &info, code, wparam, lparam ); }
/******************************************************************* * set_foreground_window */ static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) { BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; HWND previous = 0; SERVER_START_REQ( set_foreground_window ) { req->handle = wine_server_user_handle( hwnd ); if ((ret = !wine_server_call_err( req ))) { previous = wine_server_ptr_handle( reply->previous ); send_msg_old = reply->send_msg_old; send_msg_new = reply->send_msg_new; } } SERVER_END_REQ; if (ret && previous != hwnd) { if (send_msg_old) /* old window belongs to other thread */ SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 ); else if (send_msg_new) /* old window belongs to us but new one to other thread */ ret = set_active_window( 0, NULL, mouse, TRUE ); if (send_msg_new) /* new window belongs to other thread */ SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 ); else /* new window belongs to us */ ret = set_active_window( hwnd, NULL, mouse, TRUE ); } return ret; }
/***************************************************************** * CARET_Callback */ static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime) { BOOL ret; RECT r; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_STATE; req->handle = wine_server_user_handle( hwnd ); req->x = 0; req->y = 0; req->hide = 0; req->state = -1; /* toggle current state */ if ((ret = !wine_server_call( req ))) { hwnd = wine_server_ptr_handle( reply->full_handle ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && !hidden) CARET_DisplayCaret( hwnd, &r ); }
/***************************************************************** * ShowCaret (USER32.@) */ BOOL WINAPI ShowCaret( HWND hwnd ) { BOOL ret; RECT r; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_HIDE|SET_CARET_STATE; req->handle = wine_server_user_handle( hwnd ); req->x = 0; req->y = 0; req->hide = -1; req->state = 1; if ((ret = !wine_server_call_err( req ))) { hwnd = wine_server_ptr_handle( reply->full_handle ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */ { CARET_DisplayCaret( hwnd, &r ); SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback ); } return ret; }
/***************************************************************** * HideCaret (USER32.@) */ BOOL WINAPI HideCaret( HWND hwnd ) { BOOL ret; RECT r; int old_state = 0; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_HIDE|SET_CARET_STATE; req->handle = wine_server_user_handle( hwnd ); req->x = 0; req->y = 0; req->hide = 1; req->state = 0; if ((ret = !wine_server_call_err( req ))) { hwnd = wine_server_ptr_handle( reply->full_handle ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; old_state = reply->old_state; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && !hidden) { if (old_state) CARET_DisplayCaret( hwnd, &r ); KillSystemTimer( hwnd, TIMERID ); } return ret; }
LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) { struct hook_info info; ZeroMemory( &info, sizeof(info) - sizeof(info.module) ); SERVER_START_REQ( get_hook_info ) { req->handle = wine_server_user_handle( hhook ); req->get_next = 0; req->event = EVENT_MIN; wine_server_set_reply( req, info.module, sizeof(info.module)-sizeof(WCHAR) ); if (!wine_server_call_err( req )) { info.module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info.handle = wine_server_ptr_handle( reply->handle ); info.id = reply->id; info.pid = reply->pid; info.tid = reply->tid; info.proc = wine_server_get_ptr( reply->proc ); info.next_unicode = reply->unicode; } } SERVER_END_REQ; info.prev_unicode = TRUE; /* assume Unicode for this function */ return call_hook( &info, code, wparam, lparam ); }
/*********************************************************************** * send_mouse_input * * Update the various window states on a mouse event. */ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y, DWORD mouse_data, unsigned long time) { INPUT input; HWND top_level_hwnd; top_level_hwnd = GetAncestor(hwnd, GA_ROOT); if ((flags & MOUSEEVENTF_MOVE) && (flags & MOUSEEVENTF_ABSOLUTE)) { RECT rect; /* update the wine server Z-order */ SetRect(&rect, x, y, x + 1, y + 1); MapWindowPoints(0, top_level_hwnd, (POINT *)&rect, 2); SERVER_START_REQ(update_window_zorder) { req->window = wine_server_user_handle(top_level_hwnd); req->rect.left = rect.left; req->rect.top = rect.top; req->rect.right = rect.right; req->rect.bottom = rect.bottom; wine_server_call(req); } SERVER_END_REQ; }
static inline BOOL find_first_hook(DWORD id, DWORD event, HWND hwnd, LONG object_id, LONG child_id, struct hook_info *info) { struct user_thread_info *thread_info = get_user_thread_info(); BOOL ret; if (!HOOK_IsHooked( id )) { TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks ); return FALSE; } SERVER_START_REQ( start_hook_chain ) { req->id = id; req->event = event; req->window = wine_server_user_handle( hwnd ); req->object_id = object_id; req->child_id = child_id; wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) ); ret = !wine_server_call( req ); if (ret) { info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info->handle = wine_server_ptr_handle( reply->handle ); info->proc = wine_server_get_ptr( reply->proc ); info->tid = reply->tid; thread_info->active_hooks = reply->active_hooks; } } SERVER_END_REQ; return ret && (info->tid || info->proc); }
/********************************************************************** * set_capture_window */ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) { HWND previous = 0; UINT flags = 0; BOOL ret; if (gui_flags & GUI_INMENUMODE) flags |= CAPTURE_MENU; if (gui_flags & GUI_INMOVESIZE) flags |= CAPTURE_MOVESIZE; SERVER_START_REQ( set_capture_window ) { req->handle = wine_server_user_handle( hwnd ); req->flags = flags; if ((ret = !wine_server_call_err( req ))) { previous = wine_server_ptr_handle( reply->previous ); hwnd = wine_server_ptr_handle( reply->full_handle ); } } SERVER_END_REQ; if (ret) { USER_Driver->pSetCapture( hwnd, gui_flags ); if (previous && previous != hwnd) SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd ); if (prev_ret) *prev_ret = previous; } return ret; }
/*********************************************************************** * send_mouse_input * * Update the various window states on a mouse event. */ static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y, unsigned int state, DWORD mouse_data, Time time ) { struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); POINT pt; INPUT input; if (!data) return; if (window == data->whole_window) { x += data->whole_rect.left - data->client_rect.left; y += data->whole_rect.top - data->client_rect.top; } if (window == root_window) { x += virtual_screen_rect.left; y += virtual_screen_rect.top; } pt.x = x; pt.y = y; if (GetWindowLongW( data->hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) pt.x = data->client_rect.right - data->client_rect.left - 1 - pt.x; MapWindowPoints( hwnd, 0, &pt, 1 ); if (InterlockedExchangePointer( (void **)&cursor_window, hwnd ) != hwnd || GetTickCount() - last_time_modified > 100) { cursor_window = hwnd; sync_window_cursor( data ); } last_time_modified = GetTickCount(); if (hwnd != GetDesktopWindow()) hwnd = GetAncestor( hwnd, GA_ROOT ); /* update the wine server Z-order */ if (window != x11drv_thread_data()->grab_window && /* ignore event if a button is pressed, since the mouse is then grabbed too */ !(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask|Button6Mask|Button7Mask))) { RECT rect; SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 ); MapWindowPoints( 0, hwnd, (POINT *)&rect, 2 ); SERVER_START_REQ( update_window_zorder ) { req->window = wine_server_user_handle( hwnd ); req->rect.left = rect.left; req->rect.top = rect.top; req->rect.right = rect.right; req->rect.bottom = rect.bottom; wine_server_call( req ); } SERVER_END_REQ; }
/*********************************************************************** * UnhookWinEvent [USER32.@] * * Remove an event hook for a set of events. * * PARAMS * hEventHook [I] Event hook to remove * * RETURNS * Success: TRUE. The event hook has been removed. * Failure: FALSE, if hEventHook is invalid. */ BOOL WINAPI UnhookWinEvent(HWINEVENTHOOK hEventHook) { BOOL ret; SERVER_START_REQ( remove_hook ) { req->handle = wine_server_user_handle( hEventHook ); req->id = WH_WINEVENT; ret = !wine_server_call_err( req ); if (ret) get_user_thread_info()->active_hooks = reply->active_hooks; } SERVER_END_REQ; return ret; }
/************************************************************************** * CLIPBOARD_OpenClipboard */ static BOOL CLIPBOARD_OpenClipboard(HWND hWnd) { BOOL bRet; SERVER_START_REQ( set_clipboard_info ) { req->flags = SET_CB_OPEN; req->clipboard = wine_server_user_handle( hWnd ); bRet = !wine_server_call( req ); } SERVER_END_REQ; return bRet; }
/*********************************************************************** * UnhookWindowsHookEx (USER32.@) */ BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook ) { BOOL ret; SERVER_START_REQ( remove_hook ) { req->handle = wine_server_user_handle( hhook ); req->id = 0; ret = !wine_server_call_err( req ); if (ret) get_user_thread_info()->active_hooks = reply->active_hooks; } SERVER_END_REQ; if (!ret && GetLastError() == ERROR_INVALID_HANDLE) SetLastError( ERROR_INVALID_HOOK_HANDLE ); return ret; }
/************************************************************************** * CLIPBOARD_SetClipboardOwner * * Set the global wineserver clipboard owner. The current process will * be the owner and <hWnd> will get the render notifications. */ static BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd) { BOOL bRet; TRACE(" hWnd(%p)\n", hWnd); SERVER_START_REQ( set_clipboard_info ) { req->flags = SET_CB_OWNER; req->owner = wine_server_user_handle( hWnd ); bRet = !wine_server_call_err( req ); } SERVER_END_REQ; return bRet; }
/************************************************************************** * SetClipboardViewer (USER32.@) */ HWND WINAPI SetClipboardViewer( HWND hWnd ) { HWND hwndPrev = 0; SERVER_START_REQ( set_clipboard_info ) { req->flags = SET_CB_VIEWER; req->viewer = wine_server_user_handle( hWnd ); if (!wine_server_call_err( req )) hwndPrev = wine_server_ptr_handle( reply->old_viewer ); } SERVER_END_REQ; TRACE("(%p): returning %p\n", hWnd, hwndPrev); return hwndPrev; }
/*********************************************************************** * DEFWND_SetTextA * * Set the window text. */ static void DEFWND_SetTextA( HWND hwnd, LPCSTR text ) { int count; WCHAR *textW; WND *wndPtr; if (!text) text = ""; count = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 ); if (!(wndPtr = WIN_GetPtr( hwnd ))) return; if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)))) { HeapFree(GetProcessHeap(), 0, wndPtr->text); wndPtr->text = textW; MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count ); SERVER_START_REQ( set_window_text ) { req->handle = wine_server_user_handle( hwnd ); wine_server_add_data( req, textW, (count-1) * sizeof(WCHAR) ); wine_server_call( req ); } SERVER_END_REQ; }
/***************************************************************** * CreateCaret (USER32.@) */ BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height ) { BOOL ret; RECT r; int old_state = 0; int hidden = 0; HBITMAP hBmp = 0; HWND prev = 0; TRACE("hwnd=%p\n", hwnd); if (!hwnd) return FALSE; if (bitmap && (bitmap != (HBITMAP)1)) { BITMAP bmp; if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE; width = bmp.bmWidth; height = bmp.bmHeight; bmp.bmBits = NULL; hBmp = CreateBitmapIndirect(&bmp); if (hBmp) { /* copy the bitmap */ LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight); GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf); SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf); HeapFree(GetProcessHeap(), 0, buf); } } else { HDC hdc; if (!width) width = GetSystemMetrics(SM_CXBORDER); if (!height) height = GetSystemMetrics(SM_CYBORDER); /* create the uniform bitmap on the fly */ hdc = GetDC(hwnd); if (hdc) { HDC hMemDC = CreateCompatibleDC(hdc); if (hMemDC) { if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height ))) { HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp); SetRect( &r, 0, 0, width, height ); FillRect(hMemDC, &r, ULongToHandle((bitmap ? COLOR_GRAYTEXT : COLOR_WINDOW) + 1)); SelectObject(hMemDC, hPrevBmp); } DeleteDC(hMemDC); } ReleaseDC(hwnd, hdc); } } if (!hBmp) return FALSE; SERVER_START_REQ( set_caret_window ) { req->handle = wine_server_user_handle( hwnd ); req->width = width; req->height = height; if ((ret = !wine_server_call_err( req ))) { prev = wine_server_ptr_handle( reply->previous ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; old_state = reply->old_state; hidden = reply->old_hide; } } SERVER_END_REQ; if (!ret) return FALSE; if (prev && !hidden) /* hide the previous one */ { /* FIXME: won't work if prev belongs to a different process */ KillSystemTimer( prev, TIMERID ); if (old_state) CARET_DisplayCaret( prev, &r ); } if (Caret.hBmp) DeleteObject( Caret.hBmp ); Caret.hBmp = hBmp; Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 ); return TRUE; }
/******************************************************************* * set_active_window */ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) { HWND previous = GetActiveWindow(); BOOL ret; DWORD old_thread, new_thread; CBTACTIVATESTRUCT cbt; if (previous == hwnd) { if (prev) *prev = hwnd; return TRUE; } /* call CBT hook chain */ cbt.fMouse = mouse; cbt.hWndActive = previous; if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE; if (IsWindow(previous)) { SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd ); SendMessageW( previous, WM_ACTIVATE, MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd ); } SERVER_START_REQ( set_active_window ) { req->handle = wine_server_user_handle( hwnd ); if ((ret = !wine_server_call_err( req ))) previous = wine_server_ptr_handle( reply->previous ); } SERVER_END_REQ; if (!ret) return FALSE; if (prev) *prev = previous; if (previous == hwnd) return TRUE; if (hwnd) { /* send palette messages */ if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 )) SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0, SMTO_ABORTIFHUNG, 2000, NULL ); if (!IsWindow(hwnd)) return FALSE; } old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0; new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0; if (old_thread != new_thread) { HWND *list, *phwnd; if ((list = WIN_ListChildren( GetDesktopWindow() ))) { if (old_thread) { for (phwnd = list; *phwnd; phwnd++) { if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread) SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread ); } } if (new_thread) { for (phwnd = list; *phwnd; phwnd++) { if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread) SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread ); } } HeapFree( GetProcessHeap(), 0, list ); } } if (IsWindow(hwnd)) { SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous ); SendMessageW( hwnd, WM_ACTIVATE, MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ), (LPARAM)previous ); if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow()) PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); if (hwnd == GetForegroundWindow() && !IsIconic( hwnd )) USER_Driver->pSetActiveWindow( hwnd ); } /* now change focus if necessary */ if (focus) { GUITHREADINFO info; info.cbSize = sizeof(info); GetGUIThreadInfo( GetCurrentThreadId(), &info ); /* Do not change focus if the window is no more active */ if (hwnd == info.hwndActive) { if (!info.hwndFocus || !hwnd || GetAncestor( info.hwndFocus, GA_ROOT ) != hwnd) set_focus_window( hwnd ); } } return TRUE; }