summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
authorJim Grandy <jgrandy@authentic8.com>2013-07-03 10:01:18 -0700
committerJim Grandy <jgrandy@authentic8.com>2013-08-22 12:49:41 -0700
commit173ed7056f02e88ae287cd98aac96bab645f0db8 (patch)
tree4125a3613b8bcf8490649e667148815d3e6d1b5b /sesman/chansrv
parentaf4e42a08d98fff178bb9fdedf14906f0dfdb17c (diff)
downloadxrdp-proprietary-173ed7056f02e88ae287cd98aac96bab645f0db8.tar.gz
xrdp-proprietary-173ed7056f02e88ae287cd98aac96bab645f0db8.zip
Hand-apply patches (rail) from Authentic8: b01207f b9807e9 42f0128 0f0750c aef2dce
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/rail.c396
1 files changed, 375 insertions, 21 deletions
diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c
index cdb77ae0..e58a7030 100644
--- a/sesman/chansrv/rail.c
+++ b/sesman/chansrv/rail.c
@@ -19,9 +19,15 @@
/*
window manager info
http://www.freedesktop.org/wiki/Specifications/wm-spec
+
+ rail
+ [MS-RDPERP]: Remote Desktop Protocol:
+ Remote Programs Virtual Channel Extension
+ http://msdn.microsoft.com/en-us/library/cc242568(v=prot.20).aspx
*/
#include <X11/Xlib.h>
+#include <X11/Xatom.h>
#include "chansrv.h"
#include "rail.h"
#include "xcommon.h"
@@ -46,6 +52,8 @@ extern Atom g_utf8_string; /* in xcommon.c */
extern Atom g_net_wm_name; /* in xcommon.c */
extern Atom g_wm_state; /* in xcommon.c */
+static Atom g_rwd_atom = 0;
+
int g_rail_up = 0;
/* for rail_is_another_wm_running */
@@ -53,6 +61,23 @@ static int g_rail_running = 1;
/* list of valid rail windows */
static struct list* g_window_list = 0;
+/* used in valid field of struct rail_window_data */
+#define RWD_X (1 << 0)
+#define RWD_Y (1 << 1)
+#define RWD_WIDTH (1 << 2)
+#define RWD_HEIGHT (1 << 3)
+#define RWD_TITLE (1 << 4)
+
+struct rail_window_data
+{
+ int valid; /* bits for which fields are valid */
+ int x;
+ int y;
+ int width;
+ int height;
+ char title[64]; /* first 64 bytes of title for compare */
+};
+
/* Indicates a Client Execute PDU from client to server. */
#define TS_RAIL_ORDER_EXEC 0x0001
/* Indicates a Client Activate PDU from client to server. */
@@ -125,6 +150,70 @@ static int APP_CC rail_win_set_state(Window win, unsigned long state);
static int APP_CC rail_show_window(Window window_id, int show_state);
static int APP_CC rail_win_send_text(Window win);
+/*****************************************************************************/
+static struct rail_window_data* APP_CC
+rail_get_window_data(Window window)
+{
+ int bytes;
+ Atom actual_type_return;
+ int actual_format_return;
+ unsigned long nitems_return;
+ unsigned long bytes_after_return;
+ unsigned char* prop_return;
+ struct rail_window_data* rv;
+
+ LOG(10, ("chansrv::rail_get_window_data:"));
+ rv = 0;
+ actual_type_return = 0;
+ actual_format_return = 0;
+ nitems_return = 0;
+ prop_return = 0;
+ bytes = sizeof(struct rail_window_data);
+ XGetWindowProperty(g_display, window, g_rwd_atom, 0, bytes, 0,
+ XA_STRING, &actual_type_return,
+ &actual_format_return, &nitems_return,
+ &bytes_after_return, &prop_return);
+ if (prop_return == 0)
+ {
+ return 0;
+ }
+ if (nitems_return == bytes)
+ {
+ rv = (struct rail_window_data*)prop_return;
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_set_window_data(Window window, struct rail_window_data* rwd)
+{
+ int bytes;
+
+ bytes = sizeof(struct rail_window_data);
+ XChangeProperty(g_display, window, g_rwd_atom, XA_STRING, 8,
+ PropModeReplace, (unsigned char*)rwd, bytes);
+ return 0;
+}
+
+/*****************************************************************************/
+/* get the rail window data, if not exist, try to create it and return */
+static struct rail_window_data* APP_CC
+rail_get_window_data_safe(Window window)
+{
+ struct rail_window_data* rv;
+
+ rv = rail_get_window_data(window);
+ if (rv != 0)
+ {
+ return rv;
+ }
+ rv = g_malloc(sizeof(struct rail_window_data), 1);
+ rail_set_window_data(window, rv);
+ g_free(rv);
+ return rail_get_window_data(window);
+}
+
/******************************************************************************/
static int APP_CC
is_window_valid_child_of_root(unsigned int window_id)
@@ -226,6 +315,7 @@ rail_init(void)
g_window_list = list_create();
rail_send_init();
g_rail_up = 1;
+ g_rwd_atom = XInternAtom(g_display, "XRDP_RAIL_WINDOW_DATA", 0);
return 0;
}
@@ -363,7 +453,7 @@ rail_simulate_mouse_click(int button)
XFlush(g_display);
- usleep(100000);
+ g_sleep(100);
event.type = ButtonRelease;
event.xbutton.state = 0x100;
@@ -777,16 +867,30 @@ rail_process_window_move(struct stream *s, int size)
int top;
int right;
int bottom;
+ tsi16 si16;
+ struct rail_window_data* rwd;
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);
+ in_uint16_le(s, si16);
+ left = si16;
+ in_uint16_le(s, si16);
+ top = si16;
+ in_uint16_le(s, si16);
+ right = si16;
+ in_uint16_le(s, si16);
+ bottom = si16;
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);
+ rwd = (struct rail_window_data*)
+ g_malloc(sizeof(struct rail_window_data), 1);
+ rwd->x = left;
+ rwd->y = top;
+ rwd->width = right - left;
+ rwd->height = bottom - top;
+ rail_set_window_data(window_id, rwd);
+ g_free(rwd);
return 0;
}
@@ -799,13 +903,16 @@ rail_process_local_move_size(struct stream *s, int size)
int move_size_type;
int pos_x;
int pos_y;
+ tsi16 si16;
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);
+ in_uint16_le(s, si16);
+ pos_x = si16;
+ in_uint16_le(s, si16);
+ pos_y = si16;
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));
@@ -840,11 +947,14 @@ rail_process_sys_menu(struct stream *s, int size)
int window_id;
int left;
int top;
+ tsi16 si16;
LOG(10, ("chansrv::rail_process_sys_menu:"));
in_uint32_le(s, window_id);
- in_uint16_le(s, left);
- in_uint16_le(s, top);
+ in_uint16_le(s, si16);
+ left = si16;
+ in_uint16_le(s, si16);
+ top = si16;
LOG(10, (" window_id 0x%8.8x left %d top %d", window_id, left, top));
return 0;
}
@@ -959,14 +1069,37 @@ rail_data_in(struct stream *s, int chan_id, int chan_flags, int length,
/*****************************************************************************/
/* returns 0, event handled, 1 unhandled */
static int APP_CC
-rail_win_send_text(Window win) {
+rail_win_send_text(Window win)
+{
char* data = 0;
struct stream* s;
int len = 0;
int flags;
+ struct rail_window_data* rwd;
len = rail_win_get_text(win, &data);
-
+ rwd = rail_get_window_data_safe(win);
+ if (rwd != 0)
+ {
+ if (data != 0)
+ {
+ if (rwd->valid & RWD_TITLE)
+ {
+ if (g_strncmp(rwd->title, data, 63) == 0)
+ {
+ LOG(0, ("chansrv::rail_win_send_text: skipping, title not changed"));
+ XFree(data);
+ XFree(rwd);
+ return 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ LOG(0, ("chansrv::rail_win_send_text: error rail_get_window_data_safe failed"));
+ return 1;
+ }
if (data && len > 0) {
LOG(10, ("chansrv::rail_win_send_text: 0x%8.8x text %s length %d",
win, data, len));
@@ -982,7 +1115,12 @@ rail_win_send_text(Window win) {
send_rail_drawing_orders(s->data, (int)(s->end - s->data));
free_stream(s);
XFree(data);
+ /* update rail window data */
+ rwd->valid |= RWD_TITLE;
+ g_strncpy(rwd->title, data, 63);
+ rail_set_window_data(win, rwd);
}
+ XFree(rwd);
return 0;
}
@@ -1048,10 +1186,17 @@ rail_create_window(Window window_id, Window parent_id)
int flags;
int index;
Window transient_for = 0;
+ struct rail_window_data* rwd;
struct stream* s;
LOG(10, ("chansrv::rail_create_window 0x%8.8x", window_id));
+ rwd = rail_get_window_data_safe(window_id);
+ if (rwd == 0)
+ {
+ LOG(0, ("chansrv::rail_create_window: error rail_get_window_data_safe failed"));
+ return 0;
+ }
XGetGeometry(g_display, window_id, &root, &x, &y, &width, &height,
&border, &depth);
XGetWindowAttributes(g_display, window_id, &attributes);
@@ -1109,11 +1254,15 @@ rail_create_window(Window window_id, Window parent_id)
{
out_uint16_le(s, title_size); /* title_size */
out_uint8a(s, title_bytes, title_size); /* title */
+ rwd->valid |= RWD_TITLE;
+ g_strncpy(rwd->title, title_bytes, 63);
}
else
{
out_uint16_le(s, 5); /* title_size */
out_uint8a(s, "title", 5); /* title */
+ rwd->valid |= RWD_TITLE;
+ rwd->title[0] = 0;
}
LOG(10, (" set title info %d", title_size));
flags |= WINDOW_ORDER_FIELD_TITLE;
@@ -1162,6 +1311,201 @@ rail_create_window(Window window_id, Window parent_id)
send_rail_drawing_orders(s->data, (int)(s->end - s->data));
free_stream(s);
XFree(title_bytes);
+ rail_set_window_data(window_id, rwd);
+ XFree(rwd);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns 0, event handled, 1 unhandled */
+int APP_CC
+rail_configure_request_window(XConfigureRequestEvent* config)
+{
+ int num_window_rects = 1;
+ int num_visibility_rects = 1;
+ int i = 0;
+ int flags;
+ int index;
+ int window_id;
+ int mask;
+ int resized = 0;
+ struct rail_window_data* rwd;
+
+ struct stream* s;
+
+ window_id = config->window;
+ mask = config->value_mask;
+ LOG(10, ("chansrv::rail_configure_request_window: mask %d", mask));
+ rwd = rail_get_window_data(window_id);
+ if (rwd == 0)
+ {
+ rwd = (struct rail_window_data*)g_malloc(sizeof(struct rail_window_data), 1);
+ rwd->x = config->x;
+ rwd->y = config->y;
+ rwd->width = config->width;
+ rwd->height = config->height;
+ rwd->valid |= RWD_X | RWD_Y | RWD_WIDTH | RWD_HEIGHT;
+ rail_set_window_data(window_id, rwd);
+ g_free(rwd);
+ return 0;
+ }
+ if (!resized)
+ {
+ if (mask & CWX)
+ {
+ if (rwd->valid & RWD_X)
+ {
+ if (rwd->x != config->x)
+ {
+ resized = 1;
+ rwd->x = config->x;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->x = config->x;
+ rwd->valid |= RWD_X;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWY)
+ {
+ if (rwd->valid & RWD_Y)
+ {
+ if (rwd->y != config->y)
+ {
+ resized = 1;
+ rwd->y = config->y;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->y = config->y;
+ rwd->valid |= RWD_Y;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWWidth)
+ {
+ if (rwd->valid & RWD_WIDTH)
+ {
+ if (rwd->width != config->width)
+ {
+ resized = 1;
+ rwd->width = config->width;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->width = config->width;
+ rwd->valid |= RWD_WIDTH;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWHeight)
+ {
+ if (rwd->valid & RWD_HEIGHT)
+ {
+ if (rwd->height != config->height)
+ {
+ resized = 1;
+ rwd->height = config->height;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->height = config->height;
+ rwd->valid |= RWD_HEIGHT;
+ }
+ }
+ }
+ if (resized)
+ {
+ rail_set_window_data(window_id, rwd);
+ XFree(rwd);
+ }
+ else
+ {
+ XFree(rwd);
+ return 0;
+ }
+
+ LOG(10, ("chansrv::rail_configure_request_window: 0x%8.8x", window_id));
+
+
+ LOG(10, (" x %d y %d width %d height %d border_width %d", config->x,
+ config->y, config->width, config->height, config->border_width));
+
+ index = list_index_of(g_window_list, window_id);
+ if (index == -1)
+ {
+ /* window isn't mapped yet */
+ LOG(0, ("chansrv::rail_configure_request_window: window not mapped"));
+ return 0;
+ }
+
+ flags = WINDOW_ORDER_TYPE_WINDOW;
+
+ make_stream(s);
+ init_stream(s, 1024);
+
+ out_uint32_le(s, 10); /* configure_window */
+ out_uint32_le(s, window_id); /* window_id */
+
+ out_uint32_le(s, 0); /* client_offset_x */
+ out_uint32_le(s, 0); /* client_offset_y */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET;
+ out_uint32_le(s, config->width); /* client_area_width */
+ out_uint32_le(s, config->height); /* client_area_height */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE;
+ out_uint32_le(s, 0); /* rp_content */
+ out_uint32_le(s, g_root_window); /* root_parent_handle */
+ flags |= WINDOW_ORDER_FIELD_ROOT_PARENT;
+ out_uint32_le(s, config->x); /* window_offset_x */
+ out_uint32_le(s, config->y); /* window_offset_y */
+ flags |= WINDOW_ORDER_FIELD_WND_OFFSET;
+ out_uint32_le(s, 0); /* window_client_delta_x */
+ out_uint32_le(s, 0); /* window_client_delta_y */
+ flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA;
+ out_uint32_le(s, config->width); /* window_width */
+ out_uint32_le(s, config->height); /* window_height */
+ flags |= WINDOW_ORDER_FIELD_WND_SIZE;
+ out_uint16_le(s, num_window_rects); /* num_window_rects */
+ for (i = 0; i < num_window_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_WND_RECTS;
+ out_uint32_le(s, config->x); /* visible_offset_x */
+ out_uint32_le(s, config->y); /* visible_offset_y */
+ flags |= WINDOW_ORDER_FIELD_VIS_OFFSET;
+ out_uint16_le(s, num_visibility_rects); /* num_visibility_rects */
+ for (i = 0; i < num_visibility_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_VISIBILITY;
+ out_uint32_le(s, flags); /*flags*/
+
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
return 0;
}
@@ -1170,10 +1514,6 @@ rail_create_window(Window window_id, Window parent_id)
int APP_CC
rail_configure_window(XConfigureEvent *config)
{
- int x;
- int y;
- tui32 width;
- tui32 height;
int num_window_rects = 1;
int num_visibility_rects = 1;
int i = 0;
@@ -1195,7 +1535,7 @@ rail_configure_window(XConfigureEvent *config)
if (index == -1)
{
/* window isn't mapped yet */
- return;
+ return 0;
}
flags = WINDOW_ORDER_TYPE_WINDOW;
@@ -1259,6 +1599,7 @@ int APP_CC
rail_xevent(void *xevent)
{
XEvent *lxevent;
+ XEvent lastevent;
XWindowChanges xwc;
int rv;
int index;
@@ -1308,6 +1649,7 @@ rail_xevent(void *xevent)
lxevent->xconfigurerequest.window,
lxevent->xconfigurerequest.value_mask,
&xwc);
+ rail_configure_request_window(&(lxevent->xconfigurerequest));
rv = 0;
break;
@@ -1375,13 +1717,25 @@ rail_xevent(void *xevent)
case ConfigureNotify:
LOG(10, (" got ConfigureNotify 0x%8.8x event 0x%8.8x", lxevent->xconfigure.window,
lxevent->xconfigure.event));
-#if 0
- if (lxevent->xconfigure.window != lxevent->xconfigure.event &&
- !lxevent->xconfigure.override_redirect)
+ rv = 0;
+ if (lxevent->xconfigure.event != lxevent->xconfigure.window ||
+ lxevent->xconfigure.override_redirect)
{
- rail_configure_window(&lxevent->xconfigure);
- rv = 0;
+ break;
+ }
+ /* skip dup ConfigureNotify */
+ while (XCheckTypedWindowEvent(g_display,
+ lxevent->xconfigure.window,
+ ConfigureNotify, &lastevent))
+ {
+ if (lastevent.xconfigure.event == lastevent.xconfigure.window &&
+ lxevent->xconfigure.override_redirect == 0)
+ {
+ lxevent = &lastevent;
+ }
}
+#if 0
+ rail_configure_window(&(lxevent->xconfigure));
#endif
break;