Implement clipping in software.
This commit is contained in:
parent
c40a9b8994
commit
960c3e1e4a
@ -118,6 +118,36 @@ typedef struct rdp_guac_client_data {
|
|||||||
*/
|
*/
|
||||||
const guac_layer* current_surface;
|
const guac_layer* current_surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether graphical operations are restricted to a specific bounding
|
||||||
|
* rectangle.
|
||||||
|
*/
|
||||||
|
int bounded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The X coordinate of the upper-left corner of the bounding rectangle,
|
||||||
|
* if any.
|
||||||
|
*/
|
||||||
|
int bounds_left;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Y coordinate of the upper-left corner of the bounding rectangle,
|
||||||
|
* if any.
|
||||||
|
*/
|
||||||
|
int bounds_top;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The X coordinate of the lower-right corner of the bounding rectangle,
|
||||||
|
* if any.
|
||||||
|
*/
|
||||||
|
int bounds_right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Y coordinate of the lower-right corner of the bounding rectangle,
|
||||||
|
* if any.
|
||||||
|
*/
|
||||||
|
int bounds_bottom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keymap to use when translating keysyms into scancodes or sequences
|
* The keymap to use when translating keysyms into scancodes or sequences
|
||||||
* of scancodes for RDP.
|
* of scancodes for RDP.
|
||||||
|
@ -44,6 +44,42 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "rdp_bitmap.h"
|
#include "rdp_bitmap.h"
|
||||||
|
|
||||||
|
static void __guac_rdp_clip_rect(rdp_guac_client_data* data, int* x, int* y, int* w, int* h) {
|
||||||
|
|
||||||
|
if (data->bounded) {
|
||||||
|
|
||||||
|
/* Get rect coordinates */
|
||||||
|
int clipped_left = *x;
|
||||||
|
int clipped_top = *y;
|
||||||
|
int clipped_right = clipped_left + *w - 1;
|
||||||
|
int clipped_bottom = clipped_top + *h - 1;
|
||||||
|
|
||||||
|
/* Clip left */
|
||||||
|
if (clipped_left < data->bounds_left) clipped_left = data->bounds_left;
|
||||||
|
else if (clipped_left > data->bounds_left) clipped_left = data->bounds_left;
|
||||||
|
|
||||||
|
/* Clip right */
|
||||||
|
if (clipped_right < data->bounds_right) clipped_right = data->bounds_right;
|
||||||
|
else if (clipped_right > data->bounds_right) clipped_right = data->bounds_right;
|
||||||
|
|
||||||
|
/* Clip top */
|
||||||
|
if (clipped_top < data->bounds_top) clipped_top = data->bounds_top;
|
||||||
|
else if (clipped_top > data->bounds_top) clipped_top = data->bounds_top;
|
||||||
|
|
||||||
|
/* Clip bottom */
|
||||||
|
if (clipped_bottom < data->bounds_bottom) clipped_bottom = data->bounds_bottom;
|
||||||
|
else if (clipped_bottom > data->bounds_bottom) clipped_bottom = data->bounds_bottom;
|
||||||
|
|
||||||
|
/* Store new rect dimensions */
|
||||||
|
*x = clipped_left;
|
||||||
|
*y = clipped_right;
|
||||||
|
*w = clipped_right - clipped_left + 1;
|
||||||
|
*h = clipped_bottom - clipped_top + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client,
|
guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client,
|
||||||
int rop3) {
|
int rop3) {
|
||||||
|
|
||||||
@ -110,6 +146,9 @@ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) {
|
|||||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
pthread_mutex_lock(&(data->update_lock));
|
pthread_mutex_lock(&(data->update_lock));
|
||||||
|
|
||||||
|
/* Clip operation to bounds */
|
||||||
|
__guac_rdp_clip_rect(data, &(dstblt->nLeftRect), &(dstblt->nTopRect), &(dstblt->nWidth), &(dstblt->nHeight));
|
||||||
|
|
||||||
switch (dstblt->bRop) {
|
switch (dstblt->bRop) {
|
||||||
|
|
||||||
/* Blackness */
|
/* Blackness */
|
||||||
@ -155,6 +194,8 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) {
|
|||||||
const guac_layer* current_layer =
|
const guac_layer* current_layer =
|
||||||
((rdp_guac_client_data*) client->data)->current_surface;
|
((rdp_guac_client_data*) client->data)->current_surface;
|
||||||
|
|
||||||
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
|
|
||||||
/* Layer for actual transfer */
|
/* Layer for actual transfer */
|
||||||
guac_layer* buffer;
|
guac_layer* buffer;
|
||||||
|
|
||||||
@ -165,6 +206,9 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) {
|
|||||||
guac_client_log_info(client, "Using fallback PATBLT (server is ignoring "
|
guac_client_log_info(client, "Using fallback PATBLT (server is ignoring "
|
||||||
"negotiated client capabilities)");
|
"negotiated client capabilities)");
|
||||||
|
|
||||||
|
/* Clip operation to bounds */
|
||||||
|
__guac_rdp_clip_rect(data, &(patblt->nLeftRect), &(patblt->nTopRect), &(patblt->nWidth), &(patblt->nHeight));
|
||||||
|
|
||||||
/* Render rectangle based on ROP */
|
/* Render rectangle based on ROP */
|
||||||
switch (patblt->bRop) {
|
switch (patblt->bRop) {
|
||||||
|
|
||||||
@ -250,6 +294,9 @@ void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) {
|
|||||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
pthread_mutex_lock(&(data->update_lock));
|
pthread_mutex_lock(&(data->update_lock));
|
||||||
|
|
||||||
|
/* Clip operation to bounds */
|
||||||
|
__guac_rdp_clip_rect(data, &(scrblt->nLeftRect), &(scrblt->nTopRect), &(scrblt->nWidth), &(scrblt->nHeight));
|
||||||
|
|
||||||
/* Copy screen rect to current surface */
|
/* Copy screen rect to current surface */
|
||||||
guac_protocol_send_copy(client->socket,
|
guac_protocol_send_copy(client->socket,
|
||||||
GUAC_DEFAULT_LAYER,
|
GUAC_DEFAULT_LAYER,
|
||||||
@ -271,6 +318,9 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
|||||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
pthread_mutex_lock(&(data->update_lock));
|
pthread_mutex_lock(&(data->update_lock));
|
||||||
|
|
||||||
|
/* Clip operation to bounds */
|
||||||
|
__guac_rdp_clip_rect(data, &(memblt->nLeftRect), &(memblt->nTopRect), &(memblt->nWidth), &(memblt->nHeight));
|
||||||
|
|
||||||
switch (memblt->bRop) {
|
switch (memblt->bRop) {
|
||||||
|
|
||||||
/* If blackness, send black rectangle */
|
/* If blackness, send black rectangle */
|
||||||
@ -378,6 +428,10 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect
|
|||||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
pthread_mutex_lock(&(data->update_lock));
|
pthread_mutex_lock(&(data->update_lock));
|
||||||
|
|
||||||
|
/* Clip operation to bounds */
|
||||||
|
__guac_rdp_clip_rect(data, &(opaque_rect->nLeftRect), &(opaque_rect->nTopRect),
|
||||||
|
&(opaque_rect->nWidth), &(opaque_rect->nHeight));
|
||||||
|
|
||||||
guac_protocol_send_rect(client->socket, current_layer,
|
guac_protocol_send_rect(client->socket, current_layer,
|
||||||
opaque_rect->nLeftRect, opaque_rect->nTopRect,
|
opaque_rect->nLeftRect, opaque_rect->nTopRect,
|
||||||
opaque_rect->nWidth, opaque_rect->nHeight);
|
opaque_rect->nWidth, opaque_rect->nHeight);
|
||||||
@ -404,26 +458,21 @@ void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) {
|
|||||||
void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) {
|
void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) {
|
||||||
|
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
|
||||||
|
|
||||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||||
pthread_mutex_lock(&(data->update_lock));
|
|
||||||
|
|
||||||
/* Reset clip */
|
/* If no bounds given, clear bounding rect */
|
||||||
guac_protocol_send_reset(client->socket, current_layer);
|
if (bounds == NULL)
|
||||||
|
data->bounded = false;
|
||||||
|
|
||||||
/* Set clip if specified */
|
/* Otherwise, set bounding rectangle */
|
||||||
if (bounds != NULL) {
|
else {
|
||||||
guac_protocol_send_rect(client->socket, current_layer,
|
data->bounded = true;
|
||||||
bounds->left, bounds->top,
|
data->bounds_left = bounds->left;
|
||||||
bounds->right - bounds->left + 1,
|
data->bounds_top = bounds->top;
|
||||||
bounds->bottom - bounds->top + 1);
|
data->bounds_right = bounds->right;
|
||||||
|
data->bounds_bottom = bounds->bottom;
|
||||||
guac_protocol_send_clip(client->socket, current_layer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&(data->update_lock));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdp_gdi_end_paint(rdpContext* context) {
|
void guac_rdp_gdi_end_paint(rdpContext* context) {
|
||||||
|
Loading…
Reference in New Issue
Block a user