From bb733db683104e6836e05f623b628f8f0962051d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Apr 2013 16:58:14 -0400 Subject: [PATCH] wfreerdp: integrating benoit's latest code --- client/Windows/wf_event.c | 78 +++++++++++++++++++++++++++---- client/Windows/wf_gdi.c | 42 ++++++++++++++++- client/Windows/wf_interface.c | 87 +++++++++++++++++++++++++++-------- client/Windows/wf_interface.h | 9 ++++ client/common/cmdline.c | 5 ++ include/freerdp/settings.h | 10 +++- 6 files changed, 200 insertions(+), 31 deletions(-) diff --git a/client/Windows/wf_event.c b/client/Windows/wf_event.c index a81c9f1ae..c96897fb5 100644 --- a/client/Windows/wf_event.c +++ b/client/Windows/wf_event.c @@ -37,6 +37,9 @@ static HWND g_focus_hWnd; #define X_POS(lParam) (lParam & 0xFFFF) #define Y_POS(lParam) ((lParam >> 16) & 0xFFFF) +BOOL wf_scale_blt(wfInfo* wfi, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); +void wf_scale_mouse_event(wfInfo* wfi, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); + LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam) { wfInfo* wfi; @@ -167,6 +170,10 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam switch (Msg) { + case WM_ERASEBKGND: + /* Say we handled it - prevents flickering */ + return (LRESULT) 1; + case WM_PAINT: hdc = BeginPaint(hWnd, &ps); @@ -175,31 +182,29 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam w = ps.rcPaint.right - ps.rcPaint.left + 1; h = ps.rcPaint.bottom - ps.rcPaint.top + 1; - //fprintf(stderr, "WM_PAINT: x:%d y:%d w:%d h:%d\n", x, y, w, h); - - BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x - wfi->offset_x, y - wfi->offset_y, SRCCOPY); + wf_scale_blt(wfi, hdc, x, y, w, h, wfi->primary->hdc, x - wfi->offset_x, y - wfi->offset_y, SRCCOPY); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: - input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input,PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_LBUTTONUP: - input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_RBUTTONDOWN: - input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_RBUTTONUP: - input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_MOUSEMOVE: - input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_MOVE, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_MOUSEWHEEL: @@ -257,3 +262,60 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam return 0; } + +BOOL wf_scale_blt(wfInfo* wfi, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if (!ww) + ww = dw; + + if (!wh) + wh = dh; + + if (!wfi->instance->settings->SmartSizing || (ww == dw && wh == dh)) + { + return BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x1, y1, SRCCOPY); + } + else + { + SetStretchBltMode(hdc, HALFTONE); + SetBrushOrgEx(hdc, 0, 0, NULL); + + return StretchBlt(hdc, x * ww / dw, y * wh / dh, ww, wh, wfi->primary->hdc, x1, y1, dw, dh, SRCCOPY); + } + + return TRUE; +} + +void wf_scale_mouse_event(wfInfo* wfi, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if ((ww == dw) && (wh == dh)) + input->MouseEvent(input, flags, x, y); + else + input->MouseEvent(input, flags, x * dw / ww, y * dh / wh); +} diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 39c590f1c..3a15fe26a 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -166,14 +166,54 @@ HBRUSH wf_create_brush(wfInfo * wfi, rdpBrush* brush, UINT32 color, int bpp) return br; } +void wf_scale_rect(wfInfo* wfi, RECT* source) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if (!ww) + ww = dw; + + if (!wh) + wh = dh; + + if (wfi->instance->settings->SmartSizing && (ww != dw || wh != dh)) + { + source->bottom = MIN(dh, MAX(0, source->bottom * wh / dh + 2)); + source->top = MIN(dh, MAX(0, source->top * wh / dh - 2)); + source->left = MIN(dw, MAX(0, source->left * ww / dw - 2)); + source->right = MIN(dw, MAX(0, source->right * ww / dw + 2)); + } +} + void wf_invalidate_region(wfInfo* wfi, int x, int y, int width, int height) { + RECT rect; + wfi->update_rect.left = x + wfi->offset_x; wfi->update_rect.top = y + wfi->offset_y; wfi->update_rect.right = wfi->update_rect.left + width; wfi->update_rect.bottom = wfi->update_rect.top + height; + + wf_scale_rect(wfi, &(wfi->update_rect)); InvalidateRect(wfi->hwnd, &(wfi->update_rect), FALSE); - gdi_InvalidateRegion(wfi->hdc, x, y, width, height); + + rect.left = x; + rect.right = width; + rect.top = y; + rect.bottom = height; + wf_scale_rect(wfi, &rect); + gdi_InvalidateRegion(wfi->hdc, rect.left, rect.top, rect.right, rect.bottom); } void wf_update_offset(wfInfo* wfi) diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 055f93591..09c465e88 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -534,6 +534,8 @@ DWORD WINAPI wf_thread(LPVOID lpParam) int index; int rcount; int wcount; + int width; + int height; BOOL msg_ret; int quit_msg; void* rfds[32]; @@ -626,7 +628,30 @@ DWORD WINAPI wf_thread(LPVOID lpParam) { msg_ret = GetMessage(&msg, NULL, 0, 0); - if (msg_ret == 0 || msg_ret == -1) + if (instance->settings->EmbeddedWindow) + { + if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1)) + { + PostMessage(((wfContext*) instance->context)->wfi->hwnd, WM_SETFOCUS, 0, 0); + } + else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1)) + { + PostMessage(((wfContext*) instance->context)->wfi->hwnd, WM_KILLFOCUS, 0, 0); + } + } + + if (msg.message == WM_SIZE) + { + width = LOWORD(msg.lParam); + height = HIWORD(msg.lParam); + + ((wfContext*) instance->context)->wfi->client_width = width; + ((wfContext*) instance->context)->wfi->client_height = height; + + SetWindowPos(((wfContext*) instance->context)->wfi->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); + } + + if ((msg_ret == 0) || (msg_ret == -1)) { quit_msg = TRUE; break; @@ -721,11 +746,9 @@ int freerdp_client_global_uninit() wfInfo* freerdp_client_new(int argc, char** argv) { int index; + int status; wfInfo* wfi; freerdp* instance; - HINSTANCE hInstance; - - hInstance = GetModuleHandle(NULL); instance = freerdp_new(); instance->PreConnect = wf_pre_connect; @@ -745,16 +768,27 @@ wfInfo* freerdp_client_new(int argc, char** argv) wfi->client = instance->context->client; instance->context->argc = argc; - instance->context->argv = argv; - instance->context->argv = (char**) malloc(sizeof(char*) * argc); for (index = 0; index < argc; index++) - { instance->context->argv[index] = _strdup(argv[index]); - } - wfi->hWndParent = NULL; + status = freerdp_client_parse_command_line_arguments(instance->context->argc, instance->context->argv, instance->settings); + + return wfi; +} + +int freerdp_client_start(wfInfo* wfi) +{ + HWND hWndParent; + HINSTANCE hInstance; + freerdp* instance = wfi->instance; + + hInstance = GetModuleHandle(NULL); + hWndParent = (HWND) instance->settings->ParentWindowId; + instance->settings->EmbeddedWindow = (hWndParent) ? TRUE : FALSE; + + wfi->hWndParent = hWndParent; wfi->hInstance = hInstance; wfi->cursor = LoadCursor(NULL, IDC_ARROW); wfi->icon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); @@ -774,24 +808,14 @@ wfInfo* freerdp_client_new(int argc, char** argv) wfi->wndClass.hIconSm = wfi->icon; RegisterClassEx(&(wfi->wndClass)); - return wfi; -} - -int freerdp_client_start(wfInfo* wfi) -{ - int status; - freerdp* instance = wfi->instance; - wfi->keyboardThread = CreateThread(NULL, 0, wf_keyboard_thread, (void*) wfi, 0, NULL); if (!wfi->keyboardThread) return -1; - status = freerdp_client_parse_command_line_arguments(instance->context->argc, instance->context->argv, instance->settings); - freerdp_client_load_addins(instance->context->channels, instance->settings); - wfi->thread = CreateThread(NULL, 0, wf_thread, (void*) instance, 0, NULL); + wfi->thread = CreateThread(NULL, 0, wf_thread, (void*) instance, 0, &wfi->mainThreadId); if (!wfi->thread) return -1; @@ -801,6 +825,29 @@ int freerdp_client_start(wfInfo* wfi) int freerdp_client_stop(wfInfo* wfi) { + PostThreadMessage(wfi->mainThreadId, WM_QUIT, 0, 0); + return 0; +} + +int freerdp_client_focus_in(wfInfo* wfi) +{ + PostThreadMessage(wfi->mainThreadId, WM_SETFOCUS, 0, 1); + return 0; +} + +int freerdp_client_focus_out(wfInfo* wfi) +{ + PostThreadMessage(wfi->mainThreadId, WM_KILLFOCUS, 0, 1); + return 0; +} + +int wf_set_window_size(wfInfo* wfi, int width, int height) +{ + if ((width != wfi->client_width) || (height != wfi->client_height)) + { + PostThreadMessage(wfi->mainThreadId, WM_SIZE, SIZE_RESTORED, ((UINT) height << 16) | (UINT) width); + } + return 0; } diff --git a/client/Windows/wf_interface.h b/client/Windows/wf_interface.h index c9f8a3ef3..16891db82 100644 --- a/client/Windows/wf_interface.h +++ b/client/Windows/wf_interface.h @@ -81,6 +81,8 @@ struct wf_info int fullscreen; int percentscreen; char window_title[64]; + int client_width; + int client_height; HANDLE thread; HANDLE keyboardThread; @@ -105,8 +107,10 @@ struct wf_info HBRUSH brush; HBRUSH org_brush; RECT update_rect; + RECT scale_update_rect; wfBitmap* tile; + DWORD mainThreadId; RFX_CONTEXT* rfx_context; NSC_CONTEXT* nsc_context; @@ -125,6 +129,11 @@ FREERDP_API int freerdp_client_global_uninit(); FREERDP_API int freerdp_client_start(wfInfo* cfi); FREERDP_API int freerdp_client_stop(wfInfo* cfi); +FREERDP_API int freerdp_client_focus_in(wfInfo* cfi); +FREERDP_API int freerdp_client_focus_out(wfInfo* cfi); + +FREERDP_API int freerdp_client_set_window_size(wfInfo* cfi, int width, int height); + FREERDP_API cfInfo* freerdp_client_new(int argc, char** argv); FREERDP_API int freerdp_client_free(wfInfo* cfi); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index e2927eb2a..5150a9a01 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -52,6 +52,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Work area" }, { "t", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "title", "Window title" }, { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueTrue, -1, NULL, "Window decorations" }, + { "smart-sizing", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Scale remote desktop to window size" }, { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" }, { "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" }, { "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" }, @@ -1090,6 +1091,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin { settings->Decorations = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "smart-sizing") + { + settings->SmartSizing = arg->Value ? TRUE : FALSE; + } CommandLineSwitchCase(arg, "bpp") { settings->ColorDepth = atoi(arg->Value); diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 9a3375c47..0a078c280 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -602,7 +602,11 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_AsyncInput 1544 #define FreeRDP_AsyncUpdate 1545 #define FreeRDP_AsyncChannels 1546 -#define FreeRDP_ToggleFullscreen 1547 +#define FreeRDP_AsyncTransport 1547 +#define FreeRDP_ToggleFullscreen 1548 +#define FreeRDP_WmClass 1549 +#define FreeRDP_EmbeddedWindow 1550 +#define FreeRDP_SmartSizing 1551 #define FreeRDP_SoftwareGdi 1601 #define FreeRDP_LocalConnection 1602 #define FreeRDP_AuthenticationOnly 1603 @@ -961,7 +965,9 @@ struct rdp_settings ALIGN64 BOOL AsyncTransport; /* 1547 */ ALIGN64 BOOL ToggleFullscreen; /* 1548 */ ALIGN64 char* WmClass; /* 1549 */ - UINT64 padding1600[1600 - 1550]; /* 1550 */ + ALIGN64 BOOL EmbeddedWindow; /* 1550 */ + ALIGN64 BOOL SmartSizing; /* 1551 */ + UINT64 padding1600[1600 - 1552]; /* 1552 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */