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);
57 const BOOL hasZOrder = (flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) && monitoredDesktop &&
58 monitoredDesktop->numWindowIds > 0 && monitoredDesktop->windowIds;
59 const BOOL hasActive = (flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) && monitoredDesktop;
61 if (hasZOrder || hasActive)
63 JNIEnv* env =
nullptr;
64 jboolean attached = jni_attach_thread(&env);
67 jlongArray arr =
nullptr;
70 const jsize n = (jsize)monitoredDesktop->numWindowIds;
71 arr = (*env)->NewLongArray(env, n);
74 jlong* tmp = (*env)->GetLongArrayElements(env, arr,
nullptr);
77 for (jsize i = 0; i < n; i++)
78 tmp[i] = (jlong)monitoredDesktop->windowIds[i];
79 (*env)->ReleaseLongArrayElements(env, arr, tmp, 0);
83 const jlong activeWindowId = hasActive ? (jlong)monitoredDesktop->activeWindowId : 0;
84 freerdp_callback(
"OnRailMonitoredDesktop",
"(J[JJ)V", (jlong)context->instance, arr,
87 (*env)->DeleteLocalRef(env, arr);
96static UINT android_rail_server_system_param(RailClientContext* rail,
99 if (!rail || !sysparam)
100 return ERROR_INVALID_PARAMETER;
102 return CHANNEL_RC_OK;
105static UINT android_rail_server_execute_result(RailClientContext* rail,
108 if (!rail || !execResult)
109 return ERROR_INVALID_PARAMETER;
111 if (execResult->execResult != 0)
112 WLog_ERR(TAG,
"RAIL execute failed: execResult=0x%04X rawResult=0x%08X",
113 execResult->execResult, execResult->rawResult);
115 WLog_DBG(TAG,
"RAIL execute success");
117 return CHANNEL_RC_OK;
120static UINT android_rail_server_local_move_size(RailClientContext* rail,
123 if (!rail || !localMoveSize)
124 return ERROR_INVALID_PARAMETER;
126 WLog_DBG(TAG,
"RAIL window 0x%08X %s pos=(%d,%d)", localMoveSize->windowId,
127 localMoveSize->isMoveSizeStart ?
"move/size start" :
"move/size end",
128 localMoveSize->posX, localMoveSize->posY);
130 if (!localMoveSize->isMoveSizeStart)
133 rdpContext* context = (rdpContext*)afc;
134 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
135 (jlong)localMoveSize->windowId, (jint)localMoveSize->posX,
136 (jint)localMoveSize->posY, (jint)-1, (jint)-1);
138 return CHANNEL_RC_OK;
141static UINT android_rail_server_min_max_info(RailClientContext* rail,
144 if (!rail || !minMaxInfo)
145 return ERROR_INVALID_PARAMETER;
147 return CHANNEL_RC_OK;
150static UINT android_rail_server_z_order_sync(RailClientContext* rail,
153 if (!rail || !zOrderSync)
154 return ERROR_INVALID_PARAMETER;
156 return CHANNEL_RC_OK;
159static UINT android_rail_server_cloak(RailClientContext* rail,
const RAIL_CLOAK* cloak)
162 return ERROR_INVALID_PARAMETER;
164 WLog_DBG(TAG,
"RAIL window 0x%08X %s", cloak->windowId, cloak->cloak ?
"cloaked" :
"uncloaked");
165 return CHANNEL_RC_OK;
168static UINT android_rail_server_language_bar_info(RailClientContext* rail,
171 if (!rail || !langBarInfo)
172 return ERROR_INVALID_PARAMETER;
174 return CHANNEL_RC_OK;
177static UINT android_rail_server_get_appid_response(RailClientContext* rail,
180 if (!rail || !getAppIdResp)
181 return ERROR_INVALID_PARAMETER;
183 return CHANNEL_RC_OK;
186static BOOL android_rail_non_monitored_desktop(rdpContext* context,
192 freerdp_callback(
"OnRailSessionEnd",
"(J)V", (jlong)context->instance);
196static BOOL android_rail_window_state(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
199 if (!context || !orderInfo || !windowState)
202 const UINT32 flags = orderInfo->fieldFlags;
203 const BOOL isNew = (flags & WINDOW_ORDER_STATE_NEW) != 0;
204 const BOOL isHidden =
205 (flags & WINDOW_ORDER_FIELD_SHOW) && windowState->showState == WINDOW_HIDE;
209 freerdp_callback(
"OnRailWindowHide",
"(JJ)V", (jlong)context->instance,
210 (jlong)orderInfo->windowId);
214 const BOOL isShownAgain = !isNew && (flags & WINDOW_ORDER_FIELD_SHOW) && !isHidden &&
215 !(flags & WINDOW_ORDER_FIELD_WND_OFFSET);
218 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
219 (jlong)orderInfo->windowId, (jint)-1, (jint)-1, (jint)-1, (jint)-1);
225 const BOOL hasOffset = (flags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0;
226 const BOOL hasOffsetAndSize = hasOffset && (flags & WINDOW_ORDER_FIELD_WND_SIZE) != 0;
227 const INT32 x = hasOffset ? windowState->windowOffsetX : 0;
228 const INT32 y = hasOffset ? windowState->windowOffsetY : 0;
229 const INT32 w = hasOffsetAndSize ? (INT32)windowState->windowWidth : -1;
230 const INT32 h = hasOffsetAndSize ? (INT32)windowState->windowHeight : -1;
231 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
232 (jlong)orderInfo->windowId, (jint)x, (jint)y, (jint)w, (jint)h);
234 else if (flags & WINDOW_ORDER_FIELD_WND_OFFSET)
236 const BOOL hasSize = (flags & WINDOW_ORDER_FIELD_WND_SIZE) != 0;
237 freerdp_callback(
"OnRailWindowMove",
"(JJIIII)V", (jlong)context->instance,
238 (jlong)orderInfo->windowId, (jint)windowState->windowOffsetX,
239 (jint)windowState->windowOffsetY,
240 hasSize ? (jint)windowState->windowWidth : (jint)-1,
241 hasSize ? (jint)windowState->windowHeight : (jint)-1);
246static BOOL android_rail_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
248 if (!context || !orderInfo)
251 freerdp_callback(
"OnRailWindowDestroy",
"(JJ)V", (jlong)context->instance,
252 (jlong)orderInfo->windowId);
256BOOL android_rail_init(
androidContext* afc, RailClientContext* rail)
262 afc->railExecSent = FALSE;
263 rail->custom = (
void*)afc;
264 rail->ServerSystemParam = android_rail_server_system_param;
265 rail->ServerExecuteResult = android_rail_server_execute_result;
266 rail->ServerLocalMoveSize = android_rail_server_local_move_size;
267 rail->ServerMinMaxInfo = android_rail_server_min_max_info;
268 rail->ServerZOrderSync = android_rail_server_z_order_sync;
269 rail->ServerCloak = android_rail_server_cloak;
270 rail->ServerLanguageBarInfo = android_rail_server_language_bar_info;
271 rail->ServerGetAppIdResponse = android_rail_server_get_appid_response;
273 rdpContext* context = (rdpContext*)afc;
274 context->update->window->MonitoredDesktop = android_rail_monitored_desktop;
275 context->update->window->NonMonitoredDesktop = android_rail_non_monitored_desktop;
276 context->update->window->WindowCreate = android_rail_window_state;
277 context->update->window->WindowUpdate = android_rail_window_state;
278 context->update->window->WindowDelete = android_rail_window_delete;
282BOOL android_rail_uninit(
androidContext* afc, RailClientContext* rail)
287 rail->custom =
nullptr;
289 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.