Merge commit 'b5f8900bc45abbb36a03f58eed105c17a68e0516'

This commit is contained in:
Mehul Dhorda 2015-11-10 11:34:05 -08:00
commit c63ebaba3a
24 changed files with 677 additions and 245 deletions

View File

@ -776,8 +776,8 @@ if(WITH_CHANNELS)
add_subdirectory(channels) add_subdirectory(channels)
endif() endif()
if(WITH_CLIENT) if(WITH_CLIENT_COMMON OR WITH_CLIENT)
add_subdirectory(client) add_subdirectory(client)
endif() endif()
if(WITH_SERVER) if(WITH_SERVER)

View File

@ -1004,9 +1004,9 @@ static UINT cliprdr_server_receive_filecontents_response(CliprdrServerContext* c
response.cbRequested = header->dataLen - 4; response.cbRequested = header->dataLen - 4;
response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */
IFCALLRET(context->ServerFileContentsResponse, error, context, &response); IFCALLRET(context->ClientFileContentsResponse, error, context, &response);
if (error) if (error)
WLog_ERR(TAG, "ServerFileContentsResponse failed with error %lu!", error); WLog_ERR(TAG, "ClientFileContentsResponse failed with error %lu!", error);
return error; return error;
} }

View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
<!-- Button labels -->
<string name="yes"></string>
<string name="no"></string>
<string name="cancel">取消</string>
<string name="cont">继续</string>
<string name="login">登录</string>
<string name="logout">断开</string>
<!-- Home menu items -->
<string name="menu_exit">退出</string>
<string name="menu_about">关于</string>
<string name="menu_help">帮助</string>
<string name="menu_new_bookmark">新建连接</string>
<string name="menu_app_settings">设置</string>
<!-- Bookmark menu items -->
<string name="menu_title_bookmark">操作</string>
<string name="menu_connect">连接</string>
<string name="menu_edit">编辑</string>
<string name="menu_delete">删除</string>
<!-- Session menu items -->
<string name="menu_sys_keyboard">键盘</string>
<string name="menu_ext_keyboard">功能键</string>
<string name="menu_touch_pointer">触控鼠标</string>
<string name="menu_home">主目录</string>
<string name="menu_disconnect">断开连接</string>
<!-- List section headers -->
<string name="section_bookmarks">手动连接</string>
<string name="section_active_sessions">活动会话数</string>
<!-- Search strings -->
<string name="search_hint">搜索</string>
<!-- List placeholder labels -->
<string name="list_placeholder_login">登录</string>
<string name="list_placeholder_no_servers">没有服务</string>
<string name="list_placeholder_connecting">连接中 &#8230;</string>
<string name="list_placeholder_disconnecting">正在断开连接 &#8230;</string>
<string name="list_placeholder_connection_error">连接丢失</string>
<string name="list_placeholder_wrong_password">密码错误</string>
<string name="list_placeholder_invalid_username">用户名错误</string>
<string name="list_placeholder_add_bookmark">新建连接</string>
<!-- Bookmark settings strings -->
<string name="settings_cat_host">主机信息</string>
<string name="settings_label">标签*</string>
<string name="settings_hostname">远程主机ip或域名</string>
<string name="settings_port">端口</string>
<string name="settings_cat_credentials">登录信息</string>
<string name="settings_credentials">登录信息</string>
<string name="settings_username">用户名</string>
<string name="settings_password">密码</string>
<string name="settings_domain"></string>
<string name="settings_cat_settings">设置</string>
<string name="settings_screen">显示</string>
<string name="settings_cat_screen">显示设置</string>
<string name="settings_colors">颜色深度</string>
<string-array name="colors_array">
<item>High Color (16 Bit)</item>
<item>True Color (24 Bit)</item>
<item>Highest Quality (32 Bit)</item>
</string-array>
<string-array name="colors_values_array">
<item>16</item>
<item>24</item>
<item>32</item>
</string-array>
<string name="settings_resolution">分辨率</string>
<string name="resolution_automatic">自动</string>
<string name="resolution_fit">全屏</string>
<string name="resolution_custom">自定义</string>
<string-array name="resolutions_array">
<item>自动</item>
<item>全屏</item>
<item>自定义</item>
<item>640x480</item>
<item>720x480</item>
<item>800x600</item>
<item>1024x768</item>
<item>1280x1024</item>
<item>1440x900</item>
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<string-array name="resolutions_values_array">
<item>自动</item>
<item>全屏</item>
<item>自定义</item>
<item>640x480</item>
<item>720x480</item>
<item>800x600</item>
<item>1024x768</item>
<item>1280x1024</item>
<item>1440x900</item>
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<string name="settings_width">宽度</string>
<string name="settings_height">高度</string>
<string name="settings_performance">连接性能</string>
<string name="settings_cat_performance">性能设置</string>
<string name="settings_perf_remotefx">RemoteFX</string>
<string name="settings_perf_wallpaper">桌面背景</string>
<string name="settings_perf_font_smoothing">字体平滑</string>
<string name="settings_perf_desktop_composition">桌面拼合</string>
<string name="settings_perf_full_window_drag">拖动是显示窗口内容</string>
<string name="settings_perf_menu_animation">菜单动画效果</string>
<string name="settings_perf_theming">视觉样式</string>
<string name="settings_advanced">高级</string>
<string name="settings_cat_advanced">高级设置</string>
<string name="settings_enable_3g_settings">3G设置</string>
<string name="settings_screen_3g">使用3G网络时的显示设置</string>
<string name="settings_performance_3g">使用3G网络时的连接性能</string>
<string name="settings_cat_gateway">路由</string>
<string name="settings_enable_gateway_settings">使用路由</string>
<string name="settings_gateway_settings">路由设置</string>
<string name="settings_redirect_sdcard">SDCard 重定向</string>
<string name="settings_redirect_sound">音频重定向</string>
<string-array name="redirect_sound_array">
<item>不要播放</item>
<item>在远程主机播放</item>
<item>在此设备上播放</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
<string name="settings_redirect_microphone">麦克风重定向</string>
<string name="settings_security">连接协议</string>
<string-array name="security_array">
<item>自动</item>
<item>RDP</item>
<item>TLS</item>
<item>NLA</item>
</string-array>
<string-array name="security_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string name="settings_remote_program">远程程序</string>
<string name="settings_work_dir">工作目录</string>
<string name="settings_async_channel">Async channel</string>
<string name="settings_async_transport">Async transport</string>
<string name="settings_async_input">Async input</string>
<string name="settings_async_update">Async update</string>
<string name="settings_console_mode">控制台模式</string>
<!-- App settings strings -->
<string name="settings_password_present">*******</string>
<string name="settings_password_empty">未设置</string>
<string name="settings_cat_ui">用户界面</string>
<string name="settings_ui_hide_status_bar">隐藏状态栏</string>
<string name="settings_ui_hide_zoom_controls">隐藏缩放控件</string>
<string name="settings_ui_swap_mouse_buttons">交换鼠标左右键</string>
<string name="settings_ui_invert_scrolling">翻转滚动</string>
<string name="settings_ui_auto_scroll_touchpointer">触摸指针自动滚屏</string>
<string name="settings_ui_ask_on_exit">退出时确认是否退出</string>
<string name="settings_cat_power">省电设计</string>
<string name="settings_power_disconnect_timeout">关闭空闲连接</string>
<string name="settings_cat_security">安全</string>
<string name="settings_security_accept_certificates">接受所有证书</string>
<string name="settings_security_clear_certificate_cache">清除证书缓存</string>
<string name="settings_description_after_minutes">%1$d 秒后</string>
<string name="settings_description_disabled">Disabled</string>
<!-- Activity titles -->
<string name="title_bookmark_settings">连接设置</string>
<string name="title_application_settings">设置</string>
<string name="title_home">aFreeRDP - FreeRDP for Android</string>
<string name="title_create_shortcut">RDP Connections</string>
<string name="title_help">帮助</string>
<string name="title_about">关于</string>
<!-- Error message strings -->
<string name="error_bookmark_incomplete_title">不保存即退出?</string>
<string name="error_bookmark_incomplete">点击 “继续” 继续编辑,点击 "取消" 放弃当前更改</string>
<string name="error_connection_failure">建立连接失败!</string>
<!-- Info message strings -->
<string name="info_capabilities_changed">由于主机不支持您的设置所以显示设置已经修改为适应主机的设置!</string>
<string name="info_reset_success">清除证书缓存成功!</string>
<string name="info_reset_failed">清楚证书缓存失败!</string>
<!-- Dialog strings -->
<string name="dlg_title_verify_certificate">证书验证</string>
<string name="dlg_msg_verify_certificate">未能验证远程主机证书的安全性,是否连接?</string>
<string name="dlg_title_credentials">请输入您的证书</string>
<string name="dlg_title_create_shortcut">创建快捷方式</string>
<string name="dlg_msg_create_shortcut">快捷方式名称:</string>
<string name="dlg_msg_connecting">连接中 &#8230;</string>
<string name="dlg_msg_logging_in">正在登录 &#8230;</string>
<string name="dlg_title_about">关于aFreeRDP</string>
<string name="dlg_title_create_bookmark_after_qc">是否保存连接设置?</string>
<string name="dlg_msg_create_bookmark_after_qc">连接设置还没保存! 是否保存?</string>
<string name="dlg_title_save_bookmark">保存?</string>
<string name="dlg_save_bookmark">是否保存更改?</string>
<string name="dlg_dont_show_again">不再提示</string>
<string name="dlg_title_exit">退出?</string>
<string name="dlg_msg_exit">是否退出?</string>
<string name="dlg_title_clear_cert_cache">清除证书缓存?</string>
<string name="dlg_msg_clear_cert_cache">是否清除所有的证书缓存?</string>
<string name="debug_level">Debug Level</string>
<string name="settings_debug">Debug Settings</string>
</resources>

