Merge branch 'master' of git://github.com/FreeRDP/xrdp

ulab-next
LawrenceK 12 years ago
commit 69389e4a63

@ -19,4 +19,5 @@ SUBDIRS = \
keygen \ keygen \
docs \ docs \
instfiles \ instfiles \
genkeymap genkeymap \
xrdpapi

@ -109,6 +109,7 @@ AC_CONFIG_FILES([Makefile
instfiles/Makefile instfiles/Makefile
instfiles/pam.d/Makefile instfiles/pam.d/Makefile
genkeymap/Makefile genkeymap/Makefile
xrdpapi/Makefile
]) ])
# fontdump/Makefile # fontdump/Makefile
# xrdp/cursors/Makefile # xrdp/cursors/Makefile

@ -215,7 +215,7 @@ int APP_CC
xrdp_jpeg_compress(char* in_data, int width, int height, xrdp_jpeg_compress(char* in_data, int width, int height,
struct stream* s, int bpp, int byte_limit, struct stream* s, int bpp, int byte_limit,
int start_line, struct stream* temp_s, int start_line, struct stream* temp_s,
int e) int e, int quality)
{ {
return height; return height;
} }

@ -1945,10 +1945,18 @@ xrdp_orders_send_as_rfx(struct xrdp_orders* self,
int width, int height, int bpp, int width, int height, int bpp,
int hints) int hints)
{ {
if (hints & 1)
{
return 0;
}
if (bpp != 24) if (bpp != 24)
{ {
return 0; return 0;
} }
if (width * height < 64)
{
return 0;
}
return 1; return 1;
} }
#endif #endif

@ -28,14 +28,20 @@
#include "list.h" #include "list.h"
#include "file.h" #include "file.h"
#include "file_loc.h" #include "file_loc.h"
#include "log.h"
#include "rail.h"
#include "xcommon.h"
static struct trans* g_lis_trans = 0; static struct trans* g_lis_trans = 0;
static struct trans* g_con_trans = 0; static struct trans* g_con_trans = 0;
static struct trans* g_api_lis_trans = 0;
static struct trans* g_api_con_trans = 0;
static struct chan_item g_chan_items[32]; static struct chan_item g_chan_items[32];
static int g_num_chan_items = 0; static int g_num_chan_items = 0;
static int g_cliprdr_index = -1; static int g_cliprdr_index = -1;
static int g_rdpsnd_index = -1; static int g_rdpsnd_index = -1;
static int g_rdpdr_index = -1; static int g_rdpdr_index = -1;
static int g_rail_index = -1;
static tbus g_term_event = 0; static tbus g_term_event = 0;
static tbus g_thread_done_event = 0; static tbus g_thread_done_event = 0;
@ -46,57 +52,149 @@ int g_display_num = 0;
int g_cliprdr_chan_id = -1; /* cliprdr */ int g_cliprdr_chan_id = -1; /* cliprdr */
int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpsnd_chan_id = -1; /* rdpsnd */
int g_rdpdr_chan_id = -1; /* rdpdr */ int g_rdpdr_chan_id = -1; /* rdpdr */
int g_rail_chan_id = -1; /* rail */
char* g_exec_name;
tbus g_exec_event;
tbus g_exec_mutex;
tbus g_exec_sem;
int g_exec_pid = 0;
/* data in struct trans::callback_data */
struct xrdp_api_data
{
int chan_id;
char header[64];
int flags;
};
/*****************************************************************************/ /*****************************************************************************/
/* add data to chan_item, on its way to the client */
/* returns error */ /* returns error */
int APP_CC static int APP_CC
send_channel_data(int chan_id, char* data, int size) add_data_to_chan_item(struct chan_item* chan_item, char* data, int size)
{ {
struct stream * s = (struct stream *)NULL; struct stream* s;
int chan_flags = 0; struct chan_out_data* cod;
int total_size = 0;
int sent = 0;
int rv = 0;
s = trans_get_out_s(g_con_trans, 8192); make_stream(s);
if (s == 0) init_stream(s, size);
g_memcpy(s->data, data, size);
s->end = s->data + size;
cod = (struct chan_out_data*)g_malloc(sizeof(struct chan_out_data), 1);
cod->s = s;
if (chan_item->tail == 0)
{ {
return 1; chan_item->tail = cod;
chan_item->head = cod;
} }
rv = 0; else
sent = 0;
total_size = size;
while (sent < total_size)
{ {
size = MIN(1600, total_size - sent); chan_item->tail->next = cod;
chan_item->tail = cod;
}
return 0;
}
/*****************************************************************************/
/* returns error */
static int APP_CC
send_data_from_chan_item(struct chan_item* chan_item)
{
struct stream* s;
struct chan_out_data* cod;
int bytes_left;
int size;
int chan_flags;
int error;
if (chan_item->head == 0)
{
return 0;
}
cod = chan_item->head;
bytes_left = (int)(cod->s->end - cod->s->p);
size = MIN(1600, bytes_left);
chan_flags = 0; chan_flags = 0;
if (sent == 0) if (cod->s->p == cod->s->data)
{ {
chan_flags |= 1; /* first */ chan_flags |= 1; /* first */
} }
if (size + sent == total_size) if (cod->s->p + size >= cod->s->end)
{ {
chan_flags |= 2; /* last */ chan_flags |= 2; /* last */
} }
s = trans_get_out_s(g_con_trans, 8192);
out_uint32_le(s, 0); /* version */ out_uint32_le(s, 0); /* version */
out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */
out_uint32_le(s, 8); /* msg id */ out_uint32_le(s, 8); /* msg id */
out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */
out_uint16_le(s, chan_id); out_uint16_le(s, chan_item->id);
out_uint16_le(s, chan_flags); out_uint16_le(s, chan_flags);
out_uint16_le(s, size); out_uint16_le(s, size);
out_uint32_le(s, total_size); out_uint32_le(s, cod->s->size);
out_uint8a(s, data + sent, size); out_uint8a(s, cod->s->p, size);
s_mark_end(s); s_mark_end(s);
rv = trans_force_write(g_con_trans); LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
if (rv != 0) "size %d chan_flags 0x%8.8x", size, chan_flags));
error = trans_force_write(g_con_trans);
if (error != 0)
{ {
break; return 1;
} }
sent += size; cod->s->p += size;
s = trans_get_out_s(g_con_trans, 8192); if (cod->s->p >= cod->s->end)
{
free_stream(cod->s);
chan_item->head = chan_item->head->next;
if (chan_item->head == 0)
{
chan_item->tail = 0;
} }
return rv; g_free(cod);
}
return 0;
}
/*****************************************************************************/
/* returns error */
static int APP_CC
check_chan_items(void)
{
int index;
for (index = 0; index < g_num_chan_items; index++)
{
if (g_chan_items[index].head != 0)
{
send_data_from_chan_item(g_chan_items + index);
}
}
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
send_channel_data(int chan_id, char* data, int size)
{
int index;
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size));
if (chan_id == -1)
{
return 1;
}
for (index = 0; index < g_num_chan_items; index++)
{
if (g_chan_items[index].id == chan_id)
{
add_data_to_chan_item(g_chan_items + index, data, size);
check_chan_items();
return 0;
}
}
return 1;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -106,7 +204,7 @@ send_init_response_message(void)
{ {
struct stream * s = (struct stream *)NULL; struct stream * s = (struct stream *)NULL;
LOGM((LOG_LEVEL_INFO,"send_init_response_message:")) LOGM((LOG_LEVEL_INFO, "send_init_response_message:"));
s = trans_get_out_s(g_con_trans, 8192); s = trans_get_out_s(g_con_trans, 8192);
if (s == 0) if (s == 0)
{ {
@ -176,18 +274,20 @@ process_message_init(struct stream* s)
static int APP_CC static int APP_CC
process_message_channel_setup(struct stream* s) process_message_channel_setup(struct stream* s)
{ {
int num_chans = 0; int num_chans;
int index = 0; int index;
int rv = 0; int rv;
struct chan_item* ci = (struct chan_item *)NULL; struct chan_item* ci;
g_num_chan_items = 0; g_num_chan_items = 0;
g_cliprdr_index = -1; g_cliprdr_index = -1;
g_rdpsnd_index = -1; g_rdpsnd_index = -1;
g_rdpdr_index = -1; g_rdpdr_index = -1;
g_rail_index = -1;
g_cliprdr_chan_id = -1; g_cliprdr_chan_id = -1;
g_rdpsnd_chan_id = -1; g_rdpsnd_chan_id = -1;
g_rdpdr_chan_id = -1; g_rdpdr_chan_id = -1;
g_rail_chan_id = -1;
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:")); LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:"));
in_uint16_le(s, num_chans); in_uint16_le(s, num_chans);
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d", LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d",
@ -216,6 +316,15 @@ process_message_channel_setup(struct stream* s)
g_rdpdr_index = g_num_chan_items; g_rdpdr_index = g_num_chan_items;
g_rdpdr_chan_id = ci->id; g_rdpdr_chan_id = ci->id;
} }
else if (g_strcasecmp(ci->name, "rail") == 0)
{
g_rail_index = g_num_chan_items;
g_rail_chan_id = ci->id;
}
else
{
LOG(10, ("other %s", ci->name));
}
g_num_chan_items++; g_num_chan_items++;
} }
rv = send_channel_setup_response_message(); rv = send_channel_setup_response_message();
@ -231,6 +340,10 @@ process_message_channel_setup(struct stream* s)
{ {
dev_redir_init(); dev_redir_init();
} }
if (g_rail_index >= 0)
{
rail_init();
}
return rv; return rv;
} }
@ -244,6 +357,7 @@ process_message_channel_data(struct stream* s)
int rv = 0; int rv = 0;
int length = 0; int length = 0;
int total_length = 0; int total_length = 0;
struct stream* ls;
in_uint16_le(s, chan_id); in_uint16_le(s, chan_id);
in_uint16_le(s, chan_flags); in_uint16_le(s, chan_flags);
@ -251,6 +365,7 @@ process_message_channel_data(struct stream* s)
in_uint32_le(s, total_length); in_uint32_le(s, total_length);
LOGM((LOG_LEVEL_DEBUG,"process_message_channel_data: chan_id %d " LOGM((LOG_LEVEL_DEBUG,"process_message_channel_data: chan_id %d "
"chan_flags %d", chan_id, chan_flags)); "chan_flags %d", chan_id, chan_flags));
LOG(10, ("process_message_channel_data"));
rv = send_channel_data_response_message(); rv = send_channel_data_response_message();
if (rv == 0) if (rv == 0)
{ {
@ -266,6 +381,27 @@ process_message_channel_data(struct stream* s)
{ {
rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length);
} }
else if (chan_id == g_rail_chan_id)
{
rv = rail_data_in(s, chan_id, chan_flags, length, total_length);
}
else if (chan_id == ((struct xrdp_api_data*)
(g_api_con_trans->callback_data))->chan_id)
{
LOG(10, ("process_message_channel_data length %d total_length %d "
"chan_flags 0x%8.8x", length, total_length, chan_flags));
ls = g_api_con_trans->out_s;
if (chan_flags & 1) /* first */
{
init_stream(ls, total_length);
}
out_uint8a(ls, s->p, length);
if (chan_flags & 2) /* last */
{
s_mark_end(ls);
trans_force_write(g_api_con_trans);
}
}
} }
return rv; return rv;
} }
@ -276,6 +412,7 @@ static int APP_CC
process_message_channel_data_response(struct stream* s) process_message_channel_data_response(struct stream* s)
{ {
LOG(10, ("process_message_channel_data_response:")); LOG(10, ("process_message_channel_data_response:"));
check_chan_items();
return 0; return 0;
} }
@ -365,6 +502,44 @@ my_trans_data_in(struct trans* trans)
return error; return error;
} }
/*****************************************************************************/
/* returns error */
int DEFAULT_CC
my_api_trans_data_in(struct trans* trans)
{
struct stream* s;
int error;
struct xrdp_api_data* ad;
LOG(10, ("my_api_trans_data_in:"));
if (trans == 0)
{
return 0;
}
if (trans != g_api_con_trans)
{
return 1;
}
LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:"));
s = trans_get_in_s(trans);
error = g_tcp_recv(trans->sck, s->data, 8192, 0);
if (error > 0)
{
LOG(10, ("my_api_trans_data_in: got data %d", error));
ad = (struct xrdp_api_data*)(trans->callback_data);
if (send_channel_data(ad->chan_id, s->data, error) != 0)
{
LOG(0, ("my_api_trans_data_in: send_channel_data failed"));
}
}
else
{
LOG(10, ("my_api_trans_data_in: g_tcp_recv failed, or disconnected"));
return 1;
}
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
int DEFAULT_CC int DEFAULT_CC
my_trans_conn_in(struct trans* trans, struct trans* new_trans) my_trans_conn_in(struct trans* trans, struct trans* new_trans)
@ -395,6 +570,84 @@ my_trans_conn_in(struct trans* trans, struct trans* new_trans)
return 0; return 0;
} }
/*****************************************************************************/
int DEFAULT_CC
my_api_trans_conn_in(struct trans* trans, struct trans* new_trans)
{
struct xrdp_api_data* ad;
int error;
int index;
int found;
struct stream* s;
if (trans == 0)
{
return 1;
}
if (trans != g_api_lis_trans)
{
return 1;
}
if (new_trans == 0)
{
return 1;
}
LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:"));
LOG(10, ("my_api_trans_conn_in: got incoming"));
s = trans_get_in_s(new_trans);
s->end = s->data;
error = trans_force_read(new_trans, 64);
if (error != 0)
{
LOG(0, ("my_api_trans_conn_in: trans_force_read failed"));
trans_delete(new_trans);
}
s->end = s->data;
ad = (struct xrdp_api_data*)g_malloc(sizeof(struct xrdp_api_data), 1);
g_memcpy(ad->header, s->data, 64);
ad->flags = GGET_UINT32(ad->header, 16);
found = 0;
if (ad->flags | 1) /* WTS_CHANNEL_OPTION_DYNAMIC */
{
/* TODO */
found = 0;
}
else
{
for (index = 0; index < g_num_chan_items; index++)
{
LOG(10, (" %s %s", ad->header, g_chan_items[index].name));
if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0)
{
LOG(10, ("my_api_trans_conn_in: found it at %d", index));
ad->chan_id = g_chan_items[index].id;
found = 1;
break;
}
}
}
LOG(10, ("my_api_trans_conn_in: found %d", found));
if (!found)
{
ad->chan_id = -1;
}
new_trans->callback_data = ad;
trans_delete(g_api_con_trans);
g_api_con_trans = new_trans;
g_api_con_trans->trans_data_in = my_api_trans_data_in;
g_api_con_trans->header_size = 0;
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
static int APP_CC static int APP_CC
setup_listen(void) setup_listen(void)
@ -428,18 +681,39 @@ setup_listen(void)
return 0; return 0;
} }
/*****************************************************************************/
static int APP_CC
setup_api_listen(void)
{
char port[256];
int error = 0;
g_api_lis_trans = trans_create(2, 8192, 8192);
g_snprintf(port, 255, "/tmp/.xrdp/xrdpapi_%d", g_display_num);
g_api_lis_trans->trans_conn_in = my_api_trans_conn_in;
error = trans_listen(g_api_lis_trans, port);
if (error != 0)
{
LOGM((LOG_LEVEL_ERROR, "setup_api_listen: trans_listen failed for port %s",
port));
return 1;
}
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
THREAD_RV THREAD_CC THREAD_RV THREAD_CC
channel_thread_loop(void* in_val) channel_thread_loop(void* in_val)
{ {
tbus objs[32]; tbus objs[32];
int num_objs = 0; int num_objs;
int timeout = 0; int timeout;
int error = 0; int error;
THREAD_RV rv = 0; THREAD_RV rv;
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start")); LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start"));
rv = 0; rv = 0;
setup_api_listen();
error = setup_listen(); error = setup_listen();
if (error == 0) if (error == 0)
{ {
@ -448,6 +722,7 @@ channel_thread_loop(void* in_val)
objs[num_objs] = g_term_event; objs[num_objs] = g_term_event;
num_objs++; num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs); trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
{ {
if (g_is_wait_obj_set(g_term_event)) if (g_is_wait_obj_set(g_term_event))
@ -456,6 +731,7 @@ channel_thread_loop(void* in_val)
clipboard_deinit(); clipboard_deinit();
sound_deinit(); sound_deinit();
dev_redir_deinit(); dev_redir_deinit();
rail_deinit();
break; break;
} }
if (g_lis_trans != 0) if (g_lis_trans != 0)
@ -475,6 +751,7 @@ channel_thread_loop(void* in_val)
clipboard_deinit(); clipboard_deinit();
sound_deinit(); sound_deinit();
dev_redir_deinit(); dev_redir_deinit();
rail_deinit();
/* delete g_con_trans */ /* delete g_con_trans */
trans_delete(g_con_trans); trans_delete(g_con_trans);
g_con_trans = 0; g_con_trans = 0;
@ -486,7 +763,29 @@ channel_thread_loop(void* in_val)
} }
} }
} }
clipboard_check_wait_objs(); if (g_api_lis_trans != 0)
{
if (trans_check_wait_objs(g_api_lis_trans) != 0)
{
LOG(0, ("channel_thread_loop: trans_check_wait_objs failed"));
}
}
LOG(10, ("0 %p", g_api_con_trans));
if (g_api_con_trans != 0)
{
LOG(10, ("1 %p %d", g_api_con_trans, g_tcp_can_recv(g_api_con_trans->sck, 0)));
if (trans_check_wait_objs(g_api_con_trans) != 0)
{
LOG(10, ("channel_thread_loop: trans_check_wait_objs failed, "
"or disconnected"));
g_free(g_api_con_trans->callback_data);
trans_delete(g_api_con_trans);
g_api_con_trans = 0;
}
}
xcommon_check_wait_objs();
sound_check_wait_objs(); sound_check_wait_objs();
dev_redir_check_wait_objs(); dev_redir_check_wait_objs();
timeout = -1; timeout = -1;
@ -495,7 +794,9 @@ channel_thread_loop(void* in_val)
num_objs++; num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs); trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_con_trans, objs, &num_objs); trans_get_wait_objs(g_con_trans, objs, &num_objs);
clipboard_get_wait_objs(objs, &num_objs, &timeout); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_con_trans, objs, &num_objs);
xcommon_get_wait_objs(objs, &num_objs, &timeout);
sound_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout);
dev_redir_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout);
} }
@ -504,6 +805,10 @@ channel_thread_loop(void* in_val)
g_lis_trans = 0; g_lis_trans = 0;
trans_delete(g_con_trans); trans_delete(g_con_trans);
g_con_trans = 0; g_con_trans = 0;
trans_delete(g_api_lis_trans);
g_api_lis_trans = 0;
trans_delete(g_api_con_trans);
g_api_con_trans = 0;
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop")); LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop"));
g_set_wait_obj(g_thread_done_event); g_set_wait_obj(g_thread_done_event);
return rv; return rv;
@ -522,7 +827,25 @@ void DEFAULT_CC
nil_signal_handler(int sig) nil_signal_handler(int sig)
{ {
LOGM((LOG_LEVEL_INFO, "nil_signal_handler: got signal %d", sig)); LOGM((LOG_LEVEL_INFO, "nil_signal_handler: got signal %d", sig));
g_set_wait_obj(g_term_event); }
/*****************************************************************************/
void DEFAULT_CC
child_signal_handler(int sig)
{
int i1;
LOG(10, ("child_signal_handler:"));
do
{
i1 = g_waitchild();
if (i1 == g_exec_pid)
{
LOG(0, ("child_signal_handler: found pid %d", i1));
//shutdownx();
}
LOG(10, (" %d", i1));
} while (i1 >= 0);
} }
/*****************************************************************************/ /*****************************************************************************/
@ -587,6 +910,8 @@ main_cleanup(void)
{ {
g_delete_wait_obj(g_term_event); g_delete_wait_obj(g_term_event);
g_delete_wait_obj(g_thread_done_event); g_delete_wait_obj(g_thread_done_event);
g_delete_wait_obj(g_exec_event);
tc_mutex_delete(g_exec_mutex);
g_deinit(); /* os_calls */ g_deinit(); /* os_calls */
return 0; return 0;
} }
@ -595,15 +920,14 @@ main_cleanup(void)
static int APP_CC static int APP_CC
read_ini(void) read_ini(void)
{ {
char filename[256] = ""; char filename[256];
struct list* names = (struct list *)NULL; struct list* names;
struct list* values = (struct list *)NULL; struct list* values;
char* name = (char *)NULL; char* name;
char* value = (char *)NULL; char* value;
int index = 0; int index;
g_memset(filename,0,(sizeof(char)*256));
g_memset(filename,0,(sizeof(char) * 256));
names = list_create(); names = list_create();
names->auto_free = 1; names->auto_free = 1;
values = list_create(); values = list_create();
@ -630,26 +954,72 @@ read_ini(void)
return 0; return 0;
} }
/*****************************************************************************/
static int APP_CC
run_exec(void)
{
int pid;
LOG(10, ("run_exec:"));
pid = g_fork();
if (pid == 0)
{
trans_delete(g_con_trans);
g_close_wait_obj(g_term_event);
g_close_wait_obj(g_thread_done_event);
g_close_wait_obj(g_exec_event);
tc_mutex_delete(g_exec_mutex);
tc_sem_delete(g_exec_sem);
g_execlp3(g_exec_name, g_exec_name, 0);
g_exit(0);
}
g_exec_pid = pid;
tc_sem_inc(g_exec_sem);
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
int DEFAULT_CC int DEFAULT_CC
main(int argc, char** argv) main(int argc, char** argv)
{ {
tbus waiters[4];
int pid = 0; int pid = 0;
char text[256] = ""; char text[256];
char* display_text = (char *)NULL; char* home_text;
#if XRDP_CHANNEL_LOG char* display_text;
char cfg_file[256]; char log_file[256];
enum logReturns error; enum logReturns error;
#endif struct log_config logconfig;
g_init("xrdp-chansrv"); /* os_calls */ g_init("xrdp-chansrv"); /* os_calls */
home_text = g_getenv("HOME");
if (home_text == 0)
{
g_writeln("error reading HOME environment variable");
g_deinit();
return 1;
}
read_ini(); read_ini();
pid = g_getpid(); pid = g_getpid();
#if XRDP_CHANNEL_LOG
/* starting logging subsystem */ /* starting logging subsystem */
g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); g_memset(&logconfig, 0, sizeof(struct log_config));
error = log_start(cfg_file,"XRDP-Chansrv"); logconfig.program_name = "XRDP-Chansrv";
g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text);
g_writeln("chansrv::main: using log file [%s]", log_file);
if (g_file_exist(log_file))
{
g_file_delete(log_file);
}
logconfig.log_file = log_file;
logconfig.fd = -1;
logconfig.log_level = LOG_LEVEL_ERROR;
logconfig.enable_syslog = 0;
logconfig.syslog_level = 0;
error = log_start_from_param(&logconfig);
if (error != LOG_STARTUP_OK) if (error != LOG_STARTUP_OK)
{ {
switch (error) switch (error)
@ -666,21 +1036,22 @@ main(int argc, char** argv)
break; break;
} }
g_deinit(); g_deinit();
g_exit(1); return 1;
} }
LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid)); LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid));
#endif
/* set up signal handler */ /* set up signal handler */
g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_kill(term_signal_handler); /* SIGKILL */
g_signal_terminate(term_signal_handler); /* SIGTERM */ g_signal_terminate(term_signal_handler); /* SIGTERM */
g_signal_user_interrupt(term_signal_handler); /* SIGINT */ g_signal_user_interrupt(term_signal_handler); /* SIGINT */
g_signal_pipe(nil_signal_handler); /* SIGPIPE */ g_signal_pipe(nil_signal_handler); /* SIGPIPE */
g_signal_child_stop(child_signal_handler); /* SIGCHLD */
display_text = g_getenv("DISPLAY"); display_text = g_getenv("DISPLAY");
LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text)); LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text));
get_display_num_from_display(display_text); get_display_num_from_display(display_text);
if (g_display_num == 0) if (g_display_num == 0)
{ {
LOGM((LOG_LEVEL_ERROR, "main: error, display is zero")); LOGM((LOG_LEVEL_ERROR, "main: error, display is zero"));
g_deinit();
return 1; return 1;
} }
LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num)); LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num));
@ -688,14 +1059,29 @@ main(int argc, char** argv)
g_term_event = g_create_wait_obj(text); g_term_event = g_create_wait_obj(text);
g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid);
g_thread_done_event = g_create_wait_obj(text); g_thread_done_event = g_create_wait_obj(text);
g_snprintf(text, 255, "xrdp_chansrv_%8.8x_exec", pid);
g_exec_event = g_create_wait_obj(text);
g_exec_mutex = tc_mutex_create();
g_exec_sem = tc_sem_create(0);
tc_thread_create(channel_thread_loop, 0); tc_thread_create(channel_thread_loop, 0);
while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event)) while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event))
{ {
if (g_obj_wait(&g_term_event, 1, 0, 0, 0) != 0) waiters[0] = g_term_event;
waiters[1] = g_exec_event;
if (g_obj_wait(waiters, 2, 0, 0, 0) != 0)
{ {
LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed")); LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed"));
break; break;
} }
if (g_is_wait_obj_set(g_term_event))
{
break;
}
if (g_is_wait_obj_set(g_exec_event))
{
g_reset_wait_obj(g_exec_event);
run_exec();
}
} }
while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event)) while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event))
{ {

@ -21,14 +21,21 @@
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
#include "log.h"
#define XRDP_CHANNEL_LOG 0 struct chan_out_data
{
struct stream* s;
struct chan_out_data* next;
};
struct chan_item struct chan_item
{ {
int id; int id;
int flags; int flags;
char name[16]; char name[16];
struct chan_out_data* head;
struct chan_out_data* tail;
}; };
int APP_CC int APP_CC
@ -47,11 +54,25 @@ main_cleanup(void);
} \ } \
} }
#if XRDP_CHANNEL_LOG
#include "log.h"
#define LOGM(_args) do { log_message _args ; } while (0) #define LOGM(_args) do { log_message _args ; } while (0)
#else
#define LOGM(_args) #ifndef GSET_UINT8
#define GSET_UINT8(_ptr, _offset, _data) \
*((unsigned char*) (((unsigned char*)(_ptr)) + (_offset))) = (unsigned char)(_data)
#define GGET_UINT8(_ptr, _offset) \
(*((unsigned char*) (((unsigned char*)(_ptr)) + (_offset))))
#define GSET_UINT16(_ptr, _offset, _data) \
GSET_UINT8(_ptr, _offset, _data); \
GSET_UINT8(_ptr, (_offset) + 1, (_data) >> 8)
#define GGET_UINT16(_ptr, _offset) \
(GGET_UINT8(_ptr, _offset)) | \
((GGET_UINT8(_ptr, (_offset) + 1)) << 8)
#define GSET_UINT32(_ptr, _offset, _data) \
GSET_UINT16(_ptr, _offset, _data); \
GSET_UINT16(_ptr, (_offset) + 2, (_data) >> 16)
#define GGET_UINT32(_ptr, _offset) \
(GGET_UINT16(_ptr, _offset)) | \
((GGET_UINT16(_ptr, (_offset) + 2)) << 16)
#endif #endif
#endif #endif

@ -2,6 +2,7 @@
* xrdp: A Remote Desktop Protocol server. * xrdp: A Remote Desktop Protocol server.
* *
* Copyright (C) Jay Sorg 2009-2012 * Copyright (C) Jay Sorg 2009-2012
* Copyright (C) Laxmikant Rashinkar 2012
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +20,11 @@
for help see for help see
http://tronche.com/gui/x/icccm/sec-2.html#s-2 http://tronche.com/gui/x/icccm/sec-2.html#s-2
.../kde/kdebase/workspace/klipper/clipboardpoll.cpp .../kde/kdebase/workspace/klipper/clipboardpoll.cpp
Revision:
Aug 05, 2012:
Laxmikant Rashinkar (LK dot Rashinkar at gmail.com)
added clipboard support for BMP images
*/ */
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -29,6 +35,28 @@
#include "os_calls.h" #include "os_calls.h"
#include "chansrv.h" #include "chansrv.h"
#include "clipboard.h" #include "clipboard.h"
#include "xcommon.h"
static char g_bmp_image_header[] =
{
/* this is known to work */
//0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
/* THIS IS BEING SENT BY WIN2008 */
0x42, 0x4d, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00
};
extern int g_cliprdr_chan_id; /* in chansrv.c */
extern Display* g_display; /* in xcommon.c */
extern int g_x_socket; /* in xcommon.c */
extern tbus g_x_wait_obj; /* in xcommon.c */
extern Screen* g_screen; /* in xcommon.c */
extern int g_screen_num; /* in xcommon.c */
int g_clip_up = 0;
int g_waiting_for_data_response = 0;
int g_waiting_for_data_response_time = 0;
static Atom g_clipboard_atom = 0; static Atom g_clipboard_atom = 0;
static Atom g_clip_property_atom = 0; static Atom g_clip_property_atom = 0;
@ -39,12 +67,9 @@ static Atom g_primary_atom = 0;
static Atom g_secondary_atom = 0; static Atom g_secondary_atom = 0;
static Atom g_get_time_atom = 0; static Atom g_get_time_atom = 0;
static Atom g_utf8_atom = 0; static Atom g_utf8_atom = 0;
static int g_x_socket = 0; static Atom g_image_bmp_atom = 0;
static tbus g_x_wait_obj = 0;
static int g_clip_up = 0;
static Window g_wnd = 0; static Window g_wnd = 0;
static Screen* g_screen = 0;
static int g_screen_num = 0;
static int g_xfixes_event_base = 0; static int g_xfixes_event_base = 0;
static int g_last_clip_size = 0; static int g_last_clip_size = 0;
@ -64,35 +89,20 @@ static int g_data_in_size = 0;
static int g_data_in_time = 0; static int g_data_in_time = 0;
static int g_data_in_up_to_date = 0; static int g_data_in_up_to_date = 0;
static int g_got_format_announce = 0; static int g_got_format_announce = 0;
static int g_waiting_for_data_response = 0;
static int g_waiting_for_data_response_time = 0;
static Display* g_display = 0;
extern int g_cliprdr_chan_id; /* in chansrv.c */
/*****************************************************************************/ /* for image data */
int DEFAULT_CC static int g_want_image_data = 0;
clipboard_error_handler(Display* dis, XErrorEvent* xer) static XSelectionRequestEvent g_saved_selection_req_event;
{
char text[256];
XGetErrorText(dis, xer->error_code, text, 255); /* for clipboard INCR transfers */
LOGM((LOG_LEVEL_ERROR,"error [%s]", text)); static Atom g_incr_atom;
return 0; static Atom g_incr_atom_type;
} static Atom g_incr_atom_target;
static char* g_incr_data = 0;
static int g_incr_data_size = 0;
static int g_incr_in_progress = 0;
/*****************************************************************************/ static int clipboard_format_id = CB_FORMAT_UNICODETEXT;
/* The X server had an internal error. This is the last function called.
Do any cleanup that needs to be done on exit, like removing temporary files.
Don't worry about memory leaks */
int DEFAULT_CC
clipboard_fatal_handler(Display* dis)
{
LOGM((LOG_LEVEL_ALWAYS, "fatal error, exiting"));
main_cleanup();
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
/* this is one way to get the current time from the x server */ /* this is one way to get the current time from the x server */
@ -144,28 +154,9 @@ clipboard_init(void)
{ {
return 0; return 0;
} }
xcommon_init();
clipboard_deinit(); clipboard_deinit();
rv = 0; rv = 0;
/* setting the error handlers can cause problem when shutting down
chansrv on some xlibs */
//XSetErrorHandler(clipboard_error_handler);
//XSetIOErrorHandler(clipboard_fatal_handler);
g_display = XOpenDisplay(0);
if (g_display == 0)
{
LOGM((LOG_LEVEL_ERROR, "clipboard_init: XOpenDisplay failed"));
rv = 1;
}
if (rv == 0)
{
g_x_socket = XConnectionNumber(g_display);
if (g_x_socket == 0)
{
LOGM((LOG_LEVEL_ERROR, "clipboard_init: XConnectionNumber failed"));
rv = 2;
}
g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0);
}
if (rv == 0) if (rv == 0)
{ {
g_clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False); g_clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
@ -185,13 +176,11 @@ clipboard_init(void)
} }
if (rv == 0) if (rv == 0)
{ {
LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_xfixes_event_base %d", LOGM((LOG_LEVEL_DEBUG, "clipboard_init: g_xfixes_event_base %d",
g_xfixes_event_base)); g_xfixes_event_base));
st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min);
LOGM((LOG_LEVEL_ERROR, "clipboard_init st %d, maj %d min %d", st, LOGM((LOG_LEVEL_DEBUG, "clipboard_init st %d, maj %d min %d", st,
ver_maj, ver_min)); ver_maj, ver_min));
g_screen_num = DefaultScreen(g_display);
g_screen = ScreenOfDisplay(g_display, g_screen_num);
g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM",
False); False);
g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM", g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM",
@ -202,6 +191,15 @@ clipboard_init(void)
g_primary_atom = XInternAtom(g_display, "PRIMARY", False); g_primary_atom = XInternAtom(g_display, "PRIMARY", False);
g_secondary_atom = XInternAtom(g_display, "SECONDARY", False); g_secondary_atom = XInternAtom(g_display, "SECONDARY", False);
g_utf8_atom = XInternAtom(g_display, "UTF8_STRING", False); g_utf8_atom = XInternAtom(g_display, "UTF8_STRING", False);
g_image_bmp_atom = XInternAtom(g_display, "image/bmp", False);
g_incr_atom = XInternAtom(g_display, "INCR", False);
if (g_image_bmp_atom == None)
{
LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_image_bmp_atom was "
"not allocated"));
}
g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen),
0, 0, 4, 4, 0, 0, 0); 0, 0, 4, 4, 0, 0, 0);
input_mask = StructureNotifyMask | PropertyChangeMask; input_mask = StructureNotifyMask | PropertyChangeMask;
@ -251,27 +249,16 @@ clipboard_init(void)
int APP_CC int APP_CC
clipboard_deinit(void) clipboard_deinit(void)
{ {
if (g_x_wait_obj != 0)
{
g_delete_wait_obj_from_socket(g_x_wait_obj);
g_x_wait_obj = 0;
}
if (g_wnd != 0) if (g_wnd != 0)
{ {
XDestroyWindow(g_display, g_wnd); XDestroyWindow(g_display, g_wnd);
g_wnd = 0; g_wnd = 0;
} }
g_x_socket = 0;
g_free(g_last_clip_data); g_free(g_last_clip_data);
g_last_clip_data = 0; g_last_clip_data = 0;
g_last_clip_size = 0; g_last_clip_size = 0;
free_stream(g_ins); free_stream(g_ins);
g_ins = 0; g_ins = 0;
if (g_display != 0)
{
XCloseDisplay(g_display);
g_display = 0;
}
g_clip_up = 0; g_clip_up = 0;
return 0; return 0;
} }
@ -297,7 +284,7 @@ clipboard_send_data_request(void)
out_uint16_le(s, 4); /* CLIPRDR_DATA_REQUEST */ out_uint16_le(s, 4); /* CLIPRDR_DATA_REQUEST */
out_uint16_le(s, 0); /* status */ out_uint16_le(s, 0); /* status */
out_uint32_le(s, 4); /* length */ out_uint32_le(s, 4); /* length */
out_uint32_le(s, 0x0d); out_uint32_le(s, clipboard_format_id);
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_request: data out, sending " LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_request: data out, sending "
@ -330,9 +317,17 @@ clipboard_send_format_ack(void)
return rv; return rv;
} }
static char windows_native_format[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*****************************************************************************/ /*****************************************************************************/
static int APP_CC static int APP_CC
clipboard_send_format_announce(void) clipboard_send_format_announce(tui32 format_id, char* format_name)
{ {
struct stream* s; struct stream* s;
int size; int size;
@ -342,9 +337,9 @@ clipboard_send_format_announce(void)
init_stream(s, 8192); init_stream(s, 8192);
out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */ out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */
out_uint16_le(s, 0); /* status */ out_uint16_le(s, 0); /* status */
out_uint32_le(s, 0x90); /* length */ out_uint32_le(s, 4 + sizeof(windows_native_format)); /* length */
out_uint32_le(s, 0x0d); /* extra 4 bytes ? */ out_uint32_le(s, format_id);
out_uint8s(s, 0x90); out_uint8p(s, windows_native_format, sizeof(windows_native_format));
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_announce: data out, sending " LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_announce: data out, sending "
@ -384,6 +379,39 @@ clipboard_out_unicode(struct stream* s, char* text, int num_chars)
return index * 2; return index * 2;
} }
/*****************************************************************************/
static int APP_CC
clipboard_send_data_response_for_image(void)
{
struct stream* s;
int size;
int rv;
LOG(10, ("clipboard_send_data_response_for_image: g_last_clip_size %d\n",
g_last_clip_size));
make_stream(s);
init_stream(s, 64 + g_last_clip_size);
out_uint16_le(s, 5); /* CLIPRDR_DATA_RESPONSE */
out_uint16_le(s, 1); /* status */
out_uint32_le(s, g_last_clip_size); /* length */
/* insert image data */
if (g_last_clip_type == g_image_bmp_atom)
{
/* do not insert first header */
out_uint8p(s, g_last_clip_data + 14, g_last_clip_size - 14);
}
out_uint16_le(s, 0); /* nil for string */
out_uint32_le(s, 0);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
s_mark_end(s);
size = (int)(s->end - s->data);
/* HANGING HERE WHEN IMAGE DATA IS TOO BIG!!!! */
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
}
/*****************************************************************************/ /*****************************************************************************/
static int APP_CC static int APP_CC
clipboard_send_data_response(void) clipboard_send_data_response(void)
@ -397,6 +425,10 @@ clipboard_send_data_response(void)
num_chars = 0; num_chars = 0;
if (g_last_clip_data != 0) if (g_last_clip_data != 0)
{ {
if (g_last_clip_type == g_image_bmp_atom)
{
return clipboard_send_data_response_for_image();
}
if ((g_last_clip_type == XA_STRING) || (g_last_clip_type == g_utf8_atom)) if ((g_last_clip_type == XA_STRING) || (g_last_clip_type == g_utf8_atom))
{ {
num_chars = g_mbstowcs(0, g_last_clip_data, 0); num_chars = g_mbstowcs(0, g_last_clip_data, 0);
@ -491,6 +523,9 @@ clipboard_refuse_selection(XSelectionRequestEvent* req)
} }
/*****************************************************************************/ /*****************************************************************************/
/* sent by client or server when its local system clipboard is
updated with new clipboard data; contains Clipboard Format ID
and name pairs of new Clipboard Formats on the clipboard. */
static int APP_CC static int APP_CC
clipboard_process_format_announce(struct stream* s, int clip_msg_status, clipboard_process_format_announce(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -510,6 +545,8 @@ clipboard_process_format_announce(struct stream* s, int clip_msg_status,
} }
/*****************************************************************************/ /*****************************************************************************/
/* response to CB_FORMAT_LIST; used to indicate whether
processing of the Format List PDU was successful */
static int APP_CC static int APP_CC
clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -520,6 +557,8 @@ clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status,
} }
/*****************************************************************************/ /*****************************************************************************/
/* sent by recipient of CB_FORMAT_LIST; used to request data for one
of the formats that was listed in CB_FORMAT_LIST */
static int APP_CC static int APP_CC
clipboard_process_data_request(struct stream* s, int clip_msg_status, clipboard_process_data_request(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -531,6 +570,67 @@ clipboard_process_data_request(struct stream* s, int clip_msg_status,
return 0; return 0;
} }
/*****************************************************************************/
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether
processing of the CB_FORMAT_DATA_REQUEST was successful; if processing
was successful, CB_FORMAT_DATA_RESPONSE includes contents of requested
clipboard data. */
static int APP_CC
clipboard_process_data_response_for_image(struct stream * s,
int clip_msg_status,
int clip_msg_len)
{
XSelectionRequestEvent* lxev = &g_saved_selection_req_event;
char* cptr;
char cdata;
int len;
int index;
LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: "
"CLIPRDR_DATA_RESPONSE_FOR_IMAGE"));
g_waiting_for_data_response = 0;
len = (int)(s->end - s->p);
if (len < 1)
{
return 0;
}
if (g_last_clip_type == g_image_bmp_atom)
{
/* space for inserting bmp image header */
len += 14;
cptr = (char*)g_malloc(len, 0);
if (cptr == 0)
{
return 0;
}
g_memcpy(cptr, g_bmp_image_header, 14);
index = 14;
}
else
{
return 0;
}
while (s_check(s))
{
in_uint8(s, cdata);
cptr[index++] = cdata;
}
if (len >= 0)
{
g_data_in = cptr;
g_data_in_size = len;
g_data_in_time = clipboard_get_local_time();
g_data_in_up_to_date = 1;
}
clipboard_provide_selection(lxev, lxev->target, 8, cptr, len);
return 0;
}
/*****************************************************************************/
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether
processing of the CB_FORMAT_DATA_REQUEST was successful; if processing was
successful, CB_FORMAT_DATA_RESPONSE includes contents of requested
clipboard data. */
/*****************************************************************************/ /*****************************************************************************/
static int APP_CC static int APP_CC
clipboard_process_data_response(struct stream* s, int clip_msg_status, clipboard_process_data_response(struct stream* s, int clip_msg_status,
@ -543,6 +643,12 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status,
int index; int index;
int data_in_len; int data_in_len;
if (g_want_image_data)
{
g_want_image_data = 0;
clipboard_process_data_response_for_image(s, clip_msg_status, clip_msg_len);
return 0;
}
LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: " LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: "
"CLIPRDR_DATA_RESPONSE")); "CLIPRDR_DATA_RESPONSE"));
g_waiting_for_data_response = 0; g_waiting_for_data_response = 0;
@ -584,7 +690,7 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status,
} }
g_data_in_size = len; g_data_in_size = len;
g_wcstombs(g_data_in, wtext, len + 1); g_wcstombs(g_data_in, wtext, len + 1);
g_data_in_time = clipboard_get_local_time(); g_data_in_time = xcommon_get_local_time();
g_data_in_up_to_date = 1; g_data_in_up_to_date = 1;
} }
if (g_data_in != 0) if (g_data_in != 0)
@ -645,19 +751,31 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
rv = 0; rv = 0;
switch (clip_msg_id) switch (clip_msg_id)
{ {
case 2: /* CLIPRDR_FORMAT_ANNOUNCE */ /* sent by client or server when its local system clipboard is */
/* updated with new clipboard data; contains Clipboard Format ID */
/* and name pairs of new Clipboard Formats on the clipboard. */
case CB_FORMAT_LIST: /* CLIPRDR_FORMAT_ANNOUNCE */
rv = clipboard_process_format_announce(ls, clip_msg_status, rv = clipboard_process_format_announce(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
case 3: /* CLIPRDR_FORMAT_ACK */ /* response to CB_FORMAT_LIST; used to indicate whether */
/* processing of the Format List PDU was successful */
case CB_FORMAT_LIST_RESPONSE: /* CLIPRDR_FORMAT_ACK */
rv = clipboard_prcoess_format_ack(ls, clip_msg_status, rv = clipboard_prcoess_format_ack(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
case 4: /* CLIPRDR_DATA_REQUEST */ /* sent by recipient of CB_FORMAT_LIST; used to request data for one */
/* of the formats that was listed in CB_FORMAT_LIST */
case CB_FORMAT_DATA_REQUEST: /* CLIPRDR_DATA_REQUEST */
rv = clipboard_process_data_request(ls, clip_msg_status, rv = clipboard_process_data_request(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
case 5: /* CLIPRDR_DATA_RESPONSE */ /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
/* whether processing of the CB_FORMAT_DATA_REQUEST was */
/* successful; if processing was successful, */
/* CB_FORMAT_DATA_RESPONSE includes contents of requested */
/* clipboard data. */
case CB_FORMAT_DATA_RESPONSE: /* CLIPRDR_DATA_RESPONSE */
rv = clipboard_process_data_response(ls, clip_msg_status, rv = clipboard_process_data_response(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
@ -673,7 +791,8 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
/*****************************************************************************/ /*****************************************************************************/
/* this happens when a new app copies something to the clipboard /* this happens when a new app copies something to the clipboard
'CLIPBOARD' Atom 'CLIPBOARD' Atom
typedef struct { typedef struct
{
int type; int type;
unsigned long serial; unsigned long serial;
Bool send_event; Bool send_event;
@ -684,7 +803,7 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
Atom selection; Atom selection;
Time timestamp; Time timestamp;
Time selection_timestamp; Time selection_timestamp;
} XFixesSelectionNotifyEvent; */ } XFixesSelectionNotifyEvent; */
static int APP_CC static int APP_CC
clipboard_event_selection_owner_notify(XEvent* xevent) clipboard_event_selection_owner_notify(XEvent* xevent)
{ {
@ -726,12 +845,28 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0, XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0,
AnyPropertyType, &ltype, &lfmt, &ln_items, AnyPropertyType, &ltype, &lfmt, &ln_items,
&llen_after, &lxdata); &llen_after, &lxdata);
if (lxdata != 0)
{
XFree(lxdata); XFree(lxdata);
}
if (ltype == 0) if (ltype == 0)
{ {
/* XGetWindowProperty failed */ /* XGetWindowProperty failed */
return 1; return 1;
} }
if (ltype == g_incr_atom)
{
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR start"));
g_incr_in_progress = 1;
g_incr_atom_type = prop;
g_incr_data_size = 0;
g_free(g_incr_data);
g_incr_data = 0;
XDeleteProperty(g_display, g_wnd, prop);
return 0;
}
if (llen_after < 1) if (llen_after < 1)
{ {
/* no data, ok */ /* no data, ok */
@ -745,20 +880,29 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
if (ltype == 0) if (ltype == 0)
{ {
/* XGetWindowProperty failed */ /* XGetWindowProperty failed */
if (lxdata != 0)
{
XFree(lxdata); XFree(lxdata);
}
return 1; return 1;
} }
lxdata_size = (lfmt / 8) * ln_items; lxdata_size = (lfmt / 8) * ln_items;
if (lxdata_size < 1) if (lxdata_size < 1)
{ {
/* should not happen */ /* should not happen */
if (lxdata != 0)
{
XFree(lxdata); XFree(lxdata);
}
return 2; return 2;
} }
if (llen_after > 0) if (llen_after > 0)
{ {
/* should not happen */ /* should not happen */
if (lxdata != 0)
{
XFree(lxdata); XFree(lxdata);
}
return 3; return 3;
} }
if (xdata != 0) if (xdata != 0)
@ -766,7 +910,10 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
*xdata = (char*)g_malloc(lxdata_size, 0); *xdata = (char*)g_malloc(lxdata_size, 0);
g_memcpy(*xdata, lxdata, lxdata_size); g_memcpy(*xdata, lxdata, lxdata_size);
} }
if (lxdata != 0)
{
XFree(lxdata); XFree(lxdata);
}
if (xdata_size != 0) if (xdata_size != 0)
{ {
*xdata_size = lxdata_size; *xdata_size = lxdata_size;
@ -812,10 +959,13 @@ clipboard_event_selection_notify(XEvent* xevent)
int index; int index;
int convert_to_string; int convert_to_string;
int convert_to_utf8; int convert_to_utf8;
int convert_to_bmp_image;
int send_format_announce; int send_format_announce;
int atom; int atom;
int* atoms; Atom* atoms;
Atom type; Atom type;
tui32 format_id;
char format_name[32];
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:")); LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:"));
data_size = 0; data_size = 0;
@ -823,11 +973,14 @@ clipboard_event_selection_notify(XEvent* xevent)
fmt = 0; fmt = 0;
convert_to_string = 0; convert_to_string = 0;
convert_to_utf8 = 0; convert_to_utf8 = 0;
convert_to_bmp_image = 0;
send_format_announce = 0; send_format_announce = 0;
format_id = 0;
rv = 0; rv = 0;
data = 0; data = 0;
type = 0; type = 0;
lxevent = (XSelectionEvent*)xevent; lxevent = (XSelectionEvent*)xevent;
g_memset(format_name, 0, 32);
if (lxevent->property == None) if (lxevent->property == None)
{ {
LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: clip could " LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: clip could "
@ -836,6 +989,13 @@ clipboard_event_selection_notify(XEvent* xevent)
} }
if (rv == 0) if (rv == 0)
{ {
/* we need this if the call below turns out to be a
clipboard INCR operation */
if (!g_incr_in_progress)
{
g_incr_atom_target = lxevent->target;
}
rv = clipboard_get_window_property(lxevent->requestor, lxevent->property, rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
&type, &fmt, &type, &fmt,
&n_items, &data, &data_size); &n_items, &data, &data_size);
@ -852,9 +1012,10 @@ clipboard_event_selection_notify(XEvent* xevent)
{ {
if (lxevent->target == g_targets_atom) if (lxevent->target == g_targets_atom)
{ {
/* on a 64 bit machine, actual_format_return of 32 implies long */
if ((type == XA_ATOM) && (fmt == 32)) if ((type == XA_ATOM) && (fmt == 32))
{ {
atoms = (int*)data; atoms = (Atom*)data;
for (index = 0; index < n_items; index++) for (index = 0; index < n_items; index++)
{ {
atom = atoms[index]; atom = atoms[index];
@ -868,6 +1029,10 @@ clipboard_event_selection_notify(XEvent* xevent)
{ {
convert_to_string = 1; convert_to_string = 1;
} }
else if (atom == g_image_bmp_atom)
{
convert_to_bmp_image = 1;
}
} }
} }
else else
@ -882,24 +1047,42 @@ clipboard_event_selection_notify(XEvent* xevent)
LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: UTF8_STRING " LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: UTF8_STRING "
"data_size %d", data_size)); "data_size %d", data_size));
g_free(g_last_clip_data); g_free(g_last_clip_data);
g_last_clip_data = 0;
g_last_clip_size = data_size; g_last_clip_size = data_size;
g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_data = g_malloc(g_last_clip_size + 1, 0);
g_last_clip_type = g_utf8_atom; g_last_clip_type = g_utf8_atom;
g_memcpy(g_last_clip_data, data, g_last_clip_size); g_memcpy(g_last_clip_data, data, g_last_clip_size);
g_last_clip_data[g_last_clip_size] = 0; g_last_clip_data[g_last_clip_size] = 0;
send_format_announce = 1; send_format_announce = 1;
format_id = CB_FORMAT_UNICODETEXT;
} }
else if (lxevent->target == XA_STRING) else if (lxevent->target == XA_STRING)
{ {
LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: XA_STRING " LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: XA_STRING "
"data_size %d", data_size)); "data_size %d", data_size));
g_free(g_last_clip_data); g_free(g_last_clip_data);
g_last_clip_data = 0;
g_last_clip_size = data_size; g_last_clip_size = data_size;
g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_data = g_malloc(g_last_clip_size + 1, 0);
g_last_clip_type = XA_STRING; g_last_clip_type = XA_STRING;
g_memcpy(g_last_clip_data, data, g_last_clip_size); g_memcpy(g_last_clip_data, data, g_last_clip_size);
g_last_clip_data[g_last_clip_size] = 0; g_last_clip_data[g_last_clip_size] = 0;
send_format_announce = 1; send_format_announce = 1;
format_id = CB_FORMAT_UNICODETEXT;
}
else if (lxevent->target == g_image_bmp_atom)
{
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: image/bmp "
"data_size %d", data_size));
g_free(g_last_clip_data);
g_last_clip_data = 0;
g_last_clip_size = data_size;
g_last_clip_data = g_malloc(data_size, 0);
g_last_clip_type = g_image_bmp_atom;
g_memcpy(g_last_clip_data, data, data_size);
send_format_announce = 1;
format_id = CB_FORMAT_DIB;
g_strcpy(format_name, "image/bmp");
} }
else else
{ {
@ -923,9 +1106,14 @@ clipboard_event_selection_notify(XEvent* xevent)
XConvertSelection(g_display, g_clipboard_atom, XA_STRING, XConvertSelection(g_display, g_clipboard_atom, XA_STRING,
g_clip_property_atom, g_wnd, lxevent->time); g_clip_property_atom, g_wnd, lxevent->time);
} }
else if (convert_to_bmp_image)
{
XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
g_clip_property_atom, g_wnd, lxevent->time);
}
if (send_format_announce) if (send_format_announce)
{ {
if (clipboard_send_format_announce() != 0) if (clipboard_send_format_announce(format_id, format_name) != 0)
{ {
rv = 4; rv = 4;
} }
@ -949,12 +1137,17 @@ clipboard_event_selection_notify(XEvent* xevent)
Atom property; Atom property;
Time time; Time time;
} XSelectionRequestEvent; */ } XSelectionRequestEvent; */
/*
* When XGetWindowProperty and XChangeProperty talk about "format 32" it
* doesn't mean a 32bit value, but actually a long. So 32 means 4 bytes on
* a 32bit machine and 8 bytes on a 64 machine
*/
static int APP_CC static int APP_CC
clipboard_event_selection_request(XEvent* xevent) clipboard_event_selection_request(XEvent* xevent)
{ {
//XEvent xev;
XSelectionRequestEvent* lxev; XSelectionRequestEvent* lxev;
tui32 ui32[8]; XEvent xev;
Atom atom_buf[10];
Atom type; Atom type;
int fmt; int fmt;
int n_items; int n_items;
@ -977,27 +1170,27 @@ clipboard_event_selection_request(XEvent* xevent)
/* requestor is asking what the selection can be converted to */ /* requestor is asking what the selection can be converted to */
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: "
"g_targets_atom")); "g_targets_atom"));
ui32[0] = g_targets_atom; atom_buf[0] = g_targets_atom;
ui32[1] = g_timestamp_atom; atom_buf[1] = g_timestamp_atom;
ui32[2] = g_multiple_atom; atom_buf[2] = g_multiple_atom;
ui32[3] = XA_STRING; atom_buf[3] = XA_STRING;
ui32[4] = g_utf8_atom; atom_buf[4] = g_utf8_atom;
return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)ui32, 5); atom_buf[5] = g_image_bmp_atom;
return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)atom_buf, 6);
} }
else if (lxev->target == g_timestamp_atom) else if (lxev->target == g_timestamp_atom)
{ {
/* requestor is asking the time I got the selection */ /* requestor is asking the time I got the selection */
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: "
"g_timestamp_atom")); "g_timestamp_atom"));
ui32[0] = g_selection_time; atom_buf[0] = g_selection_time;
return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)ui32, 1); return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)atom_buf, 1);
} }
else if (lxev->target == g_multiple_atom) else if (lxev->target == g_multiple_atom)
{ {
/* target, property pairs */ /* target, property pairs */
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: "
"g_multiple_atom")); "g_multiple_atom"));
#if 0
if (clipboard_get_window_property(xev.xselection.requestor, if (clipboard_get_window_property(xev.xselection.requestor,
xev.xselection.property, xev.xselection.property,
&type, &fmt, &n_items, &xdata, &type, &fmt, &n_items, &xdata,
@ -1008,12 +1201,12 @@ clipboard_event_selection_request(XEvent* xevent)
/* todo */ /* todo */
g_free(xdata); g_free(xdata);
} }
#endif
} }
else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom))
{ {
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: %s", LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: %s",
XGetAtomName(g_display, lxev->target))); XGetAtomName(g_display, lxev->target)));
clipboard_format_id = CB_FORMAT_UNICODETEXT;
if (g_data_in_up_to_date) if (g_data_in_up_to_date)
{ {
return clipboard_provide_selection(lxev, lxev->target, 8, return clipboard_provide_selection(lxev, lxev->target, 8,
@ -1032,12 +1225,24 @@ clipboard_event_selection_request(XEvent* xevent)
{ {
clipboard_send_data_request(); clipboard_send_data_request();
g_waiting_for_data_response = 1; g_waiting_for_data_response = 1;
g_waiting_for_data_response_time = clipboard_get_local_time(); g_waiting_for_data_response_time = xcommon_get_local_time();
} }
g_selection_request_event_count++; g_selection_request_event_count++;
return 0; return 0;
} }
} }
else if (lxev->target == g_image_bmp_atom)
{
g_memcpy(&g_saved_selection_req_event, lxev,
sizeof(g_saved_selection_req_event));
g_last_clip_type = g_image_bmp_atom;
g_want_image_data = 1;
clipboard_format_id = CB_FORMAT_DIB;
clipboard_send_data_request();
g_waiting_for_data_response = 1;
g_waiting_for_data_response_time = clipboard_get_local_time();
return 0;
}
else else
{ {
LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown " LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown "
@ -1081,92 +1286,132 @@ clipboard_event_selection_clear(XEvent* xevent)
static int APP_CC static int APP_CC
clipboard_event_property_notify(XEvent* xevent) clipboard_event_property_notify(XEvent* xevent)
{ {
Atom actual_type_return;
int actual_format_return;
unsigned long nitems_returned;
unsigned long bytes_left;
unsigned char* data;
int rv;
int format_in_bytes;
int new_data_len;
char* cptr;
char format_name[32];
LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d "
".state %d .atom %d", xevent->xproperty.window, ".state %d .atom %d", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom)); xevent->xproperty.state, xevent->xproperty.atom));
return 0; if (g_incr_in_progress &&
} (xevent->xproperty.atom == g_incr_atom_type) &&
(xevent->xproperty.state == PropertyNewValue))
/*****************************************************************************/ {
/* returns error rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, 0, 0,
this is called to get any wait objects for the main loop AnyPropertyType, &actual_type_return, &actual_format_return,
timeout can be nil */ &nitems_returned, &bytes_left, (unsigned char **) &data);
int APP_CC if (data != 0)
clipboard_get_wait_objs(tbus* objs, int* count, int* timeout) {
{ XFree(data);
int lcount; data = 0;
}
if (bytes_left <= 0)
{
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR done"));
g_memset(format_name, 0, 32);
/* clipboard INCR cycle has completed */
g_incr_in_progress = 0;
g_last_clip_size = g_incr_data_size;
g_last_clip_data = g_incr_data;
g_incr_data = 0;
g_last_clip_type = g_incr_atom_target;
if (g_incr_atom_target == g_image_bmp_atom)
{
g_snprintf(format_name, 31, "image/bmp");
clipboard_send_format_announce(CB_FORMAT_DIB, format_name);
}
XDeleteProperty(g_display, g_wnd, g_incr_atom_type);
}
else
{
rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, bytes_left, 0,
AnyPropertyType, &actual_type_return, &actual_format_return,
&nitems_returned, &bytes_left, (unsigned char **) &data);
if ((!g_clip_up) || (objs == 0) || (count == 0)) format_in_bytes = actual_format_return / 8;
if ((actual_format_return == 32) && (sizeof(long) == 8))
{
/* on a 64 bit machine, actual_format_return of 32 implies long */
format_in_bytes = 8;
}
new_data_len = nitems_returned * format_in_bytes;
cptr = (char*)g_malloc(g_incr_data_size + new_data_len, 0);
g_memcpy(cptr, g_incr_data, g_incr_data_size);
g_free(g_incr_data);
if (cptr == NULL)
{
g_incr_data = 0;
/* cannot add any more data */
if (data != 0)
{ {
XFree(data);
}
XDeleteProperty(g_display, g_wnd, g_incr_atom_type);
return 0; return 0;
} }
lcount = *count; g_incr_data = cptr;
objs[lcount] = g_x_wait_obj; g_memcpy(g_incr_data + g_incr_data_size, data, new_data_len);
lcount++; g_incr_data_size += new_data_len;
*count = lcount; if (data)
{
XFree(data);
}
XDeleteProperty(g_display, g_wnd, g_incr_atom_type);
}
}
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
/* returns 0, event handled, 1 unhandled */
int APP_CC int APP_CC
clipboard_check_wait_objs(void) clipboard_xevent(void* xevent)
{ {
XEvent xevent; XEvent* lxevent;
int time_diff;
if (!g_clip_up) if (!g_clip_up)
{ {
return 0; return 1;
}
if (g_is_wait_obj_set(g_x_wait_obj))
{
if (XPending(g_display) < 1)
{
/* something is wrong, should not get here */
LOGM((LOG_LEVEL_ERROR, "clipboard_check_wait_objs: sck closed"));
return 0;
}
if (g_waiting_for_data_response)
{
time_diff = clipboard_get_local_time() -
g_waiting_for_data_response_time;
if (time_diff > 1000)
{
LOGM((LOG_LEVEL_ERROR, "clipboard_check_wait_objs: warning, "
"waiting for data response too long"));
}
} }
while (XPending(g_display) > 0) lxevent = (XEvent*)xevent;
{ switch (lxevent->type)
XNextEvent(g_display, &xevent);
switch (xevent.type)
{ {
case SelectionNotify: case SelectionNotify:
clipboard_event_selection_notify(&xevent); clipboard_event_selection_notify(lxevent);
break; break;
case SelectionRequest: case SelectionRequest:
clipboard_event_selection_request(&xevent); clipboard_event_selection_request(lxevent);
break; break;
case SelectionClear: case SelectionClear:
clipboard_event_selection_clear(&xevent); clipboard_event_selection_clear(lxevent);
break; break;
case MappingNotify: case MappingNotify:
break; break;
case PropertyNotify: case PropertyNotify:
clipboard_event_property_notify(&xevent); clipboard_event_property_notify(lxevent);
break;
case UnmapNotify:
LOG(0, ("chansrv::clipboard_xevent: got UnmapNotify"));
break;
case ClientMessage:
LOG(0, ("chansrv::clipboard_xevent: got ClientMessage"));
break; break;
default: default:
if (xevent.type == g_xfixes_event_base + if (lxevent->type == g_xfixes_event_base +
XFixesSetSelectionOwnerNotify) XFixesSetSelectionOwnerNotify)
{ {
clipboard_event_selection_owner_notify(&xevent); clipboard_event_selection_owner_notify(lxevent);
break;
}
LOGM((LOG_LEVEL_ERROR, "clipboard_check_wait_objs unknown type %d",
xevent.type));
break; break;
} }
} /* we didn't handle this message */
return 1;
} }
return 0; return 0;
} }

