RDP(5/5):Leagor Virtual Channel Extension

由于一些原因,须要增强远程桌面协议,对如何增强,rdp推荐自写新扩展。新增扩展的扩展名叫“leagor”,使用和cliprdr一样的静态通道。目前要增加的功能主要有两个。

  1. 运行时改变朝向
  2. 拖拽复制

一、运行时改变朝向

在android,一些app启动时会强制使用一种朝向,像固定要竖屏,而这种朝向会和桌面正用的横屏不一致。另外,一些app运行中会改变朝向。

注:尝试过不增加扩展、在现有协议上把当前朝向发向client。1)发每一帧图像时发朝向字段。gfx发送图像用的是RDPGFX_WIRE_TO_SURFACE_PDU_1,在这当中把某个字段用作传朝向。像surfaceId,可如果这值在过程中发生变化,mstsc.exe就报错:“由于协议错误,会话连接将断开。请重新连接到远程计算机”。2)当朝向发生改时,发向client。因为有滞后,这种方法可能会导致client会有数帧图像使用了错误朝向,但朝向影响的是鼠标、触摸,一旦收到正确的朝向就能修正回来。已有的协议是否能支持发这个改变的朝向?像Monitor Layout PDU,一来并不是所有client都支持这个命令,mstsc.exe就可能不支持,二来它不是为传朝向用的。

当朝向发生改变时,leagor扩展使用Server Orientation Update PDU。在方向上,该pdu只会由server发向client,不须要有应答。

图1 Server Orientation Update PDU
  • initialOrientation。初始朝向。远程会话开始时设备朝向,或开始h264编码那一刻的朝向。值有四个:KOS_DISPLAY_ORIENTATION_0、KOS_DISPLAY_ORIENTATION_90、KOS_DISPLAY_ORIENTATION_270、KOS_DISPLAY_ORIENTATION_270。
  • currentOrientation。当前朝向,可能值和initialOrientation一样。远程会话开始时,client立即会收到一个Server Orientation Update PDU,那个pdu的当前朝向一定等于初始朝向。

为支持运行时改变朝向,当发生朝向变化时,server需把新朝向发向client。另外,为能让client正确计算坐标值,server还须要让client知道初始朝向。通过初始朝向,client知道启动时是横屏还是竖屏,两种情况极可能需要不一样的处理坐标方法。

launcher用的是server h264编码、cient h264解码,以着视频方式传输图像,要理解launcher如何处理朝向就须要清楚当朝向发生变化时,视频中的图像如何变换。

图2 朝向变化导致的有效图像位置变化

图2的左侧是server端,右侧是client端,android 7.1,初始朝向是Orientation_0时进行h264压缩。这个压缩有着以下特点。

  • 视频尺寸是1920x1080,当中发生朝向变化时,不会改变视频尺寸,改变的是桌面图像放置在1920x1080中哪块区域。像90、270时,桌面图像只占{656, 0, 607, 1080},其它的补黑色。
  • 改变朝向后,桌面图像在视频中出现的都是“正放”结果。图中90、180、270时,解码出来就是“正放”。因而client解码后,为让用户看到“正放”,不必进行额外处理。
  • 当90、270,这种桌面尺寸无法“等于”视频尺寸时,使用的是保持宽高比、居中。适配方式除居中外,还可用其它方法,像拉伸。图中的第5行。或许,同样初始朝向、当前朝向下,不同开发板会使用不同适配方法。对firefly aio3399j(android 7.1)开发板,初始朝向横屏、运行时变成竖屏,使用的是居中适配;初始朝向是竖屏、运行时变成横屏,使用的则是拉伸适配。
  • 受朝向改变影响,client在收到鼠标/触摸事件,须处理发向server的坐标值。
  • 在android,为能让inputflinger计算正确坐标,给的screenWidth、screenHeight需是ORIENTATION_0时的屏幕宽度和高度,即使当前朝向是90、270。

