summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
authorJim Grandy <jgrandy@authentic8.com>2013-07-06 08:42:05 -0700
committerJim Grandy <jgrandy@authentic8.com>2013-07-26 12:25:02 -0700
commit29e61134c3ffb9b1fb3d3d7b36f16819fa5feece (patch)
tree86749c96c923268dd13474168a72c928105b7f0b /sesman/chansrv
parent8c4019b9086a0bd9d50bfa17d0ef8bcf0147d32c (diff)
downloadxrdp-proprietary-29e61134c3ffb9b1fb3d3d7b36f16819fa5feece.tar.gz
xrdp-proprietary-29e61134c3ffb9b1fb3d3d7b36f16819fa5feece.zip
Hand-apply patches (chansrv/rail) from Authentic8: 516fd1d 6a4fb28 c038a99
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/chansrv.c139
-rw-r--r--sesman/chansrv/chansrv.h2
-rw-r--r--sesman/chansrv/rail.c162
3 files changed, 212 insertions, 91 deletions
diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c
index d5fbd765..2603d598 100644
--- a/sesman/chansrv/chansrv.c
+++ b/sesman/chansrv/chansrv.c
@@ -76,6 +76,143 @@ int g_exec_pid = 0;
/* this variable gets bumped up once per DVC we create */
tui32 g_dvc_chan_id = 100;
+struct timeout_obj
+{
+ tui32 mstime;
+ void* data;
+ void (*callback)(void* data);
+ struct timeout_obj* next;
+};
+
+static struct timeout_obj* g_timeout_head = 0;
+static struct timeout_obj* g_timeout_tail = 0;
+
+/*****************************************************************************/
+int APP_CC
+add_timeout(int msoffset, void (*callback)(void* data), void* data)
+{
+ struct timeout_obj* tobj;
+ tui32 now;
+
+ LOG(10, ("add_timeout:"));
+ now = g_time3();
+ tobj = g_malloc(sizeof(struct timeout_obj), 1);
+ tobj->mstime = now + msoffset;
+ tobj->callback = callback;
+ tobj->data = data;
+ if (g_timeout_tail == 0)
+ {
+ g_timeout_head = tobj;
+ g_timeout_tail = tobj;
+ }
+ else
+ {
+ g_timeout_tail->next = tobj;
+ g_timeout_tail = tobj;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+get_timeout(int* timeout)
+{
+ struct timeout_obj* tobj;
+ tui32 now;
+ int ltimeout;
+
+ LOG(10, ("get_timeout:"));
+ ltimeout = *timeout;
+ if (ltimeout < 1)
+ {
+ ltimeout = 0;
+ }
+ tobj = g_timeout_head;
+ if (tobj != 0)
+ {
+ now = g_time3();
+ while (tobj != 0)
+ {
+ LOG(10, (" now %u tobj->mstime %u", now, tobj->mstime));
+ if (now < tobj->mstime)
+ {
+ ltimeout = tobj->mstime - now;
+ }
+ tobj = tobj->next;
+ }
+ }
+ if (ltimeout > 0)
+ {
+ LOG(10, (" ltimeout %d", ltimeout));
+ if (*timeout < 1)
+ {
+ *timeout = ltimeout;
+ }
+ else
+ {
+ if (*timeout > ltimeout)
+ {
+ *timeout = ltimeout;
+ }
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+check_timeout(void)
+{
+ struct timeout_obj* tobj;
+ struct timeout_obj* last_tobj;
+ struct timeout_obj* temp_tobj;
+ int count;
+ tui32 now;
+
+ LOG(10, ("check_timeout:"));
+ count = 0;
+ tobj = g_timeout_head;
+ if (tobj != 0)
+ {
+ last_tobj = 0;
+ while (tobj != 0)
+ {
+ count++;
+ now = g_time3();
+ if (now >= tobj->mstime)
+ {
+ tobj->callback(tobj->data);
+ if (last_tobj == 0)
+ {
+ g_timeout_head = tobj->next;
+ if (g_timeout_head == 0)
+ {
+ g_timeout_tail = 0;
+ }
+ }
+ else
+ {
+ last_tobj->next = tobj->next;
+ if (g_timeout_tail == tobj)
+ {
+ g_timeout_tail = last_tobj;
+ }
+ }
+ temp_tobj = tobj;
+ tobj = tobj->next;
+ g_free(temp_tobj);
+ }
+ else
+ {
+ last_tobj = tobj;
+ tobj = tobj->next;
+ }
+ }
+ }
+ LOG(10, (" count %d", count));
+ return 0;
+}
+
/*****************************************************************************/
/* add data to chan_item, on its way to the client */
/* returns error */
@@ -940,6 +1077,7 @@ channel_thread_loop(void *in_val)
while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
{
+ check_timeout();
if (g_is_wait_obj_set(g_term_event))
{
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set"));
@@ -1022,6 +1160,7 @@ channel_thread_loop(void *in_val)
sound_get_wait_objs(objs, &num_objs, &timeout);
dev_redir_get_wait_objs(objs, &num_objs, &timeout);
xfuse_get_wait_objs(objs, &num_objs, &timeout);
+ get_timeout(&timeout);
} /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */
}
diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h
index 61b62e4e..2d18a711 100644
--- a/sesman/chansrv/chansrv.h
+++ b/sesman/chansrv/chansrv.h
@@ -57,6 +57,8 @@ struct xrdp_api_data
int APP_CC send_channel_data(int chan_id, char *data, int size);
int APP_CC send_rail_drawing_orders(char* data, int size);
int APP_CC main_cleanup(void);
+int APP_CC
+add_timeout(int msoffset, void (*callback)(void* data), void* data);
int APP_CC find_empty_slot_in_dvc_channels();
struct xrdp_api_data *APP_CC struct_from_dvc_chan_id(tui32 dvc_chan_id);
int remove_struct_with_chan_id(tui32 dvc_chan_id);
diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c
index a0964914..59b19411 100644
--- a/sesman/chansrv/rail.c
+++ b/sesman/chansrv/rail.c
@@ -61,6 +61,10 @@ static int g_rail_running = 1;
/* list of valid rail windows */
static struct list* g_window_list = 0;
+static int g_got_focus = 0;
+static int g_focus_counter = 0;
+static Window g_focus_win = 0;
+
/* used in valid field of struct rail_window_data */
#define RWD_X (1 << 0)
#define RWD_Y (1 << 1)
@@ -151,6 +155,24 @@ static int APP_CC rail_show_window(Window window_id, int show_state);
static int APP_CC rail_win_send_text(Window win);
/*****************************************************************************/
+static int APP_CC
+rail_send_key_esc(int window_id)
+{
+ XEvent event;
+
+ g_memset(&event, 0, sizeof(event));
+ event.type = KeyPress;
+ event.xkey.same_screen = True;
+ event.xkey.root = g_root_window;
+ event.xkey.window = window_id;
+ event.xkey.keycode = 9;
+ XSendEvent(g_display, window_id, True, 0xfff, &event);
+ event.type = KeyRelease;
+ XSendEvent(g_display, window_id, True, 0xfff, &event);
+ return 0;
+}
+
+/*****************************************************************************/
static struct rail_window_data* APP_CC
rail_get_window_data(Window window)
{
@@ -414,87 +436,35 @@ rail_process_exec(struct stream *s, int size)
return 0;
}
-/*****************************************************************************/
-static void APP_CC
-rail_simulate_mouse_click(int button)
-{
- /*
- * The below code can be referenced from:
- * http://www.linuxquestions.org/questions/programming-9/simulating-a-mouse-click-594576/#post2936738
- */
- XEvent event;
- g_memset(&event, 0x00, sizeof(event));
-
- event.type = ButtonPress;
- event.xbutton.button = button;
- event.xbutton.same_screen = True;
-
- XQueryPointer(g_display, g_root_window, &event.xbutton.root,
- &event.xbutton.window, &event.xbutton.x_root,
- &event.xbutton.y_root, &event.xbutton.x,
- &event.xbutton.y, &event.xbutton.state);
-
- event.xbutton.subwindow = event.xbutton.window;
-
- while(event.xbutton.subwindow)
- {
- event.xbutton.window = event.xbutton.subwindow;
-
- XQueryPointer(g_display, event.xbutton.window, &event.xbutton.root,
- &event.xbutton.subwindow, &event.xbutton.x_root,
- &event.xbutton.y_root, &event.xbutton.x,
- &event.xbutton.y, &event.xbutton.state);
- }
-
- if(XSendEvent(g_display, PointerWindow, True, 0xfff, &event) == 0)
- {
- LOG(0, (" error sending mouse event"));
- }
-
- XFlush(g_display);
-
- g_sleep(100);
-
- event.type = ButtonRelease;
- event.xbutton.state = 0x100;
-
- if(XSendEvent(g_display, PointerWindow, True, 0xfff, &event) == 0)
- {
- LOG(0, (" error sending mouse event"));
- }
-
- XFlush(g_display);
-}
-
/******************************************************************************/
static int APP_CC
-rail_win_popdown(int window_id)
+rail_win_popdown(void)
{
int rv = 0;
- unsigned int i;
+ int i;
unsigned int nchild;
Window r;
Window p;
Window* children;
+ XWindowAttributes window_attributes;
/*
* Check the tree of current existing X windows and dismiss
- * the managed rail popups by simulating a mouse click, so
+ * the managed rail popups by simulating a esc key, so
* that the requested window can be closed properly.
*/
XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild);
- for (i = 0; i < nchild; i++)
+ for (i = nchild - 1; i >= 0; i--)
{
- XWindowAttributes window_attributes;
XGetWindowAttributes(g_display, children[i], &window_attributes);
if (window_attributes.override_redirect &&
window_attributes.map_state == IsViewable &&
- list_index_of(g_window_list, children[i]) >= 0) {
- LOG(0, (" dismiss pop up 0x%8.8x", children[i]));
- rail_simulate_mouse_click(Button1);
+ list_index_of(g_window_list, children[i]) >= 0)
+ {
+ LOG(10, (" dismiss pop up 0x%8.8x", children[i]));
+ rail_send_key_esc(children[i]);
rv = 1;
- break;
}
}
@@ -510,13 +480,7 @@ rail_close_window(int window_id)
LOG(0, ("chansrv::rail_close_window:"));
- if (rail_win_popdown(window_id))
- {
- return 0;
- }
-
- /* don't receive UnmapNotify for closing window */
- XSelectInput(g_display, window_id, PropertyChangeMask);
+ rail_win_popdown();
g_memset(&ce, 0, sizeof(ce));
ce.xclient.type = ClientMessage;
@@ -532,6 +496,18 @@ rail_close_window(int window_id)
}
/*****************************************************************************/
+void DEFAULT_CC
+my_timoeut(void* data)
+{
+ LOG(10, ("my_timoeut: g_got_focus %d", g_got_focus));
+ if (g_focus_counter == (int)(long)data)
+ {
+ LOG(10, ("my_timoeut: g_focus_counter %d", g_focus_counter));
+ rail_win_popdown();
+ }
+}
+
+/*****************************************************************************/
static int APP_CC
rail_process_activate(struct stream *s, int size)
{
@@ -543,22 +519,37 @@ rail_process_activate(struct stream *s, int size)
LOG(10, ("chansrv::rail_process_activate:"));
in_uint32_le(s, window_id);
in_uint8(s, enabled);
+ g_focus_counter++;
+ g_got_focus = enabled;
LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled));
XGetWindowAttributes(g_display, window_id, &window_attributes);
if (enabled)
{
- if (window_attributes.map_state != IsViewable)
+ if (g_focus_win == window_id)
{
/* In case that window is unmapped upon minimization and not yet mapped*/
XMapWindow(g_display, window_id);
}
- XGetTransientForHint(g_display, window_id, &transient_for);
- if (transient_for > 0)
+ else
{
- // Owner window should be raised up as well
- XRaiseWindow(g_display, transient_for);
+ rail_win_popdown();
+ if (window_attributes.map_state != IsViewable)
+ {
+ /* In case that window is unmapped upon minimization and not yet mapped */
+ XMapWindow(g_display, window_id);
+ }
+ XGetTransientForHint(g_display, window_id, &transient_for);
+ if (transient_for > 0)
+ {
+ /* Owner window should be raised up as well */
+ XRaiseWindow(g_display, transient_for);
+ }
+ 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);
}
LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id));
XRaiseWindow(g_display, window_id);
@@ -570,10 +561,7 @@ rail_process_activate(struct stream *s, int size)
LOG(10, (" window attributes: override_redirect %d",
window_attributes.override_redirect));
- if (window_attributes.override_redirect) {
- LOG(10, (" dismiss popup window 0x%8.8x", window_id));
- XUnmapWindow(g_display, window_id);
- }
+ add_timeout(200, my_timoeut, (void*)(long)g_focus_counter);
}
return 0;
}
@@ -1094,7 +1082,7 @@ rail_win_send_text(Window win)
{
if (g_strncmp(rwd->title, data, 63) == 0)
{
- LOG(0, ("chansrv::rail_win_send_text: skipping, title not changed"));
+ LOG(10, ("chansrv::rail_win_send_text: skipping, title not changed"));
XFree(data);
XFree(rwd);
return 0;
@@ -1665,6 +1653,10 @@ rail_xevent(void *xevent)
case CreateNotify:
LOG(10, (" got CreateNotify window 0x%8.8x parent 0x%8.8x",
lxevent->xcreatewindow.window, lxevent->xcreatewindow.parent));
+ XSelectInput(g_display, lxevent->xcreatewindow.window,
+ PropertyChangeMask | StructureNotifyMask |
+ FocusChangeMask |
+ EnterWindowMask | LeaveWindowMask);
break;
case DestroyNotify:
@@ -1680,8 +1672,6 @@ rail_xevent(void *xevent)
case MapRequest:
LOG(10, (" got MapRequest window 0x%8.8x", lxevent->xmaprequest.window));
- XSelectInput(g_display, lxevent->xmaprequest.window,
- PropertyChangeMask | StructureNotifyMask);
XMapWindow(g_display, lxevent->xmaprequest.window);
break;
@@ -1709,23 +1699,12 @@ rail_xevent(void *xevent)
if (lxevent->xunmap.window != lxevent->xunmap.event &&
is_window_valid_child_of_root(lxevent->xunmap.window))
{
- int state = rail_win_get_state(lxevent->xunmap.window);
index = list_index_of(g_window_list, lxevent->xunmap.window);
LOG(10, (" window 0x%8.8x is unmapped", lxevent->xunmap.window));
if (index >= 0)
{
-#if 0
- XGetWindowAttributes(g_display, lxevent->xunmap.window, &wnd_attributes);
- if (wnd_attributes.override_redirect)
- {
- LOG(10, (" hide popup"));
- rail_show_window(lxevent->xunmap.window, 0x0);
- rv = 0;
- }
-#else
rail_show_window(lxevent->xunmap.window, 0x0);
rv = 0;
-#endif
}
}
break;
@@ -1757,6 +1736,7 @@ rail_xevent(void *xevent)
case FocusIn:
LOG(10, (" got FocusIn"));
+ g_focus_win = lxevent->xfocus.window;
break;
case ButtonPress: