diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index 0c7e1608a..5e7adc73a 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -41,11 +41,13 @@ #include #include +#include #include #include #include #include "wf_gdi.h" +#include "wf_rail.h" #include "wf_channels.h" #include "wf_graphics.h" #include "wf_cliprdr.h" @@ -78,34 +80,50 @@ void wf_sw_end_paint(wfContext* wfc) { int i; rdpGdi* gdi; - INT32 x, y; - UINT32 w, h; int ninvalid; - RECT update_rect; + RECT updateRect; HGDI_RGN cinvalid; + REGION16 invalidRegion; + RECTANGLE_16 invalidRect; + const RECTANGLE_16* extents; + rdpContext* context = (rdpContext*) wfc; - gdi = ((rdpContext*) wfc)->gdi; - - if (gdi->primary->hdc->hwnd->ninvalid < 1) - return; + gdi = context->gdi; ninvalid = gdi->primary->hdc->hwnd->ninvalid; cinvalid = gdi->primary->hdc->hwnd->cinvalid; + if (ninvalid < 1) + return; + + region16_init(&invalidRegion); + for (i = 0; i < ninvalid; i++) { - x = cinvalid[i].x; - y = cinvalid[i].y; - w = cinvalid[i].w; - h = cinvalid[i].h; + invalidRect.left = cinvalid[i].x; + invalidRect.top = cinvalid[i].y; + invalidRect.right = cinvalid[i].x + cinvalid[i].w; + invalidRect.bottom = cinvalid[i].y + cinvalid[i].h; - update_rect.left = x; - update_rect.top = y; - update_rect.right = x + w; - update_rect.bottom = y + h; - - InvalidateRect(wfc->hwnd, &update_rect, FALSE); + region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect); } + + if (!region16_is_empty(&invalidRegion)) + { + extents = region16_extents(&invalidRegion); + + updateRect.left = extents->left; + updateRect.top = extents->top; + updateRect.right = extents->right; + updateRect.bottom = extents->bottom; + + InvalidateRect(wfc->hwnd, &updateRect, FALSE); + + if (wfc->rail) + wf_rail_invalidate_region(wfc, &invalidRegion); + } + + region16_uninit(&invalidRegion); } void wf_sw_desktop_resize(wfContext* wfc) @@ -1110,7 +1128,7 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context) wfc->instance = instance; wfc->settings = instance->settings; context->channels = freerdp_channels_new(); - + return 0; } diff --git a/client/Windows/wf_rail.c b/client/Windows/wf_rail.c index 0867de495..40a26ab0b 100644 --- a/client/Windows/wf_rail.c +++ b/client/Windows/wf_rail.c @@ -25,6 +25,9 @@ #include "wf_rail.h" +#define GET_X_LPARAM(lParam) ((UINT16) (lParam & 0xFFFF)) +#define GET_Y_LPARAM(lParam) ((UINT16) ((lParam >> 16) & 0xFFFF)) + /* RemoteApp Core Protocol Extension */ struct _WINDOW_STYLE @@ -283,8 +286,13 @@ LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara int x, y; int width; int height; + UINT32 xPos; + UINT32 yPos; PAINTSTRUCT ps; + UINT32 inputFlags; wfContext* wfc = NULL; + rdpInput* input = NULL; + rdpContext* context = NULL; wfRailWindow* railWindow; railWindow = (wfRailWindow*) GetWindowLongPtr(hWnd, GWLP_USERDATA); @@ -292,6 +300,12 @@ LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara if (railWindow) wfc = railWindow->wfc; + if (wfc) + context = (rdpContext*) wfc; + + if (context) + input = context->input; + switch (msg) { case WM_PAINT: @@ -313,6 +327,79 @@ LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara } break; + case WM_LBUTTONDOWN: + { + if (!railWindow || !input) + return 0; + + xPos = GET_X_LPARAM(lParam) + railWindow->x; + yPos = GET_Y_LPARAM(lParam) + railWindow->y; + inputFlags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1; + + if (input) + input->MouseEvent(input, inputFlags, xPos, yPos); + } + break; + + case WM_LBUTTONUP: + { + if (!railWindow || !input) + return 0; + + xPos = GET_X_LPARAM(lParam) + railWindow->x; + yPos = GET_Y_LPARAM(lParam) + railWindow->y; + inputFlags = PTR_FLAGS_BUTTON1; + + if (input) + input->MouseEvent(input, inputFlags, xPos, yPos); + } + break; + + case WM_RBUTTONDOWN: + { + if (!railWindow || !input) + return 0; + + xPos = GET_X_LPARAM(lParam) + railWindow->x; + yPos = GET_Y_LPARAM(lParam) + railWindow->y; + inputFlags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2; + + if (input) + input->MouseEvent(input, inputFlags, xPos, yPos); + } + break; + + case WM_RBUTTONUP: + { + if (!railWindow || !input) + return 0; + + xPos = GET_X_LPARAM(lParam) + railWindow->x; + yPos = GET_Y_LPARAM(lParam) + railWindow->y; + inputFlags = PTR_FLAGS_BUTTON2; + + if (input) + input->MouseEvent(input, inputFlags, xPos, yPos); + } + break; + + case WM_MOUSEMOVE: + { + if (!railWindow || !input) + return 0; + + xPos = GET_X_LPARAM(lParam) + railWindow->x; + yPos = GET_Y_LPARAM(lParam) + railWindow->y; + inputFlags = PTR_FLAGS_MOVE; + + if (input) + input->MouseEvent(input, inputFlags, xPos, yPos); + } + break; + + case WM_MOUSEWHEEL: + break; + case WM_CLOSE: DestroyWindow(hWnd); break; @@ -328,8 +415,9 @@ LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara return 0; } -#define RAIL_DISABLED_WINDOW_STYLES (WS_BORDER | WS_THICKFRAME | WS_DLGFRAME | WS_CAPTION | WS_OVERLAPPED) -#define RAIL_DISABLED_EXTENDED_WINDOW_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) +#define RAIL_DISABLED_WINDOW_STYLES (WS_BORDER | WS_THICKFRAME | WS_DLGFRAME | WS_CAPTION | \ + WS_OVERLAPPED | WS_VSCROLL | WS_HSCROLL | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) +#define RAIL_DISABLED_EXTENDED_WINDOW_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE) static void wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { @@ -863,6 +951,52 @@ static int wf_rail_server_get_appid_response(RailClientContext* context, RAIL_GE return 1; } +void wf_rail_invalidate_region(wfContext* wfc, REGION16* invalidRegion) +{ + int index; + int count; + RECT updateRect; + RECTANGLE_16 windowRect; + ULONG_PTR* pKeys = NULL; + wfRailWindow* railWindow; + const RECTANGLE_16* extents; + REGION16 windowInvalidRegion; + + region16_init(&windowInvalidRegion); + + count = HashTable_GetKeys(wfc->railWindows, &pKeys); + + for (index = 0; index < count; index++) + { + railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows, (void*) pKeys[index]); + + if (railWindow) + { + windowRect.left = railWindow->x; + windowRect.top = railWindow->y; + windowRect.right = railWindow->x + railWindow->width; + windowRect.bottom = railWindow->y + railWindow->height; + + region16_clear(&windowInvalidRegion); + region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect); + + if (!region16_is_empty(&windowInvalidRegion)) + { + extents = region16_extents(&windowInvalidRegion); + + updateRect.left = extents->left - railWindow->x; + updateRect.top = extents->top - railWindow->y; + updateRect.right = extents->right - railWindow->x; + updateRect.bottom = extents->bottom - railWindow->y; + + InvalidateRect(railWindow->hWnd, &updateRect, FALSE); + } + } + } + + region16_uninit(&windowInvalidRegion); +} + void wf_rail_init(wfContext* wfc, RailClientContext* rail) { rdpContext* context = (rdpContext*) wfc; diff --git a/client/Windows/wf_rail.h b/client/Windows/wf_rail.h index 39458313a..d9dd8c03f 100644 --- a/client/Windows/wf_rail.h +++ b/client/Windows/wf_rail.h @@ -44,4 +44,6 @@ struct wf_rail_window void wf_rail_init(wfContext* wfc, RailClientContext* rail); void wf_rail_uninit(wfContext* wfc, RailClientContext* rail); +void wf_rail_invalidate_region(wfContext* wfc, REGION16* invalidRegion); + #endif