@ -2,6 +2,7 @@
* xrdp: A Remote Desktop Protocol server. * xrdp: A Remote Desktop Protocol server.
* *
* Copyright (C) Jay Sorg 2009-2012 * Copyright (C) Jay Sorg 2009-2012
* Copyright (C) Laxmikant Rashinkar 2012
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +23,22 @@
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
#define CB_FORMAT_LIST 2
#define CB_FORMAT_LIST_RESPONSE 3
#define CB_FORMAT_DATA_REQUEST 4
#define CB_FORMAT_DATA_RESPONSE 5
/* Clipboard Formats */
#define CB_FORMAT_RAW 0x0000
#define CB_FORMAT_TEXT 0x0001
#define CB_FORMAT_DIB 0x0008
#define CB_FORMAT_UNICODETEXT 0x000D
#define CB_FORMAT_HTML 0xD010
#define CB_FORMAT_PNG 0xD011
#define CB_FORMAT_JPEG 0xD012
#define CB_FORMAT_GIF 0xD013
int APP_CC int APP_CC
clipboard_init(void); clipboard_init(void);
int APP_CC int APP_CC
@ -30,8 +47,6 @@ int APP_CC
clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
int total_length); int total_length);
int APP_CC int APP_CC
clipboard_get_wait_objs(tbus* objs, int* count, int* timeout); clipboard_xevent(void* xevent);
int APP_CC
clipboard_check_wait_objs(void);
#endif #endif