View File

@ -19,7 +19,7 @@
add_subdirectory(common) add_subdirectory(common)
if(FREERDP_VENDOR) if(FREERDP_VENDOR AND WITH_CLIENT)
if(WIN32) if(WIN32)
add_subdirectory(Windows) add_subdirectory(Windows)
else() else()
@ -58,28 +58,28 @@ if(FREERDP_VENDOR)
endif() endif()
# Pick up other clients # Pick up other clients
if(WITH_CLIENT)
set(FILENAME "ModuleOptions.cmake")
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}")
set(FILENAME "ModuleOptions.cmake") foreach(FILEPATH ${FILEPATHS})
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}") if(${FILEPATH} MATCHES "^([^/]*)/+${FILENAME}")
string(REGEX REPLACE "^([^/]*)/+${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH})
foreach(FILEPATH ${FILEPATHS}) set(FREERDP_CLIENT_ENABLED 0)
if(${FILEPATH} MATCHES "^([^/]*)/+${FILENAME}") include(${FILEPATH})
string(REGEX REPLACE "^([^/]*)/+${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH}) if(FREERDP_CLIENT_ENABLED)
set(FREERDP_CLIENT_ENABLED 0) if(NOT (${FREERDP_CLIENT_VENDOR} MATCHES "FreeRDP"))
include(${FILEPATH}) list(APPEND FREERDP_EXTRA_CLIENTS ${FREERDP_CLIENT})
if(FREERDP_CLIENT_ENABLED) if(${FREERDP_CLIENT_VENDOR} MATCHES "${VENDOR}")
if(NOT (${FREERDP_CLIENT_VENDOR} MATCHES "FreeRDP")) set(CLIENT_VENDOR_PATH "client/${FREERDP_CLIENT}" PARENT_SCOPE)
list(APPEND FREERDP_EXTRA_CLIENTS ${FREERDP_CLIENT}) endif()
if(${FREERDP_CLIENT_VENDOR} MATCHES "${VENDOR}")
set(CLIENT_VENDOR_PATH "client/${FREERDP_CLIENT}" PARENT_SCOPE)
endif() endif()
endif() endif()
endif() endif()
endif() endforeach()
endforeach()
foreach(FREERDP_CLIENT ${FREERDP_EXTRA_CLIENTS})
add_subdirectory(${FREERDP_CLIENT})
endforeach()
foreach(FREERDP_CLIENT ${FREERDP_EXTRA_CLIENTS})
add_subdirectory(${FREERDP_CLIENT})
endforeach()
endif()

View File

@ -342,7 +342,7 @@ BOOL xf_sw_end_paint(rdpContext* context)
xf_lock_x11(xfc, FALSE); xf_lock_x11(xfc, FALSE);
xf_rail_paint(xfc, x, y, x + w - 1, y + h - 1); xf_rail_paint(xfc, x, y, x + w, y + h);
xf_unlock_x11(xfc, FALSE); xf_unlock_x11(xfc, FALSE);
} }
@ -455,7 +455,7 @@ BOOL xf_hw_end_paint(rdpContext* context)
xf_lock_x11(xfc, FALSE); xf_lock_x11(xfc, FALSE);
xf_rail_paint(xfc, x, y, x + w - 1, y + h - 1); xf_rail_paint(xfc, x, y, x + w, y + h);
xf_unlock_x11(xfc, FALSE); xf_unlock_x11(xfc, FALSE);
} }
@ -1852,7 +1852,11 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False); xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False);
xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False); xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, "_NET_WM_STATE_FULLSCREEN", False); xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, "_NET_WM_STATE_FULLSCREEN", False);
xfc->_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
xfc->_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display, "_NET_WM_FULLSCREEN_MONITORS", False); xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display, "_NET_WM_FULLSCREEN_MONITORS", False);
xfc->_NET_WM_NAME = XInternAtom(xfc->display, "_NET_WM_NAME", False);
xfc->_NET_WM_PID = XInternAtom(xfc->display, "_NET_WM_PID", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", False); xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", False);
xfc->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_NORMAL", False); xfc->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
xfc->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_DIALOG", False); xfc->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
@ -1863,6 +1867,8 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfc->display, "_NET_WM_STATE_SKIP_PAGER", False); xfc->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfc->display, "_NET_WM_STATE_SKIP_PAGER", False);
xfc->_NET_WM_MOVERESIZE = XInternAtom(xfc->display, "_NET_WM_MOVERESIZE", False); xfc->_NET_WM_MOVERESIZE = XInternAtom(xfc->display, "_NET_WM_MOVERESIZE", False);
xfc->_NET_MOVERESIZE_WINDOW = XInternAtom(xfc->display, "_NET_MOVERESIZE_WINDOW", False); xfc->_NET_MOVERESIZE_WINDOW = XInternAtom(xfc->display, "_NET_MOVERESIZE_WINDOW", False);
xfc->UTF8_STRING = XInternAtom(xfc->display, "UTF8_STRING", FALSE);
xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False); xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False);
xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False); xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False); xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);

