11#include <freerdp/config.h>
17#include <freerdp/client/rail.h>
18#include <freerdp/settings.h>
19#include <freerdp/window.h>
21#include "android_jni_callback.h"
22#include "android_rail.h"
24#define TAG CLIENT_TAG("android.rail")
26static BOOL android_rail_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
29 if (!context || !orderInfo)
32 const UINT32 flags = orderInfo->fieldFlags;
34 if (flags & WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED)
37 if (afc->rail && !afc->railExecSent)
43 afc->railExecSent = TRUE;
44 WLog_DBG(TAG,
"RAIL ARC_COMPLETED -> sending exec");
45 UINT rc = client_rail_server_start_cmd(afc->rail);
46 if (rc != CHANNEL_RC_OK)
48 afc->railExecSent = FALSE;
49 WLog_ERR(TAG,
"RAIL start cmd failed after ARC_COMPLETED: %u", rc);
56 const BOOL hasZOrder = (flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) && monitoredDesktop &&
57 monitoredDesktop->numWindowIds > 0 && monitoredDesktop->windowIds;
58 const BOOL hasActive = (flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) && monitoredDesktop;
60 if (hasZOrder || hasActive)
63 jboolean attached = jni_attach_thread(&env);
66 jlongArray arr = NULL;
69 const jsize n = (jsize)monitoredDesktop->numWindowIds;
70 arr = (*env)->NewLongArray(env, n);
73 jlong* tmp = (*env)->GetLongArrayElements(env, arr, NULL);
76 for (jsize i = 0; i < n; i++)
77 tmp[i] = (jlong)monitoredDesktop->windowIds[i];
78 (*env)->ReleaseLongArrayElements(env, arr, tmp, 0);
82 const jlong activeWindowId = hasActive ? (jlong)monitoredDesktop->activeWindowId : 0;
83 freerdp_callback(
"OnRailMonitoredDesktop",
"(J[JJ)V", (jlong)context->instance, arr,
86 (*env)->DeleteLocalRef(env, arr);
95static UINT android_rail_server_system_param(RailClientContext* rail,
98 if (!rail || !sysparam)
99 return ERROR_INVALID_PARAMETER;
101 return CHANNEL_RC_OK;
104static UINT android_rail_server_execute_result(RailClientContext* rail,
107 if (!rail || !execResult)
108 return ERROR_INVALID_PARAMETER;
110 if (execResult->execResult != 0)
111 WLog_ERR(TAG,
"RAIL execute failed: execResult=0x%04X rawResult=0x%08X",
112 execResult->execResult, execResult->rawResult);
114 WLog_DBG(TAG,
"RAIL execute success");
116 return CHANNEL_RC_OK;
119static UINT android_rail_server_local_move_size(RailClientContext* rail,
122 if (!rail || !localMoveSize)
123 return ERROR_INVALID_PARAMETER;
125 WLog_DBG(TAG,
"RAIL window 0x%08X %s pos=(%d,%d)", localMoveSize->windowId,
126 localMoveSize->isMoveSizeStart ?
"move/size start" :
"move/size end",
127 localMoveSize->posX, localMoveSize->posY);
129 if (!localMoveSize->isMoveSizeStart)
132 rdpContext* context = (rdpContext*)afc;
133 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
134 (jlong)localMoveSize->windowId, (jint)localMoveSize->posX,
135 (jint)localMoveSize->posY, (jint)-1, (jint)-1);
137 return CHANNEL_RC_OK;
140static UINT android_rail_server_min_max_info(RailClientContext* rail,
143 if (!rail || !minMaxInfo)
144 return ERROR_INVALID_PARAMETER;
146 return CHANNEL_RC_OK;
149static UINT android_rail_server_z_order_sync(RailClientContext* rail,
152 if (!rail || !zOrderSync)
153 return ERROR_INVALID_PARAMETER;
155 return CHANNEL_RC_OK;
158static UINT android_rail_server_cloak(RailClientContext* rail,
const RAIL_CLOAK* cloak)
161 return ERROR_INVALID_PARAMETER;
163 WLog_DBG(TAG,
"RAIL window 0x%08X %s", cloak->windowId, cloak->cloak ?
"cloaked" :
"uncloaked");
164 return CHANNEL_RC_OK;
167static UINT android_rail_server_language_bar_info(RailClientContext* rail,
170 if (!rail || !langBarInfo)
171 return ERROR_INVALID_PARAMETER;
173 return CHANNEL_RC_OK;
176static UINT android_rail_server_get_appid_response(RailClientContext* rail,
179 if (!rail || !getAppIdResp)
180 return ERROR_INVALID_PARAMETER;
182 return CHANNEL_RC_OK;
185static BOOL android_rail_non_monitored_desktop(rdpContext* context,
191 freerdp_callback(
"OnRailSessionEnd",
"(J)V", (jlong)context->instance);
195static BOOL android_rail_window_state(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
198 if (!context || !orderInfo || !windowState)
201 const UINT32 flags = orderInfo->fieldFlags;
202 const BOOL isNew = (flags & WINDOW_ORDER_STATE_NEW) != 0;
203 const BOOL isHidden =
204 (flags & WINDOW_ORDER_FIELD_SHOW) && windowState->showState == WINDOW_HIDE;
208 freerdp_callback(
"OnRailWindowHide",
"(JJ)V", (jlong)context->instance,
209 (jlong)orderInfo->windowId);
213 const BOOL isShownAgain = !isNew && (flags & WINDOW_ORDER_FIELD_SHOW) && !isHidden &&
214 !(flags & WINDOW_ORDER_FIELD_WND_OFFSET);
217 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
218 (jlong)orderInfo->windowId, (jint)-1, (jint)-1, (jint)-1, (jint)-1);
224 const BOOL hasOffset = (flags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0;
225 const BOOL hasOffsetAndSize = hasOffset && (flags & WINDOW_ORDER_FIELD_WND_SIZE) != 0;
226 const INT32 x = hasOffset ? windowState->windowOffsetX : 0;
227 const INT32 y = hasOffset ? windowState->windowOffsetY : 0;
228 const INT32 w = hasOffsetAndSize ? (INT32)windowState->windowWidth : -1;
229 const INT32 h = hasOffsetAndSize ? (INT32)windowState->windowHeight : -1;
230 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
231 (jlong)orderInfo->windowId, (jint)x, (jint)y, (jint)w, (jint)h);
233 else if (flags & WINDOW_ORDER_FIELD_WND_OFFSET)
235 const BOOL hasSize = (flags & WINDOW_ORDER_FIELD_WND_SIZE) != 0;
236 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
237 (jlong)orderInfo->windowId, (jint)windowState->windowOffsetX,
238 (jint)windowState->windowOffsetY,
239 hasSize ? (jint)windowState->windowWidth : (jint)-1,
240 hasSize ? (jint)windowState->windowHeight : (jint)-1);
245static BOOL android_rail_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
247 if (!context || !orderInfo)
250 freerdp_callback(
"OnRailWindowDestroy",
"(JJ)V", (jlong)context->instance,
251 (jlong)orderInfo->windowId);
255BOOL android_rail_init(
androidContext* afc, RailClientContext* rail)
261 afc->railExecSent = FALSE;
262 rail->custom = (
void*)afc;
263 rail->ServerSystemParam = android_rail_server_system_param;
264 rail->ServerExecuteResult = android_rail_server_execute_result;
265 rail->ServerLocalMoveSize = android_rail_server_local_move_size;
266 rail->ServerMinMaxInfo = android_rail_server_min_max_info;
267 rail->ServerZOrderSync = android_rail_server_z_order_sync;
268 rail->ServerCloak = android_rail_server_cloak;
269 rail->ServerLanguageBarInfo = android_rail_server_language_bar_info;
270 rail->ServerGetAppIdResponse = android_rail_server_get_appid_response;
272 rdpContext* context = (rdpContext*)afc;
273 context->update->window->MonitoredDesktop = android_rail_monitored_desktop;
274 context->update->window->NonMonitoredDesktop = android_rail_non_monitored_desktop;
275 context->update->window->WindowCreate = android_rail_window_state;
276 context->update->window->WindowUpdate = android_rail_window_state;
277 context->update->window->WindowDelete = android_rail_window_delete;
281BOOL android_rail_uninit(
androidContext* afc, RailClientContext* rail)
288 afc->railExecSent = FALSE;
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.