@ -22,6 +22,656 @@
*/ */
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include "chansrv.h"
#include "rail.h" #include "rail.h"
#include "xcommon.h" #include "xcommon.h"
#include "log.h" #include "log.h"
#include "os_calls.h"
#include "thread_calls.h"
extern int g_rail_chan_id; /* in chansrv.c */
extern int g_display_num; /* in chansrv.c */
extern char* g_exec_name; /* in chansrv.c */
extern tbus g_exec_event; /* in chansrv.c */
extern tbus g_exec_mutex; /* in chansrv.c */
extern tbus g_exec_sem; /* in chansrv.c */
extern Display* g_display; /* in xcommon.c */
extern Screen* g_screen; /* in xcommon.c */
extern Window g_root_window; /* in xcommon.c */
extern Atom g_wm_delete_window_atom; /* in xcommon.c */
extern Atom g_wm_protocols_atom; /* in xcommon.c */
int g_rail_up = 0;
/* for rail_is_another_wm_running */
static int g_rail_running = 1;
/* Indicates a Client Execute PDU from client to server. */
#define TS_RAIL_ORDER_EXEC 0x0001
/* Indicates a Client Activate PDU from client to server. */
#define TS_RAIL_ORDER_ACTIVATE 0x0002
/* Indicates a Client System Parameters Update PDU from client
to server or a Server System Parameters Update PDU
from server to client. */
#define TS_RAIL_ORDER_SYSPARAM 0x0003
/* Indicates a Client System Command PDU from client to server. */
#define TS_RAIL_ORDER_SYSCOMMAND 0x0004
/* Indicates a bi-directional Handshake PDU. */
#define TS_RAIL_ORDER_HANDSHAKE 0x0005
/* Indicates a Client Notify Event PDU from client to server. */
#define TS_RAIL_ORDER_NOTIFY_EVENT 0x0006
/* Indicates a Client Window Move PDU from client to server. */
#define TS_RAIL_ORDER_WINDOWMOVE 0x0008
/* Indicates a Server Move/Size Start PDU and a Server Move/Size
End PDU from server to client. */
#define TS_RAIL_ORDER_LOCALMOVESIZE 0x0009
/* Indicates a Server Min Max Info PDU from server to client. */
#define TS_RAIL_ORDER_MINMAXINFO 0x000a
/* Indicates a Client Information PDU from client to server. */
#define TS_RAIL_ORDER_CLIENTSTATUS 0x000b
/* Indicates a Client System Menu PDU from client to server. */
#define TS_RAIL_ORDER_SYSMENU 0x000c
/* Indicates a Server Language Bar Information PDU from server to
client, or a Client Language Bar Information PDU from client to server. */
#define TS_RAIL_ORDER_LANGBARINFO 0x000d
/* Indicates a Server Execute Result PDU from server to client. */
#define TS_RAIL_ORDER_EXEC_RESULT 0x0080
/* Indicates a Client Get Application ID PDU from client to server. */
#define TS_RAIL_ORDER_GET_APPID_REQ 0x000E
/* Indicates a Server Get Application ID Response PDU from
server to client. */
#define TS_RAIL_ORDER_GET_APPID_RESP 0x000F
/* Resize the window. */
#define SC_SIZE 0xF000
/* Move the window. */
#define SC_MOVE 0xF010
/* Minimize the window. */
#define SC_MINIMIZE 0xF020
/* Maximize the window. */
#define SC_MAXIMIZE 0xF030
/* Close the window. */
#define SC_CLOSE 0xF060
/* The ALT + SPACE key combination was pressed; display
the window's system menu. */
#define SC_KEYMENU 0xF100
/* Restore the window to its original shape and size. */
#define SC_RESTORE 0xF120
/* Perform the default action of the window's system menu. */
#define SC_DEFAULT 0xF160
/******************************************************************************/
static int APP_CC
is_window_valid_child_of_root(unsigned int window_id)
{
int found;
unsigned int i;
unsigned int nchild;
Window r;
Window p;
Window* children;
found = 0;
XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild);
for (i = 0; i < nchild; i++)
{
if (window_id == children[i])
{
found = 1;
break;
}
}
XFree(children);
return found;
}
/*****************************************************************************/
static int APP_CC
rail_send_init(void)
{
struct stream* s;
int bytes;
char* size_ptr;
LOG(10, ("chansrv::rail_send_init:"));
make_stream(s);
init_stream(s, 8182);
out_uint16_le(s, TS_RAIL_ORDER_HANDSHAKE);
size_ptr = s->p;
out_uint16_le(s, 0); /* size, set later */
out_uint32_le(s, 1); /* build number */
s_mark_end(s);
bytes = (int)((s->end - s->data) - 4);
size_ptr[0] = bytes;
size_ptr[1] = bytes >> 8;
bytes = (int)(s->end - s->data);
send_channel_data(g_rail_chan_id, s->data, bytes);
free_stream(s);
return 0;
}
/******************************************************************************/
static int DEFAULT_CC
anotherWMRunning(Display* display, XErrorEvent* xe)
{
g_rail_running = 0;
return -1;
}
/******************************************************************************/
static int APP_CC
rail_is_another_wm_running(void)
{
XErrorHandler old;
g_rail_running = 1;
old = XSetErrorHandler((XErrorHandler)anotherWMRunning);
XSelectInput(g_display, g_root_window,
PropertyChangeMask | StructureNotifyMask |
SubstructureRedirectMask | ButtonPressMask |
SubstructureNotifyMask | FocusChangeMask |
EnterWindowMask | LeaveWindowMask);
XSync(g_display, 0);
XSetErrorHandler((XErrorHandler)old);
g_rail_up = g_rail_running;
if (!g_rail_up)
{
return 1;
}
return 0;
}
/*****************************************************************************/
int APP_CC
rail_init(void)
{
LOG(10, ("chansrv::rail_init:"));
xcommon_init();
if (rail_is_another_wm_running())
{
log_message(LOG_LEVEL_ERROR, "rail_init: another window manager "
"is running");
}
rail_send_init();
g_rail_up = 1;
return 0;
}
/*****************************************************************************/
int APP_CC
rail_deinit(void)
{
if (g_rail_up)
{
/* no longer window manager */
XSelectInput(g_display, g_root_window, 0);
g_rail_up = 0;
}
return 0;
}
/*****************************************************************************/
static char* APP_CC
read_uni(struct stream* s, int num_chars)
{
twchar* rchrs;
char* rv;
int index;
int lchars;
rchrs = 0;
rv = 0;
if (num_chars > 0)
{
rchrs = (twchar*)g_malloc((num_chars + 1) * sizeof(twchar), 0);
for (index = 0; index < num_chars; index++)
{
in_uint16_le(s, rchrs[index]);
}
rchrs[num_chars] = 0;
lchars = g_wcstombs(0, rchrs, 0);
if (lchars > 0)
{
rv = (char*)g_malloc((lchars + 1) * 4, 0);
g_wcstombs(rv, rchrs, lchars);
rv[lchars] = 0;
}
}
g_free(rchrs);
return rv;
}
/*****************************************************************************/
static int APP_CC
rail_process_exec(struct stream* s, int size)
{
int pid;
int flags;
int ExeOrFileLength;
int WorkingDirLength;
int ArgumentsLen;
char* ExeOrFile;
char* WorkingDir;
char* Arguments;
LOG(0, ("chansrv::rail_process_exec:"));
in_uint16_le(s, flags);
in_uint16_le(s, ExeOrFileLength);
in_uint16_le(s, WorkingDirLength);
in_uint16_le(s, ArgumentsLen);
ExeOrFile = read_uni(s, ExeOrFileLength);
WorkingDir = read_uni(s, WorkingDirLength);
Arguments = read_uni(s, ArgumentsLen);
LOG(10, (" flags 0x%8.8x ExeOrFileLength %d WorkingDirLength %d "
"ArgumentsLen %d ExeOrFile [%s] WorkingDir [%s] "
"Arguments [%s]", flags, ExeOrFileLength, WorkingDirLength,
ArgumentsLen, ExeOrFile, WorkingDir, Arguments));
if (g_strlen(ExeOrFile) > 0)
{
LOG(10, ("rail_process_exec: pre"));
/* ask main thread to fork */
tc_mutex_lock(g_exec_mutex);
g_exec_name = ExeOrFile;
g_set_wait_obj(g_exec_event);
tc_sem_dec(g_exec_sem);
tc_mutex_unlock(g_exec_mutex);
LOG(10, ("rail_process_exec: post"));
}
g_free(ExeOrFile);
g_free(WorkingDir);
g_free(Arguments);
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_activate(struct stream* s, int size)
{
int window_id;
int enabled;
LOG(10, ("chansrv::rail_process_activate:"));
in_uint32_le(s, window_id);
in_uint8(s, enabled);
LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled));
if (enabled)
{
LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id));
XRaiseWindow(g_display, window_id);
LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id));
XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime);
}
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_system_param(struct stream* s, int size)
{
int system_param;
LOG(10, ("chansrv::rail_process_system_param:"));
in_uint32_le(s, system_param);
LOG(10, (" system_param 0x%8.8x", system_param));
return 0;
}
/******************************************************************************/
static int APP_CC
rail_close_window(int window_id)
{
XEvent ce;
LOG(0, ("chansrv::rail_close_window:"));
g_memset(&ce, 0, sizeof(ce));
ce.xclient.type = ClientMessage;
ce.xclient.message_type = g_wm_protocols_atom;
ce.xclient.display = g_display;
ce.xclient.window = window_id;
ce.xclient.format = 32;
ce.xclient.data.l[0] = g_wm_delete_window_atom;
ce.xclient.data.l[1] = CurrentTime;
XSendEvent(g_display, window_id, False, NoEventMask, &ce);
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_system_command(struct stream* s, int size)
{
int window_id;
int command;
LOG(10, ("chansrv::rail_process_system_command:"));
in_uint32_le(s, window_id);
in_uint16_le(s, command);
switch (command)
{
case SC_SIZE:
LOG(10, (" window_id 0x%8.8x SC_SIZE", window_id));
break;
case SC_MOVE:
LOG(10, (" window_id 0x%8.8x SC_MOVE", window_id));
break;
case SC_MINIMIZE:
LOG(10, (" window_id 0x%8.8x SC_MINIMIZE", window_id));
break;
case SC_MAXIMIZE:
LOG(10, (" window_id 0x%8.8x SC_MAXIMIZE", window_id));
break;
case SC_CLOSE:
LOG(10, (" window_id 0x%8.8x SC_CLOSE", window_id));
rail_close_window(window_id);
break;
case SC_KEYMENU:
LOG(10, (" window_id 0x%8.8x SC_KEYMENU", window_id));
break;
case SC_RESTORE:
LOG(10, (" window_id 0x%8.8x SC_RESTORE", window_id));
break;
case SC_DEFAULT:
LOG(10, (" window_id 0x%8.8x SC_DEFAULT", window_id));
break;
default:
LOG(10, (" window_id 0x%8.8x unknown command command %d",
window_id, command));
break;
}
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_handshake(struct stream* s, int size)
{
int build_number;
LOG(10, ("chansrv::rail_process_handshake:"));
in_uint32_le(s, build_number);
LOG(10, (" build_number 0x%8.8x", build_number));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_notify_event(struct stream* s, int size)
{
int window_id;
int notify_id;
int message;
LOG(10, ("chansrv::rail_process_notify_event:"));
in_uint32_le(s, window_id);
in_uint32_le(s, notify_id);
in_uint32_le(s, message);
LOG(10, (" window_id 0x%8.8x notify_id 0x%8.8x message 0x%8.8x",
window_id, notify_id, message));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_window_move(struct stream* s, int size)
{
int window_id;
int left;
int top;
int right;
int bottom;
LOG(10, ("chansrv::rail_process_window_move:"));
in_uint32_le(s, window_id);
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
LOG(10, (" window_id 0x%8.8x left %d top %d right %d bottom %d width %d height %d",
window_id, left, top, right, bottom, right - left, bottom - top));
XMoveResizeWindow(g_display, window_id, left, top, right - left, bottom - top);
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_local_move_size(struct stream* s, int size)
{
int window_id;
int is_move_size_start;
int move_size_type;
int pos_x;
int pos_y;
LOG(10, ("chansrv::rail_process_local_move_size:"));
in_uint32_le(s, window_id);
in_uint16_le(s, is_move_size_start);
in_uint16_le(s, move_size_type);
in_uint16_le(s, pos_x);
in_uint16_le(s, pos_y);
LOG(10, (" window_id 0x%8.8x is_move_size_start %d move_size_type %d "
"pos_x %d pos_y %d", window_id, is_move_size_start, move_size_type,
pos_x, pos_y));
return 0;
}
/*****************************************************************************/
/* server to client only */
static int APP_CC
rail_process_min_max_info(struct stream* s, int size)
{
LOG(10, ("chansrv::rail_process_min_max_info:"));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_client_status(struct stream* s, int size)
{
int flags;
LOG(10, ("chansrv::rail_process_client_status:"));
in_uint32_le(s, flags);
LOG(10, (" flags 0x%8.8x", flags));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_sys_menu(struct stream* s, int size)
{
int window_id;
int left;
int top;
LOG(10, ("chansrv::rail_process_sys_menu:"));
in_uint32_le(s, window_id);
in_uint16_le(s, left);
in_uint16_le(s, top);
LOG(10, (" window_id 0x%8.8x left %d top %d", window_id, left, top));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_lang_bar_info(struct stream* s, int size)
{
int language_bar_status;
LOG(10, ("chansrv::rail_process_lang_bar_info:"));
in_uint32_le(s, language_bar_status);
LOG(10, (" language_bar_status 0x%8.8x", language_bar_status));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_appid_req(struct stream* s, int size)
{
LOG(10, ("chansrv::rail_process_appid_req:"));
return 0;
}
/*****************************************************************************/
static int APP_CC
rail_process_appid_resp(struct stream* s, int size)
{
LOG(10, ("chansrv::rail_process_appid_resp:"));
return 0;
}
/*****************************************************************************/
/* server to client only */
static int APP_CC
rail_process_exec_result(struct stream* s, int size)
{
LOG(10, ("chansrv::rail_process_exec_result:"));
return 0;
}
/*****************************************************************************/
/* data in from client ( client -> xrdp -> chansrv ) */
int APP_CC
rail_data_in(struct stream* s, int chan_id, int chan_flags, int length,
int total_length)
{
int code;
int size;
LOG(10, ("chansrv::rail_data_in:"));
in_uint8(s, code);
in_uint8s(s, 1);
in_uint16_le(s, size);
switch (code)
{
case TS_RAIL_ORDER_EXEC: /* 1 */
rail_process_exec(s, size);
break;
case TS_RAIL_ORDER_ACTIVATE: /* 2 */
rail_process_activate(s, size);
break;
case TS_RAIL_ORDER_SYSPARAM: /* 3 */
rail_process_system_param(s, size);
break;
case TS_RAIL_ORDER_SYSCOMMAND: /* 4 */
rail_process_system_command(s, size);
break;
case TS_RAIL_ORDER_HANDSHAKE: /* 5 */
rail_process_handshake(s, size);
break;
case TS_RAIL_ORDER_NOTIFY_EVENT: /* 6 */
rail_process_notify_event(s, size);
break;
case TS_RAIL_ORDER_WINDOWMOVE: /* 8 */
rail_process_window_move(s, size);
break;
case TS_RAIL_ORDER_LOCALMOVESIZE: /* 9 */
rail_process_local_move_size(s, size);
break;
case TS_RAIL_ORDER_MINMAXINFO: /* 10 */
rail_process_min_max_info(s, size);
break;
case TS_RAIL_ORDER_CLIENTSTATUS: /* 11 */
rail_process_client_status(s, size);
break;
case TS_RAIL_ORDER_SYSMENU: /* 12 */
rail_process_sys_menu(s, size);
break;
case TS_RAIL_ORDER_LANGBARINFO: /* 13 */
rail_process_lang_bar_info(s, size);
break;
case TS_RAIL_ORDER_GET_APPID_REQ: /* 14 */
rail_process_appid_req(s, size);
break;
case TS_RAIL_ORDER_GET_APPID_RESP: /* 15 */
rail_process_appid_resp(s, size);
break;
case TS_RAIL_ORDER_EXEC_RESULT: /* 128 */
rail_process_exec_result(s, size);
break;
default:
LOG(10, ("rail_data_in: unknown code %d size %d", code, size));
break;
}
XFlush(g_display);
return 0;
}
/*****************************************************************************/
/* returns 0, event handled, 1 unhandled */
int APP_CC
rail_xevent(void* xevent)
{
XEvent* lxevent;
XWindowChanges xwc;
int rv;
int nchildren_return = 0;
Window root_return;
Window parent_return;
Window *children_return;
Window wreturn;
int revert_to;
XWindowAttributes wnd_attributes;
LOG(10, ("chansrv::rail_xevent:"));
if (!g_rail_up)
{
return 1;
}
rv = 1;
lxevent = (XEvent*)xevent;
switch (lxevent->type)
{
case ConfigureRequest:
LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window));
g_memset(&xwc, 0, sizeof(xwc));
xwc.x = lxevent->xconfigurerequest.x;
xwc.y = lxevent->xconfigurerequest.y;
xwc.width = lxevent->xconfigurerequest.width;
xwc.height = lxevent->xconfigurerequest.height;
xwc.border_width = lxevent->xconfigurerequest.border_width;
xwc.sibling = lxevent->xconfigurerequest.above;
xwc.stack_mode = lxevent->xconfigurerequest.detail;
XConfigureWindow(g_display,
lxevent->xconfigurerequest.window,
lxevent->xconfigurerequest.value_mask,
&xwc);
rv = 0;
break;
case MapRequest:
LOG(10, (" got MapRequest"));
XMapWindow(g_display, lxevent->xmaprequest.window);
rv = 0;
break;
case MapNotify:
LOG(10, (" got MapNotify"));
break;
case UnmapNotify:
LOG(10, (" got UnmapNotify"));
break;
case ConfigureNotify:
LOG(10, (" got ConfigureNotify"));
break;
case FocusIn:
LOG(10, (" got FocusIn"));
break;
case ButtonPress:
LOG(10, (" got ButtonPress"));
break;
case EnterNotify:
LOG(10, (" got EnterNotify"));
break;
case LeaveNotify:
LOG(10, (" got LeaveNotify"));
break;
}
return rv;
}

@ -19,4 +19,17 @@
#ifndef _RAIL_H_ #ifndef _RAIL_H_
#define _RAIL_H_ #define _RAIL_H_
#include "arch.h"
#include "parse.h"
int APP_CC
rail_init(void);
int APP_CC
rail_deinit(void);
int APP_CC
rail_data_in(struct stream* s, int chan_id, int chan_flags,
int length, int total_length);
int APP_CC
rail_xevent(void* xevent);
#endif #endif

@ -25,3 +25,163 @@
#include "clipboard.h" #include "clipboard.h"
#include "rail.h" #include "rail.h"
extern int g_clip_up; /* in clipboard.c */
extern int g_waiting_for_data_response; /* in clipboard.c */
extern int g_waiting_for_data_response_time; /* in clipboard.c */
extern int g_rail_up; /* in rail.c */
Display* g_display = 0;
int g_x_socket = 0;
tbus g_x_wait_obj = 0;
Screen* g_screen = 0;
int g_screen_num = 0;
Window g_root_window = 0;
Atom g_wm_delete_window_atom = 0;
Atom g_wm_protocols_atom = 0;
/*****************************************************************************/
static int DEFAULT_CC
xcommon_error_handler(Display* dis, XErrorEvent* xer)
{
char text[256];
XGetErrorText(dis, xer->error_code, text, 255);
LOGM((LOG_LEVEL_ERROR, "X error [%s](%d) opcodes %d/%d "
"resource 0x%lx", text, xer->error_code,
xer->request_code, xer->minor_code, xer->resourceid));
return 0;
}
/*****************************************************************************/
/* The X server had an internal error. This is the last function called.
Do any cleanup that needs to be done on exit, like removing temporary files.
Don't worry about memory leaks */
static int DEFAULT_CC
xcommon_fatal_handler(Display* dis)
{
return 0;
}
/*****************************************************************************/
/* returns time in miliseconds
this is like g_time2 in os_calls, but not miliseconds since machine was
up, something else
this is a time value similar to what the xserver uses */
int APP_CC
xcommon_get_local_time(void)
{
return g_time3();
}
/******************************************************************************/
/* this should be called first */
int APP_CC
xcommon_init(void)
{
if (g_display != 0)
{
LOG(10, ("xcommon_init: xcommon_init already called"));
return 0;
}
g_display = XOpenDisplay(0);
if (g_display == 0)
{
LOGM((LOG_LEVEL_ERROR, "xcommon_init: error, XOpenDisplay failed"));
return 1;
}
LOG(0, ("xcommon_init: connected to display ok"));
/* setting the error handlers can cause problem when shutting down
chansrv on some xlibs */
XSetErrorHandler(xcommon_error_handler);
//XSetIOErrorHandler(xcommon_fatal_handler);
g_x_socket = XConnectionNumber(g_display);
if (g_x_socket == 0)
{
LOGM((LOG_LEVEL_ERROR, "xcommon_init: XConnectionNumber failed"));
return 1;
}
g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0);
g_screen_num = DefaultScreen(g_display);
g_screen = ScreenOfDisplay(g_display, g_screen_num);
g_root_window = RootWindowOfScreen(g_screen);
g_wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", 0);
g_wm_protocols_atom = XInternAtom(g_display, "WM_PROTOCOLS", 0);
return 0;
}
/*****************************************************************************/
/* returns error
this is called to get any wait objects for the main loop
timeout can be nil */
int APP_CC
xcommon_get_wait_objs(tbus* objs, int* count, int* timeout)
{
int lcount;
if (((!g_clip_up) && (!g_rail_up)) || (objs == 0) || (count == 0))
{
LOG(10, ("xcommon_get_wait_objs: nothing to do"));
return 0;
}
lcount = *count;
objs[lcount] = g_x_wait_obj;
lcount++;
*count = lcount;
return 0;
}
/*****************************************************************************/
int APP_CC
xcommon_check_wait_objs(void)
{
XEvent xevent;
int time_diff;
int clip_rv;
int rail_rv;
if ((!g_clip_up) && (!g_rail_up))
{
LOG(10, ("xcommon_check_wait_objs: nothing to do"));
return 0;
}
if (g_is_wait_obj_set(g_x_wait_obj))
{
if (XPending(g_display) < 1)
{
/* something is wrong, should not get here */
LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: sck closed"));
return 0;
}
if (g_waiting_for_data_response)
{
time_diff = xcommon_get_local_time() -
g_waiting_for_data_response_time;
if (time_diff > 10000)
{
LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, "
"waiting for data response too long"));
}
}
while (XPending(g_display) > 0)
{
g_memset(&xevent, 0, sizeof(xevent));
XNextEvent(g_display, &xevent);
clip_rv = clipboard_xevent(&xevent);
rail_rv = rail_xevent(&xevent);
if ((clip_rv == 1) && (rail_rv == 1))
{
LOG(10, ("xcommon_check_wait_objs unknown xevent type %d", xevent.type));
}
}
}
return 0;
}

@ -22,11 +22,11 @@
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
int APP_CC
xcommon_init(void);
int APP_CC int APP_CC
xcommon_get_local_time(void); xcommon_get_local_time(void);
int APP_CC int APP_CC
xcommon_init(void);
int APP_CC
xcommon_get_wait_objs(tbus* objs, int* count, int* timeout); xcommon_get_wait_objs(tbus* objs, int* count, int* timeout);
int APP_CC int APP_CC
xcommon_check_wait_objs(void); xcommon_check_wait_objs(void);

@ -15,7 +15,8 @@ bin_PROGRAMS = \
xrdp-sesrun \ xrdp-sesrun \
xrdp-sestest \ xrdp-sestest \
xrdp-sesadmin \ xrdp-sesadmin \
xrdp-dis xrdp-dis \
xrdp-xcon
xrdp_sesrun_SOURCES = \ xrdp_sesrun_SOURCES = \
sesrun.c \ sesrun.c \
@ -31,6 +32,9 @@ xrdp_sesadmin_SOURCES = \
xrdp_dis_SOURCES = \ xrdp_dis_SOURCES = \
dis.c dis.c
xrdp_xcon_SOURCES = \
xcon.c
xrdp_sesrun_LDADD = \ xrdp_sesrun_LDADD = \
$(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommon.la
@ -41,3 +45,7 @@ xrdp_sestest_LDADD = \
xrdp_sesadmin_LDADD = \ xrdp_sesadmin_LDADD = \
$(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommon.la \
$(top_builddir)/sesman/libscp/libscp.la $(top_builddir)/sesman/libscp/libscp.la
xrdp_xcon_LDADD = \
-L/usr/X11R6/lib \
-lX11

@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
Display* g_display = 0;
int g_x_socket = 0;
int main(int argc, char** argv)
{
fd_set rfds;
int i1;
XEvent xevent;
g_display = XOpenDisplay(0);
if (g_display == 0)
{
printf("XOpenDisplay failed\n");
return 0;
}
g_x_socket = XConnectionNumber(g_display);
while (1)
{
FD_ZERO(&rfds);
FD_SET(g_x_socket, &rfds);
i1 = select(g_x_socket + 1, &rfds, 0, 0, 0);
if (i1 < 0)
{
break;
}
XNextEvent(g_display, &xevent);
}
return 0;
}

@ -19,9 +19,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# flex bison libxml2-dev intltool # debian packages needed
# xsltproc # flex bison libxml2-dev intltool xsltproc xutils-dev python-libxml2 g++ xutils
# xutils-dev python-libxml2
download_file() download_file()
{ {
@ -222,7 +221,7 @@ make_it()
echo "*** processing module $mod_name ($count of $num_modules) ***" echo "*** processing module $mod_name ($count of $num_modules) ***"
echo "" echo ""
extract_it $mod_file $mod_name $mod_args extract_it $mod_file $mod_name "$mod_args"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "" echo ""
echo "extract failed for module $mod_name" echo "extract failed for module $mod_name"

@ -57,6 +57,7 @@ CFLAGS = -O2 -Wall -fno-strength-reduce \
-I../../render \ -I../../render \
-I../xfree86/common \ -I../xfree86/common \
-I../xfree86/os-support \ -I../xfree86/os-support \
-I../../../common \
-D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_REENTRANT \ -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_REENTRANT \
-DGLX_USE_MESA -DXRECORD -D_GNU_SOURCE -DXAPPGROUP \ -DGLX_USE_MESA -DXRECORD -D_GNU_SOURCE -DXAPPGROUP \
-DTOGCUP -DSINGLEDEPTH -DXFree86Server \ -DTOGCUP -DSINGLEDEPTH -DXFree86Server \

@ -70,7 +70,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "exevents.h" #include "exevents.h"
#include "xserver-properties.h" #include "xserver-properties.h"
#include "xkbsrv.h" #include "xkbsrv.h"
#include "../../../common/xrdp_client_info.h" /* in xrdp/common */
#include "xrdp_client_info.h"
#include "xrdp_constants.h"
//#include "colormapst.h" //#include "colormapst.h"
@ -175,12 +177,79 @@ typedef rdpWindowRec* rdpWindowPtr;
#define GETWINPRIV(_pWindow) \ #define GETWINPRIV(_pWindow) \
(rdpWindowPtr)dixGetPrivateAddr(&(_pWindow->devPrivates), &g_rdpWindowIndex) (rdpWindowPtr)dixGetPrivateAddr(&(_pWindow->devPrivates), &g_rdpWindowIndex)
#define XR_IS_ROOT(_pWindow) ((_pWindow)->drawable.pScreen->root == (_pWindow))
/* for tooltips */
#define XR_STYLE_TOOLTIP (0x80000000)
#define XR_EXT_STYLE_TOOLTIP (0x00000080 | 0x00000008)
/* for normal desktop windows */
/* WS_TILEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
WS_MINIMIZEBOX | WS_MAXIMIZEBOX) */
#define XR_STYLE_NORMAL (0x00C00000 | 0x00080000 | 0x00040000 | 0x00010000 | 0x00020000)
#define XR_EXT_STYLE_NORMAL (0x00040000)
/* for dialogs */
#define XR_STYLE_DIALOG (0x80000000)
#define XR_EXT_STYLE_DIALOG (0x00040000)
#define RDI_FILL 1
#define RDI_IMGLL 2 /* lossless */
#define RDI_IMGLY 3 /* lossy */
#define RDI_LINE 4
struct urdp_draw_item_fill
{
int opcode;
int fg_color;
int bg_color;
int pad0;
};
struct urdp_draw_item_img
{
int opcode;
int pad0;
};
struct urdp_draw_item_line
{
int opcode;
int fg_color;
int bg_color;
int width;
xSegment* segs;
int nseg;
int flags;
};
union urdp_draw_item
{
struct urdp_draw_item_fill fill;
struct urdp_draw_item_img img;
struct urdp_draw_item_line line;
};
struct rdp_draw_item
{
int type;
int flags;
struct rdp_draw_item* prev;
struct rdp_draw_item* next;
RegionPtr reg;
union urdp_draw_item u;
};
struct _rdpPixmapRec struct _rdpPixmapRec
{ {
int status; int status;
int rdpindex; int rdpindex;
int allocBytes; int allocBytes;
int con_number; int con_number;
int is_dirty;
int pad0;
struct rdp_draw_item* draw_item_head;
struct rdp_draw_item* draw_item_tail;
}; };
typedef struct _rdpPixmapRec rdpPixmapRec; typedef struct _rdpPixmapRec rdpPixmapRec;
typedef rdpPixmapRec* rdpPixmapPtr; typedef rdpPixmapRec* rdpPixmapPtr;
@ -242,11 +311,34 @@ int
g_chmod_hex(const char* filename, int flags); g_chmod_hex(const char* filename, int flags);
void void
hexdump(unsigned char *p, unsigned int len); hexdump(unsigned char *p, unsigned int len);
void
RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg);
/* rdpdraw.c */ /* rdpdraw.c */
Bool Bool
rdpCloseScreen(int i, ScreenPtr pScreen); rdpCloseScreen(int i, ScreenPtr pScreen);
int
draw_item_add(rdpPixmapRec* priv, struct rdp_draw_item* di);
int
draw_item_remove(rdpPixmapRec* priv, struct rdp_draw_item* di);
int
draw_item_remove_all(rdpPixmapRec* priv);
int
draw_item_pack(rdpPixmapRec* priv);
int
draw_item_add_img_region(rdpPixmapRec* priv, RegionPtr reg, int opcode,
int type);
int
draw_item_add_fill_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode);
int
draw_item_add_line_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode, int width, xSegment* segs, int nsegs,
int is_segment);
PixmapPtr PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
unsigned usage_hint); unsigned usage_hint);
@ -404,6 +496,12 @@ rdpup_paint_rect_os(int x, int y, int cx, int cy,
int rdpindex, int srcx, int srcy); int rdpindex, int srcx, int srcy);
void void
rdpup_set_hints(int hints, int mask); rdpup_set_hints(int hints, int mask);
void
rdpup_create_window(WindowPtr pWindow, rdpWindowRec* priv);
void
rdpup_delete_window(WindowPtr pWindow, rdpWindowRec* priv);
int
rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv);
#if defined(X_BYTE_ORDER) #if defined(X_BYTE_ORDER)
# if X_BYTE_ORDER == X_LITTLE_ENDIAN # if X_BYTE_ORDER == X_LITTLE_ENDIAN

@ -37,6 +37,8 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_can_do_pix_to_pix; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -241,11 +243,13 @@ rdpCopyAreaPixmapToWnd(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv,
if (num_clips > 0) if (num_clips > 0)
{ {
rdpup_begin_update(); rdpup_begin_update();
LLOGLN(10, ("rdpCopyAreaPixmapToWnd: num_clips %d", num_clips));
for (j = 0; j < num_clips; j++) for (j = 0; j < num_clips; j++)
{ {
box = REGION_RECTS(&clip_reg)[j]; box = REGION_RECTS(&clip_reg)[j];
LLOGLN(10, ("rdpCopyAreaPixmapToWnd: %d %d %d %d", box.x1, box.y1, box.x2, box.y2)); LLOGLN(10, ("rdpCopyAreaPixmapToWnd: %d %d %d %d", box.x1, box.y1, box.x2, box.y2));
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
LLOGLN(10, ("rdpCopyAreaPixmapToWnd: %d %d", w, h));
rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy);
} }
rdpup_reset_clip(); rdpup_reset_clip();
@ -281,6 +285,7 @@ rdpCopyAreaPixmapToPixmap(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv,
pGC, srcx, srcy, w, h, dstx, dsty); pGC, srcx, srcy, w, h, dstx, dsty);
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, &(pDstPixmap->drawable), pGC); cd = rdp_get_clip(&clip_reg, &(pDstPixmap->drawable), pGC);
LLOGLN(10, ("rdpCopyAreaPixmapToPixmap: cd %d", cd));
ldstx = pDstPixmap->drawable.x + dstx; ldstx = pDstPixmap->drawable.x + dstx;
ldsty = pDstPixmap->drawable.y + dsty; ldsty = pDstPixmap->drawable.y + dsty;
lsrcx = pSrcPixmap->drawable.x + srcx; lsrcx = pSrcPixmap->drawable.x + srcx;
@ -290,6 +295,7 @@ rdpCopyAreaPixmapToPixmap(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv,
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
rdpup_begin_update(); rdpup_begin_update();
rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy);
LLOGLN(10, ("%d %d %d %d %d %d", ldstx, ldsty, w, h, lsrcx, lsrcy));
rdpup_end_update(); rdpup_end_update();
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
} }
@ -300,11 +306,13 @@ rdpCopyAreaPixmapToPixmap(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv,
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
rdpup_begin_update(); rdpup_begin_update();
LLOGLN(10, ("rdpCopyAreaPixmapToPixmap: num_clips %d", num_clips));
for (j = 0; j < num_clips; j++) for (j = 0; j < num_clips; j++)
{ {
box = REGION_RECTS(&clip_reg)[j]; box = REGION_RECTS(&clip_reg)[j];
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy);
LLOGLN(10, ("%d %d %d %d %d %d", ldstx, ldsty, w, h, lsrcx, lsrcy));
} }
rdpup_reset_clip(); rdpup_reset_clip();
rdpup_end_update(); rdpup_end_update();
@ -323,11 +331,15 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
RegionPtr rv; RegionPtr rv;
RegionRec clip_reg; RegionRec clip_reg;
RegionRec box_reg; RegionRec box_reg;
RegionRec reg1;
int num_clips; int num_clips;
int cd; int cd;
int j; int j;
int can_do_screen_blt; int can_do_screen_blt;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
struct image_data id; struct image_data id;
BoxRec box; BoxRec box;
BoxPtr pbox; BoxPtr pbox;
@ -335,6 +347,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pSrcPriv; rdpPixmapRec* pSrcPriv;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
WindowPtr pDstWnd; WindowPtr pDstWnd;
WindowPtr pSrcWnd; WindowPtr pSrcWnd;
@ -367,6 +380,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
can_do_screen_blt = pGC->alu == GXcopy; can_do_screen_blt = pGC->alu == GXcopy;
if (can_do_screen_blt) if (can_do_screen_blt)
{ {
rdpup_check_dirty(pDstPixmap, pDstPriv);
return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC, return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC,
srcx, srcy, w, h, dstx, dsty); srcx, srcy, w, h, dstx, dsty);
} }
@ -385,6 +399,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
pDstWnd = (WindowPtr)pDst; pDstWnd = (WindowPtr)pDst;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
rdpup_check_dirty(pSrcPixmap, pSrcPriv);
return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC, return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC,
srcx, srcy, w, h, dstx, dsty); srcx, srcy, w, h, dstx, dsty);
} }
@ -395,6 +410,10 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{ {
if (g_can_do_pix_to_pix)
{
rdpup_check_dirty(pSrcPixmap, pSrcPriv);
rdpup_check_dirty(pDstPixmap, pDstPriv);
return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv, return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv,
pDstPixmap, pDstPriv, pDstPixmap, pDstPriv,
pGC, srcx, srcy, w, h, pGC, srcx, srcy, w, h,
@ -403,22 +422,39 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
} }
} }
} }
}
/* do original call */ /* do original call */
rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDst->type == DRAWABLE_PIXMAP) if (pDst->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDst; pDstPixmap = (PixmapPtr)pDst;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpCopyArea: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDst->type == DRAWABLE_WINDOW) if (pDst->type == DRAWABLE_WINDOW)
@ -426,12 +462,13 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
pDstWnd = (WindowPtr)pDst; pDstWnd = (WindowPtr)pDst;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return rv; return rv;
} }
@ -439,15 +476,41 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDst, pGC); cd = rdp_get_clip(&clip_reg, pDst, pGC);
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + dstx;
box.y1 = pDst->y + dsty;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + dstx;
box.y1 = pDst->y + dsty;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&box_reg, &box, 0);
RegionIntersect(&clip_reg, &clip_reg, &box_reg);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type);
RegionUninit(&box_reg);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
box.x1 = pDst->x + dstx; box.x1 = pDst->x + dstx;
@ -476,7 +539,11 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return rv; return rv;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -68,34 +69,57 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
RegionPtr rv; RegionPtr rv;
RegionRec clip_reg; RegionRec clip_reg;
RegionRec box_reg; RegionRec box_reg;
RegionRec reg1;
RegionRec reg2;
int cd; int cd;
int num_clips; int num_clips;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
BoxPtr pbox; BoxPtr pbox;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpCopyPlane:")); LLOGLN(10, ("rdpCopyPlane:"));
/* do original call */ /* do original call */
rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, bitPlane); dstx, dsty, bitPlane);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDst->type == DRAWABLE_PIXMAP) if (pDst->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDst; pDstPixmap = (PixmapPtr)pDst;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpCopyPlane: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDst->type == DRAWABLE_WINDOW) if (pDst->type == DRAWABLE_WINDOW)
@ -103,12 +127,13 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
pDstWnd = (WindowPtr)pDst; pDstWnd = (WindowPtr)pDst;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return rv; return rv;
} }
@ -116,15 +141,44 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDst, pGC); cd = rdp_get_clip(&clip_reg, pDst, pGC);
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + dstx;
box.y1 = pDst->y + dsty;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + dstx;
box.y1 = pDst->y + dsty;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
RegionUninit(&reg2);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
box.x1 = pDst->x + dstx; box.x1 = pDst->x + dstx;
@ -152,6 +206,11 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1);
}
return rv; return rv;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -64,6 +65,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
{ {
RegionRec clip_reg; RegionRec clip_reg;
RegionRec box_reg; RegionRec box_reg;
RegionRec reg1;
int num_clips; int num_clips;
int cd; int cd;
int maxx; int maxx;
@ -73,50 +75,18 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
int i; int i;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpFillPolygon:")); LLOGLN(10, ("rdpFillPolygon:"));
/* do original call */
rdpFillPolygonOrg(pDrawable, pGC, shape, mode, count, pPts);
got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP)
{
pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv))
{
rdpup_switch_os_surface(pDstPriv->rdpindex);
rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1;
}
}
else
{
if (pDrawable->type == DRAWABLE_WINDOW)
{
pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable)
{
rdpup_get_screen_image_rect(&id);
got_id = 1;
}
}
}
if (!got_id)
{
return;
}
RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
if (cd != 0)
{
box.x1 = 0; box.x1 = 0;
box.y1 = 0; box.y1 = 0;
box.x2 = 0; box.x2 = 0;
@ -145,25 +115,91 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
{ {
miny = pPts[i].y; miny = pPts[i].y;
} }
}
box.x1 = pDrawable->x + minx; box.x1 = pDrawable->x + minx;
box.y1 = pDrawable->y + miny; box.y1 = pDrawable->y + miny;
box.x2 = pDrawable->x + maxx + 1; box.x2 = pDrawable->x + maxx + 1;
box.y2 = pDrawable->y + maxy + 1; box.y2 = pDrawable->y + maxy + 1;
} }
/* do original call */
rdpFillPolygonOrg(pDrawable, pGC, shape, mode, count, pPts);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP)
{
pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpFillPolygon: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{
rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1;
}
} }
} }
else
{
if (pDrawable->type == DRAWABLE_WINDOW)
{
pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable)
{
post_process = 1;
rdpup_get_screen_image_rect(&id);
got_id = 1;
}
}
}
if (!post_process)
{
return;
}
RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&box_reg, &box, 0); RegionInit(&box_reg, &box, 0);
RegionIntersect(&clip_reg, &clip_reg, &box_reg); RegionIntersect(&clip_reg, &clip_reg, &box_reg);
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
@ -173,8 +209,12 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&box_reg); RegionUninit(&box_reg);
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -68,7 +68,7 @@ rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
LLOGLN(0, ("rdpFillSpans: todo")); LLOGLN(10, ("rdpFillSpans: todo"));
/* do original call */ /* do original call */
rdpFillSpansOrg(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); rdpFillSpansOrg(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -68,11 +69,15 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int cd; int cd;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpImageGlyphBlt:")); LLOGLN(10, ("rdpImageGlyphBlt:"));
@ -84,18 +89,34 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpImageGlyphBlt: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -103,12 +124,13 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -123,17 +145,32 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
@ -143,9 +180,13 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return; return;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -66,11 +67,15 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
int cd; int cd;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpImageText16:")); LLOGLN(10, ("rdpImageText16:"));
@ -82,18 +87,34 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rdpImageText16Org(pDrawable, pGC, x, y, count, chars); rdpImageText16Org(pDrawable, pGC, x, y, count, chars);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpImageText16: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -101,12 +122,13 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -121,29 +143,49 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
{ {
box = REGION_RECTS(&reg)[j]; box = REGION_RECTS(&reg)[j];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return; return;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -66,11 +67,15 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
int cd; int cd;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpImageText8:")); LLOGLN(10, ("rdpImageText8:"));
@ -82,18 +87,34 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rdpImageText8Org(pDrawable, pGC, x, y, count, chars); rdpImageText8Org(pDrawable, pGC, x, y, count, chars);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpImageText8: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -101,12 +122,13 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -121,29 +143,49 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
{ {
box = REGION_RECTS(&reg)[j]; box = REGION_RECTS(&reg)[j];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return; return;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -66,12 +67,16 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
int i; int i;
int num_clips; int num_clips;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
xRectangle* rects; xRectangle* rects;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyArc:")); LLOGLN(10, ("rdpPolyArc:"));
@ -97,18 +102,34 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
/* do original call */ /* do original call */
rdpPolyArcOrg(pDrawable, pGC, narcs, parcs); rdpPolyArcOrg(pDrawable, pGC, narcs, parcs);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyArc: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -116,12 +137,13 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
g_free(rects); g_free(rects);
return; return;
@ -136,15 +158,23 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
tmpRegion = RegionFromRects(narcs, rects, CT_NONE); tmpRegion = RegionFromRects(narcs, rects, CT_NONE);
num_clips = REGION_NUM_RECTS(tmpRegion); num_clips = REGION_NUM_RECTS(tmpRegion);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (i = num_clips - 1; i >= 0; i--) for (i = num_clips - 1; i >= 0; i--)
{ {
box = REGION_RECTS(tmpRegion)[i]; box = REGION_RECTS(tmpRegion)[i];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionDestroy(tmpRegion); RegionDestroy(tmpRegion);
} }
} }
@ -156,19 +186,30 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
RegionIntersect(tmpRegion, tmpRegion, &clip_reg); RegionIntersect(tmpRegion, tmpRegion, &clip_reg);
num_clips = REGION_NUM_RECTS(tmpRegion); num_clips = REGION_NUM_RECTS(tmpRegion);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (i = num_clips - 1; i >= 0; i--) for (i = num_clips - 1; i >= 0; i--)
{ {
box = REGION_RECTS(tmpRegion)[i]; box = REGION_RECTS(tmpRegion)[i];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionDestroy(tmpRegion); RegionDestroy(tmpRegion);
} }
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
g_free(rects); g_free(rects);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -66,12 +67,16 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
int i; int i;
int num_clips; int num_clips;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
xRectangle* rects; xRectangle* rects;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyFillArc:")); LLOGLN(10, ("rdpPolyFillArc:"));
@ -97,18 +102,34 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
/* do original call */ /* do original call */
rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs); rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyFillArc: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -116,12 +137,13 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
g_free(rects); g_free(rects);
return; return;
@ -136,15 +158,23 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
tmpRegion = RegionFromRects(narcs, rects, CT_NONE); tmpRegion = RegionFromRects(narcs, rects, CT_NONE);
num_clips = REGION_NUM_RECTS(tmpRegion); num_clips = REGION_NUM_RECTS(tmpRegion);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (i = num_clips - 1; i >= 0; i--) for (i = num_clips - 1; i >= 0; i--)
{ {
box = REGION_RECTS(tmpRegion)[i]; box = REGION_RECTS(tmpRegion)[i];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionDestroy(tmpRegion); RegionDestroy(tmpRegion);
} }
} }
@ -156,19 +186,30 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
RegionIntersect(tmpRegion, tmpRegion, &clip_reg); RegionIntersect(tmpRegion, tmpRegion, &clip_reg);
num_clips = REGION_NUM_RECTS(tmpRegion); num_clips = REGION_NUM_RECTS(tmpRegion);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (i = num_clips - 1; i >= 0; i--) for (i = num_clips - 1; i >= 0; i--)
{ {
box = REGION_RECTS(tmpRegion)[i]; box = REGION_RECTS(tmpRegion)[i];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionDestroy(tmpRegion); RegionDestroy(tmpRegion);
} }
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
g_free(rects); g_free(rects);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -68,10 +69,15 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
BoxRec box; BoxRec box;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyFillRect:")); LLOGLN(10, ("rdpPolyFillRect:"));
@ -81,18 +87,32 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
/* do original call */ /* do original call */
rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit);
got_id = 0; dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_FILL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -100,12 +120,13 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
RegionDestroy(fill_reg); RegionDestroy(fill_reg);
return; return;
@ -114,6 +135,27 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDrawable, pGC); cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
if (cd == 1) /* no clip */ if (cd == 1) /* no clip */
{
if (dirty_type != 0)
{
if (pGC->fillStyle == 0 && /* solid fill */
(pGC->alu == GXclear ||
pGC->alu == GXset ||
pGC->alu == GXinvert ||
pGC->alu == GXnoop ||
pGC->alu == GXand ||
pGC->alu == GXcopy /*||
pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
{
draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel,
pGC->alu);
}
else
{
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL);
}
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
if (pGC->fillStyle == 0 && /* solid fill */ if (pGC->fillStyle == 0 && /* solid fill */
@ -139,16 +181,39 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--)
{ {
box = REGION_RECTS(fill_reg)[j]; box = REGION_RECTS(fill_reg)[j];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
} }
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) /* clip */ else if (cd == 2) /* clip */
{ {
RegionIntersect(&clip_reg, &clip_reg, fill_reg); RegionIntersect(&clip_reg, &clip_reg, fill_reg);
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
if (pGC->fillStyle == 0 && /* solid fill */
(pGC->alu == GXclear ||
pGC->alu == GXset ||
pGC->alu == GXinvert ||
pGC->alu == GXnoop ||
pGC->alu == GXand ||
pGC->alu == GXcopy /*||
pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
{
draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu);
}
else
{
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL);
}
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
if (pGC->fillStyle == 0 && /* solid fill */ if (pGC->fillStyle == 0 && /* solid fill */
@ -180,7 +245,11 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
RegionDestroy(fill_reg); RegionDestroy(fill_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -68,11 +69,15 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int cd; int cd;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyGlyphBlt:")); LLOGLN(10, ("rdpPolyGlyphBlt:"));
@ -84,18 +89,34 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyGlyphBlt: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -103,12 +124,13 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -123,29 +145,49 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
{ {
box = REGION_RECTS(&reg)[j]; box = REGION_RECTS(&reg)[j];
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return; return;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -61,6 +62,8 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
int npt, DDXPointPtr in_pts) int npt, DDXPointPtr in_pts)
{ {
RegionRec clip_reg; RegionRec clip_reg;
RegionRec reg1;
RegionRec reg2;
int num_clips; int num_clips;
int cd; int cd;
int x; int x;
@ -68,6 +71,9 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
int i; int i;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
BoxRec total_box; BoxRec total_box;
DDXPointPtr pts; DDXPointPtr pts;
@ -76,8 +82,10 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyPoint:")); LLOGLN(10, ("rdpPolyPoint:"));
LLOGLN(10, ("rdpPolyPoint: npt %d", npt));
if (npt > 32) if (npt > 32)
{ {
@ -123,18 +131,34 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
/* do original call */ /* do original call */
rdpPolyPointOrg(pDrawable, pGC, mode, npt, in_pts); rdpPolyPointOrg(pDrawable, pGC, mode, npt, in_pts);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyPoint: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -142,12 +166,13 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -157,6 +182,25 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
if (cd == 1) if (cd == 1)
{ {
if (npt > 0) if (npt > 0)
{
if (dirty_type != 0)
{
RegionInit(&reg1, NullBox, 0);
for (i = 0; i < npt; i++)
{
box.x1 = pts[i].x;
box.y1 = pts[i].y;
box.x2 = box.x1 + 1;
box.y2 = box.y1 + 1;
RegionInit(&reg2, &box, 0);
RegionUnion(&reg1, &reg1, &reg2);
RegionUninit(&reg2);
}
draw_item_add_fill_region(pDirtyPriv, &reg1, pGC->fgPixel,
pGC->alu);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
@ -169,10 +213,31 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
else if (cd == 2) else if (cd == 2)
{ {
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (npt > 0 && num_clips > 0) if (npt > 0 && num_clips > 0)
{
if (dirty_type != 0)
{
RegionInit(&reg1, NullBox, 0);
for (i = 0; i < npt; i++)
{
box.x1 = pts[i].x;
box.y1 = pts[i].y;
box.x2 = box.x1 + 1;
box.y2 = box.y1 + 1;
RegionInit(&reg2, &box, 0);
RegionUnion(&reg1, &reg1, &reg2);
RegionUninit(&reg2);
}
RegionIntersect(&reg1, &reg1, &clip_reg);
draw_item_add_fill_region(pDirtyPriv, &reg1, pGC->fgPixel,
pGC->alu);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
@ -191,10 +256,14 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (pts != stack_pts) if (pts != stack_pts)
{ {
g_free(pts); g_free(pts);
} }
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -71,6 +72,9 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
int up; int up;
int down; int down;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
xRectangle* regRects; xRectangle* regRects;
xRectangle* r; xRectangle* r;
xRectangle* rect1; xRectangle* rect1;
@ -80,6 +84,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyRectangle:")); LLOGLN(10, ("rdpPolyRectangle:"));
@ -93,18 +98,34 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
/* do original call */ /* do original call */
rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects); rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyRectangle: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -112,12 +133,13 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
g_free(rect1); g_free(rect1);
return; return;
@ -163,6 +185,22 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
if (cd == 1) if (cd == 1)
{ {
if (regRects != 0) if (regRects != 0)
{
if (dirty_type != 0)
{
fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE);
if (pGC->lineStyle == LineSolid)
{
draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel,
pGC->alu);
}
else
{
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type);
}
RegionDestroy(fill_reg);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
if (pGC->lineStyle == LineSolid) if (pGC->lineStyle == LineSolid)
@ -187,6 +225,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
else if (cd == 2) else if (cd == 2)
{ {
if (regRects != 0) if (regRects != 0)
@ -195,6 +234,20 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
RegionIntersect(&clip_reg, &clip_reg, fill_reg); RegionIntersect(&clip_reg, &clip_reg, fill_reg);
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
if (pGC->lineStyle == LineSolid)
{
draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu);
}
else
{
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type);
}
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
if (pGC->lineStyle == LineSolid) if (pGC->lineStyle == LineSolid)
@ -218,11 +271,15 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionDestroy(fill_reg); RegionDestroy(fill_reg);
} }
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
g_free(regRects); g_free(regRects);
g_free(rect1); g_free(rect1);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -63,14 +64,19 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
int i; int i;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
xSegment* segs; xSegment* segs;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolySegment:")); LLOGLN(10, ("rdpPolySegment:"));
LLOGLN(10, (" nseg %d", nseg));
segs = 0; segs = 0;
if (nseg) /* get the rects */ if (nseg) /* get the rects */
@ -88,18 +94,34 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
/* do original call */ /* do original call */
rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs); rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolySegment: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -107,12 +129,13 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
g_free(segs); g_free(segs);
return; return;
@ -120,9 +143,20 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDrawable, pGC); cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
LLOGLN(10, ("rdpPolySegment: cd %d", cd));
if (cd == 1) /* no clip */ if (cd == 1) /* no clip */
{ {
if (segs != 0) if (segs != 0)
{
if (dirty_type != 0)
{
RegionUninit(&clip_reg);
RegionInit(&clip_reg, NullBox, 0);
RegionAroundSegs(&clip_reg, segs, nseg);
draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu, pGC->lineWidth, segs, nseg, 1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
@ -136,9 +170,17 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
rdpup_end_update(); rdpup_end_update();
} }
} }
}
else if (cd == 2) /* clip */ else if (cd == 2) /* clip */
{ {
if (segs != 0) if (segs != 0)
{
if (dirty_type != 0)
{
draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu, pGC->lineWidth, segs, nseg, 1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
@ -151,6 +193,8 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
for (i = 0; i < nseg; i++) for (i = 0; i < nseg; i++)
{ {
rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2);
LLOGLN(10, (" %d %d %d %d", segs[i].x1, segs[i].y1,
segs[i].x2, segs[i].y2));
} }
} }
rdpup_reset_clip(); rdpup_reset_clip();
@ -158,7 +202,11 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
rdpup_end_update(); rdpup_end_update();
} }
} }
}
g_free(segs); g_free(segs);
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -69,11 +70,15 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
int j; int j;
int rv; int rv;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyText16:")); LLOGLN(10, ("rdpPolyText16:"));
@ -85,18 +90,34 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rv = rdpPolyText16Org(pDrawable, pGC, x, y, count, chars); rv = rdpPolyText16Org(pDrawable, pGC, x, y, count, chars);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyText16: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -104,12 +125,13 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return rv; return rv;
} }
@ -124,17 +146,32 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
@ -144,9 +181,13 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return rv; return rv;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -69,11 +70,15 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
int j; int j;
int rv; int rv;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolyText8:")); LLOGLN(10, ("rdpPolyText8:"));
@ -85,18 +90,34 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
/* do original call */ /* do original call */
rv = rdpPolyText8Org(pDrawable, pGC, x, y, count, chars); rv = rdpPolyText8Org(pDrawable, pGC, x, y, count, chars);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolyText8: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -104,12 +125,13 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return rv; return rv;
} }
@ -124,17 +146,32 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
cd = rdp_get_clip(&reg, pDrawable, pGC); cd = rdp_get_clip(&reg, pDrawable, pGC);
} }
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionIntersect(&reg, &reg, &reg1); RegionIntersect(&reg, &reg, &reg1);
num_clips = REGION_NUM_RECTS(&reg); num_clips = REGION_NUM_RECTS(&reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
@ -144,9 +181,13 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
} }
RegionUninit(&reg); RegionUninit(&reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
return rv; return rv;
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -65,45 +66,106 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
int cd; int cd;
int i; int i;
int j; int j;
int x1;
int y1;
int x2;
int y2;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
DDXPointPtr ppts; xSegment* segs;
int nseg;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPolylines:")); LLOGLN(10, ("rdpPolylines:"));
LLOGLN(10, (" npt %d mode %d x %d y %d", npt, mode,
ppts = 0; pDrawable->x, pDrawable->y));
if (npt > 0) #if 0
{ LLOGLN(0, (" points"));
ppts = (DDXPointPtr)g_malloc(sizeof(DDXPointRec) * npt, 0);
for (i = 0; i < npt; i++) for (i = 0; i < npt; i++)
{ {
ppts[i] = pptInit[i]; LLOGLN(0, (" %d %d", pptInit[i].x, pptInit[i].y));
}
#endif
/* convert lines to line segments */
nseg = npt - 1;
segs = 0;
if (npt > 1)
{
segs = (xSegment*)g_malloc(sizeof(xSegment) * nseg, 0);
segs[0].x1 = pptInit[0].x + pDrawable->x;
segs[0].y1 = pptInit[0].y + pDrawable->y;
if (mode == CoordModeOrigin)
{
segs[0].x2 = pptInit[1].x + pDrawable->x;
segs[0].y2 = pptInit[1].y + pDrawable->y;
for (i = 2; i < npt; i++)
{
segs[i - 1].x1 = segs[i - 2].x2;
segs[i - 1].y1 = segs[i - 2].y2;
segs[i - 1].x2 = pptInit[i].x + pDrawable->x;
segs[i - 1].y2 = pptInit[i].y + pDrawable->y;
}
}
else
{
segs[0].x2 = segs[0].x1 + pptInit[1].x;
segs[0].y2 = segs[0].y1 + pptInit[1].y;
for (i = 2; i < npt; i++)
{
segs[i - 1].x1 = segs[i - 2].x2;
segs[i - 1].y1 = segs[i - 2].y2;
segs[i - 1].x2 = segs[i - 1].x1 + pptInit[i].x;
segs[i - 1].y2 = segs[i - 1].y1 + pptInit[i].y;
} }
} }
}
else
{
LLOGLN(0, ("rdpPolylines: weird npt [%d]", npt));
}
#if 0
LLOGLN(0, (" segments"));
for (i = 0; i < nseg; i++)
{
LLOGLN(0, (" %d %d %d %d", segs[i].x1, segs[i].y1,
segs[i].x2, segs[i].y2));
}
#endif
/* do original call */ /* do original call */
rdpPolylinesOrg(pDrawable, pGC, mode, npt, pptInit); rdpPolylinesOrg(pDrawable, pGC, mode, npt, pptInit);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPolylines: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -111,14 +173,15 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
g_free(ppts); g_free(segs);
return; return;
} }
@ -126,38 +189,42 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
cd = rdp_get_clip(&clip_reg, pDrawable, pGC); cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
if (cd == 1) if (cd == 1)
{ {
if (ppts != 0) if (segs != 0)
{
if (dirty_type != 0)
{
RegionUninit(&clip_reg);
RegionInit(&clip_reg, NullBox, 0);
RegionAroundSegs(&clip_reg, segs, nseg);
draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu, pGC->lineWidth, segs, nseg, 0);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
rdpup_set_opcode(pGC->alu); rdpup_set_opcode(pGC->alu);
rdpup_set_pen(0, pGC->lineWidth); rdpup_set_pen(0, pGC->lineWidth);
x1 = ppts[0].x + pDrawable->x; for (i = 0; i < nseg; i++)
y1 = ppts[0].y + pDrawable->y;
for (i = 1; i < npt; i++)
{
if (mode == CoordModeOrigin)
{ {
x2 = pDrawable->x + ppts[i].x; rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2);
y2 = pDrawable->y + ppts[i].y;
}
else
{
x2 = x1 + ppts[i].x;
y2 = y1 + ppts[i].y;
}
rdpup_draw_line(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
} }
rdpup_set_opcode(GXcopy); rdpup_set_opcode(GXcopy);
rdpup_end_update(); rdpup_end_update();
} }
} }
}
else if (cd == 2) else if (cd == 2)
{ {
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (ppts != 0 && num_clips > 0) if (nseg != 0 && num_clips > 0)
{
if (dirty_type != 0)
{
draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
pGC->alu, pGC->lineWidth, segs, nseg, 0);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_fgcolor(pGC->fgPixel);
@ -167,23 +234,9 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
{ {
box = REGION_RECTS(&clip_reg)[j]; box = REGION_RECTS(&clip_reg)[j];
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
x1 = ppts[0].x + pDrawable->x; for (i = 0; i < nseg; i++)
y1 = ppts[0].y + pDrawable->y;
for (i = 1; i < npt; i++)
{
if (mode == CoordModeOrigin)
{ {
x2 = pDrawable->x + ppts[i].x; rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2);
y2 = pDrawable->y + ppts[i].y;
}
else
{
x2 = x1 + ppts[i].x;
y2 = y1 + ppts[i].y;
}
rdpup_draw_line(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
} }
} }
rdpup_reset_clip(); rdpup_reset_clip();
@ -191,7 +244,11 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
rdpup_end_update(); rdpup_end_update();
} }
} }
}
g_free(segs);
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
g_free(ppts); if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -62,33 +63,54 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
{ {
RegionRec clip_reg; RegionRec clip_reg;
RegionRec box_reg; RegionRec box_reg;
RegionRec reg1;
int num_clips; int num_clips;
int cd; int cd;
int j; int j;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpPushPixels:")); LLOGLN(10, ("rdpPushPixels:"));
/* do original call */ /* do original call */
rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y); rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDst->type == DRAWABLE_PIXMAP) if (pDst->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDst; pDstPixmap = (PixmapPtr)pDst;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPutImage: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDst->type == DRAWABLE_WINDOW) if (pDst->type == DRAWABLE_WINDOW)
@ -96,12 +118,13 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
pDstWnd = (WindowPtr)pDst; pDstWnd = (WindowPtr)pDst;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -110,17 +133,42 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDst, pGC); cd = rdp_get_clip(&clip_reg, pDst, pGC);
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + x;
box.y1 = pDst->y + y;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(0, x, y, w, h); rdpup_send_area(0, pDst->x + x, pDst->y + y, w, h);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{ {
box.x1 = pDst->x + x;
box.y1 = pDst->y + y;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&box_reg, &box, 0); RegionInit(&box_reg, &box, 0);
RegionIntersect(&clip_reg, &clip_reg, &box_reg); RegionIntersect(&clip_reg, &clip_reg, &box_reg);
num_clips = REGION_NUM_RECTS(&clip_reg); num_clips = REGION_NUM_RECTS(&clip_reg);
if (num_clips > 0) if (num_clips > 0)
{
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = num_clips - 1; j >= 0; j--) for (j = num_clips - 1; j >= 0; j--)
@ -130,8 +178,12 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&box_reg); RegionUninit(&box_reg);
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -64,31 +65,54 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
RegionRec clip_reg; RegionRec clip_reg;
int cd; int cd;
int j; int j;
int reset_surface;
int post_process;
int got_id; int got_id;
int dirty_type;
BoxRec box; BoxRec box;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
RegionRec reg1;
RegionRec reg2;
LLOGLN(10, ("rdpPutImage:")); LLOGLN(10, ("rdpPutImage:"));
LLOGLN(10, ("rdpPutImage: drawable id 0x%x", (int)(pDst->id))); LLOGLN(10, ("rdpPutImage: drawable id 0x%x", (int)(pDst->id)));
/* do original call */ /* do original call */
rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits); rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDst->type == DRAWABLE_PIXMAP) if (pDst->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDst; pDstPixmap = (PixmapPtr)pDst;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpPutImage: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDst->type == DRAWABLE_WINDOW) if (pDst->type == DRAWABLE_WINDOW)
@ -96,24 +120,54 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
pDstWnd = (WindowPtr)pDst; pDstWnd = (WindowPtr)pDst;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
RegionInit(&clip_reg, NullBox, 0); RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDst, pGC); cd = rdp_get_clip(&clip_reg, pDst, pGC);
if (cd == 1) if (cd == 1)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + x;
box.y1 = pDst->y + y;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h); rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h);
rdpup_end_update(); rdpup_end_update();
} }
}
else if (cd == 2) else if (cd == 2)
{
if (dirty_type != 0)
{
box.x1 = pDst->x + x;
box.y1 = pDst->y + y;
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
RegionUninit(&reg2);
}
else if (got_id)
{ {
rdpup_begin_update(); rdpup_begin_update();
for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
@ -125,6 +179,10 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
rdpup_reset_clip(); rdpup_reset_clip();
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -37,6 +37,7 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */ extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@ -63,29 +64,48 @@ rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc,
RegionRec clip_reg; RegionRec clip_reg;
int cd; int cd;
int got_id; int got_id;
int dirty_type;
int post_process;
int reset_surface;
struct image_data id; struct image_data id;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
LLOGLN(10, ("rdpSetSpans: todo"));
LLOGLN(0, ("rdpSetSpans: todo"));
/* do original call */ /* do original call */
rdpSetSpansOrg(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); rdpSetSpansOrg(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (pDrawable->type == DRAWABLE_PIXMAP) if (pDrawable->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)pDrawable; pDstPixmap = (PixmapPtr)pDrawable;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpSetSpans: gettig dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
} }
} }
}
else else
{ {
if (pDrawable->type == DRAWABLE_WINDOW) if (pDrawable->type == DRAWABLE_WINDOW)
@ -93,12 +113,13 @@ rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc,
pDstWnd = (WindowPtr)pDrawable; pDstWnd = (WindowPtr)pDrawable;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -106,10 +127,25 @@ rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc,
cd = rdp_get_clip(&clip_reg, pDrawable, pGC); cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
if (cd == 1) if (cd == 1)
{ {
if (dirty_type != 0)
{
}
else if (got_id)
{
}
} }
else if (cd == 2) else if (cd == 2)
{ {
if (dirty_type != 0)
{
}
else if (got_id)
{
}
} }
RegionUninit(&clip_reg); RegionUninit(&clip_reg);
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }

@ -46,14 +46,6 @@ Xserver drawing ops and funcs
#include "rdpPolyGlyphBlt.h" #include "rdpPolyGlyphBlt.h"
#include "rdpPushPixels.h" #include "rdpPushPixels.h"
#if 1
#define DEBUG_OUT_FUNCS(arg)
#define DEBUG_OUT_OPS(arg)
#else
#define DEBUG_OUT_FUNCS(arg) ErrorF arg
#define DEBUG_OUT_OPS(arg) ErrorF arg
#endif
#define LOG_LEVEL 1 #define LOG_LEVEL 1
#define LLOG(_level, _args) \ #define LLOG(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
@ -67,9 +59,14 @@ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */ extern Bool g_wrapPixmap; /* from rdpmain.c */
extern WindowPtr g_invalidate_window; /* in rdpmain.c */
extern int g_use_rail; /* in rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
ColormapPtr g_rdpInstalledColormap; ColormapPtr g_rdpInstalledColormap;
static int g_doing_font = 0;
GCFuncs g_rdpGCFuncs = GCFuncs g_rdpGCFuncs =
{ {
rdpValidateGC, rdpChangeGC, rdpCopyGC, rdpDestroyGC, rdpChangeClip, rdpValidateGC, rdpChangeGC, rdpCopyGC, rdpDestroyGC, rdpChangeClip,
@ -287,7 +284,7 @@ rdpChangeGC(GCPtr pGC, unsigned long mask)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpChangeGC\n")); LLOGLN(10, ("in rdpChangeGC"));
GC_FUNC_PROLOGUE(pGC); GC_FUNC_PROLOGUE(pGC);
pGC->funcs->ChangeGC(pGC, mask); pGC->funcs->ChangeGC(pGC, mask);
GC_FUNC_EPILOGUE(pGC); GC_FUNC_EPILOGUE(pGC);
@ -299,7 +296,7 @@ rdpCopyGC(GCPtr src, unsigned long mask, GCPtr dst)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpCopyGC\n")); LLOGLN(10, ("in rdpCopyGC"));
GC_FUNC_PROLOGUE(dst); GC_FUNC_PROLOGUE(dst);
dst->funcs->CopyGC(src, mask, dst); dst->funcs->CopyGC(src, mask, dst);
GC_FUNC_EPILOGUE(dst); GC_FUNC_EPILOGUE(dst);
@ -311,7 +308,7 @@ rdpDestroyGC(GCPtr pGC)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpDestroyGC\n")); LLOGLN(10, ("in rdpDestroyGC"));
GC_FUNC_PROLOGUE(pGC); GC_FUNC_PROLOGUE(pGC);
pGC->funcs->DestroyGC(pGC); pGC->funcs->DestroyGC(pGC);
GC_FUNC_EPILOGUE(pGC); GC_FUNC_EPILOGUE(pGC);
@ -323,7 +320,7 @@ rdpChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpChangeClip\n")); LLOGLN(10, ("in rdpChangeClip"));
GC_FUNC_PROLOGUE(pGC); GC_FUNC_PROLOGUE(pGC);
pGC->funcs->ChangeClip(pGC, type, pValue, nrects); pGC->funcs->ChangeClip(pGC, type, pValue, nrects);
GC_FUNC_EPILOGUE(pGC); GC_FUNC_EPILOGUE(pGC);
@ -335,7 +332,7 @@ rdpDestroyClip(GCPtr pGC)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpDestroyClip\n")); LLOGLN(10, ("in rdpDestroyClip"));
GC_FUNC_PROLOGUE(pGC); GC_FUNC_PROLOGUE(pGC);
pGC->funcs->DestroyClip(pGC); pGC->funcs->DestroyClip(pGC);
GC_FUNC_EPILOGUE(pGC); GC_FUNC_EPILOGUE(pGC);
@ -347,7 +344,7 @@ rdpCopyClip(GCPtr dst, GCPtr src)
{ {
rdpGCRec* priv; rdpGCRec* priv;
DEBUG_OUT_FUNCS(("in rdpCopyClip\n")); LLOGLN(0, ("in rdpCopyClip"));
GC_FUNC_PROLOGUE(dst); GC_FUNC_PROLOGUE(dst);
dst->funcs->CopyClip(dst, src); dst->funcs->CopyClip(dst, src);
GC_FUNC_EPILOGUE(dst); GC_FUNC_EPILOGUE(dst);
@ -374,7 +371,7 @@ rdpCopyClip(GCPtr dst, GCPtr src)
Bool Bool
rdpCloseScreen(int i, ScreenPtr pScreen) rdpCloseScreen(int i, ScreenPtr pScreen)
{ {
DEBUG_OUT_OPS(("in rdpCloseScreen\n")); LLOGLN(10, ("in rdpCloseScreen"));
pScreen->CloseScreen = g_rdpScreen.CloseScreen; pScreen->CloseScreen = g_rdpScreen.CloseScreen;
pScreen->CreateGC = g_rdpScreen.CreateGC; pScreen->CreateGC = g_rdpScreen.CreateGC;
//pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground; //pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground;
@ -385,6 +382,223 @@ rdpCloseScreen(int i, ScreenPtr pScreen)
return 1; return 1;
} }
/******************************************************************************/
int
draw_item_add(rdpPixmapRec* priv, struct rdp_draw_item* di)
{
if (priv->draw_item_tail == 0)
{
priv->draw_item_tail = di;
priv->draw_item_head = di;
}
else
{
di->prev = priv->draw_item_tail;
priv->draw_item_tail->next = di;
priv->draw_item_tail = di;
}
return 0;
}
/******************************************************************************/
int
draw_item_remove(rdpPixmapRec* priv, struct rdp_draw_item* di)
{
if (di->prev != 0)
{
di->prev->next = di->next;
}
if (di->next != 0)
{
di->next->prev = di->prev;
}
if (priv->draw_item_head == di)
{
priv->draw_item_head = di->next;
}
if (priv->draw_item_tail == di)
{
priv->draw_item_tail = di->prev;
}
if (di->type == RDI_LINE)
{
if (di->u.line.segs != 0)
{
g_free(di->u.line.segs);
}
}
RegionDestroy(di->reg);
g_free(di);
return 0;
}
/******************************************************************************/
int
draw_item_remove_all(rdpPixmapRec* priv)
{
struct rdp_draw_item* di;
di = priv->draw_item_head;
while (di != 0)
{
draw_item_remove(priv, di);
di = priv->draw_item_head;
}
return 0;
}
/******************************************************************************/
int
draw_item_pack(rdpPixmapRec* priv)
{
struct rdp_draw_item* di;
struct rdp_draw_item* di_prev;
#if 1
/* look for repeating draw types */
if (priv->draw_item_head != 0)
{
if (priv->draw_item_head->next != 0)
{
di_prev = priv->draw_item_head;
di = priv->draw_item_head->next;
while (di != 0)
{
if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL"));
RegionUnion(di_prev->reg, di_prev->reg, di->reg);
draw_item_remove(priv, di);
di = di_prev->next;
}
else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY"));
RegionUnion(di_prev->reg, di_prev->reg, di->reg);
draw_item_remove(priv, di);
di = di_prev->next;
}
else
{
di_prev = di;
di = di_prev->next;
}
}
}
}
#endif
#if 1
/* subtract regions */
if (priv->draw_item_tail != 0)
{
if (priv->draw_item_tail->prev != 0)
{
di = priv->draw_item_tail;
while (di->prev != 0)
{
/* skip subtract flag
* draw items like line can't be used to clear(subtract) previous
* draw items since they are not opaque
* eg they can not be the 'S' in 'D = M - S'
* the region for line draw items is the clip region */
if ((di->flags & 1) == 0)
{
di_prev = di->prev;
while (di_prev != 0)
{
/* D = M - S */
RegionSubtract(di_prev->reg, di_prev->reg, di->reg);
di_prev = di_prev->prev;
}
}
di = di->prev;
}
}
}
#endif
#if 1
/* remove draw items with empty regions */
di = priv->draw_item_head;
di_prev = 0;
while (di != 0)
{
if (!RegionNotEmpty(di->reg))
{
LLOGLN(10, ("draw_item_pack: removing empty item type %d", di->type));
draw_item_remove(priv, di);
di = di_prev == 0 ? priv->draw_item_head : di_prev->next;
}
else
{
di_prev = di;
di = di->next;
}
}
#endif
return 0;
}
/******************************************************************************/
int
draw_item_add_img_region(rdpPixmapRec* priv, RegionPtr reg, int opcode,
int type)
{
struct rdp_draw_item* di;
di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1);
di->type = type;
di->reg = RegionCreate(NullBox, 0);
RegionCopy(di->reg, reg);
di->u.img.opcode = opcode;
draw_item_add(priv, di);
return 0;
}
/******************************************************************************/
int
draw_item_add_fill_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode)
{
struct rdp_draw_item* di;
di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1);
di->type = RDI_FILL;
di->u.fill.fg_color = color;
di->u.fill.opcode = opcode;
di->reg = RegionCreate(NullBox, 0);
RegionCopy(di->reg, reg);
draw_item_add(priv, di);
return 0;
}
/******************************************************************************/
int
draw_item_add_line_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode, int width, xSegment* segs, int nseg,
int is_segment)
{
struct rdp_draw_item* di;
LLOGLN(10, ("draw_item_add_line_region:"));
di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1);
di->type = RDI_LINE;
di->u.line.fg_color = color;
di->u.line.opcode = opcode;
di->u.line.width = width;
di->u.line.segs = (xSegment*)g_malloc(sizeof(xSegment) * nseg, 1);
memcpy(di->u.line.segs, segs, sizeof(xSegment) * nseg);
di->u.line.nseg = nseg;
if (is_segment)
{
di->u.line.flags = 1;
}
di->reg = RegionCreate(NullBox, 0);
di->flags |= 1;
RegionCopy(di->reg, reg);
draw_item_add(priv, di);
return 0;
}
/******************************************************************************/ /******************************************************************************/
PixmapPtr PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
@ -397,12 +611,13 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
org_width = width; org_width = width;
/* width must be a multiple of 4 in rdp */ /* width must be a multiple of 4 in rdp */
width = (width + 3) & ~3; width = (width + 3) & ~3;
LLOGLN(10, ("rdpCreatePixmap: width %d org_width %d", width, org_width)); LLOGLN(10, ("rdpCreatePixmap: width %d org_width %d depth %d screen depth %d",
width, org_width, depth, g_rdpScreen.depth));
pScreen->CreatePixmap = g_rdpScreen.CreatePixmap; pScreen->CreatePixmap = g_rdpScreen.CreatePixmap;
rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint); rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint);
priv = GETPIXPRIV(rv); priv = GETPIXPRIV(rv);
priv->rdpindex = -1; priv->rdpindex = -1;
if ((rv->drawable.depth == g_rdpScreen.depth) && if ((rv->drawable.depth >= g_rdpScreen.depth) &&
(org_width > 1) && (height > 1)) (org_width > 1) && (height > 1))
{ {
priv->allocBytes = width * height * g_Bpp; priv->allocBytes = width * height * g_Bpp;
@ -418,6 +633,8 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
return rv; return rv;
} }
extern struct rdpup_os_bitmap* g_os_bitmaps;
/******************************************************************************/ /******************************************************************************/
Bool Bool
rdpDestroyPixmap(PixmapPtr pPixmap) rdpDestroyPixmap(PixmapPtr pPixmap)
@ -435,6 +652,7 @@ rdpDestroyPixmap(PixmapPtr pPixmap)
{ {
rdpup_remove_os_bitmap(priv->rdpindex); rdpup_remove_os_bitmap(priv->rdpindex);
rdpup_delete_os_surface(priv->rdpindex); rdpup_delete_os_surface(priv->rdpindex);
draw_item_remove_all(priv);
} }
} }
pScreen = pPixmap->drawable.pScreen; pScreen = pPixmap->drawable.pScreen;
@ -452,13 +670,16 @@ rdpCreateWindow(WindowPtr pWindow)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpCreateWindow:\n"); LLOGLN(10, ("rdpCreateWindow:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
//ErrorF(" %p status %d\n", priv, priv->status); LLOGLN(10, (" %p status %d", priv, priv->status));
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->CreateWindow = g_rdpScreen.CreateWindow; pScreen->CreateWindow = g_rdpScreen.CreateWindow;
rv = pScreen->CreateWindow(pWindow); rv = pScreen->CreateWindow(pWindow);
pScreen->CreateWindow = rdpCreateWindow; pScreen->CreateWindow = rdpCreateWindow;
if (g_use_rail)
{
}
return rv; return rv;
} }
@ -470,12 +691,15 @@ rdpDestroyWindow(WindowPtr pWindow)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpDestroyWindow:\n"); LLOGLN(10, ("rdpDestroyWindow:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->DestroyWindow = g_rdpScreen.DestroyWindow; pScreen->DestroyWindow = g_rdpScreen.DestroyWindow;
rv = pScreen->DestroyWindow(pWindow); rv = pScreen->DestroyWindow(pWindow);
pScreen->DestroyWindow = rdpDestroyWindow; pScreen->DestroyWindow = rdpDestroyWindow;
if (g_use_rail)
{
}
return rv; return rv;
} }
@ -487,12 +711,20 @@ rdpPositionWindow(WindowPtr pWindow, int x, int y)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpPositionWindow:\n"); LLOGLN(10, ("rdpPositionWindow:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->PositionWindow = g_rdpScreen.PositionWindow; pScreen->PositionWindow = g_rdpScreen.PositionWindow;
rv = pScreen->PositionWindow(pWindow, x, y); rv = pScreen->PositionWindow(pWindow, x, y);
pScreen->PositionWindow = rdpPositionWindow; pScreen->PositionWindow = rdpPositionWindow;
if (g_use_rail)
{
if (priv->status == 1)
{
LLOGLN(10, ("rdpPositionWindow:"));
LLOGLN(10, (" x %d y %d", x, y));
}
}
return rv; return rv;
} }
@ -504,12 +736,30 @@ rdpRealizeWindow(WindowPtr pWindow)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpRealizeWindow:\n"); LLOGLN(10, ("rdpRealizeWindow:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->RealizeWindow = g_rdpScreen.RealizeWindow; pScreen->RealizeWindow = g_rdpScreen.RealizeWindow;
rv = pScreen->RealizeWindow(pWindow); rv = pScreen->RealizeWindow(pWindow);
pScreen->RealizeWindow = rdpRealizeWindow; pScreen->RealizeWindow = rdpRealizeWindow;
if (g_use_rail)
{
if ((pWindow != g_invalidate_window) && (pWindow->parent != 0))
{
if (XR_IS_ROOT(pWindow->parent))
{
LLOGLN(10, ("rdpRealizeWindow:"));
LLOGLN(10, (" pWindow %p id 0x%x pWindow->parent %p id 0x%x x %d "
"y %d width %d height %d",
pWindow, pWindow->drawable.id,
pWindow->parent, pWindow->parent->drawable.id,
pWindow->drawable.x, pWindow->drawable.y,
pWindow->drawable.width, pWindow->drawable.height));
priv->status = 1;
rdpup_create_window(pWindow, priv);
}
}
}
return rv; return rv;
} }
@ -521,12 +771,21 @@ rdpUnrealizeWindow(WindowPtr pWindow)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpUnrealizeWindow:\n"); LLOGLN(10, ("rdpUnrealizeWindow:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->UnrealizeWindow = g_rdpScreen.UnrealizeWindow; pScreen->UnrealizeWindow = g_rdpScreen.UnrealizeWindow;
rv = pScreen->UnrealizeWindow(pWindow); rv = pScreen->UnrealizeWindow(pWindow);
pScreen->UnrealizeWindow = rdpUnrealizeWindow; pScreen->UnrealizeWindow = rdpUnrealizeWindow;
if (g_use_rail)
{
if (priv->status == 1)
{
LLOGLN(10, ("rdpUnrealizeWindow:"));
priv->status = 0;
rdpup_delete_window(pWindow, priv);
}
}
return rv; return rv;
} }
@ -538,12 +797,15 @@ rdpChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
rdpWindowRec* priv; rdpWindowRec* priv;
Bool rv; Bool rv;
ErrorF("rdpChangeWindowAttributes:\n"); LLOGLN(10, ("rdpChangeWindowAttributes:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->ChangeWindowAttributes = g_rdpScreen.ChangeWindowAttributes; pScreen->ChangeWindowAttributes = g_rdpScreen.ChangeWindowAttributes;
rv = pScreen->ChangeWindowAttributes(pWindow, mask); rv = pScreen->ChangeWindowAttributes(pWindow, mask);
pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes; pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes;
if (g_use_rail)
{
}
return rv; return rv;
} }
@ -554,11 +816,14 @@ rdpWindowExposures(WindowPtr pWindow, RegionPtr pRegion, RegionPtr pBSRegion)
ScreenPtr pScreen; ScreenPtr pScreen;
rdpWindowRec* priv; rdpWindowRec* priv;
ErrorF("rdpWindowExposures:\n"); LLOGLN(10, ("rdpWindowExposures:"));
priv = GETWINPRIV(pWindow); priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen; pScreen = pWindow->drawable.pScreen;
pScreen->WindowExposures = g_rdpScreen.WindowExposures; pScreen->WindowExposures = g_rdpScreen.WindowExposures;
pScreen->WindowExposures(pWindow, pRegion, pBSRegion); pScreen->WindowExposures(pWindow, pRegion, pBSRegion);
if (g_use_rail)
{
}
pScreen->WindowExposures = rdpWindowExposures; pScreen->WindowExposures = rdpWindowExposures;
} }
@ -569,7 +834,7 @@ rdpCreateGC(GCPtr pGC)
rdpGCRec* priv; rdpGCRec* priv;
Bool rv; Bool rv;
DEBUG_OUT_OPS(("in rdpCreateGC\n")); LLOGLN(10, ("in rdpCreateGC\n"));
priv = GETGCPRIV(pGC); priv = GETGCPRIV(pGC);
g_pScreen->CreateGC = g_rdpScreen.CreateGC; g_pScreen->CreateGC = g_rdpScreen.CreateGC;
rv = g_pScreen->CreateGC(pGC); rv = g_pScreen->CreateGC(pGC);
@ -602,7 +867,7 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
BoxRec box1; BoxRec box1;
BoxRec box2; BoxRec box2;
DEBUG_OUT_OPS(("in rdpCopyWindow\n")); LLOGLN(10, ("in rdpCopyWindow"));
RegionInit(&reg, NullBox, 0); RegionInit(&reg, NullBox, 0);
RegionCopy(&reg, pOldRegion); RegionCopy(&reg, pOldRegion);
g_pScreen->CopyWindow = g_rdpScreen.CopyWindow; g_pScreen->CopyWindow = g_rdpScreen.CopyWindow;
@ -661,7 +926,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h,
BoxRec box; BoxRec box;
RegionRec reg; RegionRec reg;
DEBUG_OUT_OPS(("in rdpClearToBackground\n")); LLOGLN(10, ("in rdpClearToBackground"));
g_pScreen->ClearToBackground = g_rdpScreen.ClearToBackground; g_pScreen->ClearToBackground = g_rdpScreen.ClearToBackground;
g_pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures); g_pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures);
if (!generateExposures) if (!generateExposures)
@ -703,7 +968,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed)
int j; int j;
BoxRec box; BoxRec box;
DEBUG_OUT_OPS(("in rdpRestoreAreas\n")); LLOGLN(10, ("in rdpRestoreAreas"));
RegionInit(&reg, NullBox, 0); RegionInit(&reg, NullBox, 0);
RegionCopy(&reg, prgnExposed); RegionCopy(&reg, prgnExposed);
g_pScreen->RestoreAreas = g_rdpScreen.RestoreAreas; g_pScreen->RestoreAreas = g_rdpScreen.RestoreAreas;
@ -792,12 +1057,18 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
RegionRec reg1; RegionRec reg1;
RegionRec reg2; RegionRec reg2;
DrawablePtr p; DrawablePtr p;
int dirty_type;
int j; int j;
int num_clips; int num_clips;
int post_process;
int reset_surface;
int got_id; int got_id;
int lx;
int ly;
WindowPtr pDstWnd; WindowPtr pDstWnd;
PixmapPtr pDstPixmap; PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv; rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
struct image_data id; struct image_data id;
LLOGLN(10, ("rdpComposite:")); LLOGLN(10, ("rdpComposite:"));
@ -809,16 +1080,34 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
p = pDst->pDrawable; p = pDst->pDrawable;
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0; got_id = 0;
if (p->type == DRAWABLE_PIXMAP) if (p->type == DRAWABLE_PIXMAP)
{ {
pDstPixmap = (PixmapPtr)p; pDstPixmap = (PixmapPtr)p;
pDstPriv = GETPIXPRIV(pDstPixmap); pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv)) if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpComposite: gettig dirty"));
pDstPriv->is_dirty = 1;
dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
pDirtyPriv = pDstPriv;
}
else
{ {
rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id); rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1; got_id = 1;
LLOGLN(10, ("rdpComposite: offscreen"));
}
} }
} }
else else
@ -828,12 +1117,14 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
pDstWnd = (WindowPtr)p; pDstWnd = (WindowPtr)p;
if (pDstWnd->viewable) if (pDstWnd->viewable)
{ {
post_process = 1;
rdpup_get_screen_image_rect(&id); rdpup_get_screen_image_rect(&id);
got_id = 1; got_id = 1;
LLOGLN(10, ("rdpComposite: screen"));
} }
} }
} }
if (!got_id) if (!post_process)
{ {
return; return;
} }
@ -847,9 +1138,16 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
RegionInit(&reg1, &box, 0); RegionInit(&reg1, &box, 0);
RegionInit(&reg2, NullBox, 0); RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, pDst->clientClip); RegionCopy(&reg2, pDst->clientClip);
RegionTranslate(&reg2, p->x + pDst->clipOrigin.x, lx = p->x + pDst->clipOrigin.x;
p->y + pDst->clipOrigin.y); ly = p->y + pDst->clipOrigin.y;
RegionTranslate(&reg2, lx, ly);
RegionIntersect(&reg1, &reg1, &reg2); RegionIntersect(&reg1, &reg1, &reg2);
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
}
else if (got_id)
{
num_clips = REGION_NUM_RECTS(&reg1); num_clips = REGION_NUM_RECTS(&reg1);
if (num_clips > 0) if (num_clips > 0)
{ {
@ -861,6 +1159,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
} }
rdpup_end_update(); rdpup_end_update();
} }
}
RegionUninit(&reg1); RegionUninit(&reg1);
RegionUninit(&reg2); RegionUninit(&reg2);
} }
@ -870,11 +1169,23 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
box.y1 = p->y + yDst; box.y1 = p->y + yDst;
box.x2 = box.x1 + width; box.x2 = box.x1 + width;
box.y2 = box.y1 + height; box.y2 = box.y1 + height;
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type);
RegionUninit(&reg1);
}
else if (got_id)
{
rdpup_begin_update(); rdpup_begin_update();
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
rdpup_end_update(); rdpup_end_update();
} }
}
if (reset_surface)
{
rdpup_switch_os_surface(-1); rdpup_switch_os_surface(-1);
}
} }
/******************************************************************************/ /******************************************************************************/
@ -889,10 +1200,8 @@ rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
LLOGLN(10, ("rdpGlyphs:")); LLOGLN(10, ("rdpGlyphs:"));
LLOGLN(10, ("rdpGlyphs: nlists %d len %d", nlists, lists->len)); LLOGLN(10, ("rdpGlyphs: nlists %d len %d", nlists, lists->len));
if (g_rdpScreen.client_info.jpeg)
{
rdpup_set_hints(1, 1); rdpup_set_hints(1, 1);
} g_doing_font = 1;
for (index = 0; index < lists->len; index++) for (index = 0; index < lists->len; index++)
{ {
LLOGLN(10, (" index %d size %d refcnt %d width %d height %d", LLOGLN(10, (" index %d size %d refcnt %d width %d height %d",
@ -904,9 +1213,7 @@ rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
nlists, lists, glyphs); nlists, lists, glyphs);
ps->Glyphs = rdpGlyphs; ps->Glyphs = rdpGlyphs;
if (g_rdpScreen.client_info.jpeg)
{
rdpup_set_hints(0, 1); rdpup_set_hints(0, 1);
} g_doing_font = 0;
LLOGLN(10, ("rdpGlyphs: out")); LLOGLN(10, ("rdpGlyphs: out"));
} }

@ -791,6 +791,25 @@ check_keysa(void)
/******************************************************************************/ /******************************************************************************/
void void
sendDownUpKeyEvent(int type, int x_scancode)
{
/* if type is keydown, send keydown + keyup */
/* this allows us to ignore keyup events */
if (type == KeyPress)
{
rdpEnqueueKey(KeyPress, x_scancode);
rdpEnqueueKey(KeyRelease, x_scancode);
}
}
/**
* @param down - true for KeyDown events, false otherwise
* @param param1 - ASCII code of pressed key
* @param param2 -
* @param param3 - scancode of pressed key
* @param param4 -
******************************************************************************/
void
KbdAddEvent(int down, int param1, int param2, int param3, int param4) KbdAddEvent(int down, int param1, int param2, int param3, int param4)
{ {
int rdp_scancode; int rdp_scancode;
@ -799,63 +818,75 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
int is_spe; int is_spe;
int type; int type;
#if 0
fprintf(stderr, "down=0x%x param1=0x%x param2=0x%x param3=0x%x "
"param4=0x%x\n", down, param1, param2, param3, param4);
#endif
type = down ? KeyPress : KeyRelease; type = down ? KeyPress : KeyRelease;
rdp_scancode = param3; rdp_scancode = param3;
is_ext = param4 & 256; /* 0x100 */ is_ext = param4 & 256; /* 0x100 */
is_spe = param4 & 512; /* 0x200 */ is_spe = param4 & 512; /* 0x200 */
x_scancode = 0; x_scancode = 0;
switch (rdp_scancode) switch (rdp_scancode)
{ {
case 58: /* caps lock */
case 42: /* left shift */
case 54: /* right shift */
case 70: /* scroll lock */
x_scancode = rdp_scancode + MIN_KEY_CODE;
if (x_scancode > 0)
{
rdpEnqueueKey(type, x_scancode);
}
break;
case 56: /* left - right alt button */
if (is_ext)
{
x_scancode = 113; /* right alt button */
}
else
{
x_scancode = 64; /* left alt button */
}
rdpEnqueueKey(type, x_scancode);
break;
case 15: /* tab */ case 15: /* tab */
if (!down && !g_tab_down) if (!down && !g_tab_down)
{ {
check_keysa(); check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */
/* leave x_scancode 0 here, we don't want the tab key up */
} }
else else
{ {
x_scancode = 23; sendDownUpKeyEvent(type, 23);
} }
g_tab_down = down; g_tab_down = down;
break; break;
case 28: /* Enter or Return */
x_scancode = is_ext ? 108 : 36;
break;
case 29: /* left or right ctrl */ case 29: /* left or right ctrl */
/* this is to handle special case with pause key sending /* this is to handle special case with pause key sending control first */
control first */
if (is_spe) if (is_spe)
{ {
if (down) if (down)
{ {
g_pause_spe = 1; g_pause_spe = 1;
}
/* leave x_scancode 0 here, we don't want the control key down */ /* leave x_scancode 0 here, we don't want the control key down */
} }
}
else else
{ {
x_scancode = is_ext ? 109 : 37; x_scancode = is_ext ? 109 : 37;
g_ctrl_down = down ? x_scancode : 0; g_ctrl_down = down ? x_scancode : 0;
rdpEnqueueKey(type, x_scancode);
} }
break; break;
case 42: /* left shift */
x_scancode = 50;
g_shift_down = down ? x_scancode : 0;
break;
case 53: /* / */
x_scancode = is_ext ? 112 : 61;
break;
case 54: /* right shift */
x_scancode = 62;
g_shift_down = down ? x_scancode : 0;
break;
case 55: /* * on KP or Print Screen */
x_scancode = is_ext ? 111 : 63;
break;
case 56: /* left or right alt */
x_scancode = is_ext ? 113 : 64;
g_alt_down = down ? x_scancode : 0;
break;
case 69: /* Pause or Num Lock */ case 69: /* Pause or Num Lock */
if (g_pause_spe) if (g_pause_spe)
{ {
@ -869,60 +900,93 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
{ {
x_scancode = g_ctrl_down ? 110 : 77; x_scancode = g_ctrl_down ? 110 : 77;
} }
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 70: /* scroll lock */
x_scancode = 78; case 28: /* Enter or Return */
if (!down) x_scancode = is_ext ? 108 : 36;
{ sendDownUpKeyEvent(type, x_scancode);
g_scroll_lock_down = !g_scroll_lock_down; break;
}
case 53: /* / */
x_scancode = is_ext ? 112 : 61;
sendDownUpKeyEvent(type, x_scancode);
break;
case 55: /* * on KP or Print Screen */
x_scancode = is_ext ? 111 : 63;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 71: /* 7 or Home */ case 71: /* 7 or Home */
x_scancode = is_ext ? 97 : 79; x_scancode = is_ext ? 97 : 79;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 72: /* 8 or Up */ case 72: /* 8 or Up */
x_scancode = is_ext ? 98 : 80; x_scancode = is_ext ? 98 : 80;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 73: /* 9 or PgUp */ case 73: /* 9 or PgUp */
x_scancode = is_ext ? 99 : 81; x_scancode = is_ext ? 99 : 81;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 75: /* 4 or Left */ case 75: /* 4 or Left */
x_scancode = is_ext ? 100 : 83; x_scancode = is_ext ? 100 : 83;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 77: /* 6 or Right */ case 77: /* 6 or Right */
x_scancode = is_ext ? 102 : 85; x_scancode = is_ext ? 102 : 85;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 79: /* 1 or End */ case 79: /* 1 or End */
x_scancode = is_ext ? 103 : 87; x_scancode = is_ext ? 103 : 87;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 80: /* 2 or Down */ case 80: /* 2 or Down */
x_scancode = is_ext ? 104 : 88; x_scancode = is_ext ? 104 : 88;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 81: /* 3 or PgDn */ case 81: /* 3 or PgDn */
x_scancode = is_ext ? 105 : 89; x_scancode = is_ext ? 105 : 89;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 82: /* 0 or Insert */ case 82: /* 0 or Insert */
x_scancode = is_ext ? 106 : 90; x_scancode = is_ext ? 106 : 90;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 83: /* . or Delete */ case 83: /* . or Delete */
x_scancode = is_ext ? 107 : 91; x_scancode = is_ext ? 107 : 91;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 91: /* left win key */ case 91: /* left win key */
x_scancode = 115; rdpEnqueueKey(type, 115);
break; break;
case 92: /* right win key */ case 92: /* right win key */
x_scancode = 116; rdpEnqueueKey(type, 116);
break; break;
case 93: /* menu key */ case 93: /* menu key */
x_scancode = 117; rdpEnqueueKey(type, 117);
break; break;
default: default:
x_scancode = rdp_scancode + MIN_KEY_CODE; x_scancode = rdp_scancode + MIN_KEY_CODE;
break;
}
if (x_scancode > 0) if (x_scancode > 0)
{ {
rdpEnqueueKey(type, x_scancode); sendDownUpKeyEvent(type, x_scancode);
}
break;
} }
} }

@ -42,9 +42,16 @@ DevPrivateKeyRec g_rdpPixmapIndex;
DeviceIntPtr g_pointer = 0; DeviceIntPtr g_pointer = 0;
DeviceIntPtr g_keyboard = 0; DeviceIntPtr g_keyboard = 0;
Bool g_wrapWindow = 0; int g_can_do_pix_to_pix = 1;
int g_do_dirty_os = 1; /* delay remoting off screen bitmaps */
Bool g_wrapWindow = 1;
Bool g_wrapPixmap = 1; Bool g_wrapPixmap = 1;
/* if true, running in RemoteApp / RAIL mode */
int g_use_rail = 0;
WindowPtr g_invalidate_window = 0;
/* if true, use a unix domain socket instead of a tcp socket */ /* if true, use a unix domain socket instead of a tcp socket */
int g_use_uds = 0; int g_use_uds = 0;
char g_uds_data[256] = ""; /* data */ char g_uds_data[256] = ""; /* data */

@ -530,3 +530,43 @@ void
FontCacheExtensionInit(INITARGS) FontCacheExtensionInit(INITARGS)
{ {
} }
/******************************************************************************/
void
RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg)
{
int index;
BoxRec box;
RegionRec treg;
index = 0;
while (index < nseg)
{
if (segs[index].x1 < segs[index].x2)
{
box.x1 = segs[index].x1;
box.x2 = segs[index].x2;
}
else
{
box.x1 = segs[index].x2;
box.x2 = segs[index].x1;
}
box.x2++;
if (segs[index].y1 < segs[index].y2)
{
box.y1 = segs[index].y1;
box.y2 = segs[index].y2;
}
else
{
box.y1 = segs[index].y2;
box.y2 = segs[index].y1;
}
box.y2++;
RegionInit(&treg, &box, 0);
RegionUnion(reg, reg, &treg);
RegionUninit(&treg);
index++;
}
}

@ -34,6 +34,7 @@ extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
extern DeviceIntPtr g_pointer; /* in rdpmain.c */ extern DeviceIntPtr g_pointer; /* in rdpmain.c */
extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ extern DeviceIntPtr g_keyboard; /* in rdpmain.c */
extern ScreenPtr g_pScreen; /* in rdpmain.c */ extern ScreenPtr g_pScreen; /* in rdpmain.c */
extern WindowPtr g_invalidate_window; /* in rdpmain.c */
static XID g_wid = 0; static XID g_wid = 0;
@ -108,8 +109,10 @@ rdpInvalidateArea(ScreenPtr pScreen, int x, int y, int cx, int cy)
wVisual(pScreen->root), &result); wVisual(pScreen->root), &result);
if (result == 0) if (result == 0)
{ {
g_invalidate_window = pWin;
MapWindow(pWin, serverClient); MapWindow(pWin, serverClient);
DeleteWindow(pWin, None); DeleteWindow(pWin, None);
g_invalidate_window = pWin;
} }
return 0; return 0;
} }

