Milestone 5: deliver embedded RDP sessions and lifecycle hardening
92
third_party/FreeRDP/client/Windows/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP Windows cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "wfreerdp-client")
|
||||
set(MODULE_PREFIX "FREERDP_CLIENT_WINDOWS_CONTROL")
|
||||
|
||||
include(WarnUnmaintained)
|
||||
warn_unmaintained(${MODULE_NAME} "-DWITH_CLIENT_WINDOWS=OFF")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
wf_gdi.c
|
||||
wf_gdi.h
|
||||
wf_event.c
|
||||
wf_event.h
|
||||
wf_channels.c
|
||||
wf_channels.h
|
||||
wf_graphics.c
|
||||
wf_graphics.h
|
||||
wf_cliprdr.c
|
||||
wf_cliprdr.h
|
||||
wf_rail.c
|
||||
wf_rail.h
|
||||
wf_client.c
|
||||
wf_client.h
|
||||
wf_floatbar.c
|
||||
wf_floatbar.h
|
||||
wf_defaults.h
|
||||
wf_defaults.c
|
||||
resource/wfreerdp.rc
|
||||
resource/resource.h
|
||||
)
|
||||
|
||||
option(WITH_WINDOWS_CERT_STORE
|
||||
"Build ${MODULE_NAME} with additional certificate validation against windows certificate store" ON
|
||||
)
|
||||
if(WITH_WINDOWS_CERT_STORE)
|
||||
add_compile_definitions("WITH_WINDOWS_CERT_STORE")
|
||||
endif()
|
||||
|
||||
option(WITH_WIN_CONSOLE "Build ${MODULE_NAME} with console support" OFF)
|
||||
if(WITH_WIN_CONSOLE)
|
||||
add_compile_definitions("WITH_WIN_CONSOLE")
|
||||
set(WIN32_GUI_FLAG "TRUE")
|
||||
else()
|
||||
set(WIN32_GUI_FLAG "WIN32")
|
||||
endif()
|
||||
|
||||
option(WITH_PROGRESS_BAR "Build ${MODULE_NAME} with connect progress bar (Windows 7+ or 2008 R2+)" ON)
|
||||
if(WITH_PROGRESS_BAR)
|
||||
add_compile_definitions("WITH_PROGRESS_BAR")
|
||||
endif()
|
||||
|
||||
if(CLIENT_INTERFACE_SHARED)
|
||||
addtargetwithresourcefile(${MODULE_NAME} "SHARED" "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
|
||||
else()
|
||||
addtargetwithresourcefile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
|
||||
endif()
|
||||
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
|
||||
|
||||
list(APPEND PUB_LIBS freerdp-client)
|
||||
list(APPEND PUB_LIBS winpr freerdp)
|
||||
|
||||
list(APPEND PRIV_LIBS msimg32.lib credui.lib)
|
||||
|
||||
if(MINGW)
|
||||
list(APPEND PRIV_LIBS ntdll.lib) # only required with MINGW
|
||||
endif()
|
||||
target_link_libraries(${MODULE_NAME} PUBLIC ${PUB_LIBS})
|
||||
target_link_libraries(${MODULE_NAME} PRIVATE ${PRIV_LIBS})
|
||||
|
||||
if(WITH_CLIENT_INTERFACE)
|
||||
install(TARGETS ${MODULE_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries
|
||||
)
|
||||
endif()
|
||||
add_subdirectory(cli)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Windows")
|
||||
3
third_party/FreeRDP/client/Windows/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
set(FREERDP_CLIENT_NAME "wfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "Windows")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
||||
32
third_party/FreeRDP/client/Windows/cli/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP Windows cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "wfreerdp")
|
||||
set(MODULE_PREFIX "FREERDP_CLIENT_WINDOWS")
|
||||
|
||||
include_directories(..)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS wfreerdp.c wfreerdp.h ../resource/wfreerdp.rc)
|
||||
|
||||
addtargetwithresourcefile(${MODULE_NAME} "${WIN32_GUI_FLAG}" "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} wfreerdp-client)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Windows")
|
||||
152
third_party/FreeRDP/client/Windows/cli/wfreerdp.c
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Client
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/constants.h>
|
||||
|
||||
#include <freerdp/client/file.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
|
||||
#include "../resource/resource.h"
|
||||
|
||||
#include <wf_client.h>
|
||||
#include <wf_defaults.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
int status;
|
||||
HANDLE thread;
|
||||
wfContext* wfc;
|
||||
DWORD dwExitCode;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
LPWSTR cmd;
|
||||
char** argv = nullptr;
|
||||
RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
|
||||
int ret = 1;
|
||||
int argc = 0;
|
||||
LPWSTR* args = nullptr;
|
||||
|
||||
WINPR_UNUSED(hInstance);
|
||||
WINPR_UNUSED(hPrevInstance);
|
||||
WINPR_UNUSED(lpCmdLine);
|
||||
WINPR_UNUSED(nCmdShow);
|
||||
|
||||
RdpClientEntry(&clientEntryPoints);
|
||||
context = freerdp_client_context_new(&clientEntryPoints);
|
||||
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
cmd = GetCommandLineW();
|
||||
|
||||
if (!cmd)
|
||||
goto out;
|
||||
|
||||
args = CommandLineToArgvW(cmd, &argc);
|
||||
|
||||
if (!args || (argc <= 0))
|
||||
goto out;
|
||||
|
||||
argv = calloc((size_t)argc, sizeof(char*));
|
||||
|
||||
if (!argv)
|
||||
goto out;
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
int size = WideCharToMultiByte(CP_UTF8, 0, args[i], -1, nullptr, 0, nullptr, nullptr);
|
||||
if (size <= 0)
|
||||
goto out;
|
||||
argv[i] = calloc((size_t)size, sizeof(char));
|
||||
|
||||
if (!argv[i])
|
||||
goto out;
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, args[i], -1, argv[i], size, nullptr, nullptr) != size)
|
||||
goto out;
|
||||
}
|
||||
|
||||
freerdp_client_warn_deprecated(argc, argv);
|
||||
|
||||
settings = context->settings;
|
||||
wfc = (wfContext*)context;
|
||||
|
||||
if (!settings || !wfc)
|
||||
goto out;
|
||||
|
||||
status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
|
||||
if (status)
|
||||
{
|
||||
ret = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
AddDefaultSettings(settings);
|
||||
|
||||
if (freerdp_client_start(context) != 0)
|
||||
goto out;
|
||||
|
||||
thread = freerdp_client_get_thread(context);
|
||||
|
||||
if (thread)
|
||||
{
|
||||
if (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
GetExitCodeThread(thread, &dwExitCode);
|
||||
ret = (int)dwExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
if (freerdp_client_stop(context) != 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
freerdp_client_context_free(context);
|
||||
|
||||
if (argv)
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
free(argv[i]);
|
||||
|
||||
free(argv);
|
||||
}
|
||||
|
||||
LocalFree(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WITH_WIN_CONSOLE
|
||||
int main()
|
||||
{
|
||||
return WinMain(nullptr, nullptr, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
27
third_party/FreeRDP/client/Windows/cli/wfreerdp.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Client
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_FREERDP_H
|
||||
#define FREERDP_CLIENT_WIN_FREERDP_H
|
||||
|
||||
#include "wf_interface.h"
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_FREERDP_H */
|
||||
BIN
third_party/FreeRDP/client/Windows/resource/FreeRDP.ico
vendored
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/close.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/close_active.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/lock.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/lock_active.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/minimize.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/minimize_active.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
12
third_party/FreeRDP/client/Windows/resource/resource.h
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
#define IDI_ICON1 101
|
||||
#define IDB_MINIMIZE 103
|
||||
#define IDB_MINIMIZE_ACT 104
|
||||
#define IDB_LOCK 105
|
||||
#define IDB_LOCK_ACT 106
|
||||
#define IDB_UNLOCK 107
|
||||
#define IDB_UNLOCK_ACT 108
|
||||
#define IDB_CLOSE 109
|
||||
#define IDB_CLOSE_ACT 100
|
||||
#define IDB_RESTORE 111
|
||||
#define IDB_RESTORE_ACT 112
|
||||
BIN
third_party/FreeRDP/client/Windows/resource/restore.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/restore_active.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/unlock.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
third_party/FreeRDP/client/Windows/resource/unlock_active.bmp
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
14
third_party/FreeRDP/client/Windows/resource/wfreerdp.rc
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
IDI_ICON1 ICON "FreeRDP.ico"
|
||||
IDB_MINIMIZE BITMAP "minimize.bmp"
|
||||
IDB_MINIMIZE_ACT BITMAP "minimize_active.bmp"
|
||||
IDB_LOCK BITMAP "lock.bmp"
|
||||
IDB_LOCK_ACT BITMAP "lock_active.bmp"
|
||||
IDB_UNLOCK BITMAP "unlock.bmp"
|
||||
IDB_UNLOCK_ACT BITMAP "unlock_active.bmp"
|
||||
IDB_CLOSE BITMAP "close.bmp"
|
||||
IDB_CLOSE_ACT BITMAP "close_active.bmp"
|
||||
IDB_RESTORE BITMAP "restore.bmp"
|
||||
IDB_RESTORE_ACT BITMAP "restore_active.bmp"
|
||||
86
third_party/FreeRDP/client/Windows/wf_channels.c
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include "wf_channels.h"
|
||||
|
||||
#include "wf_rail.h"
|
||||
#include "wf_cliprdr.h"
|
||||
|
||||
#include <freerdp/gdi/gfx.h>
|
||||
#include <freerdp/gdi/video.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG CLIENT_TAG("windows")
|
||||
|
||||
void wf_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(wfc);
|
||||
WINPR_ASSERT(e);
|
||||
|
||||
settings = wfc->common.context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wf_rail_init(wfc, (RailClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wf_cliprdr_init(wfc, (CliprdrClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wfc->disp = (DispClientContext*)e->pInterface;
|
||||
}
|
||||
else
|
||||
freerdp_client_OnChannelConnectedEventHandler(context, e);
|
||||
}
|
||||
|
||||
void wf_OnChannelDisconnectedEventHandler(void* context, const ChannelDisconnectedEventArgs* e)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(wfc);
|
||||
WINPR_ASSERT(e);
|
||||
|
||||
settings = wfc->common.context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wf_rail_uninit(wfc, (RailClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wf_cliprdr_uninit(wfc, (CliprdrClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wfc->disp = nullptr;
|
||||
}
|
||||
else
|
||||
freerdp_client_OnChannelDisconnectedEventHandler(context, e);
|
||||
}
|
||||
36
third_party/FreeRDP/client/Windows/wf_channels.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_CHANNELS_H
|
||||
#define FREERDP_CLIENT_WIN_CHANNELS_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/client.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/client/rdpei.h>
|
||||
#include <freerdp/client/rdpgfx.h>
|
||||
#include <freerdp/client/encomsp.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/client/disp.h>
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
void wf_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e);
|
||||
void wf_OnChannelDisconnectedEventHandler(void* context, const ChannelDisconnectedEventArgs* e);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_CHANNELS_H */
|
||||
1542
third_party/FreeRDP/client/Windows/wf_client.c
vendored
Normal file
158
third_party/FreeRDP/client/Windows/wf_client.h
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Client
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_INTERFACE_H
|
||||
#define FREERDP_CLIENT_WIN_INTERFACE_H
|
||||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#ifdef WITH_PROGRESS_BAR
|
||||
#include <shobjidl.h>
|
||||
#endif
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/gdi/dc.h>
|
||||
#include <freerdp/gdi/region.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <freerdp/client/rail.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/client/file.h>
|
||||
|
||||
#include "wf_channels.h"
|
||||
#include "wf_floatbar.h"
|
||||
#include "wf_event.h"
|
||||
#include "wf_cliprdr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// System menu constants
|
||||
#define SYSCOMMAND_ID_SMARTSIZING 1000
|
||||
#define SYSCOMMAND_ID_REQUEST_CONTROL 1001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpBitmap _bitmap;
|
||||
HDC hdc;
|
||||
HBITMAP bitmap;
|
||||
HBITMAP org_bitmap;
|
||||
BYTE* pdata;
|
||||
} wfBitmap;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpPointer pointer;
|
||||
HCURSOR cursor;
|
||||
} wfPointer;
|
||||
|
||||
struct wf_context
|
||||
{
|
||||
rdpClientContext common;
|
||||
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
int fullscreen_toggle;
|
||||
int fullscreen;
|
||||
int percentscreen;
|
||||
WCHAR* window_title;
|
||||
int client_x;
|
||||
int client_y;
|
||||
int client_width;
|
||||
int client_height;
|
||||
|
||||
HANDLE keyboardThread;
|
||||
|
||||
HICON icon;
|
||||
HWND hWndParent;
|
||||
HINSTANCE hInstance;
|
||||
WNDCLASSEX wndClass;
|
||||
LPCTSTR wndClassName;
|
||||
HCURSOR hDefaultCursor;
|
||||
|
||||
UINT systemMenuInsertPosition;
|
||||
|
||||
HWND hwnd;
|
||||
BOOL is_shown;
|
||||
ITaskbarList3* taskBarList;
|
||||
POINT diff;
|
||||
|
||||
wfBitmap* primary;
|
||||
wfBitmap* drawing;
|
||||
HCURSOR cursor;
|
||||
HBRUSH brush;
|
||||
HBRUSH org_brush;
|
||||
RECT update_rect;
|
||||
RECT scale_update_rect;
|
||||
|
||||
DWORD mainThreadId;
|
||||
DWORD keyboardThreadId;
|
||||
|
||||
rdpFile* connectionRdpFile;
|
||||
|
||||
BOOL disablewindowtracking;
|
||||
|
||||
BOOL updating_scrollbars;
|
||||
BOOL xScrollVisible;
|
||||
int xMinScroll;
|
||||
int xCurrentScroll;
|
||||
int xMaxScroll;
|
||||
|
||||
BOOL yScrollVisible;
|
||||
int yMinScroll;
|
||||
int yCurrentScroll;
|
||||
int yMaxScroll;
|
||||
|
||||
void* clipboard;
|
||||
CliprdrClientContext* cliprdr;
|
||||
|
||||
wfFloatBar* floatbar;
|
||||
|
||||
RailClientContext* rail;
|
||||
wHashTable* railWindows;
|
||||
BOOL isConsole;
|
||||
|
||||
DispClientContext* disp;
|
||||
UINT64 lastSentDate;
|
||||
BOOL wasMaximized;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client Interface
|
||||
*/
|
||||
|
||||
FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
|
||||
FREERDP_API int freerdp_client_set_window_size(wfContext* wfc, int width, int height);
|
||||
FREERDP_API void wf_size_scrollbars(wfContext* wfc, UINT32 client_width, UINT32 client_height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_INTERFACE_H */
|
||||
2567
third_party/FreeRDP/client/Windows/wf_cliprdr.c
vendored
Normal file
27
third_party/FreeRDP/client/Windows/wf_cliprdr.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Clipboard Redirection
|
||||
*
|
||||
* Copyright 2012 Jason Champion
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef FREERDP_CLIENT_WIN_CLIPRDR_H
|
||||
#define FREERDP_CLIENT_WIN_CLIPRDR_H
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
BOOL wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr);
|
||||
BOOL wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_CLIPRDR_H */
|
||||
164
third_party/FreeRDP/client/Windows/wf_defaults.c
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2022 Stefan Koell
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincred.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
#include "wf_defaults.h"
|
||||
|
||||
static PCWSTR ValidateString(const BYTE* pb, ULONG cb)
|
||||
{
|
||||
if (!pb || !cb)
|
||||
return 0;
|
||||
|
||||
if (cb % sizeof(WCHAR) != 0)
|
||||
return 0;
|
||||
|
||||
return (PCWSTR)pb;
|
||||
}
|
||||
|
||||
static void AddDefaultSettings_I(rdpSettings* settings, size_t idHostname, size_t idUsername,
|
||||
size_t idDomain, size_t idPassword)
|
||||
{
|
||||
static const PSTR TERMSRV = "TERMSRV/%s";
|
||||
|
||||
PSTR TargetName = nullptr;
|
||||
PSTR UserName = nullptr;
|
||||
PWSTR TargetNameW = nullptr;
|
||||
PWSTR ServerHostNameW = nullptr;
|
||||
PWSTR ParsedUserNameW = nullptr;
|
||||
PWSTR ParsedDomainW = nullptr;
|
||||
PWSTR PasswordNullTerminatedW = nullptr;
|
||||
PCREDENTIALW Credential = WINPR_C_ARRAY_INIT;
|
||||
|
||||
PCSTR ServerHostname = freerdp_settings_get_string(settings, idHostname);
|
||||
|
||||
if (!ServerHostname)
|
||||
return;
|
||||
|
||||
BOOL bExistUserName = freerdp_settings_get_string(settings, idUsername) != 0;
|
||||
BOOL bExistPassword = freerdp_settings_get_string(settings, idPassword) != 0;
|
||||
|
||||
if (bExistUserName && bExistPassword)
|
||||
return;
|
||||
|
||||
int len = _snprintf(TargetName, 0, TERMSRV, ServerHostname);
|
||||
if (len < 0)
|
||||
goto fail;
|
||||
|
||||
len++;
|
||||
TargetName = (PSTR)malloc(len);
|
||||
|
||||
if (!TargetName)
|
||||
goto fail;
|
||||
|
||||
_snprintf(TargetName, len, TERMSRV, ServerHostname);
|
||||
|
||||
TargetName[len - 1] = 0;
|
||||
|
||||
TargetNameW = ConvertUtf8ToWCharAlloc(TargetName, nullptr);
|
||||
if (!TargetNameW)
|
||||
goto fail;
|
||||
|
||||
if (!CredReadW(TargetNameW, CRED_TYPE_GENERIC, 0, &Credential))
|
||||
goto fail;
|
||||
|
||||
if (!bExistPassword)
|
||||
{
|
||||
const WCHAR* PasswordW =
|
||||
ValidateString(Credential->CredentialBlob, Credential->CredentialBlobSize);
|
||||
|
||||
PasswordNullTerminatedW = (PWSTR)calloc(Credential->CredentialBlobSize + 1, sizeof(WCHAR));
|
||||
|
||||
if (!PasswordNullTerminatedW)
|
||||
goto fail;
|
||||
|
||||
memcpy(PasswordNullTerminatedW, PasswordW, Credential->CredentialBlobSize * sizeof(WCHAR));
|
||||
|
||||
if (PasswordNullTerminatedW)
|
||||
{
|
||||
if (!freerdp_settings_set_string_from_utf16(settings, idPassword,
|
||||
PasswordNullTerminatedW))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bExistUserName)
|
||||
{
|
||||
const WCHAR* UserNameW = Credential->UserName;
|
||||
|
||||
if (UserNameW)
|
||||
{
|
||||
ParsedUserNameW = calloc(CREDUI_MAX_USERNAME_LENGTH + 1, sizeof(WCHAR));
|
||||
if (!ParsedUserNameW)
|
||||
goto fail;
|
||||
|
||||
ParsedDomainW = calloc(CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1, sizeof(WCHAR));
|
||||
if (!ParsedDomainW)
|
||||
goto fail;
|
||||
|
||||
DWORD ParseResult =
|
||||
CredUIParseUserNameW(UserNameW, ParsedUserNameW, CREDUI_MAX_USERNAME_LENGTH + 1,
|
||||
ParsedDomainW, CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1);
|
||||
|
||||
if (ParseResult == NO_ERROR)
|
||||
{
|
||||
if (!freerdp_settings_set_string_from_utf16(settings, idUsername, ParsedUserNameW))
|
||||
goto fail;
|
||||
|
||||
if (*ParsedDomainW != 0)
|
||||
{
|
||||
if (!freerdp_settings_set_string_from_utf16(settings, idDomain, ParsedDomainW))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (ParseResult == ERROR_INVALID_ACCOUNT_NAME)
|
||||
{
|
||||
if (!freerdp_settings_set_string_from_utf16(settings, idUsername, UserNameW))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
if (Credential)
|
||||
{
|
||||
CredFree(Credential);
|
||||
}
|
||||
free(TargetName);
|
||||
free(UserName);
|
||||
free(TargetNameW);
|
||||
free(ServerHostNameW);
|
||||
free(ParsedUserNameW);
|
||||
free(ParsedDomainW);
|
||||
free(PasswordNullTerminatedW);
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI AddDefaultSettings(rdpSettings* settings)
|
||||
{
|
||||
AddDefaultSettings_I(settings, FreeRDP_ServerHostname, FreeRDP_Username, FreeRDP_Domain,
|
||||
FreeRDP_Password);
|
||||
AddDefaultSettings_I(settings, FreeRDP_GatewayHostname, FreeRDP_GatewayUsername,
|
||||
FreeRDP_GatewayDomain, FreeRDP_GatewayPassword);
|
||||
}
|
||||
28
third_party/FreeRDP/client/Windows/wf_defaults.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2022 Stefan Koell
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_DEFAULTS_H
|
||||
#define FREERDP_CLIENT_WIN_DEFAULTS_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
FREERDP_API void WINAPI AddDefaultSettings(_Inout_ rdpSettings* settings);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_DEFAULTS_H */
|
||||
1004
third_party/FreeRDP/client/Windows/wf_event.c
vendored
Normal file
45
third_party/FreeRDP/client/Windows/wf_event.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Event Handling
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_EVENT_H
|
||||
#define FREERDP_CLIENT_WIN_EVENT_H
|
||||
|
||||
#include "wf_client.h"
|
||||
#include <freerdp/log.h>
|
||||
|
||||
LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void wf_event_focus_in(wfContext* wfc);
|
||||
|
||||
BOOL wf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags);
|
||||
|
||||
#define KBD_TAG CLIENT_TAG("windows")
|
||||
#ifdef WITH_DEBUG_KBD
|
||||
#define DEBUG_KBD(...) WLog_DBG(KBD_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_KBD(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_EVENT_H */
|
||||
733
third_party/FreeRDP/client/Windows/wf_floatbar.c
vendored
Normal file
@@ -0,0 +1,733 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Float Bar
|
||||
*
|
||||
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include "wf_client.h"
|
||||
#include "wf_floatbar.h"
|
||||
|
||||
#include "resource/resource.h"
|
||||
#include "wf_gdi.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Msimg32.lib")
|
||||
#endif
|
||||
|
||||
#define TAG CLIENT_TAG("windows.floatbar")
|
||||
|
||||
/* TIMERs */
|
||||
#define TIMER_HIDE 1
|
||||
#define TIMER_ANIMAT_SHOW 2
|
||||
#define TIMER_ANIMAT_HIDE 3
|
||||
|
||||
/* Button Type */
|
||||
#define BUTTON_LOCKPIN 0
|
||||
#define BUTTON_MINIMIZE 1
|
||||
#define BUTTON_RESTORE 2
|
||||
#define BUTTON_CLOSE 3
|
||||
#define BTN_MAX 4
|
||||
|
||||
/* bmp size */
|
||||
#define BACKGROUND_W 576
|
||||
#define BACKGROUND_H 27
|
||||
#define BUTTON_OFFSET 5
|
||||
#define BUTTON_Y 2
|
||||
#define BUTTON_WIDTH 23
|
||||
#define BUTTON_HEIGHT 21
|
||||
#define BUTTON_SPACING 1
|
||||
|
||||
#define LOCK_X (BACKGROUND_H + BUTTON_OFFSET)
|
||||
#define CLOSE_X ((BACKGROUND_W - (BACKGROUND_H + BUTTON_OFFSET)) - BUTTON_WIDTH)
|
||||
#define RESTORE_X (CLOSE_X - (BUTTON_WIDTH + BUTTON_SPACING))
|
||||
#define MINIMIZE_X (RESTORE_X - (BUTTON_WIDTH + BUTTON_SPACING))
|
||||
#define TEXT_X (BACKGROUND_H + ((BUTTON_WIDTH + BUTTON_SPACING) * 3) + 5)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wfFloatBar* floatbar;
|
||||
int type;
|
||||
int x, y, h, w;
|
||||
int active;
|
||||
HBITMAP bmp;
|
||||
HBITMAP bmp_act;
|
||||
|
||||
/* Lock Specified */
|
||||
HBITMAP locked_bmp;
|
||||
HBITMAP locked_bmp_act;
|
||||
HBITMAP unlocked_bmp;
|
||||
HBITMAP unlocked_bmp_act;
|
||||
} Button;
|
||||
|
||||
struct s_FloatBar
|
||||
{
|
||||
HINSTANCE root_window;
|
||||
DWORD flags;
|
||||
HWND parent;
|
||||
HWND hwnd;
|
||||
RECT rect;
|
||||
LONG width;
|
||||
LONG height;
|
||||
LONG offset;
|
||||
wfContext* wfc;
|
||||
Button* buttons[BTN_MAX];
|
||||
BOOL shown;
|
||||
BOOL locked;
|
||||
HDC hdcmem;
|
||||
RECT textRect;
|
||||
UINT_PTR animating;
|
||||
};
|
||||
|
||||
static BOOL floatbar_kill_timers(wfFloatBar* floatbar)
|
||||
{
|
||||
UINT_PTR timers[] = { TIMER_HIDE, TIMER_ANIMAT_HIDE, TIMER_ANIMAT_SHOW };
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(timers); x++)
|
||||
KillTimer(floatbar->hwnd, timers[x]);
|
||||
|
||||
floatbar->animating = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL floatbar_animation(wfFloatBar* const floatbar, const BOOL show)
|
||||
{
|
||||
UINT_PTR timer = show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE;
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
if (floatbar->shown == show)
|
||||
return TRUE;
|
||||
|
||||
if (floatbar->animating == timer)
|
||||
return TRUE;
|
||||
|
||||
floatbar->animating = timer;
|
||||
|
||||
if (SetTimer(floatbar->hwnd, timer, USER_TIMER_MINIMUM, nullptr) == 0)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL floatbar_trigger_hide(wfFloatBar* floatbar)
|
||||
{
|
||||
if (!floatbar_kill_timers(floatbar))
|
||||
return FALSE;
|
||||
|
||||
if (!floatbar->locked && floatbar->shown)
|
||||
{
|
||||
if (SetTimer(floatbar->hwnd, TIMER_HIDE, 3000, nullptr) == 0)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL floatbar_hide(wfFloatBar* floatbar)
|
||||
{
|
||||
if (!floatbar_kill_timers(floatbar))
|
||||
return FALSE;
|
||||
|
||||
floatbar->offset = floatbar->height - 2;
|
||||
|
||||
if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
|
||||
floatbar->height, TRUE))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
floatbar->shown = FALSE;
|
||||
|
||||
if (!floatbar_trigger_hide(floatbar))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL floatbar_show(wfFloatBar* floatbar)
|
||||
{
|
||||
if (!floatbar_kill_timers(floatbar))
|
||||
return FALSE;
|
||||
|
||||
floatbar->offset = 0;
|
||||
|
||||
if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
|
||||
floatbar->height, TRUE))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
floatbar->shown = TRUE;
|
||||
|
||||
if (!floatbar_trigger_hide(floatbar))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL button_set_locked(Button* button, BOOL locked)
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
button->bmp = button->locked_bmp;
|
||||
button->bmp_act = button->locked_bmp_act;
|
||||
}
|
||||
else
|
||||
{
|
||||
button->bmp = button->unlocked_bmp;
|
||||
button->bmp_act = button->unlocked_bmp_act;
|
||||
}
|
||||
|
||||
InvalidateRect(button->floatbar->hwnd, nullptr, FALSE);
|
||||
UpdateWindow(button->floatbar->hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL update_locked_state(wfFloatBar* floatbar)
|
||||
{
|
||||
Button* button;
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
button = floatbar->buttons[3];
|
||||
|
||||
if (!button_set_locked(button, floatbar->locked))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int button_hit(Button* const button)
|
||||
{
|
||||
wfFloatBar* const floatbar = button->floatbar;
|
||||
|
||||
switch (button->type)
|
||||
{
|
||||
case BUTTON_LOCKPIN:
|
||||
floatbar->locked = !floatbar->locked;
|
||||
update_locked_state(floatbar);
|
||||
break;
|
||||
|
||||
case BUTTON_MINIMIZE:
|
||||
ShowWindow(floatbar->parent, SW_MINIMIZE);
|
||||
break;
|
||||
|
||||
case BUTTON_RESTORE:
|
||||
wf_toggle_fullscreen(floatbar->wfc);
|
||||
break;
|
||||
|
||||
case BUTTON_CLOSE:
|
||||
SendMessage(floatbar->parent, WM_DESTROY, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int button_paint(const Button* const button, const HDC hdc)
|
||||
{
|
||||
if (button != nullptr)
|
||||
{
|
||||
wfFloatBar* floatbar = button->floatbar;
|
||||
BLENDFUNCTION bf;
|
||||
SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
|
||||
bf.BlendOp = AC_SRC_OVER;
|
||||
bf.BlendFlags = 0;
|
||||
bf.SourceConstantAlpha = 255;
|
||||
bf.AlphaFormat = AC_SRC_ALPHA;
|
||||
AlphaBlend(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0,
|
||||
button->w, button->h, bf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Button* floatbar_create_button(wfFloatBar* const floatbar, const int type, const int resid,
|
||||
const int resid_act, const int x, const int y, const int h,
|
||||
const int w)
|
||||
{
|
||||
Button* button = (Button*)calloc(1, sizeof(Button));
|
||||
|
||||
if (!button)
|
||||
return nullptr;
|
||||
|
||||
button->floatbar = floatbar;
|
||||
button->type = type;
|
||||
button->x = x;
|
||||
button->y = y;
|
||||
button->w = w;
|
||||
button->h = h;
|
||||
button->active = FALSE;
|
||||
button->bmp = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid), IMAGE_BITMAP, 0,
|
||||
0, LR_DEFAULTCOLOR);
|
||||
button->bmp_act = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid_act),
|
||||
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
||||
return button;
|
||||
}
|
||||
|
||||
static Button* floatbar_create_lock_button(wfFloatBar* const floatbar, const int unlock_resid,
|
||||
const int unlock_resid_act, const int lock_resid,
|
||||
const int lock_resid_act, const int x, const int y,
|
||||
const int h, const int w)
|
||||
{
|
||||
Button* button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid,
|
||||
unlock_resid_act, x, y, h, w);
|
||||
|
||||
if (!button)
|
||||
return nullptr;
|
||||
|
||||
button->unlocked_bmp = button->bmp;
|
||||
button->unlocked_bmp_act = button->bmp_act;
|
||||
button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid),
|
||||
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
||||
button->locked_bmp_act =
|
||||
(HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP,
|
||||
0, 0, LR_DEFAULTCOLOR);
|
||||
return button;
|
||||
}
|
||||
|
||||
static Button* floatbar_get_button(const wfFloatBar* const floatbar, const int x, const int y)
|
||||
{
|
||||
if ((y > BUTTON_Y) && (y < BUTTON_Y + BUTTON_HEIGHT))
|
||||
{
|
||||
for (int i = 0; i < BTN_MAX; i++)
|
||||
{
|
||||
if ((floatbar->buttons[i] != nullptr) && (x > floatbar->buttons[i]->x) &&
|
||||
(x < floatbar->buttons[i]->x + floatbar->buttons[i]->w))
|
||||
{
|
||||
return floatbar->buttons[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BOOL floatbar_paint(wfFloatBar* const floatbar, const HDC hdc)
|
||||
{
|
||||
HPEN hpen;
|
||||
HGDIOBJECT orig;
|
||||
/* paint background */
|
||||
GRADIENT_RECT gradientRect = { 0, 1 };
|
||||
COLORREF rgbTop = RGB(117, 154, 198);
|
||||
COLORREF rgbBottom = RGB(6, 55, 120);
|
||||
const int top = 0;
|
||||
int left = 0;
|
||||
int bottom = BACKGROUND_H - 1;
|
||||
int right = BACKGROUND_W - 1;
|
||||
const int angleOffset = BACKGROUND_H - 1;
|
||||
TRIVERTEX triVertext[2] = { { left, top, GetRValue(rgbTop) << 8, GetGValue(rgbTop) << 8,
|
||||
GetBValue(rgbTop) << 8, 0x0000 },
|
||||
{ right, bottom, GetRValue(rgbBottom) << 8,
|
||||
GetGValue(rgbBottom) << 8, GetBValue(rgbBottom) << 8, 0x0000 } };
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
GradientFill(hdc, triVertext, 2, &gradientRect, 1, GRADIENT_FILL_RECT_V);
|
||||
/* paint shadow */
|
||||
hpen = CreatePen(PS_SOLID, 1, RGB(71, 71, 71));
|
||||
orig = SelectObject(hdc, hpen);
|
||||
MoveToEx(hdc, left, top, nullptr);
|
||||
LineTo(hdc, left + angleOffset, bottom);
|
||||
LineTo(hdc, right - angleOffset, bottom);
|
||||
LineTo(hdc, right + 1, top - 1);
|
||||
DeleteObject(hpen);
|
||||
hpen = CreatePen(PS_SOLID, 1, RGB(107, 141, 184));
|
||||
SelectObject(hdc, hpen);
|
||||
left += 1;
|
||||
bottom -= 1;
|
||||
right -= 1;
|
||||
MoveToEx(hdc, left, top, nullptr);
|
||||
LineTo(hdc, left + (angleOffset - 1), bottom);
|
||||
LineTo(hdc, right - (angleOffset - 1), bottom);
|
||||
LineTo(hdc, right + 1, top - 1);
|
||||
DeleteObject(hpen);
|
||||
SelectObject(hdc, orig);
|
||||
|
||||
const size_t wlen = wcslen(floatbar->wfc->window_title);
|
||||
DrawText(hdc, floatbar->wfc->window_title, WINPR_ASSERTING_INT_CAST(int, wlen),
|
||||
&floatbar->textRect,
|
||||
DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
|
||||
|
||||
/* paint buttons */
|
||||
|
||||
for (int i = 0; i < BTN_MAX; i++)
|
||||
button_paint(floatbar->buttons[i], hdc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK floatbar_proc(const HWND hWnd, const UINT Msg, const WPARAM wParam,
|
||||
const LPARAM lParam)
|
||||
{
|
||||
static int dragging = FALSE;
|
||||
static int lbtn_dwn = FALSE;
|
||||
static int btn_dwn_x = 0;
|
||||
static wfFloatBar* floatbar;
|
||||
static TRACKMOUSEEVENT tme;
|
||||
PAINTSTRUCT ps;
|
||||
Button* button;
|
||||
HDC hdc;
|
||||
int pos_x;
|
||||
int pos_y;
|
||||
NONCLIENTMETRICS ncm;
|
||||
int xScreen = GetSystemMetrics(SM_CXSCREEN);
|
||||
|
||||
switch (Msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
floatbar = ((wfFloatBar*)((CREATESTRUCT*)lParam)->lpCreateParams);
|
||||
floatbar->hwnd = hWnd;
|
||||
GetWindowRect(floatbar->hwnd, &floatbar->rect);
|
||||
floatbar->width = floatbar->rect.right - floatbar->rect.left;
|
||||
floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
|
||||
hdc = GetDC(hWnd);
|
||||
floatbar->hdcmem = CreateCompatibleDC(hdc);
|
||||
ReleaseDC(hWnd, hdc);
|
||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
tme.hwndTrack = hWnd;
|
||||
tme.dwHoverTime = HOVER_DEFAULT;
|
||||
// Use caption font, white, draw transparent
|
||||
GetClientRect(hWnd, &floatbar->textRect);
|
||||
InflateRect(&floatbar->textRect, -TEXT_X, 0);
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
|
||||
SelectObject(hdc, CreateFontIndirect(&ncm.lfCaptionFont));
|
||||
floatbar_trigger_hide(floatbar);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
floatbar_paint(floatbar, hdc);
|
||||
EndPaint(hWnd, &ps);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
pos_x = lParam & 0xffff;
|
||||
pos_y = (lParam >> 16) & 0xffff;
|
||||
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||
|
||||
if (!button)
|
||||
{
|
||||
SetCapture(hWnd);
|
||||
dragging = TRUE;
|
||||
btn_dwn_x = lParam & 0xffff;
|
||||
}
|
||||
else
|
||||
lbtn_dwn = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
pos_x = lParam & 0xffff;
|
||||
pos_y = (lParam >> 16) & 0xffff;
|
||||
ReleaseCapture();
|
||||
dragging = FALSE;
|
||||
|
||||
if (lbtn_dwn)
|
||||
{
|
||||
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||
|
||||
if (button)
|
||||
button_hit(button);
|
||||
|
||||
lbtn_dwn = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
pos_x = lParam & 0xffff;
|
||||
pos_y = (lParam >> 16) & 0xffff;
|
||||
|
||||
if (!floatbar->locked)
|
||||
floatbar_animation(floatbar, TRUE);
|
||||
|
||||
if (dragging)
|
||||
{
|
||||
floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
|
||||
|
||||
if (floatbar->rect.left < 0)
|
||||
floatbar->rect.left = 0;
|
||||
else if (floatbar->rect.left > xScreen - floatbar->width)
|
||||
floatbar->rect.left = xScreen - floatbar->width;
|
||||
|
||||
MoveWindow(hWnd, floatbar->rect.left, 0, floatbar->width, floatbar->height, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < BTN_MAX; i++)
|
||||
{
|
||||
if (floatbar->buttons[i] != nullptr)
|
||||
{
|
||||
floatbar->buttons[i]->active = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||
|
||||
if (button)
|
||||
button->active = TRUE;
|
||||
|
||||
InvalidateRect(hWnd, nullptr, FALSE);
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
|
||||
TrackMouseEvent(&tme);
|
||||
break;
|
||||
|
||||
case WM_CAPTURECHANGED:
|
||||
dragging = FALSE;
|
||||
break;
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
for (int i = 0; i < BTN_MAX; i++)
|
||||
{
|
||||
if (floatbar->buttons[i] != nullptr)
|
||||
{
|
||||
floatbar->buttons[i]->active = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
InvalidateRect(hWnd, nullptr, FALSE);
|
||||
UpdateWindow(hWnd);
|
||||
floatbar_trigger_hide(floatbar);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_TIMER:
|
||||
switch (wParam)
|
||||
{
|
||||
case TIMER_HIDE:
|
||||
floatbar_animation(floatbar, FALSE);
|
||||
break;
|
||||
|
||||
case TIMER_ANIMAT_SHOW:
|
||||
{
|
||||
floatbar->offset--;
|
||||
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
|
||||
floatbar->width, floatbar->height, TRUE);
|
||||
|
||||
if (floatbar->offset <= 0)
|
||||
floatbar_show(floatbar);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TIMER_ANIMAT_HIDE:
|
||||
{
|
||||
floatbar->offset++;
|
||||
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
|
||||
floatbar->width, floatbar->height, TRUE);
|
||||
|
||||
if (floatbar->offset >= floatbar->height - 2)
|
||||
floatbar_hide(floatbar);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
DeleteDC(floatbar->hdcmem);
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL floatbar_window_create(wfFloatBar* floatbar)
|
||||
{
|
||||
WNDCLASSEX wnd_cls;
|
||||
HWND barWnd;
|
||||
HRGN hRgn;
|
||||
POINT pt[4];
|
||||
RECT rect;
|
||||
LONG x;
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
if (!GetWindowRect(floatbar->parent, &rect))
|
||||
return FALSE;
|
||||
|
||||
x = (rect.right - rect.left - BACKGROUND_W) / 2;
|
||||
wnd_cls.cbSize = sizeof(WNDCLASSEX);
|
||||
wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wnd_cls.lpfnWndProc = floatbar_proc;
|
||||
wnd_cls.cbClsExtra = 0;
|
||||
wnd_cls.cbWndExtra = 0;
|
||||
wnd_cls.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
|
||||
wnd_cls.hCursor = LoadCursor(floatbar->root_window, IDC_ARROW);
|
||||
wnd_cls.hbrBackground = nullptr;
|
||||
wnd_cls.lpszMenuName = nullptr;
|
||||
wnd_cls.lpszClassName = L"floatbar";
|
||||
wnd_cls.hInstance = floatbar->root_window;
|
||||
wnd_cls.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
|
||||
RegisterClassEx(&wnd_cls);
|
||||
barWnd =
|
||||
CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W,
|
||||
BACKGROUND_H, floatbar->parent, nullptr, floatbar->root_window, floatbar);
|
||||
|
||||
if (barWnd == nullptr)
|
||||
return FALSE;
|
||||
|
||||
pt[0].x = 0;
|
||||
pt[0].y = 0;
|
||||
pt[1].x = BACKGROUND_W;
|
||||
pt[1].y = 0;
|
||||
pt[2].x = BACKGROUND_W - BACKGROUND_H;
|
||||
pt[2].y = BACKGROUND_H;
|
||||
pt[3].x = BACKGROUND_H;
|
||||
pt[3].y = BACKGROUND_H;
|
||||
hRgn = CreatePolygonRgn(pt, 4, ALTERNATE);
|
||||
SetWindowRgn(barWnd, hRgn, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_floatbar_free(wfFloatBar* floatbar)
|
||||
{
|
||||
if (!floatbar)
|
||||
return;
|
||||
|
||||
free(floatbar);
|
||||
}
|
||||
|
||||
wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags)
|
||||
{
|
||||
wfFloatBar* floatbar;
|
||||
|
||||
/* Floatbar not enabled */
|
||||
if ((flags & 0x0001) == 0)
|
||||
return nullptr;
|
||||
|
||||
if (!wfc)
|
||||
return nullptr;
|
||||
|
||||
// TODO: Disable for remote app
|
||||
floatbar = (wfFloatBar*)calloc(1, sizeof(wfFloatBar));
|
||||
|
||||
if (!floatbar)
|
||||
return nullptr;
|
||||
|
||||
floatbar->root_window = window;
|
||||
floatbar->flags = flags;
|
||||
floatbar->wfc = wfc;
|
||||
floatbar->locked = (flags & 0x0002) != 0;
|
||||
floatbar->shown = (flags & 0x0006) != 0; /* If it is loked or shown show it */
|
||||
floatbar->hwnd = nullptr;
|
||||
floatbar->parent = wfc->hwnd;
|
||||
floatbar->hdcmem = nullptr;
|
||||
|
||||
if (wfc->fullscreen_toggle)
|
||||
{
|
||||
floatbar->buttons[0] =
|
||||
floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT,
|
||||
MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||
floatbar->buttons[1] =
|
||||
floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT,
|
||||
RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
floatbar->buttons[0] = nullptr;
|
||||
floatbar->buttons[1] = nullptr;
|
||||
}
|
||||
|
||||
floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT,
|
||||
CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||
floatbar->buttons[3] =
|
||||
floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT,
|
||||
LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||
|
||||
if (!floatbar_window_create(floatbar))
|
||||
goto fail;
|
||||
|
||||
if (!update_locked_state(floatbar))
|
||||
goto fail;
|
||||
|
||||
if (!wf_floatbar_toggle_fullscreen(
|
||||
floatbar, freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_Fullscreen)))
|
||||
goto fail;
|
||||
|
||||
return floatbar;
|
||||
fail:
|
||||
wf_floatbar_free(floatbar);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen)
|
||||
{
|
||||
BOOL show_fs, show_wn;
|
||||
|
||||
if (!floatbar)
|
||||
return FALSE;
|
||||
|
||||
show_fs = (floatbar->flags & 0x0010) != 0;
|
||||
show_wn = (floatbar->flags & 0x0020) != 0;
|
||||
|
||||
if ((show_fs && fullscreen) || (show_wn && !fullscreen))
|
||||
{
|
||||
ShowWindow(floatbar->hwnd, SW_SHOWNORMAL);
|
||||
Sleep(10);
|
||||
|
||||
if (floatbar->shown)
|
||||
floatbar_show(floatbar);
|
||||
else
|
||||
floatbar_hide(floatbar);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowWindow(floatbar->hwnd, SW_HIDE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
33
third_party/FreeRDP/client/Windows/wf_floatbar.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Float Bar
|
||||
*
|
||||
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_FLOATBAR_H
|
||||
#define FREERDP_CLIENT_WIN_FLOATBAR_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
typedef struct s_FloatBar wfFloatBar;
|
||||
typedef struct wf_context wfContext;
|
||||
|
||||
wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags);
|
||||
void wf_floatbar_free(wfFloatBar* floatbar);
|
||||
|
||||
BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_FLOATBAR_H */
|
||||
864
third_party/FreeRDP/client/Windows/wf_gdi.c
vendored
Normal file
@@ -0,0 +1,864 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows GDI
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
|
||||
#include "wf_client.h"
|
||||
#include "wf_graphics.h"
|
||||
#include "wf_gdi.h"
|
||||
|
||||
#define TAG CLIENT_TAG("windows.gdi")
|
||||
|
||||
static const BYTE wf_rop2_table[] = {
|
||||
R2_BLACK, /* 0 */
|
||||
R2_NOTMERGEPEN, /* DPon */
|
||||
R2_MASKNOTPEN, /* DPna */
|
||||
R2_NOTCOPYPEN, /* Pn */
|
||||
R2_MASKPENNOT, /* PDna */
|
||||
R2_NOT, /* Dn */
|
||||
R2_XORPEN, /* DPx */
|
||||
R2_NOTMASKPEN, /* DPan */
|
||||
R2_MASKPEN, /* DPa */
|
||||
R2_NOTXORPEN, /* DPxn */
|
||||
R2_NOP, /* D */
|
||||
R2_MERGENOTPEN, /* DPno */
|
||||
R2_COPYPEN, /* P */
|
||||
R2_MERGEPENNOT, /* PDno */
|
||||
R2_MERGEPEN, /* PDo */
|
||||
R2_WHITE, /* 1 */
|
||||
};
|
||||
|
||||
static BOOL wf_decode_color(wfContext* wfc, const UINT32 srcColor, COLORREF* color, UINT32* format)
|
||||
{
|
||||
rdpGdi* gdi;
|
||||
rdpSettings* settings;
|
||||
UINT32 SrcFormat, DstFormat;
|
||||
|
||||
if (!wfc)
|
||||
return FALSE;
|
||||
|
||||
gdi = wfc->common.context.gdi;
|
||||
settings = wfc->common.context.settings;
|
||||
|
||||
if (!gdi || !settings)
|
||||
return FALSE;
|
||||
|
||||
SrcFormat = gdi_get_pixel_format(freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth));
|
||||
|
||||
if (format)
|
||||
*format = SrcFormat;
|
||||
|
||||
switch (FreeRDPGetBitsPerPixel(gdi->dstFormat))
|
||||
{
|
||||
case 32:
|
||||
DstFormat = PIXEL_FORMAT_ABGR32;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
DstFormat = PIXEL_FORMAT_BGR24;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
DstFormat = PIXEL_FORMAT_RGB16;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*color = FreeRDPConvertColor(srcColor, SrcFormat, DstFormat, &gdi->palette);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_set_rop2(HDC hdc, int rop2)
|
||||
{
|
||||
if ((rop2 < 0x01) || (rop2 > 0x10))
|
||||
{
|
||||
WLog_ERR(TAG, "Unsupported ROP2: %d", rop2);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetROP2(hdc, wf_rop2_table[rop2 - 1]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static wfBitmap* wf_glyph_new(wfContext* wfc, GLYPH_DATA* glyph)
|
||||
{
|
||||
wfBitmap* glyph_bmp;
|
||||
glyph_bmp = wf_image_new(wfc, glyph->cx, glyph->cy, PIXEL_FORMAT_MONO, glyph->aj);
|
||||
if (!glyph_bmp)
|
||||
WLog_ERR(TAG, "wf_image_new failed for glyph");
|
||||
return glyph_bmp;
|
||||
}
|
||||
|
||||
static void wf_glyph_free(wfBitmap* glyph)
|
||||
{
|
||||
wf_image_free(glyph);
|
||||
}
|
||||
|
||||
static BYTE* wf_glyph_convert(wfContext* wfc, int width, int height, const BYTE* data)
|
||||
{
|
||||
const int src_bytes_per_row = (width + 7) / 8;
|
||||
const int dst_bytes_per_row = src_bytes_per_row + (src_bytes_per_row % 2);
|
||||
BYTE* cdata = (BYTE*)malloc(dst_bytes_per_row * height);
|
||||
if (!cdata)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed for cdata buffer");
|
||||
return nullptr;
|
||||
}
|
||||
const BYTE* src = data;
|
||||
|
||||
for (int indexy = 0; indexy < height; indexy++)
|
||||
{
|
||||
BYTE* dst = &cdata[1ull * indexy * dst_bytes_per_row];
|
||||
|
||||
for (int indexx = 0; indexx < dst_bytes_per_row; indexx++)
|
||||
{
|
||||
if (indexx < src_bytes_per_row)
|
||||
*dst++ = *src++;
|
||||
else
|
||||
*dst++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return cdata;
|
||||
}
|
||||
|
||||
static HBRUSH wf_create_brush(wfContext* wfc, rdpBrush* brush, UINT32 color, UINT32 bpp)
|
||||
{
|
||||
HBRUSH br;
|
||||
LOGBRUSH lbr;
|
||||
BYTE* cdata;
|
||||
BYTE ipattern[8];
|
||||
HBITMAP pattern = nullptr;
|
||||
lbr.lbStyle = brush->style;
|
||||
|
||||
if (lbr.lbStyle == BS_DIBPATTERN || lbr.lbStyle == BS_DIBPATTERN8X8 ||
|
||||
lbr.lbStyle == BS_DIBPATTERNPT)
|
||||
lbr.lbColor = DIB_RGB_COLORS;
|
||||
else
|
||||
lbr.lbColor = color;
|
||||
|
||||
if (lbr.lbStyle == BS_PATTERN || lbr.lbStyle == BS_PATTERN8X8)
|
||||
{
|
||||
if (brush->bpp > 1)
|
||||
{
|
||||
UINT32 format = gdi_get_pixel_format(bpp);
|
||||
pattern = wf_create_dib(wfc, 8, 8, format, brush->data, nullptr);
|
||||
lbr.lbHatch = (ULONG_PTR)pattern;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UINT32 i = 0; i != 8; i++)
|
||||
ipattern[7 - i] = brush->data[i];
|
||||
|
||||
cdata = wf_glyph_convert(wfc, 8, 8, ipattern);
|
||||
pattern = CreateBitmap(8, 8, 1, 1, cdata);
|
||||
lbr.lbHatch = (ULONG_PTR)pattern;
|
||||
free(cdata);
|
||||
}
|
||||
}
|
||||
else if (lbr.lbStyle == BS_HATCHED)
|
||||
{
|
||||
lbr.lbHatch = brush->hatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
lbr.lbHatch = 0;
|
||||
}
|
||||
|
||||
br = CreateBrushIndirect(&lbr);
|
||||
SetBrushOrgEx(wfc->drawing->hdc, brush->x, brush->y, nullptr);
|
||||
|
||||
if (pattern != nullptr)
|
||||
DeleteObject(pattern);
|
||||
|
||||
return br;
|
||||
}
|
||||
|
||||
BOOL wf_scale_rect(wfContext* wfc, RECT* source)
|
||||
{
|
||||
UINT32 ww, wh, dw, dh;
|
||||
rdpSettings* settings;
|
||||
|
||||
if (!wfc || !source || !wfc->common.context.settings)
|
||||
return FALSE;
|
||||
|
||||
settings = wfc->common.context.settings;
|
||||
|
||||
if (!settings)
|
||||
return FALSE;
|
||||
|
||||
dw = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
||||
dh = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
||||
|
||||
if (!wfc->client_width)
|
||||
wfc->client_width = dw;
|
||||
|
||||
if (!wfc->client_height)
|
||||
wfc->client_height = dh;
|
||||
|
||||
ww = wfc->client_width;
|
||||
wh = wfc->client_height;
|
||||
|
||||
if (!ww)
|
||||
ww = dw;
|
||||
|
||||
if (!wh)
|
||||
wh = dh;
|
||||
|
||||
if (freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_SmartSizing) &&
|
||||
(ww != dw || wh != dh))
|
||||
{
|
||||
source->bottom = source->bottom * wh / dh + 20;
|
||||
source->top = source->top * wh / dh - 20;
|
||||
source->left = source->left * ww / dw - 20;
|
||||
source->right = source->right * ww / dw + 20;
|
||||
}
|
||||
|
||||
source->bottom -= wfc->yCurrentScroll;
|
||||
source->top -= wfc->yCurrentScroll;
|
||||
source->left -= wfc->xCurrentScroll;
|
||||
source->right -= wfc->xCurrentScroll;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_invalidate_region(wfContext* wfc, UINT32 x, UINT32 y, UINT32 width, UINT32 height)
|
||||
{
|
||||
RECT rect;
|
||||
rdpGdi* gdi = wfc->common.context.gdi;
|
||||
wfc->update_rect.left = x + wfc->offset_x;
|
||||
wfc->update_rect.top = y + wfc->offset_y;
|
||||
wfc->update_rect.right = wfc->update_rect.left + width;
|
||||
wfc->update_rect.bottom = wfc->update_rect.top + height;
|
||||
wf_scale_rect(wfc, &(wfc->update_rect));
|
||||
InvalidateRect(wfc->hwnd, &(wfc->update_rect), FALSE);
|
||||
rect.left = x;
|
||||
rect.right = width;
|
||||
rect.top = y;
|
||||
rect.bottom = height;
|
||||
wf_scale_rect(wfc, &rect);
|
||||
gdi_InvalidateRegion(gdi->primary->hdc, rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void wf_update_offset(wfContext* wfc)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
settings = wfc->common.context.settings;
|
||||
|
||||
if (wfc->fullscreen)
|
||||
{
|
||||
if (freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_UseMultimon))
|
||||
{
|
||||
int x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
int y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
int w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
int h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
wfc->offset_x = (w - freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)) / 2;
|
||||
|
||||
if (wfc->offset_x < x)
|
||||
wfc->offset_x = x;
|
||||
|
||||
wfc->offset_y = (h - freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)) / 2;
|
||||
|
||||
if (wfc->offset_y < y)
|
||||
wfc->offset_y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
wfc->offset_x = (GetSystemMetrics(SM_CXSCREEN) -
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)) /
|
||||
2;
|
||||
|
||||
if (wfc->offset_x < 0)
|
||||
wfc->offset_x = 0;
|
||||
|
||||
wfc->offset_y = (GetSystemMetrics(SM_CYSCREEN) -
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)) /
|
||||
2;
|
||||
|
||||
if (wfc->offset_y < 0)
|
||||
wfc->offset_y = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wfc->offset_x = 0;
|
||||
wfc->offset_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wf_resize_window(wfContext* wfc)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
settings = wfc->common.context.settings;
|
||||
|
||||
if (wfc->fullscreen)
|
||||
{
|
||||
if (freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_UseMultimon))
|
||||
{
|
||||
int x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
int y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
int w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
int h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
SetWindowLongPtr(wfc->hwnd, GWL_STYLE, WS_POPUP);
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowLongPtr(wfc->hwnd, GWL_STYLE, WS_POPUP);
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN),
|
||||
GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
|
||||
}
|
||||
}
|
||||
else if (!freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_Decorations))
|
||||
{
|
||||
SetWindowLongPtr(wfc->hwnd, GWL_STYLE, WS_CHILD);
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_EmbeddedWindow))
|
||||
{
|
||||
if (!wfc->client_height)
|
||||
wfc->client_height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
||||
|
||||
if (!wfc->client_width)
|
||||
wfc->client_width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
||||
|
||||
wf_update_canvas_diff(wfc);
|
||||
/* Now resize to get full canvas size and room for caption and borders */
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, wfc->client_x, wfc->client_y,
|
||||
wfc->client_width + wfc->diff.x, wfc->client_height + wfc->diff.y,
|
||||
0 /*SWP_FRAMECHANGED*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now resize to get full canvas size and room for caption and borders */
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0,
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight),
|
||||
SWP_FRAMECHANGED);
|
||||
wf_update_canvas_diff(wfc);
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, -1, -1,
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) + wfc->diff.x,
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) + wfc->diff.y,
|
||||
SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowLongPtr(wfc->hwnd, GWL_STYLE,
|
||||
WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX |
|
||||
WS_MAXIMIZEBOX);
|
||||
|
||||
if (!wfc->client_height)
|
||||
wfc->client_height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
||||
|
||||
if (!wfc->client_width)
|
||||
wfc->client_width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
||||
|
||||
if (!wfc->client_x)
|
||||
wfc->client_x = 10;
|
||||
|
||||
if (!wfc->client_y)
|
||||
wfc->client_y = 10;
|
||||
|
||||
wf_update_canvas_diff(wfc);
|
||||
/* Now resize to get full canvas size and room for caption and borders */
|
||||
int width, height;
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing) &&
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingWidth) &&
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingHeight))
|
||||
{
|
||||
width = freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingWidth);
|
||||
height = freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = wfc->client_width + wfc->diff.x;
|
||||
height = wfc->client_height + wfc->diff.y;
|
||||
}
|
||||
|
||||
int xpos, ypos;
|
||||
if ((freerdp_settings_get_uint32(settings, FreeRDP_DesktopPosX) != UINT32_MAX) &&
|
||||
(freerdp_settings_get_uint32(settings, FreeRDP_DesktopPosY) != UINT32_MAX))
|
||||
{
|
||||
xpos = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPosX);
|
||||
ypos = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPosY);
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = wfc->client_x;
|
||||
ypos = wfc->client_y;
|
||||
}
|
||||
SetWindowPos(wfc->hwnd, HWND_TOP, xpos, ypos, width, height, 0 /*SWP_FRAMECHANGED*/);
|
||||
// wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height);
|
||||
}
|
||||
|
||||
wf_update_offset(wfc);
|
||||
}
|
||||
|
||||
void wf_toggle_fullscreen(wfContext* wfc)
|
||||
{
|
||||
ShowWindow(wfc->hwnd, SW_HIDE);
|
||||
wfc->fullscreen = !wfc->fullscreen;
|
||||
|
||||
if (wfc->fullscreen)
|
||||
{
|
||||
wfc->disablewindowtracking = TRUE;
|
||||
}
|
||||
|
||||
wf_floatbar_toggle_fullscreen(wfc->floatbar, wfc->fullscreen);
|
||||
SetParent(wfc->hwnd, wfc->fullscreen ? nullptr : wfc->hWndParent);
|
||||
wf_resize_window(wfc);
|
||||
ShowWindow(wfc->hwnd, SW_SHOW);
|
||||
SetForegroundWindow(wfc->hwnd);
|
||||
|
||||
if (!wfc->fullscreen)
|
||||
{
|
||||
// Re-enable window tracking AFTER resizing it back, otherwise it can lean to repositioning
|
||||
// errors.
|
||||
wfc->disablewindowtracking = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_palette_update(rdpContext* context, const PALETTE_UPDATE* palette)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_set_null_clip_rgn(wfContext* wfc)
|
||||
{
|
||||
SelectClipRgn(wfc->drawing->hdc, nullptr);
|
||||
}
|
||||
|
||||
void wf_set_clip_rgn(wfContext* wfc, int x, int y, int width, int height)
|
||||
{
|
||||
HRGN clip;
|
||||
clip = CreateRectRgn(x, y, x + width, y + height);
|
||||
SelectClipRgn(wfc->drawing->hdc, clip);
|
||||
DeleteObject(clip);
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds)
|
||||
{
|
||||
HRGN hrgn;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !bounds)
|
||||
return FALSE;
|
||||
|
||||
if (bounds != nullptr)
|
||||
{
|
||||
hrgn = CreateRectRgn(bounds->left, bounds->top, bounds->right + 1, bounds->bottom + 1);
|
||||
SelectClipRgn(wfc->drawing->hdc, hrgn);
|
||||
DeleteObject(hrgn);
|
||||
}
|
||||
else
|
||||
SelectClipRgn(wfc->drawing->hdc, nullptr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !dstblt)
|
||||
return FALSE;
|
||||
|
||||
if (!BitBlt(wfc->drawing->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth,
|
||||
dstblt->nHeight, nullptr, 0, 0, gdi_rop3_code(dstblt->bRop)))
|
||||
return FALSE;
|
||||
|
||||
wf_invalidate_region(wfc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
||||
{
|
||||
HBRUSH brush;
|
||||
HBRUSH org_brush;
|
||||
int org_bkmode;
|
||||
COLORREF fgcolor;
|
||||
COLORREF bgcolor;
|
||||
COLORREF org_bkcolor;
|
||||
COLORREF org_textcolor;
|
||||
BOOL rc;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !patblt)
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, patblt->foreColor, &fgcolor, nullptr))
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, patblt->backColor, &bgcolor, nullptr))
|
||||
return FALSE;
|
||||
|
||||
brush = wf_create_brush(wfc, &patblt->brush, fgcolor,
|
||||
freerdp_settings_get_uint32(context->settings, FreeRDP_ColorDepth));
|
||||
org_bkmode = SetBkMode(wfc->drawing->hdc, OPAQUE);
|
||||
org_bkcolor = SetBkColor(wfc->drawing->hdc, bgcolor);
|
||||
org_textcolor = SetTextColor(wfc->drawing->hdc, fgcolor);
|
||||
org_brush = (HBRUSH)SelectObject(wfc->drawing->hdc, brush);
|
||||
rc = PatBlt(wfc->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth,
|
||||
patblt->nHeight, gdi_rop3_code(patblt->bRop));
|
||||
SelectObject(wfc->drawing->hdc, org_brush);
|
||||
DeleteObject(brush);
|
||||
SetBkMode(wfc->drawing->hdc, org_bkmode);
|
||||
SetBkColor(wfc->drawing->hdc, org_bkcolor);
|
||||
SetTextColor(wfc->drawing->hdc, org_textcolor);
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth,
|
||||
patblt->nHeight);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !scrblt || !wfc->drawing)
|
||||
return FALSE;
|
||||
|
||||
if (!BitBlt(wfc->drawing->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth,
|
||||
scrblt->nHeight, wfc->primary->hdc, scrblt->nXSrc, scrblt->nYSrc,
|
||||
gdi_rop3_code(scrblt->bRop)))
|
||||
return FALSE;
|
||||
|
||||
wf_invalidate_region(wfc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect)
|
||||
{
|
||||
RECT rect;
|
||||
HBRUSH brush;
|
||||
COLORREF brush_color;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !opaque_rect)
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, opaque_rect->color, &brush_color, nullptr))
|
||||
return FALSE;
|
||||
|
||||
rect.left = opaque_rect->nLeftRect;
|
||||
rect.top = opaque_rect->nTopRect;
|
||||
rect.right = opaque_rect->nLeftRect + opaque_rect->nWidth;
|
||||
rect.bottom = opaque_rect->nTopRect + opaque_rect->nHeight;
|
||||
brush = CreateSolidBrush(brush_color);
|
||||
FillRect(wfc->drawing->hdc, &rect, brush);
|
||||
DeleteObject(brush);
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, rect.left, rect.top, rect.right - rect.left + 1,
|
||||
rect.bottom - rect.top + 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_multi_opaque_rect(rdpContext* context,
|
||||
const MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
|
||||
{
|
||||
RECT rect;
|
||||
HBRUSH brush;
|
||||
COLORREF brush_color;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !multi_opaque_rect)
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, multi_opaque_rect->color, &brush_color, nullptr))
|
||||
return FALSE;
|
||||
|
||||
for (UINT32 i = 0; i < multi_opaque_rect->numRectangles; i++)
|
||||
{
|
||||
const DELTA_RECT* rectangle = &multi_opaque_rect->rectangles[i];
|
||||
rect.left = rectangle->left;
|
||||
rect.top = rectangle->top;
|
||||
rect.right = rectangle->left + rectangle->width;
|
||||
rect.bottom = rectangle->top + rectangle->height;
|
||||
brush = CreateSolidBrush(brush_color);
|
||||
FillRect(wfc->drawing->hdc, &rect, brush);
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, rect.left, rect.top, rect.right - rect.left + 1,
|
||||
rect.bottom - rect.top + 1);
|
||||
|
||||
DeleteObject(brush);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_line_to(rdpContext* context, const LINE_TO_ORDER* line_to)
|
||||
{
|
||||
HPEN pen;
|
||||
HPEN org_pen;
|
||||
int x, y, w, h;
|
||||
COLORREF pen_color;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !line_to)
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, line_to->penColor, &pen_color, nullptr))
|
||||
return FALSE;
|
||||
|
||||
pen = CreatePen(line_to->penStyle, line_to->penWidth, pen_color);
|
||||
wf_set_rop2(wfc->drawing->hdc, line_to->bRop2);
|
||||
org_pen = (HPEN)SelectObject(wfc->drawing->hdc, pen);
|
||||
MoveToEx(wfc->drawing->hdc, line_to->nXStart, line_to->nYStart, nullptr);
|
||||
LineTo(wfc->drawing->hdc, line_to->nXEnd, line_to->nYEnd);
|
||||
x = (line_to->nXStart < line_to->nXEnd) ? line_to->nXStart : line_to->nXEnd;
|
||||
y = (line_to->nYStart < line_to->nYEnd) ? line_to->nYStart : line_to->nYEnd;
|
||||
w = (line_to->nXStart < line_to->nXEnd) ? (line_to->nXEnd - line_to->nXStart)
|
||||
: (line_to->nXStart - line_to->nXEnd);
|
||||
h = (line_to->nYStart < line_to->nYEnd) ? (line_to->nYEnd - line_to->nYStart)
|
||||
: (line_to->nYStart - line_to->nYEnd);
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, x, y, w, h);
|
||||
|
||||
SelectObject(wfc->drawing->hdc, org_pen);
|
||||
DeleteObject(pen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_polyline(rdpContext* context, const POLYLINE_ORDER* polyline)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int org_rop2;
|
||||
HPEN hpen;
|
||||
HPEN org_hpen;
|
||||
COLORREF pen_color;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !polyline)
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, polyline->penColor, &pen_color, nullptr))
|
||||
return FALSE;
|
||||
|
||||
hpen = CreatePen(0, 1, pen_color);
|
||||
org_rop2 = wf_set_rop2(wfc->drawing->hdc, polyline->bRop2);
|
||||
org_hpen = (HPEN)SelectObject(wfc->drawing->hdc, hpen);
|
||||
|
||||
if (polyline->numDeltaEntries > 0)
|
||||
{
|
||||
POINT* pts;
|
||||
POINT temp;
|
||||
int numPoints;
|
||||
numPoints = polyline->numDeltaEntries + 1;
|
||||
pts = (POINT*)malloc(sizeof(POINT) * numPoints);
|
||||
if (!pts)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed for polyline points");
|
||||
goto fail;
|
||||
}
|
||||
pts[0].x = temp.x = polyline->xStart;
|
||||
pts[0].y = temp.y = polyline->yStart;
|
||||
|
||||
for (UINT32 i = 0; i < polyline->numDeltaEntries; i++)
|
||||
{
|
||||
temp.x += polyline->points[i].x;
|
||||
temp.y += polyline->points[i].y;
|
||||
pts[i + 1].x = temp.x;
|
||||
pts[i + 1].y = temp.y;
|
||||
}
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, wfc->client_x, wfc->client_y, wfc->client_width,
|
||||
wfc->client_height);
|
||||
|
||||
Polyline(wfc->drawing->hdc, pts, numPoints);
|
||||
free(pts);
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
fail:
|
||||
SelectObject(wfc->drawing->hdc, org_hpen);
|
||||
wf_set_rop2(wfc->drawing->hdc, org_rop2);
|
||||
DeleteObject(hpen);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
||||
{
|
||||
wfBitmap* bitmap;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !memblt)
|
||||
return FALSE;
|
||||
|
||||
bitmap = (wfBitmap*)memblt->bitmap;
|
||||
|
||||
if (!bitmap || !wfc->drawing || !wfc->drawing->hdc)
|
||||
return FALSE;
|
||||
|
||||
if (!BitBlt(wfc->drawing->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth,
|
||||
memblt->nHeight, bitmap->hdc, memblt->nXSrc, memblt->nYSrc,
|
||||
gdi_rop3_code(memblt->bRop)))
|
||||
return FALSE;
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth,
|
||||
memblt->nHeight);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
HDC hdc;
|
||||
wfBitmap* bitmap;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
COLORREF fgcolor, bgcolor, orgColor;
|
||||
HBRUSH orgBrush = nullptr, brush = nullptr;
|
||||
|
||||
if (!context || !mem3blt)
|
||||
return FALSE;
|
||||
|
||||
bitmap = (wfBitmap*)mem3blt->bitmap;
|
||||
|
||||
if (!bitmap || !wfc->drawing || !wfc->drawing->hdc)
|
||||
return FALSE;
|
||||
|
||||
hdc = wfc->drawing->hdc;
|
||||
|
||||
if (!wf_decode_color(wfc, mem3blt->foreColor, &fgcolor, nullptr))
|
||||
return FALSE;
|
||||
|
||||
if (!wf_decode_color(wfc, mem3blt->backColor, &bgcolor, nullptr))
|
||||
return FALSE;
|
||||
|
||||
orgColor = SetTextColor(hdc, fgcolor);
|
||||
|
||||
switch (mem3blt->brush.style)
|
||||
{
|
||||
case GDI_BS_SOLID:
|
||||
brush = CreateSolidBrush(fgcolor);
|
||||
break;
|
||||
|
||||
case GDI_BS_HATCHED:
|
||||
case GDI_BS_PATTERN:
|
||||
{
|
||||
HBITMAP bmp = CreateBitmap(8, 8, 1, mem3blt->brush.bpp, mem3blt->brush.data);
|
||||
brush = CreatePatternBrush(bmp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
orgBrush = SelectObject(hdc, brush);
|
||||
|
||||
if (!BitBlt(hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight,
|
||||
bitmap->hdc, mem3blt->nXSrc, mem3blt->nYSrc, gdi_rop3_code(mem3blt->bRop)))
|
||||
goto fail;
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
wf_invalidate_region(wfc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth,
|
||||
mem3blt->nHeight);
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
|
||||
if (brush)
|
||||
SelectObject(hdc, orgBrush);
|
||||
|
||||
SetTextColor(hdc, orgColor);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL wf_gdi_surface_frame_marker(rdpContext* context,
|
||||
const SURFACE_FRAME_MARKER* surface_frame_marker)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
|
||||
if (!context || !surface_frame_marker || !context->instance)
|
||||
return FALSE;
|
||||
|
||||
settings = context->settings;
|
||||
|
||||
if (!settings)
|
||||
return FALSE;
|
||||
|
||||
if (surface_frame_marker->frameAction == SURFACECMD_FRAMEACTION_END &&
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_FrameAcknowledge) > 0)
|
||||
{
|
||||
IFCALL(context->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_gdi_register_update_callbacks(rdpUpdate* update)
|
||||
{
|
||||
rdpPrimaryUpdate* primary = update->primary;
|
||||
update->Palette = wf_gdi_palette_update;
|
||||
update->SetBounds = wf_gdi_set_bounds;
|
||||
primary->DstBlt = wf_gdi_dstblt;
|
||||
primary->PatBlt = wf_gdi_patblt;
|
||||
primary->ScrBlt = wf_gdi_scrblt;
|
||||
primary->OpaqueRect = wf_gdi_opaque_rect;
|
||||
primary->MultiOpaqueRect = wf_gdi_multi_opaque_rect;
|
||||
primary->LineTo = wf_gdi_line_to;
|
||||
primary->Polyline = wf_gdi_polyline;
|
||||
primary->MemBlt = wf_gdi_memblt;
|
||||
primary->Mem3Blt = wf_gdi_mem3blt;
|
||||
update->SurfaceFrameMarker = wf_gdi_surface_frame_marker;
|
||||
}
|
||||
|
||||
void wf_update_canvas_diff(wfContext* wfc)
|
||||
{
|
||||
RECT rc_client, rc_wnd;
|
||||
int dx, dy;
|
||||
GetClientRect(wfc->hwnd, &rc_client);
|
||||
GetWindowRect(wfc->hwnd, &rc_wnd);
|
||||
dx = (rc_wnd.right - rc_wnd.left) - rc_client.right;
|
||||
dy = (rc_wnd.bottom - rc_wnd.top) - rc_client.bottom;
|
||||
|
||||
if (!wfc->disablewindowtracking)
|
||||
{
|
||||
wfc->diff.x = dx;
|
||||
wfc->diff.y = dy;
|
||||
}
|
||||
}
|
||||
37
third_party/FreeRDP/client/Windows/wf_gdi.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows GDI
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_GDI_H
|
||||
#define FREERDP_CLIENT_WIN_GDI_H
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
void wf_invalidate_region(wfContext* wfc, UINT32 x, UINT32 y, UINT32 width, UINT32 height);
|
||||
void wf_update_offset(wfContext* wfc);
|
||||
void wf_resize_window(wfContext* wfc);
|
||||
void wf_toggle_fullscreen(wfContext* wfc);
|
||||
BOOL wf_scale_rect(wfContext* wfc, RECT* source);
|
||||
|
||||
void wf_gdi_register_update_callbacks(rdpUpdate* update);
|
||||
|
||||
void wf_update_canvas_diff(wfContext* wfc);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_GDI_H */
|
||||
379
third_party/FreeRDP/client/Windows/wf_graphics.c
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Graphical Objects
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/codecs.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "wf_gdi.h"
|
||||
#include "wf_graphics.h"
|
||||
|
||||
#define TAG CLIENT_TAG("windows")
|
||||
|
||||
HBITMAP wf_create_dib(wfContext* wfc, UINT32 width, UINT32 height, UINT32 srcFormat,
|
||||
const BYTE* data, BYTE** pdata)
|
||||
{
|
||||
HDC hdc;
|
||||
int negHeight;
|
||||
HBITMAP bitmap;
|
||||
BITMAPINFO bmi;
|
||||
BYTE* cdata = nullptr;
|
||||
UINT32 dstFormat = srcFormat;
|
||||
/**
|
||||
* See: http://msdn.microsoft.com/en-us/library/dd183376
|
||||
* if biHeight is positive, the bitmap is bottom-up
|
||||
* if biHeight is negative, the bitmap is top-down
|
||||
* Since we get top-down bitmaps, let's keep it that way
|
||||
*/
|
||||
negHeight = (height < 0) ? height : height * (-1);
|
||||
hdc = GetDC(nullptr);
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
|
||||
bmi.bmiHeader.biWidth = width;
|
||||
bmi.bmiHeader.biHeight = negHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = FreeRDPGetBitsPerPixel(dstFormat);
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&cdata, nullptr, 0);
|
||||
|
||||
if (data)
|
||||
freerdp_image_copy(cdata, dstFormat, 0, 0, 0, width, height, data, srcFormat, 0, 0, 0,
|
||||
&wfc->common.context.gdi->palette, FREERDP_FLIP_NONE);
|
||||
|
||||
if (pdata)
|
||||
*pdata = cdata;
|
||||
|
||||
ReleaseDC(nullptr, hdc);
|
||||
GdiFlush();
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
wfBitmap* wf_image_new(wfContext* wfc, UINT32 width, UINT32 height, UINT32 format, const BYTE* data)
|
||||
{
|
||||
wfBitmap* image = (wfBitmap*)malloc(sizeof(wfBitmap));
|
||||
if (!image)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed for wfBitmap");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HDC hdc = GetDC(nullptr);
|
||||
image->hdc = CreateCompatibleDC(hdc);
|
||||
image->bitmap = wf_create_dib(wfc, width, height, format, data, &(image->pdata));
|
||||
image->org_bitmap = (HBITMAP)SelectObject(image->hdc, image->bitmap);
|
||||
ReleaseDC(nullptr, hdc);
|
||||
return image;
|
||||
}
|
||||
|
||||
void wf_image_free(wfBitmap* image)
|
||||
{
|
||||
if (image != 0)
|
||||
{
|
||||
SelectObject(image->hdc, image->org_bitmap);
|
||||
DeleteObject(image->bitmap);
|
||||
DeleteDC(image->hdc);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bitmap Class */
|
||||
|
||||
static BOOL wf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
HDC hdc;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
|
||||
|
||||
if (!context || !bitmap)
|
||||
return FALSE;
|
||||
|
||||
wf_bitmap = (wfBitmap*)bitmap;
|
||||
hdc = GetDC(nullptr);
|
||||
wf_bitmap->hdc = CreateCompatibleDC(hdc);
|
||||
|
||||
if (!bitmap->data)
|
||||
wf_bitmap->bitmap = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height);
|
||||
else
|
||||
wf_bitmap->bitmap = wf_create_dib(wfc, bitmap->width, bitmap->height, bitmap->format,
|
||||
bitmap->data, nullptr);
|
||||
|
||||
wf_bitmap->org_bitmap = (HBITMAP)SelectObject(wf_bitmap->hdc, wf_bitmap->bitmap);
|
||||
ReleaseDC(nullptr, hdc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void wf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
|
||||
|
||||
if (wf_bitmap != 0)
|
||||
{
|
||||
SelectObject(wf_bitmap->hdc, wf_bitmap->org_bitmap);
|
||||
DeleteObject(wf_bitmap->bitmap);
|
||||
DeleteDC(wf_bitmap->hdc);
|
||||
|
||||
winpr_aligned_free(wf_bitmap->_bitmap.data);
|
||||
wf_bitmap->_bitmap.data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL wf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
BOOL rc;
|
||||
UINT32 width, height;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
|
||||
|
||||
if (!context || !bitmap)
|
||||
return FALSE;
|
||||
|
||||
width = bitmap->right - bitmap->left + 1;
|
||||
height = bitmap->bottom - bitmap->top + 1;
|
||||
rc = BitBlt(wfc->primary->hdc, bitmap->left, bitmap->top, width, height, wf_bitmap->hdc, 0, 0,
|
||||
SRCCOPY);
|
||||
wf_invalidate_region(wfc, bitmap->left, bitmap->top, width, height);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL wf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
wfBitmap* bmp = (wfBitmap*)bitmap;
|
||||
rdpGdi* gdi = context->gdi;
|
||||
|
||||
if (!gdi || !wfc)
|
||||
return FALSE;
|
||||
|
||||
if (primary)
|
||||
wfc->drawing = wfc->primary;
|
||||
else if (!bmp)
|
||||
return FALSE;
|
||||
else
|
||||
wfc->drawing = bmp;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Pointer Class */
|
||||
|
||||
static BOOL flip_bitmap(const BYTE* src, BYTE* dst, UINT32 scanline, UINT32 nHeight)
|
||||
{
|
||||
BYTE* bottomLine = dst + scanline * (nHeight - 1);
|
||||
|
||||
for (UINT32 x = 0; x < nHeight; x++)
|
||||
{
|
||||
memcpy(bottomLine, src, scanline);
|
||||
src += scanline;
|
||||
bottomLine -= scanline;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_Pointer_New(rdpContext* context, rdpPointer* pointer)
|
||||
{
|
||||
HCURSOR hCur;
|
||||
ICONINFO info;
|
||||
rdpGdi* gdi;
|
||||
BOOL rc = FALSE;
|
||||
|
||||
if (!context || !pointer)
|
||||
return FALSE;
|
||||
|
||||
gdi = context->gdi;
|
||||
|
||||
if (!gdi)
|
||||
return FALSE;
|
||||
|
||||
info.fIcon = FALSE;
|
||||
info.xHotspot = pointer->xPos;
|
||||
info.yHotspot = pointer->yPos;
|
||||
|
||||
if (pointer->xorBpp == 1)
|
||||
{
|
||||
BYTE* pdata = nullptr;
|
||||
|
||||
if ((pointer->lengthAndMask > 0) || (pointer->lengthXorMask > 0))
|
||||
{
|
||||
pdata =
|
||||
(BYTE*)winpr_aligned_malloc(pointer->lengthAndMask + pointer->lengthXorMask, 16);
|
||||
|
||||
if (!pdata)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CopyMemory(pdata, pointer->andMaskData, pointer->lengthAndMask);
|
||||
CopyMemory(pdata + pointer->lengthAndMask, pointer->xorMaskData, pointer->lengthXorMask);
|
||||
info.hbmMask = CreateBitmap(pointer->width, pointer->height * 2, 1, 1, pdata);
|
||||
winpr_aligned_free(pdata);
|
||||
info.hbmColor = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 srcFormat;
|
||||
BYTE* pdata = nullptr;
|
||||
|
||||
if (pointer->lengthAndMask > 0)
|
||||
{
|
||||
pdata = (BYTE*)winpr_aligned_malloc(pointer->lengthAndMask, 16);
|
||||
|
||||
if (!pdata)
|
||||
goto fail;
|
||||
flip_bitmap(pointer->andMaskData, pdata, (pointer->width + 7) / 8, pointer->height);
|
||||
}
|
||||
|
||||
info.hbmMask = CreateBitmap(pointer->width, pointer->height, 1, 1, pdata);
|
||||
winpr_aligned_free(pdata);
|
||||
|
||||
/* currently color xorBpp is only 24 per [T128] section 8.14.3 */
|
||||
srcFormat = gdi_get_pixel_format(pointer->xorBpp);
|
||||
|
||||
if (!srcFormat)
|
||||
goto fail;
|
||||
|
||||
info.hbmColor = wf_create_dib((wfContext*)context, pointer->width, pointer->height,
|
||||
gdi->dstFormat, nullptr, &pdata);
|
||||
|
||||
if (!info.hbmColor)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_image_copy_from_pointer_data(
|
||||
pdata, gdi->dstFormat, 0, 0, 0, pointer->width, pointer->height,
|
||||
pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData,
|
||||
pointer->lengthAndMask, pointer->xorBpp, &gdi->palette))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
hCur = CreateIconIndirect(&info);
|
||||
((wfPointer*)pointer)->cursor = hCur;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
|
||||
if (info.hbmMask)
|
||||
DeleteObject(info.hbmMask);
|
||||
|
||||
if (info.hbmColor)
|
||||
DeleteObject(info.hbmColor);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void wf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
|
||||
{
|
||||
HCURSOR hCur;
|
||||
|
||||
if (!context || !pointer)
|
||||
return;
|
||||
|
||||
hCur = ((wfPointer*)pointer)->cursor;
|
||||
|
||||
if (hCur != 0)
|
||||
DestroyIcon(hCur);
|
||||
}
|
||||
|
||||
static BOOL wf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
|
||||
{
|
||||
HCURSOR hCur;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
|
||||
if (!context || !pointer)
|
||||
return FALSE;
|
||||
|
||||
hCur = ((wfPointer*)pointer)->cursor;
|
||||
|
||||
if (hCur != nullptr)
|
||||
{
|
||||
SetCursor(hCur);
|
||||
wfc->cursor = hCur;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_Pointer_SetNull(rdpContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_Pointer_SetDefault(rdpContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL wf_register_pointer(rdpGraphics* graphics)
|
||||
{
|
||||
wfContext* wfc;
|
||||
rdpPointer pointer = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!graphics)
|
||||
return FALSE;
|
||||
|
||||
wfc = (wfContext*)graphics->context;
|
||||
pointer.size = sizeof(wfPointer);
|
||||
pointer.New = wf_Pointer_New;
|
||||
pointer.Free = wf_Pointer_Free;
|
||||
pointer.Set = wf_Pointer_Set;
|
||||
pointer.SetNull = wf_Pointer_SetNull;
|
||||
pointer.SetDefault = wf_Pointer_SetDefault;
|
||||
pointer.SetPosition = wf_Pointer_SetPosition;
|
||||
graphics_register_pointer(graphics, &pointer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Graphics Module */
|
||||
|
||||
BOOL wf_register_graphics(rdpGraphics* graphics)
|
||||
{
|
||||
wfContext* wfc;
|
||||
rdpGlyph glyph;
|
||||
rdpBitmap bitmap;
|
||||
|
||||
if (!graphics)
|
||||
return FALSE;
|
||||
|
||||
wfc = (wfContext*)graphics->context;
|
||||
bitmap = *graphics->Bitmap_Prototype;
|
||||
bitmap.size = sizeof(wfBitmap);
|
||||
bitmap.New = wf_Bitmap_New;
|
||||
bitmap.Free = wf_Bitmap_Free;
|
||||
bitmap.Paint = wf_Bitmap_Paint;
|
||||
bitmap.SetSurface = wf_Bitmap_SetSurface;
|
||||
graphics_register_bitmap(graphics, &bitmap);
|
||||
glyph = *graphics->Glyph_Prototype;
|
||||
graphics_register_glyph(graphics, &glyph);
|
||||
return TRUE;
|
||||
}
|
||||
34
third_party/FreeRDP/client/Windows/wf_graphics.h
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Windows Graphical Objects
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_GRAPHICS_H
|
||||
#define FREERDP_CLIENT_WIN_GRAPHICS_H
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
HBITMAP wf_create_dib(wfContext* wfc, UINT32 width, UINT32 height, UINT32 format, const BYTE* data,
|
||||
BYTE** pdata);
|
||||
wfBitmap* wf_image_new(wfContext* wfc, UINT32 width, UINT32 height, UINT32 format,
|
||||
const BYTE* data);
|
||||
void wf_image_free(wfBitmap* image);
|
||||
|
||||
BOOL wf_register_pointer(rdpGraphics* graphics);
|
||||
BOOL wf_register_graphics(rdpGraphics* graphics);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WIN_GRAPHICS_H */
|
||||
994
third_party/FreeRDP/client/Windows/wf_rail.c
vendored
Normal file
@@ -0,0 +1,994 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2013-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/client/rail.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "wf_rail.h"
|
||||
|
||||
#define TAG CLIENT_TAG("windows")
|
||||
|
||||
#define GET_X_LPARAM(lParam) ((UINT16)(lParam & 0xFFFF))
|
||||
#define GET_Y_LPARAM(lParam) ((UINT16)((lParam >> 16) & 0xFFFF))
|
||||
|
||||
struct wf_rail_window
|
||||
{
|
||||
wfContext* wfc;
|
||||
|
||||
HWND hWnd;
|
||||
|
||||
DWORD dwStyle;
|
||||
DWORD dwExStyle;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
char* title;
|
||||
};
|
||||
|
||||
/* RemoteApp Core Protocol Extension */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 style;
|
||||
const char* name;
|
||||
BOOL multi;
|
||||
} WINDOW_STYLE;
|
||||
|
||||
static const WINDOW_STYLE WINDOW_STYLES[] = { { WS_BORDER, "WS_BORDER", FALSE },
|
||||
{ WS_CAPTION, "WS_CAPTION", FALSE },
|
||||
{ WS_CHILD, "WS_CHILD", FALSE },
|
||||
{ WS_CLIPCHILDREN, "WS_CLIPCHILDREN", FALSE },
|
||||
{ WS_CLIPSIBLINGS, "WS_CLIPSIBLINGS", FALSE },
|
||||
{ WS_DISABLED, "WS_DISABLED", FALSE },
|
||||
{ WS_DLGFRAME, "WS_DLGFRAME", FALSE },
|
||||
{ WS_GROUP, "WS_GROUP", FALSE },
|
||||
{ WS_HSCROLL, "WS_HSCROLL", FALSE },
|
||||
{ WS_ICONIC, "WS_ICONIC", FALSE },
|
||||
{ WS_MAXIMIZE, "WS_MAXIMIZE", FALSE },
|
||||
{ WS_MAXIMIZEBOX, "WS_MAXIMIZEBOX", FALSE },
|
||||
{ WS_MINIMIZE, "WS_MINIMIZE", FALSE },
|
||||
{ WS_MINIMIZEBOX, "WS_MINIMIZEBOX", FALSE },
|
||||
{ WS_OVERLAPPED, "WS_OVERLAPPED", FALSE },
|
||||
{ WS_OVERLAPPEDWINDOW, "WS_OVERLAPPEDWINDOW", TRUE },
|
||||
{ WS_POPUP, "WS_POPUP", FALSE },
|
||||
{ WS_POPUPWINDOW, "WS_POPUPWINDOW", TRUE },
|
||||
{ WS_SIZEBOX, "WS_SIZEBOX", FALSE },
|
||||
{ WS_SYSMENU, "WS_SYSMENU", FALSE },
|
||||
{ WS_TABSTOP, "WS_TABSTOP", FALSE },
|
||||
{ WS_THICKFRAME, "WS_THICKFRAME", FALSE },
|
||||
{ WS_VISIBLE, "WS_VISIBLE", FALSE } };
|
||||
|
||||
static const WINDOW_STYLE EXTENDED_WINDOW_STYLES[] = {
|
||||
{ WS_EX_ACCEPTFILES, "WS_EX_ACCEPTFILES", FALSE },
|
||||
{ WS_EX_APPWINDOW, "WS_EX_APPWINDOW", FALSE },
|
||||
{ WS_EX_CLIENTEDGE, "WS_EX_CLIENTEDGE", FALSE },
|
||||
{ WS_EX_COMPOSITED, "WS_EX_COMPOSITED", FALSE },
|
||||
{ WS_EX_CONTEXTHELP, "WS_EX_CONTEXTHELP", FALSE },
|
||||
{ WS_EX_CONTROLPARENT, "WS_EX_CONTROLPARENT", FALSE },
|
||||
{ WS_EX_DLGMODALFRAME, "WS_EX_DLGMODALFRAME", FALSE },
|
||||
{ WS_EX_LAYERED, "WS_EX_LAYERED", FALSE },
|
||||
{ WS_EX_LAYOUTRTL, "WS_EX_LAYOUTRTL", FALSE },
|
||||
{ WS_EX_LEFT, "WS_EX_LEFT", FALSE },
|
||||
{ WS_EX_LEFTSCROLLBAR, "WS_EX_LEFTSCROLLBAR", FALSE },
|
||||
{ WS_EX_LTRREADING, "WS_EX_LTRREADING", FALSE },
|
||||
{ WS_EX_MDICHILD, "WS_EX_MDICHILD", FALSE },
|
||||
{ WS_EX_NOACTIVATE, "WS_EX_NOACTIVATE", FALSE },
|
||||
{ WS_EX_NOINHERITLAYOUT, "WS_EX_NOINHERITLAYOUT", FALSE },
|
||||
{ WS_EX_NOPARENTNOTIFY, "WS_EX_NOPARENTNOTIFY", FALSE },
|
||||
{ WS_EX_OVERLAPPEDWINDOW, "WS_EX_OVERLAPPEDWINDOW", TRUE },
|
||||
{ WS_EX_PALETTEWINDOW, "WS_EX_PALETTEWINDOW", TRUE },
|
||||
{ WS_EX_RIGHT, "WS_EX_RIGHT", FALSE },
|
||||
{ WS_EX_RIGHTSCROLLBAR, "WS_EX_RIGHTSCROLLBAR", FALSE },
|
||||
{ WS_EX_RTLREADING, "WS_EX_RTLREADING", FALSE },
|
||||
{ WS_EX_STATICEDGE, "WS_EX_STATICEDGE", FALSE },
|
||||
{ WS_EX_TOOLWINDOW, "WS_EX_TOOLWINDOW", FALSE },
|
||||
{ WS_EX_TOPMOST, "WS_EX_TOPMOST", FALSE },
|
||||
{ WS_EX_TRANSPARENT, "WS_EX_TRANSPARENT", FALSE },
|
||||
{ WS_EX_WINDOWEDGE, "WS_EX_WINDOWEDGE", FALSE }
|
||||
};
|
||||
|
||||
static void PrintWindowStyles(UINT32 style)
|
||||
{
|
||||
WLog_INFO(TAG, "\tWindow Styles:\t{");
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(WINDOW_STYLES); i++)
|
||||
{
|
||||
if (style & WINDOW_STYLES[i].style)
|
||||
{
|
||||
if (WINDOW_STYLES[i].multi)
|
||||
{
|
||||
if ((style & WINDOW_STYLES[i].style) != WINDOW_STYLES[i].style)
|
||||
continue;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "\t\t%s", WINDOW_STYLES[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintExtendedWindowStyles(UINT32 style)
|
||||
{
|
||||
WLog_INFO(TAG, "\tExtended Window Styles:\t{");
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(EXTENDED_WINDOW_STYLES); i++)
|
||||
{
|
||||
if (style & EXTENDED_WINDOW_STYLES[i].style)
|
||||
{
|
||||
if (EXTENDED_WINDOW_STYLES[i].multi)
|
||||
{
|
||||
if ((style & EXTENDED_WINDOW_STYLES[i].style) != EXTENDED_WINDOW_STYLES[i].style)
|
||||
continue;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "\t\t%s", EXTENDED_WINDOW_STYLES[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintRailWindowState(const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
|
||||
WLog_INFO(TAG, "WindowCreate: WindowId: 0x%08X", orderInfo->windowId);
|
||||
else
|
||||
WLog_INFO(TAG, "WindowUpdate: WindowId: 0x%08X", orderInfo->windowId);
|
||||
|
||||
WLog_INFO(TAG, "{");
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
|
||||
{
|
||||
WLog_INFO(TAG, "\tOwnerWindowId: 0x%08X", windowState->ownerWindowId);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
||||
{
|
||||
WLog_INFO(TAG, "\tStyle: 0x%08X ExtendedStyle: 0x%08X", windowState->style,
|
||||
windowState->extendedStyle);
|
||||
PrintWindowStyles(windowState->style);
|
||||
PrintExtendedWindowStyles(windowState->extendedStyle);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
WLog_INFO(TAG, "\tShowState: %u", windowState->showState);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
const WCHAR* str = (const WCHAR*)windowState->titleInfo.string;
|
||||
char* title =
|
||||
ConvertWCharNToUtf8Alloc(str, windowState->titleInfo.length / sizeof(WCHAR), nullptr);
|
||||
WLog_INFO(TAG, "\tTitleInfo: %s (length = %hu)", title, windowState->titleInfo.length);
|
||||
free(title);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
{
|
||||
WLog_INFO(TAG, "\tClientOffsetX: %d ClientOffsetY: %d", windowState->clientOffsetX,
|
||||
windowState->clientOffsetY);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
{
|
||||
WLog_INFO(TAG, "\tClientAreaWidth: %u ClientAreaHeight: %u", windowState->clientAreaWidth,
|
||||
windowState->clientAreaHeight);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
{
|
||||
WLog_INFO(TAG, "\tRPContent: %u", windowState->RPContent);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
{
|
||||
WLog_INFO(TAG, "\tRootParentHandle: 0x%08X", windowState->rootParentHandle);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
{
|
||||
WLog_INFO(TAG, "\tWindowOffsetX: %d WindowOffsetY: %d", windowState->windowOffsetX,
|
||||
windowState->windowOffsetY);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
{
|
||||
WLog_INFO(TAG, "\tWindowClientDeltaX: %d WindowClientDeltaY: %d",
|
||||
windowState->windowClientDeltaX, windowState->windowClientDeltaY);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
{
|
||||
WLog_INFO(TAG, "\tWindowWidth: %u WindowHeight: %u", windowState->windowWidth,
|
||||
windowState->windowHeight);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
{
|
||||
RECTANGLE_16* rect;
|
||||
WLog_INFO(TAG, "\tnumWindowRects: %u", windowState->numWindowRects);
|
||||
|
||||
for (UINT32 index = 0; index < windowState->numWindowRects; index++)
|
||||
{
|
||||
rect = &windowState->windowRects[index];
|
||||
WLog_INFO(TAG, "\twindowRect[%u]: left: %hu top: %hu right: %hu bottom: %hu", index,
|
||||
rect->left, rect->top, rect->right, rect->bottom);
|
||||
}
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
{
|
||||
WLog_INFO(TAG, "\tvisibileOffsetX: %d visibleOffsetY: %d", windowState->visibleOffsetX,
|
||||
windowState->visibleOffsetY);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
{
|
||||
RECTANGLE_16* rect;
|
||||
WLog_INFO(TAG, "\tnumVisibilityRects: %u", windowState->numVisibilityRects);
|
||||
|
||||
for (UINT32 index = 0; index < windowState->numVisibilityRects; index++)
|
||||
{
|
||||
rect = &windowState->visibilityRects[index];
|
||||
WLog_INFO(TAG, "\tvisibilityRect[%u]: left: %hu top: %hu right: %hu bottom: %hu", index,
|
||||
rect->left, rect->top, rect->right, rect->bottom);
|
||||
}
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "}");
|
||||
}
|
||||
|
||||
static void PrintRailIconInfo(const WINDOW_ORDER_INFO* orderInfo, const ICON_INFO* iconInfo)
|
||||
{
|
||||
WLog_INFO(TAG, "ICON_INFO");
|
||||
WLog_INFO(TAG, "{");
|
||||
WLog_INFO(TAG, "\tbigIcon: %s",
|
||||
(orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? "true" : "false");
|
||||
WLog_INFO(TAG, "\tcacheEntry; 0x%08X", iconInfo->cacheEntry);
|
||||
WLog_INFO(TAG, "\tcacheId: 0x%08X", iconInfo->cacheId);
|
||||
WLog_INFO(TAG, "\tbpp: %u", iconInfo->bpp);
|
||||
WLog_INFO(TAG, "\twidth: %u", iconInfo->width);
|
||||
WLog_INFO(TAG, "\theight: %u", iconInfo->height);
|
||||
WLog_INFO(TAG, "\tcbColorTable: %u", iconInfo->cbColorTable);
|
||||
WLog_INFO(TAG, "\tcbBitsMask: %u", iconInfo->cbBitsMask);
|
||||
WLog_INFO(TAG, "\tcbBitsColor: %u", iconInfo->cbBitsColor);
|
||||
WLog_INFO(TAG, "\tcolorTable: %p", (void*)iconInfo->colorTable);
|
||||
WLog_INFO(TAG, "\tbitsMask: %p", (void*)iconInfo->bitsMask);
|
||||
WLog_INFO(TAG, "\tbitsColor: %p", (void*)iconInfo->bitsColor);
|
||||
WLog_INFO(TAG, "}");
|
||||
}
|
||||
|
||||
LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HDC hDC;
|
||||
int x, y;
|
||||
int width;
|
||||
int height;
|
||||
UINT32 xPos;
|
||||
UINT32 yPos;
|
||||
PAINTSTRUCT ps;
|
||||
UINT32 inputFlags;
|
||||
wfContext* wfc = nullptr;
|
||||
rdpInput* input = nullptr;
|
||||
rdpContext* context = nullptr;
|
||||
wfRailWindow* railWindow;
|
||||
railWindow = (wfRailWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||
|
||||
if (railWindow)
|
||||
wfc = railWindow->wfc;
|
||||
|
||||
if (wfc)
|
||||
context = (rdpContext*)wfc;
|
||||
|
||||
if (context)
|
||||
input = context->input;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (!wfc)
|
||||
return 0;
|
||||
|
||||
hDC = BeginPaint(hWnd, &ps);
|
||||
x = ps.rcPaint.left;
|
||||
y = ps.rcPaint.top;
|
||||
width = ps.rcPaint.right - ps.rcPaint.left + 1;
|
||||
height = ps.rcPaint.bottom - ps.rcPaint.top + 1;
|
||||
BitBlt(hDC, x, y, width, height, wfc->primary->hdc, railWindow->x + x,
|
||||
railWindow->y + y, SRCCOPY);
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
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;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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 BOOL wf_rail_window_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
wfRailWindow* railWindow = nullptr;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
UINT32 fieldFlags = orderInfo->fieldFlags;
|
||||
PrintRailWindowState(orderInfo, windowState);
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_STATE_NEW)
|
||||
{
|
||||
BOOL rc;
|
||||
HANDLE hInstance;
|
||||
WCHAR* titleW = nullptr;
|
||||
WNDCLASSEX wndClassEx = WINPR_C_ARRAY_INIT;
|
||||
railWindow = (wfRailWindow*)calloc(1, sizeof(wfRailWindow));
|
||||
|
||||
if (!railWindow)
|
||||
return FALSE;
|
||||
|
||||
railWindow->wfc = wfc;
|
||||
railWindow->dwStyle = windowState->style;
|
||||
railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
|
||||
railWindow->dwExStyle = windowState->extendedStyle;
|
||||
railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
|
||||
railWindow->x = windowState->windowOffsetX;
|
||||
railWindow->y = windowState->windowOffsetY;
|
||||
railWindow->width = windowState->windowWidth;
|
||||
railWindow->height = windowState->windowHeight;
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
const WCHAR* str = (const WCHAR*)windowState->titleInfo.string;
|
||||
char* title = nullptr;
|
||||
|
||||
if (windowState->titleInfo.length == 0)
|
||||
{
|
||||
if (!(title = _strdup("")))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to duplicate empty window title string");
|
||||
/* error handled below */
|
||||
}
|
||||
}
|
||||
else if (!(title = ConvertWCharNToUtf8Alloc(
|
||||
str, windowState->titleInfo.length / sizeof(WCHAR), nullptr)))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to convert window title");
|
||||
/* error handled below */
|
||||
}
|
||||
|
||||
railWindow->title = title;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(railWindow->title = _strdup("RdpRailWindow")))
|
||||
WLog_ERR(TAG, "failed to duplicate default window title string");
|
||||
}
|
||||
|
||||
if (!railWindow->title)
|
||||
{
|
||||
free(railWindow);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
titleW = ConvertUtf8ToWCharAlloc(railWindow->title, nullptr);
|
||||
hInstance = GetModuleHandle(nullptr);
|
||||
|
||||
wndClassEx.cbSize = sizeof(WNDCLASSEX);
|
||||
wndClassEx.style = 0;
|
||||
wndClassEx.lpfnWndProc = wf_RailWndProc;
|
||||
wndClassEx.cbClsExtra = 0;
|
||||
wndClassEx.cbWndExtra = 0;
|
||||
wndClassEx.hIcon = nullptr;
|
||||
wndClassEx.hCursor = nullptr;
|
||||
wndClassEx.hbrBackground = nullptr;
|
||||
wndClassEx.lpszMenuName = nullptr;
|
||||
wndClassEx.lpszClassName = _T("RdpRailWindow");
|
||||
wndClassEx.hInstance = hInstance;
|
||||
wndClassEx.hIconSm = nullptr;
|
||||
RegisterClassEx(&wndClassEx);
|
||||
railWindow->hWnd = CreateWindowExW(railWindow->dwExStyle, /* dwExStyle */
|
||||
_T("RdpRailWindow"), /* lpClassName */
|
||||
titleW, /* lpWindowName */
|
||||
railWindow->dwStyle, /* dwStyle */
|
||||
railWindow->x, /* x */
|
||||
railWindow->y, /* y */
|
||||
railWindow->width, /* nWidth */
|
||||
railWindow->height, /* nHeight */
|
||||
nullptr, /* hWndParent */
|
||||
nullptr, /* hMenu */
|
||||
hInstance, /* hInstance */
|
||||
nullptr /* lpParam */
|
||||
);
|
||||
|
||||
if (!railWindow->hWnd)
|
||||
{
|
||||
free(titleW);
|
||||
free(railWindow->title);
|
||||
free(railWindow);
|
||||
WLog_ERR(TAG, "CreateWindowExW failed with error %" PRIu32 "", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetWindowLongPtr(railWindow->hWnd, GWLP_USERDATA, (LONG_PTR)railWindow);
|
||||
rc = HashTable_Insert(wfc->railWindows, (void*)(UINT_PTR)orderInfo->windowId,
|
||||
(void*)railWindow);
|
||||
free(titleW);
|
||||
UpdateWindow(railWindow->hWnd);
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*)(UINT_PTR)orderInfo->windowId);
|
||||
}
|
||||
|
||||
if (!railWindow)
|
||||
return TRUE;
|
||||
|
||||
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
|
||||
{
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
{
|
||||
railWindow->x = windowState->windowOffsetX;
|
||||
railWindow->y = windowState->windowOffsetY;
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
{
|
||||
railWindow->width = windowState->windowWidth;
|
||||
railWindow->height = windowState->windowHeight;
|
||||
}
|
||||
|
||||
SetWindowPos(railWindow->hWnd, nullptr, railWindow->x, railWindow->y, railWindow->width,
|
||||
railWindow->height, 0);
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
||||
{
|
||||
railWindow->dwStyle = windowState->style;
|
||||
railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
|
||||
railWindow->dwExStyle = windowState->extendedStyle;
|
||||
railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
|
||||
SetWindowLongPtr(railWindow->hWnd, GWL_STYLE, (LONG)railWindow->dwStyle);
|
||||
SetWindowLongPtr(railWindow->hWnd, GWL_EXSTYLE, (LONG)railWindow->dwExStyle);
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
ShowWindow(railWindow->hWnd, windowState->showState);
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
const WCHAR* str = (const WCHAR*)windowState->titleInfo.string;
|
||||
char* title = nullptr;
|
||||
|
||||
if (windowState->titleInfo.length == 0)
|
||||
{
|
||||
if (!(title = _strdup("")))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to duplicate empty window title string");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (!(title = ConvertWCharNToUtf8Alloc(
|
||||
str, windowState->titleInfo.length / sizeof(WCHAR), nullptr)))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to convert window title");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(railWindow->title);
|
||||
railWindow->title = title;
|
||||
SetWindowTextW(railWindow->hWnd, str);
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
{
|
||||
HRGN hWndRect;
|
||||
HRGN hWndRects;
|
||||
RECTANGLE_16* rect;
|
||||
|
||||
if (windowState->numWindowRects > 0)
|
||||
{
|
||||
rect = &(windowState->windowRects[0]);
|
||||
hWndRects = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
|
||||
|
||||
for (UINT32 index = 1; index < windowState->numWindowRects; index++)
|
||||
{
|
||||
rect = &(windowState->windowRects[index]);
|
||||
hWndRect = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
|
||||
CombineRgn(hWndRects, hWndRects, hWndRect, RGN_OR);
|
||||
DeleteObject(hWndRect);
|
||||
}
|
||||
|
||||
SetWindowRgn(railWindow->hWnd, hWndRects, TRUE);
|
||||
DeleteObject(hWndRects);
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
{
|
||||
}
|
||||
|
||||
UpdateWindow(railWindow->hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
wfRailWindow* railWindow = nullptr;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailWindowDelete");
|
||||
railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*)(UINT_PTR)orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
return TRUE;
|
||||
|
||||
HashTable_Remove(wfc->railWindows, (void*)(UINT_PTR)orderInfo->windowId);
|
||||
DestroyWindow(railWindow->hWnd);
|
||||
free(railWindow);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_ICON_ORDER* windowIcon)
|
||||
{
|
||||
HDC hDC;
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
HICON hIcon;
|
||||
BOOL bigIcon;
|
||||
ICONINFO iconInfo = WINPR_C_ARRAY_INIT;
|
||||
BITMAPINFO bitmapInfo = WINPR_C_ARRAY_INIT;
|
||||
wfRailWindow* railWindow;
|
||||
BITMAPINFOHEADER* bitmapInfoHeader;
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailWindowIcon");
|
||||
PrintRailIconInfo(orderInfo, windowIcon->iconInfo);
|
||||
railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*)(UINT_PTR)orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
return TRUE;
|
||||
|
||||
bigIcon = (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? TRUE : FALSE;
|
||||
hDC = GetDC(railWindow->hWnd);
|
||||
iconInfo.fIcon = TRUE;
|
||||
iconInfo.xHotspot = 0;
|
||||
iconInfo.yHotspot = 0;
|
||||
|
||||
bitmapInfoHeader = &(bitmapInfo.bmiHeader);
|
||||
bpp = windowIcon->iconInfo->bpp;
|
||||
width = windowIcon->iconInfo->width;
|
||||
height = windowIcon->iconInfo->height;
|
||||
bitmapInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfoHeader->biWidth = width;
|
||||
bitmapInfoHeader->biHeight = height;
|
||||
bitmapInfoHeader->biPlanes = 1;
|
||||
bitmapInfoHeader->biBitCount = bpp;
|
||||
bitmapInfoHeader->biCompression = 0;
|
||||
bitmapInfoHeader->biSizeImage = height * width * ((bpp + 7) / 8);
|
||||
bitmapInfoHeader->biXPelsPerMeter = width;
|
||||
bitmapInfoHeader->biYPelsPerMeter = height;
|
||||
bitmapInfoHeader->biClrUsed = 0;
|
||||
bitmapInfoHeader->biClrImportant = 0;
|
||||
iconInfo.hbmMask = CreateDIBitmap(hDC, bitmapInfoHeader, CBM_INIT,
|
||||
windowIcon->iconInfo->bitsMask, &bitmapInfo, DIB_RGB_COLORS);
|
||||
iconInfo.hbmColor =
|
||||
CreateDIBitmap(hDC, bitmapInfoHeader, CBM_INIT, windowIcon->iconInfo->bitsColor,
|
||||
&bitmapInfo, DIB_RGB_COLORS);
|
||||
hIcon = CreateIconIndirect(&iconInfo);
|
||||
|
||||
if (hIcon)
|
||||
{
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
wParam = (WPARAM)bigIcon ? ICON_BIG : ICON_SMALL;
|
||||
lParam = (LPARAM)hIcon;
|
||||
SendMessage(railWindow->hWnd, WM_SETICON, wParam, lParam);
|
||||
}
|
||||
|
||||
ReleaseDC(nullptr, hDC);
|
||||
|
||||
if (windowIcon->iconInfo->cacheEntry != 0xFFFF)
|
||||
{
|
||||
/* icon should be cached */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_CACHED_ICON_ORDER* windowCachedIcon)
|
||||
{
|
||||
WLog_DBG(TAG, "RailWindowCachedIcon");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void wf_rail_notify_icon_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
||||
{
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
|
||||
{
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
|
||||
{
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
|
||||
{
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
|
||||
{
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
|
||||
{
|
||||
const ICON_INFO* iconInfo = &(notifyIconState->icon);
|
||||
PrintRailIconInfo(orderInfo, iconInfo);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL wf_rail_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailNotifyIconCreate");
|
||||
wf_rail_notify_icon_common(context, orderInfo, notifyIconState);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailNotifyIconUpdate");
|
||||
wf_rail_notify_icon_common(context, orderInfo, notifyIconState);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailNotifyIconDelete");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const MONITORED_DESKTOP_ORDER* monitoredDesktop)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailMonitorDesktop");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wf_rail_non_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
wfContext* wfc = (wfContext*)context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
WLog_DBG(TAG, "RailNonMonitorDesktop");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_rail_register_update_callbacks(rdpUpdate* update)
|
||||
{
|
||||
rdpWindowUpdate* window = update->window;
|
||||
window->WindowCreate = wf_rail_window_common;
|
||||
window->WindowUpdate = wf_rail_window_common;
|
||||
window->WindowDelete = wf_rail_window_delete;
|
||||
window->WindowIcon = wf_rail_window_icon;
|
||||
window->WindowCachedIcon = wf_rail_window_cached_icon;
|
||||
window->NotifyIconCreate = wf_rail_notify_icon_create;
|
||||
window->NotifyIconUpdate = wf_rail_notify_icon_update;
|
||||
window->NotifyIconDelete = wf_rail_notify_icon_delete;
|
||||
window->MonitoredDesktop = wf_rail_monitored_desktop;
|
||||
window->NonMonitoredDesktop = wf_rail_non_monitored_desktop;
|
||||
}
|
||||
|
||||
/* RemoteApp Virtual Channel Extension */
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_execute_result(RailClientContext* context,
|
||||
const RAIL_EXEC_RESULT_ORDER* execResult)
|
||||
{
|
||||
WLog_DBG(TAG, "RailServerExecuteResult: 0x%08X", execResult->rawResult);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_system_param(RailClientContext* context,
|
||||
const RAIL_SYSPARAM_ORDER* sysparam)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_handshake(RailClientContext* context,
|
||||
const RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
return client_rail_server_start_cmd(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_handshake_ex(RailClientContext* context,
|
||||
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
{
|
||||
return client_rail_server_start_cmd(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_local_move_size(RailClientContext* context,
|
||||
const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_min_max_info(RailClientContext* context,
|
||||
const RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_language_bar_info(RailClientContext* context,
|
||||
const RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_rail_server_get_appid_response(RailClientContext* context,
|
||||
const RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
void wf_rail_invalidate_region(wfContext* wfc, REGION16* invalidRegion)
|
||||
{
|
||||
RECT updateRect;
|
||||
RECTANGLE_16 windowRect;
|
||||
ULONG_PTR* pKeys = nullptr;
|
||||
wfRailWindow* railWindow;
|
||||
const RECTANGLE_16* extents;
|
||||
REGION16 windowInvalidRegion;
|
||||
region16_init(&windowInvalidRegion);
|
||||
size_t count = HashTable_GetKeys(wfc->railWindows, &pKeys);
|
||||
|
||||
for (size_t 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);
|
||||
}
|
||||
|
||||
BOOL wf_rail_init(wfContext* wfc, RailClientContext* rail)
|
||||
{
|
||||
rdpContext* context = (rdpContext*)wfc;
|
||||
wfc->rail = rail;
|
||||
rail->custom = (void*)wfc;
|
||||
rail->ServerExecuteResult = wf_rail_server_execute_result;
|
||||
rail->ServerSystemParam = wf_rail_server_system_param;
|
||||
rail->ServerHandshake = wf_rail_server_handshake;
|
||||
rail->ServerHandshakeEx = wf_rail_server_handshake_ex;
|
||||
rail->ServerLocalMoveSize = wf_rail_server_local_move_size;
|
||||
rail->ServerMinMaxInfo = wf_rail_server_min_max_info;
|
||||
rail->ServerLanguageBarInfo = wf_rail_server_language_bar_info;
|
||||
rail->ServerGetAppIdResponse = wf_rail_server_get_appid_response;
|
||||
wf_rail_register_update_callbacks(context->update);
|
||||
wfc->railWindows = HashTable_New(TRUE);
|
||||
return (wfc->railWindows != nullptr);
|
||||
}
|
||||
|
||||
void wf_rail_uninit(wfContext* wfc, RailClientContext* rail)
|
||||
{
|
||||
wfc->rail = nullptr;
|
||||
rail->custom = nullptr;
|
||||
HashTable_Free(wfc->railWindows);
|
||||
}
|
||||
33
third_party/FreeRDP/client/Windows/wf_rail.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2013-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_WIN_RAIL_H
|
||||
#define FREERDP_CLIENT_WIN_RAIL_H
|
||||
|
||||
typedef struct wf_rail_window wfRailWindow;
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
#include <freerdp/client/rail.h>
|
||||
|
||||
BOOL 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 /* FREERDP_CLIENT_WIN_RAIL_H */
|
||||