mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user