@ -20,12 +20,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "rdp.h" #include "rdp.h"
#include "xrdp_rail.h"
#if 1
#define DEBUG_OUT_UP(arg)
#else
#define DEBUG_OUT_UP(arg) ErrorF arg
#endif
#define LOG_LEVEL 1 #define LOG_LEVEL 1
#define LLOG(_level, _args) \ #define LLOG(_level, _args) \
@ -59,6 +54,7 @@ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */
extern int g_Bpp_mask; /* from rdpmain.c */ extern int g_Bpp_mask; /* from rdpmain.c */
extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
extern int g_use_rail; /* from rdpmain.c */
/* true is to use unix domain socket */ /* true is to use unix domain socket */
extern int g_use_uds; /* in rdpmain.c */ extern int g_use_uds; /* in rdpmain.c */
@ -147,6 +143,7 @@ rdpup_disconnect(void)
g_max_os_bitmaps = 0; g_max_os_bitmaps = 0;
g_free(g_os_bitmaps); g_free(g_os_bitmaps);
g_os_bitmaps = 0; g_os_bitmaps = 0;
g_use_rail = 0;
return 0; return 0;
} }
@ -199,7 +196,7 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
} }
index++; index++;
} }
LLOGLN(0, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index)); LLOGLN(10, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index));
/* evict old */ /* evict old */
g_os_bitmaps[oldest_index].priv->status = 0; g_os_bitmaps[oldest_index].priv->status = 0;
/* set new */ /* set new */
@ -209,8 +206,8 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
g_os_bitmap_stamp++; g_os_bitmap_stamp++;
rv = oldest_index; rv = oldest_index;
} }
LLOGLN(0, ("rdpup_add_os_bitmap: new bitmap index %d", rv)); LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv));
LLOGLN(0, (" g_pixmap_num_used %d", g_pixmap_num_used)); LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
return rv; return rv;
} }
@ -218,7 +215,8 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
int int
rdpup_remove_os_bitmap(int rdpindex) rdpup_remove_os_bitmap(int rdpindex)
{ {
LLOGLN(0, ("rdpup_remove_os_bitmap: index %d", rdpindex)); LLOGLN(10, ("rdpup_remove_os_bitmap: index %d stamp %d",
rdpindex, g_os_bitmaps[rdpindex].stamp));
if (g_os_bitmaps == 0) if (g_os_bitmaps == 0)
{ {
return 1; return 1;
@ -234,7 +232,7 @@ rdpup_remove_os_bitmap(int rdpindex)
g_os_bitmaps[rdpindex].priv = 0; g_os_bitmaps[rdpindex].priv = 0;
g_pixmap_num_used--; g_pixmap_num_used--;
} }
LLOGLN(0, (" g_pixmap_num_used %d", g_pixmap_num_used)); LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
return 0; return 0;
} }
@ -245,7 +243,7 @@ rdpup_send(char* data, int len)
{ {
int sent; int sent;
DEBUG_OUT_UP(("rdpup_send - sending %d bytes\n", len)); LLOGLN(10, ("rdpup_send - sending %d bytes", len));
if (g_sck_closed) if (g_sck_closed)
{ {
return 1; return 1;
@ -313,7 +311,7 @@ rdpup_send_pending(void)
{ {
if (g_connected && g_begin) if (g_connected && g_begin)
{ {
DEBUG_OUT_UP(("end %d\n", g_count)); LLOGLN(10, ("end %d", g_count));
out_uint16_le(g_out_s, 2); out_uint16_le(g_out_s, 2);
out_uint16_le(g_out_s, 4); out_uint16_le(g_out_s, 4);
g_count++; g_count++;
@ -428,8 +426,8 @@ process_screen_size_msg(int width, int height, int bpp)
int mmheight; int mmheight;
Bool ok; Bool ok;
ErrorF("process_screen_size_msg: set width %d height %d bpp %d\n", LLOGLN(0, ("process_screen_size_msg: set width %d height %d bpp %d",
width, height, bpp); width, height, bpp));
g_rdpScreen.rdp_width = width; g_rdpScreen.rdp_width = width;
g_rdpScreen.rdp_height = height; g_rdpScreen.rdp_height = height;
g_rdpScreen.rdp_bpp = bpp; g_rdpScreen.rdp_bpp = bpp;
@ -460,9 +458,9 @@ process_screen_size_msg(int width, int height, int bpp)
RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize); RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize);
if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height)) if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height))
{ {
ErrorF(" calling RRScreenSizeSet\n"); LLOGLN(0, (" calling RRScreenSizeSet"));
ok = RRScreenSizeSet(g_pScreen, width, height, mmwidth, mmheight); ok = RRScreenSizeSet(g_pScreen, width, height, mmwidth, mmheight);
ErrorF(" RRScreenSizeSet ok=[%d]\n", ok); LLOGLN(0, (" RRScreenSizeSet ok=[%d]", ok));
} }
return 0; return 0;
} }
@ -521,7 +519,7 @@ rdpup_send_caps(void)
rv = rdpup_send(ls->data, len); rv = rdpup_send(ls->data, len);
if (rv != 0) if (rv != 0)
{ {
ErrorF("rdpup_send_caps: rdpup_send failed\n"); LLOGLN(0, ("rdpup_send_caps: rdpup_send failed"));
} }
free_stream(ls); free_stream(ls);
return rv; return rv;
@ -531,8 +529,8 @@ rdpup_send_caps(void)
static int static int
process_version_msg(int param1, int param2, int param3, int param4) process_version_msg(int param1, int param2, int param3, int param4)
{ {
ErrorF("process_version_msg: version %d %d %d %d\n", param1, param2, LLOGLN(0, ("process_version_msg: version %d %d %d %d", param1, param2,
param3, param4); param3, param4));
if ((param1 > 0) || (param2 > 0) || (param3 > 0) || (param4 > 0)) if ((param1 > 0) || (param2 > 0) || (param3 > 0) || (param4 > 0))
{ {
rdpup_send_caps(); rdpup_send_caps();
@ -551,6 +549,7 @@ rdpup_process_msg(struct stream* s)
int param3; int param3;
int param4; int param4;
int bytes; int bytes;
int i1;
in_uint16_le(s, msg_type); in_uint16_le(s, msg_type);
if (msg_type == 103) if (msg_type == 103)
@ -560,8 +559,8 @@ rdpup_process_msg(struct stream* s)
in_uint32_le(s, param2); in_uint32_le(s, param2);
in_uint32_le(s, param3); in_uint32_le(s, param3);
in_uint32_le(s, param4); in_uint32_le(s, param4);
DEBUG_OUT_UP(("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \ LLOGLN(10, ("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d "
param4 %d\n", msg, param1, param2, param3, param4)); "param4 %d", msg, param1, param2, param3, param4));
switch (msg) switch (msg)
{ {
case 15: /* key down */ case 15: /* key down */
@ -641,15 +640,14 @@ param4 %d\n", msg, param1, param2, param3, param4));
} }
memcpy(&(g_rdpScreen.client_info), s->p - 4, bytes); memcpy(&(g_rdpScreen.client_info), s->p - 4, bytes);
g_rdpScreen.client_info.size = bytes; g_rdpScreen.client_info.size = bytes;
ErrorF("rdpup_process_msg: got client info bytes %d\n", bytes); LLOGLN(0, ("rdpup_process_msg: got client info bytes %d", bytes));
ErrorF(" jpeg support %d\n", LLOGLN(0, (" jpeg support %d", g_rdpScreen.client_info.jpeg));
g_rdpScreen.client_info.jpeg); i1 = g_rdpScreen.client_info.offscreen_support_level;
ErrorF(" offscreen support %d\n", LLOGLN(0, (" offscreen support %d", i1));
g_rdpScreen.client_info.offscreen_support_level); i1 = g_rdpScreen.client_info.offscreen_cache_size;
ErrorF(" offscreen size %d\n", LLOGLN(0, (" offscreen size %d", i1));
g_rdpScreen.client_info.offscreen_cache_size); i1 = g_rdpScreen.client_info.offscreen_cache_entries;
ErrorF(" offscreen entries %d\n", LLOGLN(0, (" offscreen entries %d", i1));
g_rdpScreen.client_info.offscreen_cache_entries);
if (g_rdpScreen.client_info.offscreen_support_level > 0) if (g_rdpScreen.client_info.offscreen_support_level > 0)
{ {
if (g_rdpScreen.client_info.offscreen_cache_entries > 0) if (g_rdpScreen.client_info.offscreen_cache_entries > 0)
@ -660,6 +658,10 @@ param4 %d\n", msg, param1, param2, param3, param4));
g_malloc(sizeof(struct rdpup_os_bitmap) * g_max_os_bitmaps, 1); g_malloc(sizeof(struct rdpup_os_bitmap) * g_max_os_bitmaps, 1);
} }
} }
if (g_rdpScreen.client_info.rail_support_level > 0)
{
g_use_rail = 1;
}
} }
else else
{ {
@ -703,7 +705,7 @@ rdpup_init(void)
{ {
if (!g_create_dir("/tmp/.xrdp")) if (!g_create_dir("/tmp/.xrdp"))
{ {
ErrorF("rdpup_init: g_create_dir failed\n"); LLOGLN(0, ("rdpup_init: g_create_dir failed"));
return 0; return 0;
} }
g_chmod_hex("/tmp/.xrdp", 0x1777); g_chmod_hex("/tmp/.xrdp", 0x1777);
@ -731,7 +733,7 @@ rdpup_init(void)
g_listen_sck = g_tcp_local_socket_stream(); g_listen_sck = g_tcp_local_socket_stream();
if (g_tcp_local_bind(g_listen_sck, g_uds_data) != 0) if (g_tcp_local_bind(g_listen_sck, g_uds_data) != 0)
{ {
ErrorF("rdpup_init: g_tcp_local_bind failed\n"); LLOGLN(0, ("rdpup_init: g_tcp_local_bind failed"));
return 0; return 0;
} }
g_tcp_listen(g_listen_sck); g_tcp_listen(g_listen_sck);
@ -837,7 +839,7 @@ rdpup_begin_update(void)
s_push_layer(g_out_s, iso_hdr, 8); s_push_layer(g_out_s, iso_hdr, 8);
out_uint16_le(g_out_s, 1); /* begin update */ out_uint16_le(g_out_s, 1); /* begin update */
out_uint16_le(g_out_s, 4); /* size */ out_uint16_le(g_out_s, 4); /* size */
DEBUG_OUT_UP(("begin %d\n", g_count)); LLOGLN(10, ("begin %d", g_count));
g_begin = 1; g_begin = 1;
g_count = 1; g_count = 1;
} }
@ -880,7 +882,7 @@ rdpup_fill_rect(short x, short y, int cx, int cy)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_fill_rect\n")); LLOGLN(10, (" rdpup_fill_rect"));
rdpup_pre_check(12); rdpup_pre_check(12);
out_uint16_le(g_out_s, 3); /* fill rect */ out_uint16_le(g_out_s, 3); /* fill rect */
out_uint16_le(g_out_s, 12); /* size */ out_uint16_le(g_out_s, 12); /* size */
@ -899,7 +901,7 @@ rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_screen_blt\n")); LLOGLN(10, (" rdpup_screen_blt"));
rdpup_pre_check(16); rdpup_pre_check(16);
out_uint16_le(g_out_s, 4); /* screen blt */ out_uint16_le(g_out_s, 4); /* screen blt */
out_uint16_le(g_out_s, 16); /* size */ out_uint16_le(g_out_s, 16); /* size */
@ -920,7 +922,7 @@ rdpup_set_clip(short x, short y, int cx, int cy)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_clip\n")); LLOGLN(10, (" rdpup_set_clip"));
rdpup_pre_check(12); rdpup_pre_check(12);
out_uint16_le(g_out_s, 10); /* set clip */ out_uint16_le(g_out_s, 10); /* set clip */
out_uint16_le(g_out_s, 12); /* size */ out_uint16_le(g_out_s, 12); /* size */
@ -939,7 +941,7 @@ rdpup_reset_clip(void)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_reset_clip\n")); LLOGLN(10, (" rdpup_reset_clip"));
rdpup_pre_check(4); rdpup_pre_check(4);
out_uint16_le(g_out_s, 11); /* reset clip */ out_uint16_le(g_out_s, 11); /* reset clip */
out_uint16_le(g_out_s, 4); /* size */ out_uint16_le(g_out_s, 4); /* size */
@ -1087,7 +1089,7 @@ rdpup_set_fgcolor(int fgcolor)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_fgcolor\n")); LLOGLN(10, (" rdpup_set_fgcolor"));
rdpup_pre_check(8); rdpup_pre_check(8);
out_uint16_le(g_out_s, 12); /* set fgcolor */ out_uint16_le(g_out_s, 12); /* set fgcolor */
out_uint16_le(g_out_s, 8); /* size */ out_uint16_le(g_out_s, 8); /* size */
@ -1105,7 +1107,7 @@ rdpup_set_bgcolor(int bgcolor)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_bgcolor\n")); LLOGLN(10, (" rdpup_set_bgcolor"));
rdpup_pre_check(8); rdpup_pre_check(8);
out_uint16_le(g_out_s, 13); /* set bg color */ out_uint16_le(g_out_s, 13); /* set bg color */
out_uint16_le(g_out_s, 8); /* size */ out_uint16_le(g_out_s, 8); /* size */
@ -1123,7 +1125,7 @@ rdpup_set_opcode(int opcode)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_opcode\n")); LLOGLN(10, (" rdpup_set_opcode"));
rdpup_pre_check(6); rdpup_pre_check(6);
out_uint16_le(g_out_s, 14); /* set opcode */ out_uint16_le(g_out_s, 14); /* set opcode */
out_uint16_le(g_out_s, 6); /* size */ out_uint16_le(g_out_s, 6); /* size */
@ -1139,7 +1141,7 @@ rdpup_set_pen(int style, int width)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_pen\n")); LLOGLN(10, (" rdpup_set_pen"));
rdpup_pre_check(8); rdpup_pre_check(8);
out_uint16_le(g_out_s, 17); /* set pen */ out_uint16_le(g_out_s, 17); /* set pen */
out_uint16_le(g_out_s, 8); /* size */ out_uint16_le(g_out_s, 8); /* size */
@ -1156,7 +1158,7 @@ rdpup_draw_line(short x1, short y1, short x2, short y2)
{ {
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_draw_line\n")); LLOGLN(10, (" rdpup_draw_line"));
rdpup_pre_check(12); rdpup_pre_check(12);
out_uint16_le(g_out_s, 18); /* draw line */ out_uint16_le(g_out_s, 18); /* draw line */
out_uint16_le(g_out_s, 12); /* size */ out_uint16_le(g_out_s, 12); /* size */
@ -1177,7 +1179,7 @@ rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask)
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_set_cursor\n")); LLOGLN(10, (" rdpup_set_cursor"));
size = 8 + 32 * (32 * 3) + 32 * (32 / 8); size = 8 + 32 * (32 * 3) + 32 * (32 / 8);
rdpup_pre_check(size); rdpup_pre_check(size);
out_uint16_le(g_out_s, 19); /* set cursor */ out_uint16_le(g_out_s, 19); /* set cursor */
@ -1202,7 +1204,7 @@ rdpup_create_os_surface(int rdpindex, int width, int height)
LLOGLN(10, ("rdpup_create_os_surface:")); LLOGLN(10, ("rdpup_create_os_surface:"));
if (g_connected) if (g_connected)
{ {
DEBUG_OUT_UP((" rdpup_create_os_surface\n")); LLOGLN(10, (" rdpup_create_os_surface width %d height %d", width, height));
rdpup_pre_check(12); rdpup_pre_check(12);
out_uint16_le(g_out_s, 20); out_uint16_le(g_out_s, 20);
out_uint16_le(g_out_s, 12); out_uint16_le(g_out_s, 12);
@ -1387,10 +1389,10 @@ rdpup_send_area(struct image_data* id, int x, int y, int w, int h)
{ {
h = id->height - y; h = id->height - y;
} }
DEBUG_OUT_UP(("%d\n", w * h)); LLOGLN(10, ("%d", w * h));
if (g_connected && g_begin) if (g_connected && g_begin)
{ {
DEBUG_OUT_UP((" rdpup_send_area\n")); LLOGLN(10, (" rdpup_send_area"));
ly = y; ly = y;
while (ly < y + h) while (ly < y + h)
{ {
@ -1402,7 +1404,7 @@ rdpup_send_area(struct image_data* id, int x, int y, int w, int h)
single_color = get_single_color(id, lx, ly, lw, lh); single_color = get_single_color(id, lx, ly, lw, lh);
if (single_color != -1) if (single_color != -1)
{ {
DEBUG_OUT_UP(("%d sending single color\n", g_count)); LLOGLN(10, ("%d sending single color", g_count));
rdpup_set_fgcolor(single_color); rdpup_set_fgcolor(single_color);
rdpup_fill_rect(lx, ly, lw, lh); rdpup_fill_rect(lx, ly, lw, lh);
} }
@ -1472,3 +1474,232 @@ rdpup_set_hints(int hints, int mask)
out_uint32_le(g_out_s, mask); out_uint32_le(g_out_s, mask);
} }
} }
/******************************************************************************/
void
rdpup_create_window(WindowPtr pWindow, rdpWindowRec* priv)
{
int bytes;
int index;
int flags;
int num_window_rects;
int num_visibility_rects;
int title_bytes;
int style;
int ext_style;
int root_id;
char title[256];
LLOGLN(10, ("rdpup_create_window: id 0x%8.8x", pWindow->drawable.id));
if (g_connected)
{
root_id = pWindow->drawable.pScreen->root->drawable.id;
if (pWindow->overrideRedirect)
{
style = XR_STYLE_TOOLTIP;
ext_style = XR_EXT_STYLE_TOOLTIP;
}
else
{
style = XR_STYLE_NORMAL;
ext_style = XR_EXT_STYLE_NORMAL;
}
flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_NEW;
strcpy(title, "title");
title_bytes = strlen(title);
num_window_rects = 1;
num_visibility_rects = 1;
/* calculate bytes */
bytes = (2 + 2) + (5 * 4) + (2 + title_bytes) + (12 * 4) +
(2 + num_window_rects * 8) + (4 + 4) +
(2 + num_visibility_rects * 8) + 4;
rdpup_pre_check(bytes);
out_uint16_le(g_out_s, 25);
out_uint16_le(g_out_s, bytes);
g_count++;
out_uint32_le(g_out_s, pWindow->drawable.id); /* window_id */
out_uint32_le(g_out_s, pWindow->parent->drawable.id); /* owner_window_id */
flags |= WINDOW_ORDER_FIELD_OWNER;
out_uint32_le(g_out_s, style); /* style */
out_uint32_le(g_out_s, ext_style); /* extended_style */
flags |= WINDOW_ORDER_FIELD_STYLE;
out_uint32_le(g_out_s, 0); /* show_state */
flags |= WINDOW_ORDER_FIELD_SHOW;
out_uint16_le(g_out_s, title_bytes); /* title_info */
out_uint8a(g_out_s, title, title_bytes);
flags |= WINDOW_ORDER_FIELD_TITLE;
out_uint32_le(g_out_s, 0); /* client_offset_x */
out_uint32_le(g_out_s, 0); /* client_offset_y */
flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET;
out_uint32_le(g_out_s, pWindow->drawable.width); /* client_area_width */
out_uint32_le(g_out_s, pWindow->drawable.height); /* client_area_height */
flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE;
out_uint32_le(g_out_s, 0); /* rp_content */
out_uint32_le(g_out_s, root_id); /* root_parent_handle */
flags |= WINDOW_ORDER_FIELD_ROOT_PARENT;
out_uint32_le(g_out_s, pWindow->drawable.x); /* window_offset_x */
out_uint32_le(g_out_s, pWindow->drawable.y); /* window_offset_y */
flags |= WINDOW_ORDER_FIELD_WND_OFFSET;
out_uint32_le(g_out_s, 0); /* window_client_delta_x */
out_uint32_le(g_out_s, 0); /* window_client_delta_y */
flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA;
out_uint32_le(g_out_s, pWindow->drawable.width); /* window_width */
out_uint32_le(g_out_s, pWindow->drawable.height); /* window_height */
flags |= WINDOW_ORDER_FIELD_WND_SIZE;
out_uint16_le(g_out_s, num_window_rects); /* num_window_rects */
for (index = 0; index < num_window_rects; index++)
{
out_uint16_le(g_out_s, 0); /* left */
out_uint16_le(g_out_s, 0); /* top */
out_uint16_le(g_out_s, pWindow->drawable.width); /* right */
out_uint16_le(g_out_s, pWindow->drawable.height); /* bottom */
}
flags |= WINDOW_ORDER_FIELD_WND_RECTS;
out_uint32_le(g_out_s, 0); /* visible_offset_x */
out_uint32_le(g_out_s, 0); /* visible_offset_y */
flags |= WINDOW_ORDER_FIELD_VIS_OFFSET;
out_uint16_le(g_out_s, num_visibility_rects); /* num_visibility_rects */
for (index = 0; index < num_visibility_rects; index++)
{
out_uint16_le(g_out_s, 0); /* left */
out_uint16_le(g_out_s, 0); /* top */
out_uint16_le(g_out_s, pWindow->drawable.width); /* right */
out_uint16_le(g_out_s, pWindow->drawable.height); /* bottom */
}
flags |= WINDOW_ORDER_FIELD_VISIBILITY;
out_uint32_le(g_out_s, flags); /* flags */
}
}
/******************************************************************************/
void
rdpup_delete_window(WindowPtr pWindow, rdpWindowRec* priv)
{
LLOGLN(10, ("rdpup_delete_window: id 0x%8.8x", pWindow->drawable.id));
if (g_connected)
{
rdpup_pre_check(8);
out_uint16_le(g_out_s, 26);
out_uint16_le(g_out_s, 8);
g_count++;
out_uint32_le(g_out_s, pWindow->drawable.id); /* window_id */
}
}
/******************************************************************************/
int
rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv)
{
int index;
int clip_index;
int count;
int num_clips;
BoxRec box;
xSegment* seg;
struct image_data id;
struct rdp_draw_item* di;
if (pDirtyPriv == 0)
{
return 0;
}
if (pDirtyPriv->is_dirty == 0)
{
return 0;
}
/* update use time / count */
g_os_bitmaps[pDirtyPriv->rdpindex].stamp = g_os_bitmap_stamp;
g_os_bitmap_stamp++;
LLOGLN(10, ("-----------------got dirty"));
rdpup_switch_os_surface(pDirtyPriv->rdpindex);
rdpup_get_pixmap_image_rect(pDirtyPixmap, &id);
rdpup_begin_update();
draw_item_pack(pDirtyPriv);
di = pDirtyPriv->draw_item_head;
while (di != 0)
{
LLOGLN(10, ("rdpup_check_dirty: type %d", di->type));
switch (di->type)
{
case RDI_FILL:
rdpup_set_fgcolor(di->u.fill.fg_color);
rdpup_set_opcode(di->u.fill.opcode);
count = REGION_NUM_RECTS(di->reg);
for (index = 0; index < count; index++)
{
box = REGION_RECTS(di->reg)[index];
LLOGLN(10, (" RDI_FILL %d %d %d %d", box.x1, box.y1,
box.x2, box.y2));
rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
}
rdpup_set_opcode(GXcopy);
break;
case RDI_IMGLL:
rdpup_set_hints(1, 1);
rdpup_set_opcode(di->u.img.opcode);
count = REGION_NUM_RECTS(di->reg);
for (index = 0; index < count; index++)
{
box = REGION_RECTS(di->reg)[index];
LLOGLN(10, (" RDI_IMGLL %d %d %d %d", box.x1, box.y1,
box.x2, box.y2));
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
}
rdpup_set_opcode(GXcopy);
rdpup_set_hints(0, 1);
break;
case RDI_IMGLY:
rdpup_set_opcode(di->u.img.opcode);
count = REGION_NUM_RECTS(di->reg);
for (index = 0; index < count; index++)
{
box = REGION_RECTS(di->reg)[index];
LLOGLN(10, (" RDI_IMGLY %d %d %d %d", box.x1, box.y1,
box.x2, box.y2));
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
}
rdpup_set_opcode(GXcopy);
break;
case RDI_LINE:
LLOGLN(10, (" RDI_LINE"));
num_clips = REGION_NUM_RECTS(di->reg);
if (num_clips > 0)
{
rdpup_set_fgcolor(di->u.line.fg_color);
rdpup_set_opcode(di->u.line.opcode);
rdpup_set_pen(0, di->u.line.width);
for (clip_index = num_clips - 1; clip_index >= 0; clip_index--)
{
box = REGION_RECTS(di->reg)[clip_index];
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
for (index = 0; index < di->u.line.nseg; index++)
{
seg = di->u.line.segs + index;
LLOGLN(10, (" RDI_LINE %d %d %d %d", seg->x1, seg->y1,
seg->x2, seg->y2));
rdpup_draw_line(seg->x1, seg->y1, seg->x2, seg->y2);
}
}
}
rdpup_reset_clip();
rdpup_set_opcode(GXcopy);
break;
}
di = di->next;
}
draw_item_remove_all(pDirtyPriv);
rdpup_end_update();
pDirtyPriv->is_dirty = 0;
rdpup_switch_os_surface(-1);
return 0;
}

@ -0,0 +1,24 @@
EXTRA_DIST = xrdpapi.h
EXTRA_DEFINES =
EXTRA_INCLUDES =
EXTRA_LIBS =
EXTRA_FLAGS =
AM_CFLAGS = \
$(EXTRA_DEFINES)
INCLUDES = \
$(EXTRA_INCLUDES)
lib_LTLIBRARIES = \
libxrdpapi.la
libxrdpapi_la_SOURCES = \
xrdpapi.c
libxrdpapi_la_LDFLAGS = \
$(EXTRA_FLAGS)
libxrdpapi_la_LIBADD = \
$(EXTRA_LIBS)

@ -0,0 +1,94 @@
// xrdp_chan_test.cpp : Basic test for virtual channel use.
// These headers are required for the windows terminal services calls.
#include "xrdpapi.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DSIZE (1024 * 4)
int main()
{
// Initialize the data for send/receive
void* hFile;
char* data;
char* data1;
data = (char*)malloc(DSIZE);
data1 = (char*)malloc(DSIZE);
int ret;
void* vcFileHandlePtr = NULL;
memset(data, 0xca, DSIZE);
memset(data1, 0, DSIZE);
unsigned int written = 0;
// Open the skel channel in current session
//void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0);
void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "TSMF", WTS_CHANNEL_OPTION_DYNAMIC);
ret = WTSVirtualChannelQuery(channel, WTSVirtualFileHandle, vcFileHandlePtr, &written);
// Write the data to the channel
ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written);
if (!ret)
{
long err = errno;
printf("error 1 0x%8.8x\n", err);
usleep(100000);
return 1;
}
else
{
printf("Sent bytes!\n");
}
if (written != DSIZE)
{
long err = errno;
printf("error 2 0x%8.8x\n", err);
usleep(100000);
return 1;
}
else
{
printf("Read bytes!\n");
}
ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written);
if (!ret)
{
long err = errno;
printf("error 3 0x%8.8x\n", err);
usleep(100000);
return 1;
}
if (written != DSIZE)
{
long err = errno;
printf("error 4 0x%8.8x\n", err);
usleep(100000);
return 1;
}
else
{
printf("Read bytes!\n");
}
ret = WTSVirtualChannelClose(channel);
if (memcmp(data, data1, DSIZE) == 0)
{
}
else
{
printf("error data no match\n");
return 1;
}
printf("Done!\n");
usleep(100000);
return 0;
}

@ -0,0 +1,383 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Thomas Goddard 2012
* Copyright (C) Jay Sorg 2012
*
* 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.
*/
/* do not use os_calls in here */
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "xrdpapi.h"
struct wts_obj
{
int fd;
int status;
char name[8];
char dname[128];
int display_num;
int flags;
};
/*****************************************************************************/
static int
get_display_num_from_display(char* display_text)
{
int index;
int mode;
int host_index;
int disp_index;
int scre_index;
char host[256];
char disp[256];
char scre[256];
index = 0;
host_index = 0;
disp_index = 0;
scre_index = 0;
mode = 0;
while (display_text[index] != 0)
{
if (display_text[index] == ':')
{
mode = 1;
}
else if (display_text[index] == '.')
{
mode = 2;
}
else if (mode == 0)
{
host[host_index] = display_text[index];
host_index++;
}
else if (mode == 1)
{
disp[disp_index] = display_text[index];
disp_index++;
}
else if (mode == 2)
{
scre[scre_index] = display_text[index];
scre_index++;
}
index++;
}
host[host_index] = 0;
disp[disp_index] = 0;
scre[scre_index] = 0;
return atoi(disp);
}
/*****************************************************************************/
void*
WTSVirtualChannelOpen(void* hServer, unsigned int SessionId,
const char* pVirtualName)
{
if (hServer != WTS_CURRENT_SERVER_HANDLE)
{
return 0;
}
return WTSVirtualChannelOpenEx(SessionId, pVirtualName, 0);
}
/*****************************************************************************/
static int
can_send(int sck, int millis)
{
struct timeval time;
fd_set wfds;
int select_rv;
FD_ZERO(&wfds);
FD_SET(sck, &wfds);
time.tv_sec = millis / 1000;
time.tv_usec = (millis * 1000) % 1000000;
select_rv = select(sck + 1, 0, &wfds, 0, &time);
if (select_rv > 0)
{
return 1;
}
return 0;
}
/*****************************************************************************/
static int
can_recv(int sck, int millis)
{
struct timeval time;
fd_set rfds;
int select_rv;
FD_ZERO(&rfds);
FD_SET(sck, &rfds);
time.tv_sec = millis / 1000;
time.tv_usec = (millis * 1000) % 1000000;
select_rv = select(sck + 1, &rfds, 0, 0, &time);
if (select_rv > 0)
{
return 1;
}
return 0;
}
/*****************************************************************************/
static int
send_init(struct wts_obj* wts)
{
char initmsg[64];
memset(initmsg, 0, 64);
strncpy(initmsg, wts->name, 8);
initmsg[16] = (wts->flags >> 0) & 0xff;
initmsg[17] = (wts->flags >> 8) & 0xff;
initmsg[18] = (wts->flags >> 16) & 0xff;
initmsg[19] = (wts->flags >> 24) & 0xff;
LLOGLN(10, ("send_init: sending %s", initmsg));
if (!can_send(wts->fd, 500))
{
return 1;
}
if (send(wts->fd, initmsg, 64, 0) != 64)
{
return 1;
}
LLOGLN(10, ("send_init: send ok!"));
return 0;
}
/*****************************************************************************/
void*
WTSVirtualChannelOpenEx(unsigned int SessionId,
const char* pVirtualName,
unsigned int flags)
{
struct wts_obj* wts;
char* display_text;
struct sockaddr_un s;
int bytes;
unsigned long llong;
if (SessionId != WTS_CURRENT_SESSION)
{
LLOGLN(0, ("WTSVirtualChannelOpenEx: SessionId bad"));
return 0;
}
wts = (struct wts_obj*)malloc(sizeof(struct wts_obj));
memset(wts, 0, sizeof(struct wts_obj));
wts->fd = -1;
wts->flags = flags;
display_text = getenv("DISPLAY");
if (display_text != 0)
{
wts->display_num = get_display_num_from_display(display_text);
}
if (wts->display_num > 0)
{
wts->fd = socket(AF_UNIX, SOCK_STREAM, 0);
/* set non blocking */
llong = fcntl(wts->fd, F_GETFL);
llong = llong | O_NONBLOCK;
fcntl(wts->fd, F_SETFL, llong);
/* connect to session chansrv */
memset(&s, 0, sizeof(struct sockaddr_un));
s.sun_family = AF_UNIX;
bytes = sizeof(s.sun_path);
snprintf(s.sun_path, bytes - 1, "/tmp/.xrdp/xrdpapi_%d", wts->display_num);
s.sun_path[bytes - 1] = 0;
bytes = sizeof(struct sockaddr_un);
if (connect(wts->fd, (struct sockaddr*)&s, bytes) == 0)
{
LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName));
strncpy(wts->name, pVirtualName, 8);
/* wait for connection to complete and send init */
if (send_init(wts) == 0)
{
/* all ok */
wts->status = 1;
}
}
}
else
{
LLOGLN(0, ("WTSVirtualChannelOpenEx: display is 0"));
}
return wts;
}
/*****************************************************************************/
int
WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer,
unsigned int Length, unsigned int* pBytesWritten)
{
struct wts_obj* wts;
int error;
int lerrno;
wts = (struct wts_obj*)hChannelHandle;
if (wts == 0)
{
return 0;
}
if (wts->status != 1)
{
return 0;
}
if (can_send(wts->fd, 0))
{
error = send(wts->fd, Buffer, Length, 0);
if (error == -1)
{
lerrno = errno;
if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) ||
(lerrno == EINPROGRESS))
{
*pBytesWritten = 0;
return 1;
}
return 0;
}
else if (error == 0)
{
return 0;
}
else if (error > 0)
{
*pBytesWritten = error;
return 1;
}
}
*pBytesWritten = 0;
return 1;
}
/*****************************************************************************/
int
WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut,
char* Buffer, unsigned int BufferSize,
unsigned int* pBytesRead)
{
struct wts_obj* wts;
int error;
int lerrno;
wts = (struct wts_obj*)hChannelHandle;
if (wts == 0)
{
return 0;
}
if (wts->status != 1)
{
return 0;
}
if (can_recv(wts->fd, TimeOut))
{
error = recv(wts->fd, Buffer, BufferSize, 0);
if (error == -1)
{
lerrno = errno;
if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) ||
(lerrno == EINPROGRESS))
{
*pBytesRead = 0;
return 1;
}
return 0;
}
else if (error == 0)
{
return 0;
}
else if (error > 0)
{
*pBytesRead = error;
return 1;
}
}
*pBytesRead = 0;
return 1;
}
/*****************************************************************************/
int
WTSVirtualChannelClose(void* hChannelHandle)
{
struct wts_obj* wts;
wts = (struct wts_obj*)hChannelHandle;
if (wts == 0)
{
return 0;
}
if (wts->fd != -1)
{
close(wts->fd);
}
free(wts);
return 1;
}
/*****************************************************************************/
int
WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
void** ppBuffer, unsigned int* pBytesReturned)
{
struct wts_obj* wts;
wts = (struct wts_obj*)hChannelHandle;
if (wts == 0)
{
return 0;
}
if (wts->status != 1)
{
return 0;
}
if (WtsVirtualClass == WTSVirtualFileHandle)
{
*pBytesReturned = 4;
*ppBuffer = malloc(4);
memcpy(*ppBuffer, &(wts->fd), 4);
}
return 1;
}
/*****************************************************************************/
void
WTSFreeMemory(void* pMemory)
{
if (pMemory != 0)
{
free(pMemory);
}
}