二、拖拽复制

剪贴板扩展已提供了复制功能。但如果复制是这么个操作步骤,1)在client端窗口A执行“复制”,2)在server窗口B执行“粘贴”,即需要在两个窗口中切换,这对用户来说有点烦锁了。拖拽复制要达到这么效果,在一个窗口,左半边是server端文件管理器,右半边是client端文件管理器,长按一侧的文件/目录,拖拽到另一侧,放开,完成复制。拖拽复制中的复制时还是使用剪贴板扩展,它提供的功能更多是让client端能实现让两个文件管理器布局在一个窗口。

拖拽复制只使用一个PDU:Explorer Update PDU。在方向上,该pdu会由server发出,也会由client发出,不论哪一端发出,都不须要有应答。

图3 Explorer Update PDU

code是事件码,data1、data2、data3是上下文参数,不同事件码有不同意义。

  • LG_EXPLORER_CODE_SHOWN。server告知client,我要显示文件管理器了。这时有两种情况,一是launcher要进入文件管理器窗口,二是launcher由后台切到前台,此时正显示文件管理器窗口。
  • LG_EXPLORER_CODE_HIDDEN。和LG_EXPLORER_CODE_SHOWN相反,server告知client,我隐藏文件管理器了。也有两种情况,一是launcher要退出文件管理器窗口,二是launcher由前台切到后台,此时正显示文件管理器窗口。
  • LG_EXPLORER_CODE_END_DRAG。只可能由client发向server,即使是server发启此次拖拽。
  • LG_EXPLORER_CODE_CAN_PASTE。只可能发生在从client复制向server。在Adnroid,对app收到mouse_motion事件,SDL只支持拖动时,即必须先按下左键。为此client在发LG_EXPLORER_CODE_START_DRAG时,需向server发一个按下左键事件。粘贴结束后,发一个松开左键事件。

2.1 从client复制文件到server的流程

  1. (client)用户在client的文件管理器长按,触发长按事件。
  2. (client)在长按事件,client向server发剪贴板扩展中的复制请求(Format List PDU)、发鼠标左键按下事件、发LG_EXPLORER_CODE_START_DRAG。
  3. (server)server收到LG_EXPLORER_CODE_START_DRAG,让自已进入拖拽中状态,检查之后每个mouse_motion事件,当可粘贴结果发生改变时,向client发LG_EXPLORER_CODE_CAN_PASTE。
  4. (client)client收到LG_EXPLORER_CODE_CAN_PASTE,根据data3值改变让用户看的是否可粘贴图标。
  5. (client)用户松开,client知道拖拽结束,向server发LG_EXPLORER_CODE_END_DRAG、发左键松开事件。
  6. (server)server收到LG_EXPLORER_CODE_END_DRAG,解析data1、data2、data3,一旦可粘贴,向client发剪贴板扩展中粘贴请求(Format Data Request PDU、File Contents Request PDU)。

2.2 从server复制文件到client的流程

  1. (server)用户在server的文件管理器长按,触发长按事件。
  2. (server)在长按事件,server向client发剪贴板扩展中的复制请求(Format List PDU)、发LG_EXPLORER_CODE_START_DRAG。
  3. (client)client收到LG_EXPLORER_CODE_START_DRAG,让自已进入拖拽中状态,检查之后每个mouse_motion事件,并根据是否可粘贴结果,改变让用户看的是否可粘贴图标。注意,此时坐标如果落在server的文件管理器,那一定是不可粘贴。
  4. (client)用户松开,client知道拖拽结束,向server发LG_EXPLORER_CODE_END_DRAG。一旦结果是可粘贴,向server发剪贴板扩展中粘贴请求(Format Data Request PDU、File Contents Request PDU)。
  5. (server)server收到LG_EXPLORER_CODE_END_DRAG,结束拖拽中状态。

全部评论: 0

    写评论: