Merge pull request #688 from bjcollins/master

Rail fixes/improvements
This commit is contained in:
Marc-André Moreau
2012-08-03 15:49:42 -07:00
11 changed files with 360 additions and 37 deletions

View File

@@ -366,8 +366,18 @@ static boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime);
if (app)
xf_rail_send_activate(xfi, event->xany.window, true);
{
xf_rail_send_activate(xfi, event->xany.window, true);
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
//Update the server with any window changes that occured while the window was not focused.
if (window != NULL)
xf_rail_adjust_position(xfi, window);
}
xf_kbd_focus_in(xfi);
if (app != true)
@@ -506,7 +516,11 @@ static boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app)
(uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom,
xfw->width, xfw->height, event->xconfigure.send_event);
if (app && ! event->xconfigure.send_event)
//additonal checks for not in a local move and not ignoring configure to send position update to server,
//also should the window not be focused then do not send to server yet(ie. resizing using window decoration).
//The server will be updated when the window gets refocused.
if (app && (!event->xconfigure.send_event || xfi->window->local_move.state == LMS_NOT_ACTIVE)
&& !xfw->rail_ignore_configure && xfi->focused)
xf_rail_adjust_position(xfi, window);
}
@@ -539,7 +553,10 @@ static boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app)
if (window != NULL)
{
/* local restore event */
xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
//This is now handled as part of the PropertyNotify
//Doing this here would inhibit the ability to restore a maximized window
//that is minimized back to the maximized state
//xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
xfWindow *xfw = (xfWindow*) window->extra;
xfw->is_mapped = true;
}
@@ -613,6 +630,92 @@ static boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app)
static boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
{
//This section handles sending the appropriate commands to the rail server
//when the window has been minimized, maximized, restored locally
//ie. not using the buttons on the rail window itself
if (app == true)
{
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
if ((((Atom)event->xproperty.atom == xfi->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
(((Atom)event->xproperty.atom == xfi->WM_STATE) && (event->xproperty.state != PropertyDelete)))
{
boolean status;
boolean maxVert = false;
boolean maxHorz = false;
boolean minimized = false;
unsigned long nitems;
unsigned long bytes;
unsigned char* prop;
int i;
status = xf_GetWindowProperty(xfi, event->xproperty.window,
xfi->_NET_WM_STATE, 12, &nitems, &bytes, &prop);
if (status != true) {
DEBUG_X11_LMS("No return _NET_WM_STATE, window is not maximized");
}
for (i=0;i<nitems;i++)
{
if ((Atom) ((uint16 **) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False))
{
maxVert = true;
}
if ((Atom) ((uint16 **)prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False))
{
maxHorz = true;
}
}
XFree(prop);
status = xf_GetWindowProperty(xfi, event->xproperty.window,
xfi->WM_STATE, 1, &nitems, &bytes, &prop);
if (status != true) {
DEBUG_X11_LMS("No return WM_STATE, window is not minimized");
}
else
{
//If the window is in the iconic state
if (((uint32) *prop == 3))
{
minimized = true;
}
else
minimized = false;
XFree(prop);
}
if (maxVert && maxHorz && !minimized && (xfi->window->rail_state != WINDOW_SHOW_MAXIMIZED))
{
DEBUG_X11_LMS("Send SC_MAXIMIZE command to rail server.");
xfi->window->rail_state = WINDOW_SHOW_MAXIMIZED;
xf_rail_send_client_system_command(xfi, window->windowId, SC_MAXIMIZE);
}
else if (minimized && (xfi->window->rail_state != WINDOW_SHOW_MINIMIZED))
{
DEBUG_X11_LMS("Send SC_MINIMIZE command to rail server.");
xfi->window->rail_state = WINDOW_SHOW_MINIMIZED;
xf_rail_send_client_system_command(xfi, window->windowId, SC_MINIMIZE);
}
else if (!minimized && !maxVert && !maxHorz && (xfi->window->rail_state != WINDOW_SHOW))
{
DEBUG_X11_LMS("Send SC_RESTORE command to rail server");
xfi->window->rail_state = WINDOW_SHOW;
xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
}
}
}
if (app != true)
{
if (xf_cliprdr_process_property_notify(xfi, event))
@@ -631,6 +734,15 @@ static boolean xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*e
{
case LMS_NOT_ACTIVE:
// No local move in progress, nothing to do
//Prevent Configure from happening during indeterminant state of Horz or Vert Max only
if ( (event->type == ConfigureNotify) && xfi->window->rail_ignore_configure)
{
DEBUG_X11_LMS("ConfigureNotify Event Ignored");
xfi->window->rail_ignore_configure = false;
return true;
}
break;
case LMS_STARTING:
// Local move initiated by RDP server, but we
@@ -677,9 +789,11 @@ static boolean xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*e
case VisibilityNotify:
case PropertyNotify:
case Expose:
case GravityNotify:
// Keep us up to date on position
break;
default:
DEBUG_X11_LMS("Event Type to break LMS: %s", X11_EVENT_STRINGS[event->type]);
// Any other event terminates move
xf_rail_end_local_move(xfi, window);
break;

View File

@@ -117,6 +117,16 @@ boolean xf_detect_monitors(xfInfo* xfi, rdpSettings* settings)
vscreen->area.bottom = MAX(vscreen->monitors[i].area.bottom, vscreen->area.bottom);
}
//if no monitor information is present then make sure variables are set accordingly
if (settings->num_monitors == 0)
{
vscreen->area.left = 0;
vscreen->area.right = settings->width -1;
vscreen->area.top = 0;
vscreen->area.bottom = settings->height - 1;
}
if (settings->num_monitors)
{
settings->width = vscreen->area.right - vscreen->area.left + 1;

View File

@@ -39,6 +39,16 @@ void xf_rail_enable_remoteapp_mode(xfInfo* xfi)
}
}
void xf_rail_disable_remoteapp_mode(xfInfo* xfi)
{
if (xfi->remote_app == true)
{
xfi->remote_app = false;
xf_create_window(xfi);
}
}
void xf_rail_paint(xfInfo* xfi, rdpRail* rail, sint32 uleft, sint32 utop, uint32 uright, uint32 ubottom)
{
xfWindow* xfw;
@@ -64,10 +74,10 @@ void xf_rail_paint(xfInfo* xfi, rdpRail* rail, sint32 uleft, sint32 utop, uint32
continue;
}
wleft = window->windowOffsetX;
wtop = window->windowOffsetY;
wright = window->windowOffsetX + window->windowWidth - 1;
wbottom = window->windowOffsetY + window->windowHeight - 1;
wleft = window->visibleOffsetX;
wtop = window->visibleOffsetY;
wright = window->visibleOffsetX + window->windowWidth - 1;
wbottom = window->visibleOffsetY + window->windowHeight - 1;
ileft = MAX(uleft, wleft);
itop = MAX(utop, wtop);
@@ -86,6 +96,14 @@ void xf_rail_paint(xfInfo* xfi, rdpRail* rail, sint32 uleft, sint32 utop, uint32
}
}
void xf_rail_DesktopNonMonitored(rdpRail *rail, rdpWindow* window)
{
xfInfo* xfi;
xfi = (xfInfo*) rail->extra;
xf_rail_disable_remoteapp_mode(xfi);
}
static void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
{
xfInfo* xfi;
@@ -116,8 +134,28 @@ static void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window)
xfi = (xfInfo*) rail->extra;
xfw = (xfWindow*) window->extra;
//The rail server like to set the window to a small size when it is minimized even though it is hidden
//in some cases this can cause the window not to restore back to its original size. Therefore we dont update
//our local window when that rail window state is minimized
if (xfw->rail_state == WINDOW_SHOW_MINIMIZED)
return;
// Do nothing if window is already in the correct position
if ( xfw->left == window->visibleOffsetX &&
xfw->top == window->visibleOffsetY &&
xfw->width == window->windowWidth &&
xfw->height == window->windowHeight)
{
//Just ensure entire window area is updated to
//handle cases where we have drawn locally before getting new bitmap
//from the server
xf_UpdateWindowArea(xfi, xfw, 0, 0, window->windowWidth, window->windowHeight);
return;
}
xf_MoveWindow(xfi, xfw,
window->windowOffsetX, window->windowOffsetY,
window->visibleOffsetX, window->visibleOffsetY,
window->windowWidth, window->windowHeight);
}
@@ -197,6 +235,7 @@ void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail)
rail->rail_SetWindowRects = xf_rail_SetWindowRects;
rail->rail_SetWindowVisibilityRects = xf_rail_SetWindowVisibilityRects;
rail->rail_DestroyWindow = xf_rail_DestroyWindow;
rail->rail_DesktopNonMonitored = xf_rail_DesktopNonMonitored;
}
static void xf_on_free_rail_client_event(RDP_EVENT* event)
@@ -275,21 +314,39 @@ void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window)
// If current window position disagrees with RDP window position, send
// update to RDP server
if ( xfw->left != window->windowOffsetX ||
xfw->top != window->windowOffsetY ||
if ( xfw->left != window->visibleOffsetX ||
xfw->top != window->visibleOffsetY ||
xfw->width != window->windowWidth ||
xfw->height != window->windowHeight)
{
//Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
//we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when
//attempting to adjust the rail window.
uint32 offsetX = 0;
uint32 offsetY = 0;
if (window->windowOffsetX < 0)
offsetX = offsetX - window->windowOffsetX;
if (window->windowOffsetY < 0)
offsetY = offsetY - window->windowOffsetY;
//windowOffset corresponds to the window location on the rail server
//but our local window is based on the visibleOffset since using the windowOffset
//can result in blank areas for a maximized window
window_move.windowId = window->windowId;
window_move.left = xfw->left;
window_move.top = xfw->top;
window_move.right = xfw->right;
window_move.bottom = xfw->bottom;
//Calculate new offsets for the rail server window
//Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset)
window_move.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
window_move.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
window_move.right = window_move.left + xfw->width;
window_move.bottom = window_move.top + xfw->height;
DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
" RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
(uint32) xfw->handle, xfw->left, xfw->top,
xfw->right, xfw->bottom, xfw->width, xfw->height,
(uint32) xfw->handle, window_move.left, window_move.top,
window_move.right, window_move.bottom, xfw->width, xfw->height,
window->windowId,
window->windowOffsetX, window->windowOffsetY,
window->windowWidth, window->windowHeight);
@@ -319,14 +376,31 @@ void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window)
xfw->left, xfw->top, xfw->right, xfw->bottom,
xfw->width, xfw->height);
//Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
//we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when
//attempting to adjust the rail window.
uint32 offsetX = 0;
uint32 offsetY = 0;
if (window->windowOffsetX < 0)
offsetX = offsetX - window->windowOffsetX;
if (window->windowOffsetY < 0)
offsetY = offsetY - window->windowOffsetY;
/*
* For keyboard moves send and explicit update to RDP server
*/
window_move.windowId = window->windowId;
window_move.left = xfw->left;
window_move.top = xfw->top;
window_move.right = xfw->right + 1; // The update to RDP the position is one past the window
window_move.bottom = xfw->bottom + 1;
//Calculate new offsets for the rail server window
//Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset)
window_move.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
window_move.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
window_move.right = window_move.left + xfw->width; // In the update to RDP the position is one past the window
window_move.bottom = window_move.top + xfw->height;
xf_send_rail_client_event(channels,
RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move);
@@ -339,13 +413,21 @@ void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window)
&root_window, &child_window,
&x, &y, &child_x, &child_y, &mask);
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
//only send the mouse coordinates if not a keyboard move or size
if ((xfw->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
(xfw->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
{
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
DEBUG_X11_LMS("Mouse coordinates. x= %i, y= %i", x, y);
}
// Proactively update the RAIL window dimensions. There is a race condition where
// we can start to receive GDI orders for the new window dimensions before we
// receive the RAIL ORDER for the new window size. This avoids that race condition.
window->windowOffsetX = xfw->left;
window->windowOffsetY = xfw->top;
window->windowOffsetX = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
window->windowOffsetY = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
window->windowWidth = xfw->width;
window->windowHeight = xfw->height;

View File

@@ -237,7 +237,7 @@ void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_st
{
Atom window_type;
if ((ex_style & WS_EX_TOPMOST) || (ex_style & WS_EX_TOOLWINDOW))
if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
{
/*
* Tooltips and menu items should be unmanaged windows
@@ -256,6 +256,12 @@ void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_st
xf_SetWindowUnlisted(xfi, window);
window_type = xfi->_NET_WM_WINDOW_TYPE_POPUP;
}
//TOPMOST window that is not a toolwindow is treated like a regular window(ie. task manager).
//Want to do this here, since the window may have type WS_POPUP
else if (ex_style & WS_EX_TOPMOST)
{
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
}
else if (style & WS_POPUP)
{
/* this includes dialogs, popups, etc, that need to be full-fledged windows */
@@ -312,7 +318,7 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height,
window->is_transient = false;
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
xfi->workArea.x, xfi->workArea.y, xfi->width, xfi->height, 0, xfi->depth, InputOutput, xfi->visual,
xfi->workArea.x, xfi->workArea.y, xfi->workArea.width, xfi->workArea.height, 0, xfi->depth, InputOutput, xfi->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs);
@@ -374,6 +380,13 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height,
XMaskEvent(xfi->display, VisibilityChangeMask, &xevent);
}
while (xevent.type != VisibilityNotify);
//The XCreateWindow call will start the window in the upper-left corner of our current
//monitor instead of the upper-left monitor for remote app mode(which uses all monitors).
//This extra call after the window is mapped will position the login window correctly
if (xfi->instance->settings->remote_app)
XMoveWindow(xfi->display, window->handle, 0, 0);
}
xf_SetWindowText(xfi, window, name);
@@ -462,6 +475,8 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width,
window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = false;
window->is_transient = false;
window->rail_state = 0;
window->rail_ignore_configure = false;
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
@@ -489,6 +504,14 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width,
xfree(class);
}
//Set the input mode hint for the WM
XWMHints *InputModeHint = XAllocWMHints();
InputModeHint->flags = (1L << 0);
InputModeHint->input = True;
XSetWMHints(xfi->display, window->handle, InputModeHint);
XFree(InputModeHint);
XSetWMProtocols(xfi->display, window->handle, &(xfi->WM_DELETE_WINDOW), 1);
input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
@@ -561,6 +584,7 @@ void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x,
window->local_move.root_x = x;
window->local_move.root_y = y;
window->local_move.state = LMS_STARTING;
window->local_move.direction = direction;
XUngrabPointer(xfi->display, CurrentTime);
@@ -661,11 +685,37 @@ void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
break;
case WINDOW_SHOW_MAXIMIZED:
XRaiseWindow(xfi->display, window->handle);
//Set the window as maximized
xf_SendClientEvent(xfi, window, xfi->_NET_WM_STATE, 4,
1,
XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False),
0);
//This is a workaround for the case where the window is maximized locally before the rail server is told to maximize
//the window, this appears to be a race condition where the local window with incomplete data and once the window is
//actually maximized on the server - an update of the new areas may not happen. So, we simply to do a full update of
//the entire window once the rail server notifies us that the window is now maximized.
if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
xf_UpdateWindowArea(xfi, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
break;
case WINDOW_SHOW:
XMapWindow(xfi->display, window->handle);
//Ensure the window is not maximized
xf_SendClientEvent(xfi, window, xfi->_NET_WM_STATE, 4,
0,
XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False),
0);
//Ignore configure requests until both the Maximized properties have been processed
//to prevent condition where WM overrides size of request due to one or both of these properties
//still being set - which causes a position adjustment to be sent back to the server
//thus causing the window to not return to its original size
if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
window->rail_ignore_configure = true;
if (window->is_transient)
{
xf_SetWindowUnlisted(xfi, window);
@@ -673,6 +723,9 @@ void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
break;
}
//Save off the current rail state of this window
window->rail_state = state;
XFlush(xfi->display);
}
@@ -730,7 +783,8 @@ void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int n
}
#ifdef WITH_XEXT
XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
//This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
//XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
xfree(xrects);
@@ -755,7 +809,8 @@ void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* re
}
#ifdef WITH_XEXT
XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
//This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
//XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
xfree(xrects);
@@ -767,15 +822,30 @@ void xf_UpdateWindowArea(xfInfo* xfi, xfWindow* window, int x, int y, int width,
rdpWindow* wnd;
wnd = window->window;
ax = x + wnd->windowOffsetX;
ay = y + wnd->windowOffsetY;
//Remote app mode uses visibleOffset instead of windowOffset
if (!xfi->remote_app)
{
ax = x + wnd->windowOffsetX;
ay = y + wnd->windowOffsetY;
if (ax + width > wnd->windowOffsetX + wnd->windowWidth)
width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax;
if (ax + width > wnd->windowOffsetX + wnd->windowWidth)
width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax;
if (ay + height > wnd->windowOffsetY + wnd->windowHeight)
height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay;
if (ay + height > wnd->windowOffsetY + wnd->windowHeight)
height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay;
}
else
{
ax = x + wnd->visibleOffsetX;
ay = y + wnd->visibleOffsetY;
if (ax + width > wnd->visibleOffsetX + wnd->windowWidth)
width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
if (ay + height > wnd->visibleOffsetY + wnd->windowHeight)
height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
}
if (xfi->sw_gdi)
{
XPutImage(xfi->display, xfi->primary, window->gc, xfi->image,

View File

@@ -58,6 +58,7 @@ struct xf_localmove
int window_x; // relative to window
int window_y;
enum xf_localmove_state state;
int direction;
};
struct xf_window
@@ -76,6 +77,8 @@ struct xf_window
boolean is_mapped;
boolean is_transient;
xfLocalMove local_move;
uint8 rail_state;
boolean rail_ignore_configure;
};
void xf_ewmhints_init(xfInfo* xfi);

View File

@@ -299,8 +299,8 @@ void xf_create_window(xfInfo* xfi)
xfi->attribs.backing_store = xfi->primary ? NotUseful : Always;
xfi->attribs.override_redirect = xfi->fullscreen;
xfi->attribs.colormap = xfi->colormap;
xfi->attribs.bit_gravity = ForgetGravity;
xfi->attribs.win_gravity = StaticGravity;
xfi->attribs.bit_gravity = NorthWestGravity;
xfi->attribs.win_gravity = NorthWestGravity;
if (xfi->instance->settings->window_title != NULL)
{
@@ -583,6 +583,7 @@ boolean xf_pre_connect(freerdp* instance)
xfi->WM_PROTOCOLS = XInternAtom(xfi->display, "WM_PROTOCOLS", False);
xfi->WM_DELETE_WINDOW = XInternAtom(xfi->display, "WM_DELETE_WINDOW", False);
xfi->WM_STATE = XInternAtom(xfi->display, "WM_STATE", False);
xf_kbd_init(xfi);

View File

@@ -160,6 +160,7 @@ struct xf_info
Atom _NET_WM_MOVERESIZE;
Atom _NET_MOVERESIZE_WINDOW;
Atom WM_STATE;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
};

View File

@@ -40,6 +40,7 @@ typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window);
typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon);
typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window);
typedef void (*railSetWindowVisibilityRects)(rdpRail* rail, rdpWindow* window);
typedef void (*railDesktopNonMonitored) (rdpRail* rail, rdpWindow* window);
struct rdp_rail
{
@@ -57,6 +58,7 @@ struct rdp_rail
railSetWindowIcon rail_SetWindowIcon;
railSetWindowRects rail_SetWindowRects;
railSetWindowVisibilityRects rail_SetWindowVisibilityRects;
railDesktopNonMonitored rail_DesktopNonMonitored;
};
FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update);

View File

@@ -48,6 +48,7 @@ FREERDP_API rdpWindow* window_list_get_by_extra_id(rdpWindowList* list, void* ex
FREERDP_API void window_list_create(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state);
FREERDP_API void window_list_update(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state);
FREERDP_API void window_list_delete(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo);
FREERDP_API void window_list_clear(rdpWindowList* list);
FREERDP_API rdpWindowList* window_list_new(rdpRail* rail);
FREERDP_API void window_list_free(rdpWindowList* list);

View File

@@ -99,11 +99,24 @@ static void rail_MonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderI
}
//This is used to switch FreeRDP back to showing the full desktop under remote app mode
//to handle cases where the screen is locked, etc. The rail server informs us that it is
//no longer monitoring the desktop. Once the desktop becomes monitored again. The full desktop
//window will be automatically destroyed and we will switch back into remote app mode.
static void rail_NonMonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderInfo)
{
rdpWindow* window;
rdpRail* rail = context->rail;
window = window_list_get_by_id(rail->list, orderInfo->windowId);
IFCALL(rail->rail_DesktopNonMonitored, rail, window);
window_list_clear(rail->list);
}
void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update)
{
rdpWindowUpdate* window = update->window;

View File

@@ -97,6 +97,16 @@ void window_list_create(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDO
{
rdpWindow* window;
//See if the window already exists
window = window_list_get_by_id(list, orderInfo->windowId);
//If the window already exists, just update the existing window
if (window != NULL)
{
window_list_update(list, orderInfo, window_state);
return;
}
window = (rdpWindow*) xzalloc(sizeof(rdpWindow));
if (window == NULL)
@@ -175,6 +185,22 @@ void window_list_delete(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo)
rail_DestroyWindow(list->rail, window);
}
void window_list_clear(rdpWindowList* list)
{
rdpWindow* current = list->head;
rdpWindow* next;
while (current != NULL)
{
list->head = current->next;
rail_DestroyWindow(list->rail, current);
current = list->head;
}
list->tail = NULL;
}
rdpWindowList* window_list_new(rdpRail* rail)
{
rdpWindowList* list;