@ -0,0 +1,76 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Thomas Goddard 2012
* Copyright (C) Jay Sorg 2012
*
* 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.
*/
/*
xrdpapi header, do not use os_calls.h, arch.h or any xrdp internal headers
this file is included in 3rd party apps
*/
#if !defined(XRDPAPI_H_)
#define XRDPAPI_H_
#ifdef __cplusplus
extern "C" {
#endif
#define WTS_CURRENT_SERVER_HANDLE 0
#define WTS_CURRENT_SESSION 0xffffffff
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_COMPRESS 0x00000008
typedef enum _WTS_VIRTUAL_CLASS
{
WTSVirtualClientData,
WTSVirtualFileHandle
} WTS_VIRTUAL_CLASS;
/*
Reference:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464(v=vs.85).aspx
*/
void*
WTSVirtualChannelOpen(void* hServer, unsigned int SessionId,
const char* pVirtualName);
void*
WTSVirtualChannelOpenEx(unsigned int SessionId,
const char* pVirtualName,
unsigned int flags);
int
WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer,
unsigned int Length, unsigned int* pBytesWritten);
int
WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut,
char* Buffer, unsigned int BufferSize,
unsigned int* pBytesRead);
int
WTSVirtualChannelClose(void* hChannelHandle);
int
WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
void** ppBuffer, unsigned int* pBytesReturned);
void
WTSFreeMemory(void* pMemory);
#ifdef __cplusplus
}
#endif
#endif /* XRDPAPI_H_ */