View File

@ -466,7 +466,7 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
return TRUE; return TRUE;
} }
if(xfc->fullscreen_toggle) if(!xfc->remote_app && xfc->fullscreen_toggle)
{ {
if (keysym == XK_Return) if (keysym == XK_Return)
{ {

View File

@ -120,7 +120,6 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
int i; int i;
int nmonitors = 0; int nmonitors = 0;
int primaryMonitorFound = FALSE; int primaryMonitorFound = FALSE;
int vX, vY, vWidth, vHeight;
VIRTUAL_SCREEN* vscreen; VIRTUAL_SCREEN* vscreen;
rdpSettings* settings = xfc->settings; rdpSettings* settings = xfc->settings;
@ -270,10 +269,10 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
if (settings->MonitorCount) if (settings->MonitorCount)
{ {
/* Initialize bounding rectangle for all monitors */ /* Initialize bounding rectangle for all monitors */
vWidth = settings->MonitorDefArray[0].width; int vX = settings->MonitorDefArray[0].x;
vHeight = settings->MonitorDefArray[0].height; int vY = settings->MonitorDefArray[0].y;
vX = settings->MonitorDefArray[0].x; int vR = vX + settings->MonitorDefArray[0].width;
vY = settings->MonitorDefArray[0].y; int vB = vY + settings->MonitorDefArray[0].height;
xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = settings->MonitorDefArray[0].orig_screen; xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = settings->MonitorDefArray[0].orig_screen;
@ -285,36 +284,36 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
/* does the same as gdk_rectangle_union */ /* does the same as gdk_rectangle_union */
int destX = MIN(vX, settings->MonitorDefArray[i].x); int destX = MIN(vX, settings->MonitorDefArray[i].x);
int destY = MIN(vY, settings->MonitorDefArray[i].y); int destY = MIN(vY, settings->MonitorDefArray[i].y);
int destWidth = MAX(vX + vWidth, settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width) - destX; int destR = MAX(vR, settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width);
int destHeight = MAX(vY + vHeight, settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height) - destY; int destB = MAX(vB, settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height);
if (vX != destX) if (vX != destX)
xfc->fullscreenMonitors.left = settings->MonitorDefArray[i].orig_screen; xfc->fullscreenMonitors.left = settings->MonitorDefArray[i].orig_screen;
if (vY != destY) if (vY != destY)
xfc->fullscreenMonitors.top = settings->MonitorDefArray[i].orig_screen; xfc->fullscreenMonitors.top = settings->MonitorDefArray[i].orig_screen;
if (vWidth != destWidth) if (vR != destR)
xfc->fullscreenMonitors.right = settings->MonitorDefArray[i].orig_screen; xfc->fullscreenMonitors.right = settings->MonitorDefArray[i].orig_screen;
if (vHeight != destHeight) if (vB != destB)
xfc->fullscreenMonitors.bottom = settings->MonitorDefArray[i].orig_screen; xfc->fullscreenMonitors.bottom = settings->MonitorDefArray[i].orig_screen;
vX = destX; vX = destX;
vY = destY; vY = destY;
vWidth = destWidth; vR = destR;
vHeight = destHeight; vB = destB;
} }
settings->DesktopPosX = vX; settings->DesktopPosX = vX;
settings->DesktopPosY = vY; settings->DesktopPosY = vY;
vscreen->area.left = 0; vscreen->area.left = 0;
vscreen->area.right = vWidth - 1; vscreen->area.right = vR - vX - 1;
vscreen->area.top = 0; vscreen->area.top = 0;
vscreen->area.bottom = vHeight - 1; vscreen->area.bottom = vB - vY - 1;
if (settings->Workarea) if (settings->Workarea)
{ {
vscreen->area.top = xfc->workArea.y; vscreen->area.top = xfc->workArea.y;
vscreen->area.bottom = (vHeight - (vHeight - (xfc->workArea.height + xfc->workArea.y))) - 1; vscreen->area.bottom = xfc->workArea.height + xfc->workArea.y - 1;
} }
/* If there are multiple monitors and we have not selected a primary */ /* If there are multiple monitors and we have not selected a primary */

View File

@ -119,25 +119,17 @@ void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
return; return;
/* If current window position disagrees with RDP window position, send update to RDP server */ /* If current window position disagrees with RDP window position, send update to RDP server */
if (appWindow->x != (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) || if (appWindow->x != appWindow->windowOffsetX ||
appWindow->y != (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) || appWindow->y != appWindow->windowOffsetY ||
appWindow->width != appWindow->windowWidth || appWindow->width != appWindow->windowWidth ||
appWindow->height != appWindow->windowHeight) appWindow->height != appWindow->windowHeight)
{ {
/*
* windowOffset corresponds to the window location on the rail server
* but our local window is based uses a local offset since the windowOffset
* can be negative and but X does not support negative values. Not using an
* offset can result in blank areas for a maximized window
*/
windowMove.windowId = appWindow->windowId; windowMove.windowId = appWindow->windowId;
/* /*
* Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
* New position is based on: Current local rail window offset +
* Local offset correction(current correction value to translate the local window offset to the server rail window offset)
*/ */
windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; windowMove.left = appWindow->x;
windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.top = appWindow->y;
windowMove.right = windowMove.left + appWindow->width; windowMove.right = windowMove.left + appWindow->width;
windowMove.bottom = windowMove.top + appWindow->height; windowMove.bottom = windowMove.top + appWindow->height;
@ -163,12 +155,10 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
/* /*
* Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
* New position is based on: Current local rail window offset +
* Local offset correction(current correction value to translate the local window offset to the server rail window offset)
* *
*/ */
windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; windowMove.left = appWindow->x;
windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.top = appWindow->y;
windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */
windowMove.bottom = windowMove.top + appWindow->height; windowMove.bottom = windowMove.top + appWindow->height;
@ -180,8 +170,6 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
XQueryPointer(xfc->display, appWindow->handle, XQueryPointer(xfc->display, appWindow->handle,
&root_window, &child_window, &x, &y, &child_x, &child_y, &mask); &root_window, &child_window, &x, &y, &child_x, &child_y, &mask);
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
/* only send the mouse coordinates if not a keyboard move or size */ /* only send the mouse coordinates if not a keyboard move or size */
if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) && if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
(appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD)) (appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
@ -194,8 +182,8 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
* we can start to receive GDI orders for the new window dimensions before we * we can start to receive GDI orders for the new window dimensions before we
* receive the RAIL ORDER for the new window size. This avoids that race condition. * receive the RAIL ORDER for the new window size. This avoids that race condition.
*/ */
appWindow->windowOffsetX = windowMove.left; appWindow->windowOffsetX = appWindow->x;
appWindow->windowOffsetY = windowMove.top; appWindow->windowOffsetY = appWindow->y;
appWindow->windowWidth = appWindow->width; appWindow->windowWidth = appWindow->width;
appWindow->windowHeight = appWindow->height; appWindow->windowHeight = appWindow->height;
appWindow->local_move.state = LMS_TERMINATING; appWindow->local_move.state = LMS_TERMINATING;
@ -277,6 +265,7 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
xfAppWindow* appWindow = NULL; xfAppWindow* appWindow = NULL;
xfContext* xfc = (xfContext*) context; xfContext* xfc = (xfContext*) context;
UINT32 fieldFlags = orderInfo->fieldFlags; UINT32 fieldFlags = orderInfo->fieldFlags;
BOOL position_or_size_updated = FALSE;
if (fieldFlags & WINDOW_ORDER_STATE_NEW) if (fieldFlags & WINDOW_ORDER_STATE_NEW)
{ {
@ -296,9 +285,7 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
appWindow->width = appWindow->windowWidth = windowState->windowWidth; appWindow->width = appWindow->windowWidth = windowState->windowWidth;
appWindow->height = appWindow->windowHeight = windowState->windowHeight; appWindow->height = appWindow->windowHeight = windowState->windowHeight;
appWindow->localWindowOffsetCorrX = 0; /* Ensure window always gets a window title */
appWindow->localWindowOffsetCorrY = 0;
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
{ {
char* title = NULL; char* title = NULL;
@ -321,8 +308,6 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) appWindow); HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) appWindow);
xf_AppWindowInit(xfc, appWindow); xf_AppWindowInit(xfc, appWindow);
return TRUE;
} }
else else
{ {
@ -333,37 +318,31 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
if (!appWindow) if (!appWindow)
return FALSE; return FALSE;
/* Keep track of any position/size update so that we can force a refresh of the window */
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) ||
(fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) ||
(fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) ||
(fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) ||
(fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) ||
(fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY))
{
position_or_size_updated = TRUE;
}
/* Update Parameters */ /* Update Parameters */
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
{ {
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) appWindow->windowOffsetX = windowState->windowOffsetX;
{ appWindow->windowOffsetY = windowState->windowOffsetY;
appWindow->windowOffsetX = windowState->windowOffsetX; }
appWindow->windowOffsetY = windowState->windowOffsetY;
/* if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
* The rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, {
* but we can only send unsigned integers to the rail server. Therefore, we maintain a local offset. appWindow->windowWidth = windowState->windowWidth;
*/ appWindow->windowHeight = windowState->windowHeight;
if (appWindow->windowOffsetX < 0)
appWindow->localWindowOffsetCorrX = 0 - appWindow->windowOffsetX;
else
appWindow->localWindowOffsetCorrX = 0;
if (appWindow->windowOffsetY < 0)
appWindow->localWindowOffsetCorrY = 0 - appWindow->windowOffsetY;
else
appWindow->localWindowOffsetCorrY = 0;
}
if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
{
appWindow->windowWidth = windowState->windowWidth;
appWindow->windowHeight = windowState->windowHeight;
}
} }
if (fieldFlags & WINDOW_ORDER_FIELD_OWNER) if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
@ -479,41 +458,43 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
xf_SetWindowText(xfc, appWindow, appWindow->title); xf_SetWindowText(xfc, appWindow, appWindow->title);
} }
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || if (position_or_size_updated)
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
{ {
UINT32 visibilityRectsOffsetX = (appWindow->visibleOffsetX - (appWindow->clientOffsetX - appWindow->windowClientDeltaX));
UINT32 visibilityRectsOffsetY = (appWindow->visibleOffsetY - (appWindow->clientOffsetY - appWindow->windowClientDeltaY));
/* /*
* The rail server like to set the window to a small size when it is minimized even though it is hidden * The rail server like to set the window to a small size when it is minimized even though it is hidden
* in some cases this can cause the window not to restore back to its original size. Therefore we don't * in some cases this can cause the window not to restore back to its original size. Therefore we don't
* update our local window when that rail window state is minimized * update our local window when that rail window state is minimized
*/ */
if (appWindow->rail_state == WINDOW_SHOW_MINIMIZED) if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
return TRUE; {
/* Do nothing if window is already in the correct position */ /* Redraw window area if already in the correct position */
if (appWindow->x == (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) && if (appWindow->x == appWindow->windowOffsetX &&
appWindow->y == (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) && appWindow->y == appWindow->windowOffsetY &&
appWindow->width == appWindow->windowWidth && appWindow->width == appWindow->windowWidth &&
appWindow->height == appWindow->windowHeight) appWindow->height == appWindow->windowHeight)
{ {
xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight); xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight);
} }
else else
{ {
xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX, appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY, xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX, appWindow->windowOffsetY,
appWindow->windowWidth, appWindow->windowHeight); appWindow->windowWidth, appWindow->windowHeight);
}
xf_SetWindowVisibilityRects(xfc, appWindow, visibilityRectsOffsetX, visibilityRectsOffsetY, appWindow->visibilityRects, appWindow->numVisibilityRects);
} }
} }
if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) /* We should only be using the visibility rects for shaping the window */
/*if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
{ {
xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects); xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects);
} }*/
if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
{
xf_SetWindowVisibilityRects(xfc, appWindow, appWindow->visibilityRects, appWindow->numVisibilityRects);
}
return TRUE; return TRUE;
} }