@ -359,6 +359,95 @@ lib_mod_event(struct mod* mod, int msg, tbus param1, tbus param2,
return rv; return rv;
} }
/******************************************************************************/
/* return error */
static int APP_CC
process_server_window_new_update(struct mod* mod, struct stream* s)
{
int flags;
int window_id;
int title_bytes;
int index;
int bytes;
int rv;
struct rail_window_state_order rwso;
g_memset(&rwso, 0, sizeof(rwso));
in_uint32_le(s, window_id);
in_uint32_le(s, rwso.owner_window_id);
in_uint32_le(s, rwso.style);
in_uint32_le(s, rwso.extended_style);
in_uint32_le(s, rwso.show_state);
in_uint16_le(s, title_bytes);
if (title_bytes > 0)
{
rwso.title_info = g_malloc(title_bytes + 1, 0);
in_uint8a(s, rwso.title_info, title_bytes);
rwso.title_info[title_bytes] = 0;
}
in_uint32_le(s, rwso.client_offset_x);
in_uint32_le(s, rwso.client_offset_y);
in_uint32_le(s, rwso.client_area_width);
in_uint32_le(s, rwso.client_area_height);
in_uint32_le(s, rwso.rp_content);
in_uint32_le(s, rwso.root_parent_handle);
in_uint32_le(s, rwso.window_offset_x);
in_uint32_le(s, rwso.window_offset_y);
in_uint32_le(s, rwso.window_client_delta_x);
in_uint32_le(s, rwso.window_client_delta_y);
in_uint32_le(s, rwso.window_width);
in_uint32_le(s, rwso.window_height);
in_uint16_le(s, rwso.num_window_rects);
if (rwso.num_window_rects > 0)
{
bytes = sizeof(struct rail_window_rect) * rwso.num_window_rects;
rwso.window_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
for (index = 0; index < rwso.num_window_rects; index++)
{
in_uint16_le(s, rwso.window_rects[index].left);
in_uint16_le(s, rwso.window_rects[index].top);
in_uint16_le(s, rwso.window_rects[index].right);
in_uint16_le(s, rwso.window_rects[index].bottom);
}
}
in_uint32_le(s, rwso.visible_offset_x);
in_uint32_le(s, rwso.visible_offset_y);
in_uint16_le(s, rwso.num_visibility_rects);
if (rwso.num_visibility_rects > 0)
{
bytes = sizeof(struct rail_window_rect) * rwso.num_visibility_rects;
rwso.visibility_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
for (index = 0; index < rwso.num_visibility_rects; index++)
{
in_uint16_le(s, rwso.visibility_rects[index].left);
in_uint16_le(s, rwso.visibility_rects[index].top);
in_uint16_le(s, rwso.visibility_rects[index].right);
in_uint16_le(s, rwso.visibility_rects[index].bottom);
}
}
in_uint32_le(s, flags);
mod->server_window_new_update(mod, window_id, &rwso, flags);
rv = 0;
g_free(rwso.title_info);
g_free(rwso.window_rects);
g_free(rwso.visibility_rects);
return rv;
}
/******************************************************************************/
/* return error */
static int APP_CC
process_server_window_delete(struct mod* mod, struct stream* s)
{
int window_id;
int rv;
in_uint32_le(s, window_id);
mod->server_window_delete(mod, window_id);
rv = 0;
return rv;
}
/******************************************************************************/ /******************************************************************************/
/* return error */ /* return error */
static int static int
@ -495,6 +584,12 @@ lib_mod_process_orders(struct mod* mod, int type, struct stream* s)
in_uint32_le(s, mask); in_uint32_le(s, mask);
rv = mod->server_set_hints(mod, hints, mask); rv = mod->server_set_hints(mod, hints, mask);
break; break;
case 25: /* server_window_new_update */
rv = process_server_window_new_update(mod, s);
break;
case 26: /* server_window_delete */
rv = process_server_window_delete(mod, s);
break;
default: default:
g_writeln("lib_mod_process_orders: unknown order type %d", type); g_writeln("lib_mod_process_orders: unknown order type %d", type);
rv = 0; rv = 0;

@ -26,6 +26,7 @@
#include "os_calls.h" #include "os_calls.h"
#include "defines.h" #include "defines.h"
#include "xrdp_client_info.h" #include "xrdp_client_info.h"
#include "xrdp_rail.h"
#define CURRENT_MOD_VER 2 #define CURRENT_MOD_VER 2
@ -88,6 +89,7 @@ struct mod
char* data, int data_len, char* data, int data_len,
int total_data_len, int flags); int total_data_len, int flags);
int (*server_bell_trigger)(struct mod* v); int (*server_bell_trigger)(struct mod* v);
/* off screen bitmaps */
int (*server_create_os_surface)(struct mod* v, int rdpindex, int (*server_create_os_surface)(struct mod* v, int rdpindex,
int width, int height); int width, int height);
int (*server_switch_os_surface)(struct mod* v, int rdpindex); int (*server_switch_os_surface)(struct mod* v, int rdpindex);
@ -96,7 +98,28 @@ struct mod
int cx, int cy, int cx, int cy,
int rdpindex, int srcx, int srcy); int rdpindex, int srcx, int srcy);
int (*server_set_hints)(struct mod* v, int hints, int mask); int (*server_set_hints)(struct mod* v, int hints, int mask);
tbus server_dumby[100 - 30]; /* align, 100 minus the number of server /* rail */
int (*server_window_new_update)(struct mod* v, int window_id,
struct rail_window_state_order* window_state,
int flags);
int (*server_window_delete)(struct mod* v, int window_id);
int (*server_window_icon)(struct mod* v,
int window_id, int cache_entry, int cache_id,
struct rail_icon_info* icon_info,
int flags);
int (*server_window_cached_icon)(struct mod* v,
int window_id, int cache_entry,
int cache_id, int flags);
int (*server_notify_new_update)(struct mod* v,
int window_id, int notify_id,
struct rail_notify_state_order* notify_state,
int flags);
int (*server_notify_delete)(struct mod* v, int window_id,
int notify_id);
int (*server_monitored_desktop)(struct mod* v,
struct rail_monitored_desktop_order* mdo,
int flags);
tbus server_dumby[100 - 37]; /* align, 100 minus the number of server
functions above */ functions above */
/* common */ /* common */
tbus handle; /* pointer to self as long */ tbus handle; /* pointer to self as long */

Loading…
Cancel
Save