View File

@ -185,30 +185,37 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
*/ */
startX = startX + xfc->instance->settings->MonitorLocalShiftX; startX = startX + xfc->instance->settings->MonitorLocalShiftX;
startY = startY + xfc->instance->settings->MonitorLocalShiftY; startY = startY + xfc->instance->settings->MonitorLocalShiftY;
/* Set monitor bounds */
if (settings->MonitorCount > 1)
{
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_FULLSCREEN_MONITORS, 5,
xfc->fullscreenMonitors.top,
xfc->fullscreenMonitors.bottom,
xfc->fullscreenMonitors.left,
xfc->fullscreenMonitors.right,
1);
}
} }
xf_ResizeDesktopWindow(xfc, window, width, height); xf_ResizeDesktopWindow(xfc, window, width, height);
if (fullscreen)
{
/* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */
XMoveWindow(xfc->display, window->handle, startX, startY);
}
/* Set the fullscreen state */ /* Set the fullscreen state */
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4,
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
xfc->_NET_WM_STATE_FULLSCREEN, 0, 0); xfc->_NET_WM_STATE_FULLSCREEN, 0, 0);
/* Only send monitor bounds if they are valid */ if (!fullscreen)
if ((xfc->fullscreenMonitors.top >= 0) &&
(xfc->fullscreenMonitors.bottom >= 0) &&
(xfc->fullscreenMonitors.left >= 0) &&
(xfc->fullscreenMonitors.right >= 0))
{ {
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_FULLSCREEN_MONITORS, 5, /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */
xfc->fullscreenMonitors.top, XMoveWindow(xfc->display, window->handle, startX, startY);
xfc->fullscreenMonitors.bottom,
xfc->fullscreenMonitors.left,
xfc->fullscreenMonitors.right,
1);
} }
XMoveWindow(xfc->display, window->handle, startX, startY);
} }
/* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */ /* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */
@ -327,7 +334,7 @@ static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid)
if (!pid) if (!pid)
pid = getpid(); pid = getpid();
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False); am_wm_pid = xfc->_NET_WM_PID;
XChangeProperty(xfc->display, window, am_wm_pid, XA_CARDINAL, XChangeProperty(xfc->display, window, am_wm_pid, XA_CARDINAL,
32, PropModeReplace, (BYTE*) &pid, 1); 32, PropModeReplace, (BYTE*) &pid, 1);
@ -567,9 +574,11 @@ void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UIN
} }
else else
{ {
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE, window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
} }
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
} }
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name) void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
@ -577,8 +586,8 @@ void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
const size_t i = strlen(name); const size_t i = strlen(name);
XStoreName(xfc->display, appWindow->handle, name); XStoreName(xfc->display, appWindow->handle, name);
Atom wm_Name = XInternAtom(xfc->display, "_NET_WM_NAME", FALSE); Atom wm_Name = xfc->_NET_WM_NAME;
Atom utf8Str = XInternAtom(xfc->display, "UTF8_STRING", FALSE); Atom utf8Str = xfc->UTF8_STRING;
XChangeProperty(xfc->display, appWindow->handle, wm_Name, utf8Str, 8, XChangeProperty(xfc->display, appWindow->handle, wm_Name, utf8Str, 8,
PropModeReplace, (unsigned char *)name, i); PropModeReplace, (unsigned char *)name, i);
@ -821,9 +830,10 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
case WINDOW_SHOW_MAXIMIZED: case WINDOW_SHOW_MAXIMIZED:
/* Set the window as maximized */ /* Set the window as maximized */
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 1, xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False), _NET_WM_STATE_ADD,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0); xfc->_NET_WM_STATE_MAXIMIZED_VERT,
xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0);
/* /*
* This is a workaround for the case where the window is maximized locally before the rail server is told to maximize * This is a workaround for the case where the window is maximized locally before the rail server is told to maximize
* the window, this appears to be a race condition where the local window with incomplete data and once the window is * the window, this appears to be a race condition where the local window with incomplete data and once the window is
@ -838,9 +848,10 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
case WINDOW_SHOW: case WINDOW_SHOW:
/* Ensure the window is not maximized */ /* Ensure the window is not maximized */
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 0, xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False), _NET_WM_STATE_REMOVE,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0); xfc->_NET_WM_STATE_MAXIMIZED_VERT,
xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0);
/* /*
* Ignore configure requests until both the Maximized properties have been processed * Ignore configure requests until both the Maximized properties have been processed
* to prevent condition where WM overrides size of request due to one or both of these properties * to prevent condition where WM overrides size of request due to one or both of these properties
@ -923,7 +934,7 @@ void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rec
} }
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects) void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX, UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects)
{ {
int i; int i;
XRectangle* xrects; XRectangle* xrects;
@ -942,7 +953,7 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG
xrects[i].height = rects[i].bottom - rects[i].top; xrects[i].height = rects[i].bottom - rects[i].top;
} }
XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0); XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, rectsOffsetX, rectsOffsetY, xrects, nrects, ShapeSet, 0);
free(xrects); free(xrects);
#endif #endif
@ -951,20 +962,14 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height) void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
{ {
int ax, ay; int ax, ay;
UINT32 translatedWindowOffsetX;
UINT32 translatedWindowOffsetY;
/* Translate the server rail window offset to a local offset */ ax = x + appWindow->windowOffsetX;
translatedWindowOffsetX = (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX); ay = y + appWindow->windowOffsetY;
translatedWindowOffsetY = (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY);
ax = x + translatedWindowOffsetX; if (ax + width > appWindow->windowOffsetX + appWindow->width)
ay = y + translatedWindowOffsetY; width = (appWindow->windowOffsetX + appWindow->width - 1) - ax;
if (ay + height > appWindow->windowOffsetY + appWindow->height)
if (ax + width > translatedWindowOffsetX + appWindow->width) height = (appWindow->windowOffsetY + appWindow->height - 1) - ay;
width = (translatedWindowOffsetX + appWindow->width - 1) - ax;
if (ay + height > translatedWindowOffsetY + appWindow->height)
height = (translatedWindowOffsetY + appWindow->height - 1) - ay;
xf_lock_x11(xfc, TRUE); xf_lock_x11(xfc, TRUE);

View File

@ -102,22 +102,22 @@ struct xf_app_window
UINT32 dwExStyle; UINT32 dwExStyle;
UINT32 showState; UINT32 showState;
UINT32 clientOffsetX; INT32 clientOffsetX;
UINT32 clientOffsetY; INT32 clientOffsetY;
UINT32 clientAreaWidth; UINT32 clientAreaWidth;
UINT32 clientAreaHeight; UINT32 clientAreaHeight;
UINT32 windowOffsetX; INT32 windowOffsetX;
UINT32 windowOffsetY; INT32 windowOffsetY;
UINT32 windowClientDeltaX; INT32 windowClientDeltaX;
UINT32 windowClientDeltaY; INT32 windowClientDeltaY;
UINT32 windowWidth; UINT32 windowWidth;
UINT32 windowHeight; UINT32 windowHeight;
UINT32 numWindowRects; UINT32 numWindowRects;
RECTANGLE_16* windowRects; RECTANGLE_16* windowRects;
UINT32 visibleOffsetX; INT32 visibleOffsetX;
UINT32 visibleOffsetY; INT32 visibleOffsetY;
UINT32 numVisibilityRects; UINT32 numVisibilityRects;
RECTANGLE_16* visibilityRects; RECTANGLE_16* visibilityRects;
@ -160,7 +160,7 @@ void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int wid
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state); void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state);
//void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon); //void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon);
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects); void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects); void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX, UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style); void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height); void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow); void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);

View File

@ -185,6 +185,8 @@ struct xf_context
xfClipboard* clipboard; xfClipboard* clipboard;
CliprdrClientContext* cliprdr; CliprdrClientContext* cliprdr;
Atom UTF8_STRING;
Atom _NET_WM_ICON; Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS; Atom _MOTIF_WM_HINTS;
Atom _NET_CURRENT_DESKTOP; Atom _NET_CURRENT_DESKTOP;
@ -192,11 +194,16 @@ struct xf_context
Atom _NET_WM_STATE; Atom _NET_WM_STATE;
Atom _NET_WM_STATE_FULLSCREEN; Atom _NET_WM_STATE_FULLSCREEN;
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_SKIP_TASKBAR; Atom _NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER; Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_FULLSCREEN_MONITORS; Atom _NET_WM_FULLSCREEN_MONITORS;
Atom _NET_WM_NAME;
Atom _NET_WM_PID;
Atom _NET_WM_WINDOW_TYPE; Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL; Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_WINDOW_TYPE_DIALOG; Atom _NET_WM_WINDOW_TYPE_DIALOG;

View File

@ -60,16 +60,17 @@ CMAKE_DEPENDENT_OPTION(TESTS_WTSAPI_EXTRA "Build extra WTSAPI tests (interactive
option(WITH_SAMPLE "Build sample code" OFF) option(WITH_SAMPLE "Build sample code" OFF)
option(WITH_CLIENT "Build client binaries" ON) option(WITH_CLIENT_COMMON "Build client common library" ON)
cmake_dependent_option(WITH_CLIENT "Build client binaries" ON WITH_CLIENT_COMMON ON)
option(WITH_SERVER "Build server binaries" OFF) option(WITH_SERVER "Build server binaries" OFF)
option(STATIC_CHANNELS "Build channels statically" ON) option(STATIC_CHANNELS "Build channels statically" ON)
option(WITH_CHANNELS "Build virtual channel plugins" ON) option(WITH_CHANNELS "Build virtual channel plugins" ON)
if(WITH_CLIENT AND WITH_CHANNELS) cmake_dependent_option(WITH_CLIENT_CHANNELS "Build virtual channel plugins" ON
option(WITH_CLIENT_CHANNELS "Build virtual channel plugins" ON) "WITH_CLIENT_COMMON;WITH_CHANNELS" ON)
endif()
if(WITH_SERVER AND WITH_CHANNELS) if(WITH_SERVER AND WITH_CHANNELS)
option(WITH_SERVER_CHANNELS "Build virtual channel plugins" ON) option(WITH_SERVER_CHANNELS "Build virtual channel plugins" ON)

View File

@ -174,22 +174,22 @@ struct _WINDOW_STATE_ORDER
UINT32 extendedStyle; UINT32 extendedStyle;
UINT32 showState; UINT32 showState;
RAIL_UNICODE_STRING titleInfo; RAIL_UNICODE_STRING titleInfo;
UINT32 clientOffsetX; INT32 clientOffsetX;
UINT32 clientOffsetY; INT32 clientOffsetY;
UINT32 clientAreaWidth; UINT32 clientAreaWidth;
UINT32 clientAreaHeight; UINT32 clientAreaHeight;
UINT32 RPContent; UINT32 RPContent;
UINT32 rootParentHandle; UINT32 rootParentHandle;
UINT32 windowOffsetX; INT32 windowOffsetX;
UINT32 windowOffsetY; INT32 windowOffsetY;
UINT32 windowClientDeltaX; INT32 windowClientDeltaX;
UINT32 windowClientDeltaY; INT32 windowClientDeltaY;
UINT32 windowWidth; UINT32 windowWidth;
UINT32 windowHeight; UINT32 windowHeight;
UINT32 numWindowRects; UINT32 numWindowRects;
RECTANGLE_16* windowRects; RECTANGLE_16* windowRects;
UINT32 visibleOffsetX; INT32 visibleOffsetX;
UINT32 visibleOffsetY; INT32 visibleOffsetY;
UINT32 numVisibilityRects; UINT32 numVisibilityRects;
RECTANGLE_16* visibilityRects; RECTANGLE_16* visibilityRects;
}; };

View File

@ -260,6 +260,12 @@ BOOL update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fastIndex)
if (opRight == 0) if (opRight == 0)
opRight = fastIndex->bkRight; opRight = fastIndex->bkRight;
/* Server can send a massive number (32766) which appears to be
* undocumented special behavior for "Erase all the way right".
* X11 has nondeterministic results asking for a draw that wide. */
if (opRight > context->instance->settings->DesktopWidth)
opRight = context->instance->settings->DesktopWidth;
if (x == -32768) if (x == -32768)
x = fastIndex->bkLeft; x = fastIndex->bkLeft;
@ -313,6 +319,10 @@ BOOL update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fastGlyph)
if (opRight == 0) if (opRight == 0)
opRight = fastGlyph->bkRight; opRight = fastGlyph->bkRight;
/* See update_gdi_fast_index opRight comment. */
if (opRight > context->instance->settings->DesktopWidth)
opRight = context->instance->settings->DesktopWidth;
if (x == -32768) if (x == -32768)
x = fastGlyph->bkLeft; x = fastGlyph->bkLeft;

View File

@ -3444,8 +3444,8 @@ int freerdp_image32_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDs
pSrcPixel++; pSrcPixel++;
} }
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcStep]; pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcPad];
pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[nDstStep]; pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[nDstPad];
} }
return 1; return 1;

View File

@ -32,6 +32,7 @@ extern "C" {
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/thread.h> #include <winpr/thread.h>
#include <winpr/winsock.h>
typedef struct _wLog wLog; typedef struct _wLog wLog;
typedef struct _wLogMessage wLogMessage; typedef struct _wLogMessage wLogMessage;
@ -115,6 +116,7 @@ struct _wLogLayout
#define WLOG_APPENDER_CALLBACK 3 #define WLOG_APPENDER_CALLBACK 3
#define WLOG_APPENDER_SYSLOG 4 #define WLOG_APPENDER_SYSLOG 4
#define WLOG_APPENDER_JOURNALD 5 #define WLOG_APPENDER_JOURNALD 5
#define WLOG_APPENDER_UDP 6
#define WLOG_PACKET_INBOUND 1 #define WLOG_PACKET_INBOUND 1
#define WLOG_PACKET_OUTBOUND 2 #define WLOG_PACKET_OUTBOUND 2
@ -213,6 +215,16 @@ struct _wLogJournaldAppender
}; };
typedef struct _wLogJournaldAppender wLogJournaldAppender; typedef struct _wLogJournaldAppender wLogJournaldAppender;
struct _wLogUdpAppender
{
WLOG_APPENDER_COMMON();
char *host;
struct sockaddr targetAddr;
int targetAddrLen;
SOCKET sock;
};
typedef struct _wLogUdpAppender wLogUdpAppender;
/** /**
* Filter * Filter

View File

@ -596,13 +596,13 @@ HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath)
BOOL PathCchIsRootA(PCSTR pszPath) BOOL PathCchIsRootA(PCSTR pszPath)
{ {
WLog_ERR(TAG, "%s: not implemented", __FUNCTION__); WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
return E_NOTIMPL; return FALSE;
} }
BOOL PathCchIsRootW(PCWSTR pszPath) BOOL PathCchIsRootW(PCWSTR pszPath)
{ {
WLog_ERR(TAG, "%s: not implemented", __FUNCTION__); WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
return E_NOTIMPL; return FALSE;
} }
/** /**

View File

@ -101,7 +101,6 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
LPSTR* pArgs; LPSTR* pArgs;
int maxNumArgs; int maxNumArgs;
int maxBufferSize; int maxBufferSize;
int currentIndex;
int cmdLineLength; int cmdLineLength;
BOOL* lpEscapedChars; BOOL* lpEscapedChars;
LPSTR lpEscapedCmdLine; LPSTR lpEscapedCmdLine;
@ -167,36 +166,29 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
p += length; p += length;
for (i = 0; i < (n / 2); i++) for (i = 0; i < (n / 2); i++)
{ *pOutput++ = '\\';
*pOutput = '\\';
pOutput++;
}
p += n + 1; p += n + 1;
if ((n % 2) != 0) if ((n % 2) != 0)
lpEscapedChars[pOutput - lpEscapedCmdLine] = TRUE; lpEscapedChars[pOutput - lpEscapedCmdLine] = TRUE;
*pOutput = '"'; *pOutput++ = '"';
pOutput++;
pLastEnd = p; pLastEnd = p;
} }
*pOutput = '\0'; *pOutput++ = '\0';
pOutput++;
lpCmdLine = (LPCSTR) lpEscapedCmdLine; lpCmdLine = (LPCSTR) lpEscapedCmdLine;
cmdLineLength = strlen(lpCmdLine); cmdLineLength = strlen(lpCmdLine);
} }
maxNumArgs = 2; maxNumArgs = 2;
currentIndex = 0;
p = (char*) lpCmdLine; p = (char*) lpCmdLine;
while (currentIndex < cmdLineLength - 1) while (p < lpCmdLine + cmdLineLength)
{ {
index = strcspn(p, " \t"); p += strcspn(p, " \t");
currentIndex += (index + 1); p += strspn(p, " \t");
p = (char*) &lpCmdLine[currentIndex];
maxNumArgs++; maxNumArgs++;
} }
@ -209,32 +201,24 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
pArgs = (LPSTR*) buffer; pArgs = (LPSTR*) buffer;
pOutput = (char*) &buffer[maxNumArgs * (sizeof(char*))]; pOutput = (char*) &buffer[maxNumArgs * (sizeof(char*))];
numArgs = 0; numArgs = 0;
currentIndex = 0;
p = (char*) lpCmdLine; p = (char*) lpCmdLine;
while (currentIndex < cmdLineLength) while (p < lpCmdLine + cmdLineLength)
{ {
pBeg = pEnd = p; pBeg = p;
while (1) while (1)
{ {
index = strcspn(p, " \t\"\0"); p += strcspn(p, " \t\"\0");
if ((*p != '"') || !lpEscapedChars[p - lpCmdLine])
if ((p[index] == '"') && (lpEscapedChars[&p[index] - lpCmdLine])) break;
{ p++;
p = &p[index + 1];
continue;
}
break;
} }
if (p[index] != '"') if (*p != '"')
{ {
/* no whitespace escaped with double quotes */ /* no whitespace escaped with double quotes */
p = &p[index + 1]; length = p - pBeg;
pEnd = p - 1;
length = (pEnd - pBeg);
CopyMemory(pOutput, pBeg, length); CopyMemory(pOutput, pBeg, length);
pOutput[length] = '\0'; pOutput[length] = '\0';
pArgs[numArgs++] = pOutput; pArgs[numArgs++] = pOutput;
@ -242,62 +226,35 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
} }
else else
{ {
p = &p[index + 1]; p++;
while (1) while (1)
{ {
index = strcspn(p, "\"\0"); p += strcspn(p, "\"\0");
if ((*p != '"') || !lpEscapedChars[p - lpCmdLine])
if ((p[index] == '"') && (lpEscapedChars[&p[index] - lpCmdLine])) break;
{ p++;
p = &p[index + 1];
continue;
}
break;
} }
if (p[index] != '"') if (*p != '"')
{
WLog_ERR(TAG, "parsing error: uneven number of unescaped double quotes!"); WLog_ERR(TAG, "parsing error: uneven number of unescaped double quotes!");
}
if (p[index] == '\0') if (*p && *(++p))
{ p += strcspn(p, " \t\0");
p = &p[index + 1];
pEnd = p - 1;
}
else
{
p = &p[index + 1];
index = strcspn(p, " \t\0");
p = &p[index + 1];
pEnd = p - 1;
}
length = 0;
pArgs[numArgs++] = pOutput; pArgs[numArgs++] = pOutput;
while (pBeg < pEnd) while (pBeg < p)
{ {
if (*pBeg != '"') if (*pBeg != '"')
{ *pOutput++ = *pBeg;
*pOutput = *pBeg;
pOutput++;
length++;
}
pBeg++; pBeg++;
} }
*pOutput = '\0'; *pOutput++ = '\0';
pOutput++;
} }
while ((*p == ' ') || (*p == '\t')) p += strspn(p, " \t");
p++;
currentIndex = (p - lpCmdLine);
} }
free(lpEscapedCmdLine); free(lpEscapedCmdLine);

View File

@ -94,6 +94,8 @@ set(${MODULE_PREFIX}_WLOG_SRCS
wlog/CallbackAppender.h wlog/CallbackAppender.h
wlog/ConsoleAppender.c wlog/ConsoleAppender.c
wlog/ConsoleAppender.h wlog/ConsoleAppender.h
wlog/UdpAppender.c
wlog/UdpAppender.h
${SYSLOG_SRCS} ${SYSLOG_SRCS}
${JOURNALD_SRCS} ${JOURNALD_SRCS}
) )

View File

@ -58,6 +58,9 @@ wLogAppender* WLog_Appender_New(wLog* log, DWORD logAppenderType)
appender = (wLogAppender*) WLog_JournaldAppender_New(log); appender = (wLogAppender*) WLog_JournaldAppender_New(log);
break; break;
#endif #endif
case WLOG_APPENDER_UDP:
appender = (wLogAppender*) WLog_UdpAppender_New(log);
break;
default: default:
fprintf(stderr, "%s: unknown handler type %d\n", __FUNCTION__, logAppenderType); fprintf(stderr, "%s: unknown handler type %d\n", __FUNCTION__, logAppenderType);
appender = NULL; appender = NULL;
@ -118,6 +121,9 @@ void WLog_Appender_Free(wLog* log, wLogAppender* appender)
WLog_JournaldAppender_Free(log, (wLogJournaldAppender *) appender); WLog_JournaldAppender_Free(log, (wLogJournaldAppender *) appender);
break; break;
#endif #endif
case WLOG_APPENDER_UDP:
WLog_UdpAppender_Free(log, (wLogUdpAppender *) appender);
break;
default: default:
fprintf(stderr, "%s: don't know how to free appender type %d\n", __FUNCTION__, appender->Type); fprintf(stderr, "%s: don't know how to free appender type %d\n", __FUNCTION__, appender->Type);
break; break;

View File

@ -26,6 +26,7 @@
#include "wlog/BinaryAppender.h" #include "wlog/BinaryAppender.h"
#include "wlog/ConsoleAppender.h" #include "wlog/ConsoleAppender.h"
#include "wlog/CallbackAppender.h" #include "wlog/CallbackAppender.h"
#include "wlog/UdpAppender.h"
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
#include "wlog/SyslogAppender.h" #include "wlog/SyslogAppender.h"

View File

@ -0,0 +1,209 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/environment.h>
#include <winpr/thread.h>
#include <winpr/wlog.h>
#include "wlog/Message.h"
#include "wlog/UdpAppender.h"
#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
static BOOL WLog_UdpAppender_Open(wLog* log, wLogUdpAppender* appender)
{
char addressString[256];
struct addrinfo hints;
struct addrinfo* result;
int status, addrLen;
char *colonPos;
if (!appender)
return FALSE;
if (appender->targetAddrLen) /* already opened */
return TRUE;
colonPos = strchr(appender->host, ':');
if (!colonPos)
return FALSE;
addrLen = colonPos - appender->host;
memcpy(addressString, appender->host, addrLen);
addressString[addrLen] = '\0';
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
status = getaddrinfo(addressString, colonPos+1, &hints, &result);
if (status != 0)
return FALSE;
if (result->ai_addrlen > sizeof(appender->targetAddr))
{
freeaddrinfo(result);
return FALSE;
}
memcpy(&appender->targetAddr, result->ai_addr, result->ai_addrlen);
appender->targetAddrLen = result->ai_addrlen;
return TRUE;
}
BOOL Wlog_UdpAppender_SetTarget(wLogUdpAppender* appender, const char *host)
{
appender->targetAddrLen = 0;
if (appender->host)
free(appender->host);
appender->host = _strdup(host);
return (appender->host != NULL) && WLog_UdpAppender_Open(NULL, appender);
}
static BOOL WLog_UdpAppender_Close(wLog* log, wLogUdpAppender* appender)
{
if (!log || !appender)
return FALSE;
return TRUE;
}
static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogUdpAppender* appender, wLogMessage* message)
{
char prefix[WLOG_MAX_PREFIX_SIZE];
if (!log || !appender || !message)
return FALSE;
message->PrefixString = prefix;
WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
_sendto(appender->sock, message->PrefixString, strlen(message->PrefixString),
0, &appender->targetAddr, appender->targetAddrLen);
_sendto(appender->sock, message->TextString, strlen(message->TextString),
0, &appender->targetAddr, appender->targetAddrLen);
_sendto(appender->sock, "\n", 1, 0, &appender->targetAddr, appender->targetAddrLen);
return TRUE;
}
static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogUdpAppender* appender, wLogMessage* message)
{
if (!log || !appender || !message)
return FALSE;
return TRUE;
}
static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogUdpAppender* appender, wLogMessage* message)
{
if (!log || !appender || !message)
return FALSE;
return TRUE;
}
wLogUdpAppender* WLog_UdpAppender_New(wLog* log)
{
wLogUdpAppender* appender;
DWORD nSize;
LPCSTR name;
appender = (wLogUdpAppender*) calloc(1, sizeof(wLogUdpAppender));
if (!appender)
return NULL;
appender->Type = WLOG_APPENDER_UDP;
appender->Open = (WLOG_APPENDER_OPEN_FN) WLog_UdpAppender_Open;
appender->Close = (WLOG_APPENDER_OPEN_FN) WLog_UdpAppender_Close;
appender->WriteMessage =
(WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_UdpAppender_WriteMessage;
appender->WriteDataMessage =
(WLOG_APPENDER_WRITE_DATA_MESSAGE_FN) WLog_UdpAppender_WriteDataMessage;
appender->WriteImageMessage =
(WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN) WLog_UdpAppender_WriteImageMessage;
appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (appender->sock == INVALID_SOCKET)
goto error_sock;
name = "WLOG_UDP_TARGET";
nSize = GetEnvironmentVariableA(name, NULL, 0);
if (nSize)
{
appender->host = (LPSTR) malloc(nSize);
if (!appender->host)
goto error_host_alloc;
GetEnvironmentVariableA(name, appender->host, nSize);
if (!WLog_UdpAppender_Open(log, appender))
goto error_open;
}
else
{
appender->host = _strdup("127.0.0.1:20000");
if (!appender->host)
goto error_host_alloc;
}
return appender;
error_open:
free(appender->host);
error_host_alloc:
closesocket(appender->sock);
error_sock:
free(appender);
return NULL;
}
void WLog_UdpAppender_Free(wLog* log, wLogUdpAppender* appender)
{
if (appender)
{
if (appender->sock != INVALID_SOCKET)
{
closesocket(appender->sock);
appender->sock = INVALID_SOCKET;
}
free(appender->host);
free(appender);
}
}

View File

@ -0,0 +1,35 @@
/**
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_
#define WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_
#include <winpr/wlog.h>
#include "wlog/wlog.h"
WINPR_API wLogUdpAppender* WLog_UdpAppender_New(wLog* log);
WINPR_API void WLog_UdpAppender_Free(wLog* log, wLogUdpAppender* appender);
WINPR_API BOOL Wlog_UdpAppender_SetTarget(wLogUdpAppender* appender, const char *host);
#endif /* WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_ */

View File

@ -706,6 +706,8 @@ wLog* WLog_GetRoot()
else if (_stricmp(env, "JOURNALD") == 0) else if (_stricmp(env, "JOURNALD") == 0)
logAppenderType = WLOG_APPENDER_JOURNALD; logAppenderType = WLOG_APPENDER_JOURNALD;
#endif #endif
else if (_stricmp(env, "UDP") == 0)
logAppenderType = WLOG_APPENDER_UDP;
free(env); free(env);
} }