mirror of https://github.com/FreeRDP/FreeRDP
xfreerdp: separate app windows from desktop windows
This commit is contained in:
parent
fb5e33440c
commit
1225c6b5ce
|
@ -62,7 +62,7 @@ struct X11Handle
|
|||
static const char* get_shm_id()
|
||||
{
|
||||
static char shm_id[64];
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
return shm_id;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
|
||||
static const size_t password_size = 512;
|
||||
|
||||
void xf_transform_window(xfContext *xfc)
|
||||
void xf_transform_window(xfContext* xfc)
|
||||
{
|
||||
int ret;
|
||||
int w;
|
||||
|
@ -133,7 +133,7 @@ void xf_transform_window(xfContext *xfc)
|
|||
}
|
||||
}
|
||||
|
||||
void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scale)
|
||||
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale)
|
||||
{
|
||||
#ifdef WITH_XRENDER
|
||||
XTransform transform;
|
||||
|
@ -142,10 +142,13 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
|
|||
XRenderPictureAttributes pa;
|
||||
XRenderPictFormat *picFormat;
|
||||
XRectangle xr;
|
||||
|
||||
picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24);
|
||||
|
||||
pa.subwindow_mode = IncludeInferiors;
|
||||
primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa);
|
||||
windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa);
|
||||
|
||||
transform.matrix[0][0] = XDoubleToFixed(1);
|
||||
transform.matrix[0][1] = XDoubleToFixed(0);
|
||||
transform.matrix[0][2] = XDoubleToFixed(0);
|
||||
|
@ -155,9 +158,10 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
|
|||
transform.matrix[2][0] = XDoubleToFixed(0);
|
||||
transform.matrix[2][1] = XDoubleToFixed(0);
|
||||
transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor);
|
||||
|
||||
if ((w != 0) && (h != 0))
|
||||
{
|
||||
if (scale == TRUE)
|
||||
if (scale)
|
||||
{
|
||||
xr.x = x * xfc->settings->ScalingFactor;
|
||||
xr.y = y * xfc->settings->ScalingFactor;
|
||||
|
@ -171,8 +175,10 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
|
|||
xr.width = w;
|
||||
xr.height = h;
|
||||
}
|
||||
|
||||
XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1);
|
||||
}
|
||||
|
||||
XRenderSetPictureTransform(xfc->display, primaryPicture, &transform);
|
||||
XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight);
|
||||
XRenderFreePicture(xfc->display, primaryPicture);
|
||||
|
@ -180,14 +186,14 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
|
|||
#endif
|
||||
}
|
||||
|
||||
void xf_sw_begin_paint(rdpContext *context)
|
||||
void xf_sw_begin_paint(rdpContext* context)
|
||||
{
|
||||
rdpGdi* gdi = context->gdi;
|
||||
gdi->primary->hdc->hwnd->invalid->null = 1;
|
||||
gdi->primary->hdc->hwnd->ninvalid = 0;
|
||||
}
|
||||
|
||||
void xf_sw_end_paint(rdpContext *context)
|
||||
void xf_sw_end_paint(rdpContext* context)
|
||||
{
|
||||
int i;
|
||||
INT32 x, y;
|
||||
|
@ -295,14 +301,14 @@ void xf_sw_desktop_resize(rdpContext* context)
|
|||
xf_unlock_x11(xfc, TRUE);
|
||||
}
|
||||
|
||||
void xf_hw_begin_paint(rdpContext *context)
|
||||
void xf_hw_begin_paint(rdpContext* context)
|
||||
{
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
xfc->hdc->hwnd->invalid->null = 1;
|
||||
xfc->hdc->hwnd->ninvalid = 0;
|
||||
}
|
||||
|
||||
void xf_hw_end_paint(rdpContext *context)
|
||||
void xf_hw_end_paint(rdpContext* context)
|
||||
{
|
||||
INT32 x, y;
|
||||
UINT32 w, h;
|
||||
|
@ -387,12 +393,12 @@ void xf_hw_end_paint(rdpContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
void xf_hw_desktop_resize(rdpContext *context)
|
||||
void xf_hw_desktop_resize(rdpContext* context)
|
||||
{
|
||||
BOOL same;
|
||||
rdpSettings *settings;
|
||||
xfContext *xfc = (xfContext *) context;
|
||||
settings = xfc->instance->settings;
|
||||
rdpSettings* settings;
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
settings = xfc->settings;
|
||||
|
||||
xf_lock_x11(xfc, TRUE);
|
||||
|
||||
|
@ -428,30 +434,35 @@ void xf_hw_desktop_resize(rdpContext *context)
|
|||
|
||||
BOOL xf_get_fds(freerdp *instance, void **rfds, int *rcount, void **wfds, int *wcount)
|
||||
{
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
rfds[*rcount] = (void *)(long)(xfc->xfds);
|
||||
(*rcount)++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL xf_process_x_events(freerdp *instance)
|
||||
BOOL xf_process_x_events(freerdp* instance)
|
||||
{
|
||||
BOOL status;
|
||||
XEvent xevent;
|
||||
int pending_status;
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
|
||||
status = TRUE;
|
||||
pending_status = TRUE;
|
||||
while(pending_status)
|
||||
|
||||
while (pending_status)
|
||||
{
|
||||
xf_lock_x11(xfc, FALSE);
|
||||
pending_status = XPending(xfc->display);
|
||||
xf_unlock_x11(xfc, FALSE);
|
||||
|
||||
if (pending_status)
|
||||
{
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(xfc->display, &xevent);
|
||||
|
||||
status = xf_event_process(instance, &xevent);
|
||||
|
||||
if (!status)
|
||||
return status;
|
||||
}
|
||||
|
@ -459,14 +470,17 @@ BOOL xf_process_x_events(freerdp *instance)
|
|||
return status;
|
||||
}
|
||||
|
||||
void xf_create_window(xfContext *xfc)
|
||||
void xf_create_window(xfContext* xfc)
|
||||
{
|
||||
XEvent xevent;
|
||||
int width, height;
|
||||
char *windowTitle;
|
||||
char* windowTitle;
|
||||
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
|
||||
width = xfc->width;
|
||||
height = xfc->height;
|
||||
|
||||
if (!xfc->remote_app)
|
||||
{
|
||||
xfc->attribs.background_pixel = BlackPixelOfScreen(xfc->screen);
|
||||
|
@ -476,25 +490,29 @@ void xf_create_window(xfContext *xfc)
|
|||
xfc->attribs.colormap = xfc->colormap;
|
||||
xfc->attribs.bit_gravity = NorthWestGravity;
|
||||
xfc->attribs.win_gravity = NorthWestGravity;
|
||||
if (xfc->instance->settings->WindowTitle)
|
||||
|
||||
if (xfc->settings->WindowTitle)
|
||||
{
|
||||
windowTitle = _strdup(xfc->instance->settings->WindowTitle);
|
||||
windowTitle = _strdup(xfc->settings->WindowTitle);
|
||||
}
|
||||
else if (xfc->settings->ServerPort == 3389)
|
||||
{
|
||||
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->settings->ServerHostname));
|
||||
sprintf(windowTitle, "FreeRDP: %s", xfc->settings->ServerHostname);
|
||||
}
|
||||
else
|
||||
if (xfc->instance->settings->ServerPort == 3389)
|
||||
{
|
||||
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname));
|
||||
sprintf(windowTitle, "FreeRDP: %s", xfc->instance->settings->ServerHostname);
|
||||
}
|
||||
else
|
||||
{
|
||||
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname) + sizeof(":00000"));
|
||||
sprintf(windowTitle, "FreeRDP: %s:%i", xfc->instance->settings->ServerHostname, xfc->instance->settings->ServerPort);
|
||||
}
|
||||
{
|
||||
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->settings->ServerHostname) + sizeof(":00000"));
|
||||
sprintf(windowTitle, "FreeRDP: %s:%i", xfc->settings->ServerHostname, xfc->settings->ServerPort);
|
||||
}
|
||||
|
||||
xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->settings->Decorations);
|
||||
|
||||
free(windowTitle);
|
||||
|
||||
if (xfc->fullscreen)
|
||||
xf_SetWindowFullscreen(xfc, xfc->window, xfc->fullscreen);
|
||||
|
||||
xfc->unobscured = (xevent.xvisibility.state == VisibilityUnobscured);
|
||||
XSetWMProtocols(xfc->display, xfc->window->handle, &(xfc->WM_DELETE_WINDOW), 1);
|
||||
xfc->drawable = xfc->window->handle;
|
||||
|
@ -509,15 +527,23 @@ void xf_toggle_fullscreen(xfContext* xfc)
|
|||
{
|
||||
Pixmap contents = 0;
|
||||
WindowStateChangeEventArgs e;
|
||||
|
||||
xf_lock_x11(xfc, TRUE);
|
||||
|
||||
contents = XCreatePixmap(xfc->display, xfc->window->handle, xfc->width, xfc->height, xfc->depth);
|
||||
|
||||
XCopyArea(xfc->display, xfc->primary, contents, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
|
||||
XDestroyWindow(xfc->display, xfc->window->handle);
|
||||
|
||||
xfc->fullscreen = (xfc->fullscreen) ? FALSE : TRUE;
|
||||
|
||||
xf_create_window(xfc);
|
||||
|
||||
XCopyArea(xfc->display, contents, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
|
||||
XFreePixmap(xfc->display, contents);
|
||||
|
||||
xf_unlock_x11(xfc, TRUE);
|
||||
|
||||
EventArgsInit(&e, "xfreerdp");
|
||||
e.state = xfc->fullscreen ? FREERDP_WINDOW_STATE_FULLSCREEN : 0;
|
||||
PubSub_OnWindowStateChange(((rdpContext *) xfc)->pubSub, xfc, &e);
|
||||
|
@ -546,14 +572,6 @@ void xf_toggle_control(xfContext* xfc)
|
|||
|
||||
int xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated)
|
||||
{
|
||||
#if 0
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
WLog_INFO(TAG, "ParticipantCreated: ParticipantId: %d GroupId: %d Flags: 0x%04X xfc: %p",
|
||||
(int) participantCreated->ParticipantId, (int) participantCreated->GroupId,
|
||||
(int) participantCreated->Flags, xfc);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -570,7 +588,7 @@ void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp)
|
|||
xfc->encomsp = NULL;
|
||||
}
|
||||
|
||||
void xf_lock_x11(xfContext *xfc, BOOL display)
|
||||
void xf_lock_x11(xfContext* xfc, BOOL display)
|
||||
{
|
||||
if (!xfc->UseXThreads)
|
||||
{
|
||||
|
@ -583,7 +601,7 @@ void xf_lock_x11(xfContext *xfc, BOOL display)
|
|||
}
|
||||
}
|
||||
|
||||
void xf_unlock_x11(xfContext *xfc, BOOL display)
|
||||
void xf_unlock_x11(xfContext* xfc, BOOL display)
|
||||
{
|
||||
if (!xfc->UseXThreads)
|
||||
{
|
||||
|
@ -596,7 +614,7 @@ void xf_unlock_x11(xfContext *xfc, BOOL display)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL xf_get_pixmap_info(xfContext *xfc)
|
||||
BOOL xf_get_pixmap_info(xfContext* xfc)
|
||||
{
|
||||
int i;
|
||||
int vi_count;
|
||||
|
@ -607,9 +625,10 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
|
|||
XPixmapFormatValues *pf;
|
||||
XPixmapFormatValues *pfs;
|
||||
XWindowAttributes window_attributes;
|
||||
|
||||
pfs = XListPixmapFormats(xfc->display, &pf_count);
|
||||
|
||||
if (pfs == NULL)
|
||||
if (!pfs)
|
||||
{
|
||||
WLog_ERR(TAG, "XListPixmapFormats failed");
|
||||
return 1;
|
||||
|
@ -641,7 +660,7 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
|
|||
|
||||
vis = XGetVisualInfo(xfc->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
|
||||
|
||||
if (vis == NULL)
|
||||
if (!vis)
|
||||
{
|
||||
WLog_ERR(TAG, "XGetVisualInfo failed");
|
||||
return FALSE;
|
||||
|
@ -683,19 +702,24 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
|
|||
|
||||
static int (*_def_error_handler)(Display *, XErrorEvent *);
|
||||
|
||||
int xf_error_handler(Display *d, XErrorEvent *ev)
|
||||
int xf_error_handler(Display* d, XErrorEvent* ev)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
int do_abort = TRUE;
|
||||
XGetErrorText(d, ev->error_code, buf, sizeof(buf));
|
||||
WLog_ERR(TAG, "%s", buf);
|
||||
|
||||
WLog_ERR(TAG, "%s", buf);
|
||||
|
||||
if (do_abort)
|
||||
abort();
|
||||
|
||||
_def_error_handler(d, ev);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int _xf_error_handler(Display *d, XErrorEvent *ev)
|
||||
int _xf_error_handler(Display* d, XErrorEvent* ev)
|
||||
{
|
||||
/*
|
||||
* ungrab the keyboard, in case a debugger is running in
|
||||
|
@ -706,18 +730,22 @@ int _xf_error_handler(Display *d, XErrorEvent *ev)
|
|||
return xf_error_handler(d, ev);
|
||||
}
|
||||
|
||||
static void xf_post_disconnect(freerdp *instance)
|
||||
static void xf_post_disconnect(freerdp* instance)
|
||||
{
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
assert(NULL != instance);
|
||||
assert(NULL != xfc);
|
||||
assert(NULL != instance->settings);
|
||||
xfContext* xfc;
|
||||
|
||||
if (!instance || !instance->context || !instance->settings)
|
||||
return;
|
||||
|
||||
xfc = (xfContext*) instance->context;
|
||||
|
||||
if (xfc->mutex)
|
||||
{
|
||||
WaitForSingleObject(xfc->mutex, INFINITE);
|
||||
CloseHandle(xfc->mutex);
|
||||
xfc->mutex = NULL;
|
||||
}
|
||||
|
||||
xf_monitors_free(xfc, instance->settings);
|
||||
}
|
||||
|
||||
|
@ -727,11 +755,12 @@ static void xf_play_sound(rdpContext* context, PLAY_SOUND_UPDATE* play_sound)
|
|||
XkbBell(xfc->display, None, 100, 0);
|
||||
}
|
||||
|
||||
void xf_check_extensions(xfContext *context)
|
||||
void xf_check_extensions(xfContext* context)
|
||||
{
|
||||
int xkb_opcode, xkb_event, xkb_error;
|
||||
int xkb_major = XkbMajorVersion;
|
||||
int xkb_minor = XkbMinorVersion;
|
||||
|
||||
if (XkbLibraryVersion( &xkb_major, &xkb_minor ) && XkbQueryExtension(context->display, &xkb_opcode, &xkb_event,
|
||||
&xkb_error, &xkb_major, &xkb_minor))
|
||||
{
|
||||
|
@ -1039,8 +1068,10 @@ BOOL xf_authenticate(freerdp *instance, char **username, char **password, char *
|
|||
// FIXME: seems this callback may be called when 'username' is not known.
|
||||
// But it doesn't do anything to fix it...
|
||||
*password = malloc(password_size * sizeof(char));
|
||||
|
||||
if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->CredentialsFromStdin) == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1054,9 +1085,10 @@ BOOL xf_authenticate(freerdp *instance, char **username, char **password, char *
|
|||
* @param fingerprint
|
||||
* @return TRUE if the certificate is trusted. FALSE otherwise.
|
||||
*/
|
||||
BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char *fingerprint)
|
||||
BOOL xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
|
||||
{
|
||||
char answer;
|
||||
|
||||
WLog_INFO(TAG, "Certificate details:");
|
||||
WLog_INFO(TAG, "\tSubject: %s", subject);
|
||||
WLog_INFO(TAG, "\tIssuer: %s", issuer);
|
||||
|
@ -1064,10 +1096,12 @@ BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char
|
|||
WLog_INFO(TAG, "The above X.509 certificate could not be verified, possibly because you do not have "
|
||||
"the CA certificate in your certificate store, or the certificate has expired. "
|
||||
"Please look at the documentation on how to create local certificate store for a private CA.");
|
||||
while(1)
|
||||
|
||||
while (1)
|
||||
{
|
||||
WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) ");
|
||||
answer = fgetc(stdin);
|
||||
|
||||
if (feof(stdin))
|
||||
{
|
||||
WLog_INFO(TAG, "Error: Could not read answer from stdin.");
|
||||
|
@ -1076,28 +1110,30 @@ BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char
|
|||
WLog_INFO(TAG, "");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (answer == 'y' || answer == 'Y')
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
if (answer == 'n' || answer == 'N')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (answer == 'n' || answer == 'N')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int xf_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
|
||||
int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
|
||||
{
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
xf_rail_disable_remoteapp_mode(xfc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void xf_window_free(xfContext *xfc)
|
||||
void xf_window_free(xfContext* xfc)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) xfc;
|
||||
|
||||
|
@ -1117,7 +1153,7 @@ void xf_window_free(xfContext *xfc)
|
|||
|
||||
if (xfc->window)
|
||||
{
|
||||
xf_DestroyWindow(xfc, xfc->window);
|
||||
xf_DestroyDesktopWindow(xfc, xfc->window);
|
||||
xfc->window = NULL;
|
||||
}
|
||||
|
||||
|
@ -1146,12 +1182,6 @@ void xf_window_free(xfContext *xfc)
|
|||
context->cache = NULL;
|
||||
}
|
||||
|
||||
if (context->rail)
|
||||
{
|
||||
rail_free(context->rail);
|
||||
context->rail = NULL;
|
||||
}
|
||||
|
||||
if (xfc->hdc)
|
||||
{
|
||||
gdi_DeleteDC(xfc->hdc);
|
||||
|
@ -1172,13 +1202,13 @@ void xf_window_free(xfContext *xfc)
|
|||
|
||||
void* xf_input_thread(void *arg)
|
||||
{
|
||||
xfContext *xfc;
|
||||
xfContext* xfc;
|
||||
HANDLE event;
|
||||
XEvent xevent;
|
||||
wMessageQueue *queue;
|
||||
int pending_status = 1;
|
||||
int process_status = 1;
|
||||
freerdp *instance = (freerdp *) arg;
|
||||
freerdp *instance = (freerdp*) arg;
|
||||
assert(NULL != instance);
|
||||
xfc = (xfContext *) instance->context;
|
||||
assert(NULL != xfc);
|
||||
|
@ -1196,9 +1226,12 @@ void* xf_input_thread(void *arg)
|
|||
if (pending_status)
|
||||
{
|
||||
xf_lock_x11(xfc, FALSE);
|
||||
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(xfc->display, &xevent);
|
||||
|
||||
process_status = xf_event_process(instance, &xevent);
|
||||
|
||||
xf_unlock_x11(xfc, FALSE);
|
||||
|
||||
if (!process_status)
|
||||
|
@ -1219,7 +1252,7 @@ void* xf_input_thread(void *arg)
|
|||
void* xf_channels_thread(void *arg)
|
||||
{
|
||||
int status;
|
||||
xfContext *xfc;
|
||||
xfContext* xfc;
|
||||
HANDLE event;
|
||||
rdpChannels *channels;
|
||||
freerdp *instance = (freerdp *) arg;
|
||||
|
@ -1241,29 +1274,34 @@ void* xf_channels_thread(void *arg)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BOOL xf_auto_reconnect(freerdp *instance)
|
||||
BOOL xf_auto_reconnect(freerdp* instance)
|
||||
{
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
UINT32 num_retries = 0;
|
||||
UINT32 max_retries = instance->settings->AutoReconnectMaxRetries;
|
||||
|
||||
/* Only auto reconnect on network disconnects. */
|
||||
if (freerdp_error_info(instance) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* A network disconnect was detected */
|
||||
WLog_INFO(TAG, "Network disconnect!");
|
||||
|
||||
if (!instance->settings->AutoReconnectionEnabled)
|
||||
{
|
||||
/* No auto-reconnect - just quit */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Perform an auto-reconnect. */
|
||||
for(;;)
|
||||
for (;;)
|
||||
{
|
||||
/* Quit retrying if max retries has been exceeded */
|
||||
if (num_retries++ >= max_retries)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Attempt the next reconnect */
|
||||
WLog_INFO(TAG, "Attempting reconnect (%u of %u)", num_retries, max_retries);
|
||||
if (freerdp_reconnect(instance))
|
||||
|
@ -1273,7 +1311,9 @@ BOOL xf_auto_reconnect(freerdp *instance)
|
|||
}
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Maximum reconnect retries exceeded");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1288,7 +1328,7 @@ void* xf_thread(void *param)
|
|||
{
|
||||
int i;
|
||||
int fds;
|
||||
xfContext *xfc;
|
||||
xfContext* xfc;
|
||||
int max_fds;
|
||||
int rcount;
|
||||
int wcount;
|
||||
|
@ -1318,8 +1358,9 @@ void* xf_thread(void *param)
|
|||
ZeroMemory(wfds, sizeof(wfds));
|
||||
ZeroMemory(&timeout, sizeof(struct timeval));
|
||||
status = freerdp_connect(instance);
|
||||
xfc = (xfContext *) instance->context;
|
||||
xfc = (xfContext*) instance->context;
|
||||
assert(NULL != xfc);
|
||||
|
||||
/* Connection succeeded. --authonly ? */
|
||||
if (instance->settings->AuthenticationOnly)
|
||||
{
|
||||
|
@ -1327,6 +1368,7 @@ void* xf_thread(void *param)
|
|||
WLog_ERR(TAG, "Authentication only, exit status %d", !status);
|
||||
ExitThread(exit_code);
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (xfc->mutex)
|
||||
|
@ -1335,10 +1377,12 @@ void* xf_thread(void *param)
|
|||
CloseHandle(xfc->mutex);
|
||||
xfc->mutex = NULL;
|
||||
}
|
||||
|
||||
xf_monitors_free(xfc, instance->settings);
|
||||
exit_code = XF_EXIT_CONN_FAILED;
|
||||
ExitThread(exit_code);
|
||||
}
|
||||
|
||||
channels = instance->context->channels;
|
||||
settings = instance->context->settings;
|
||||
async_input = settings->AsyncInput;
|
||||
|
@ -1349,11 +1393,13 @@ void* xf_thread(void *param)
|
|||
{
|
||||
input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL);
|
||||
}
|
||||
|
||||
if (async_channels)
|
||||
{
|
||||
channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_channels_thread, instance, 0, NULL);
|
||||
}
|
||||
while(!xfc->disconnect && !freerdp_shall_disconnect(instance))
|
||||
|
||||
while (!xfc->disconnect && !freerdp_shall_disconnect(instance))
|
||||
{
|
||||
rcount = 0;
|
||||
wcount = 0;
|
||||
|
@ -1516,27 +1562,28 @@ DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
|
|||
if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED))
|
||||
return reason;
|
||||
/* License error set */
|
||||
else
|
||||
if (reason >= 0x100 && reason <= 0x10A)
|
||||
reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
|
||||
else if (reason >= 0x100 && reason <= 0x10A)
|
||||
reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
|
||||
/* RDP protocol error set */
|
||||
else
|
||||
if (reason >= 0x10c9 && reason <= 0x1193)
|
||||
reason = XF_EXIT_RDP;
|
||||
else if (reason >= 0x10c9 && reason <= 0x1193)
|
||||
reason = XF_EXIT_RDP;
|
||||
/* There's no need to test protocol-independent codes: they match */
|
||||
else
|
||||
if (!(reason <= 0xB))
|
||||
reason = XF_EXIT_UNKNOWN;
|
||||
else if (!(reason <= 0xB))
|
||||
reason = XF_EXIT_UNKNOWN;
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
|
||||
void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
|
||||
{
|
||||
wMessageQueue *queue;
|
||||
xfContext *xfc = (xfContext *) context;
|
||||
wMessageQueue* queue;
|
||||
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
|
||||
if (context->settings->AsyncInput)
|
||||
{
|
||||
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
|
||||
if (queue)
|
||||
MessageQueue_PostQuit(queue, 0);
|
||||
}
|
||||
|
@ -1546,7 +1593,7 @@ void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
|
|||
}
|
||||
}
|
||||
|
||||
static void xf_ScalingFactorChangeEventHandler(rdpContext *context, ScalingFactorChangeEventArgs *e)
|
||||
static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
|
||||
{
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
|
||||
|
@ -1589,7 +1636,7 @@ static void xfreerdp_client_global_uninit()
|
|||
|
||||
}
|
||||
|
||||
static int xfreerdp_client_start(rdpContext *context)
|
||||
static int xfreerdp_client_start(rdpContext* context)
|
||||
{
|
||||
xfContext* xfc = (xfContext *) context;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "xf_rail.h"
|
||||
#include "xf_window.h"
|
||||
|
@ -208,16 +208,16 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
|
|||
}
|
||||
else
|
||||
{
|
||||
xfWindow* xfw;
|
||||
rdpWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
|
||||
|
||||
if (window)
|
||||
{
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xf_UpdateWindowArea(xfc, xfw, x, y, w, h);
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
xf_UpdateWindowArea(xfc, appWindow, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
|
|||
|
||||
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
|
||||
|
||||
if (xfc->fullscreen)
|
||||
if (xfc->fullscreen && !app)
|
||||
{
|
||||
XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
|
@ -518,21 +518,25 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app)
|
|||
|
||||
xfc->focused = TRUE;
|
||||
|
||||
if (xfc->mouse_active && (!app))
|
||||
if (xfc->mouse_active && !app)
|
||||
XGrabKeyboard(xfc->display, xfc->window->handle, TRUE, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
if (app)
|
||||
{
|
||||
xf_rail_send_activate(xfc, event->xany.window, TRUE);
|
||||
|
||||
rdpWindow* window;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
|
||||
|
||||
/* Update the server with any window changes that occurred while the window was not focused. */
|
||||
if (window)
|
||||
xf_rail_adjust_position(xfc, window);
|
||||
rdpWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
xf_rail_send_activate(xfc, event->xany.window, TRUE);
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
|
||||
|
||||
/* Update the server with any window changes that occurred while the window was not focused. */
|
||||
if (window)
|
||||
{
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
xf_rail_adjust_position(xfc, appWindow);
|
||||
}
|
||||
}
|
||||
|
||||
xf_keyboard_focus_in(xfc);
|
||||
|
@ -617,15 +621,16 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
{
|
||||
/* keep track of which window has focus so that we can apply pointer updates */
|
||||
|
||||
xfWindow* xfw;
|
||||
rdpWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
|
||||
|
||||
if (window)
|
||||
{
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xfc->window = xfw;
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
xfc->appWindow = appWindow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,61 +650,62 @@ static BOOL xf_event_LeaveNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
|
||||
{
|
||||
rdpWindow* window;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
rdpWindow* window;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
if (!xfc->remote_app || !rail)
|
||||
return TRUE;
|
||||
if (!app || !rail)
|
||||
return TRUE;
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
|
||||
|
||||
if (window)
|
||||
{
|
||||
xfWindow* xfw;
|
||||
Window childWindow;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
if (window)
|
||||
{
|
||||
Window childWindow;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
/*
|
||||
* ConfigureNotify coordinates are expressed relative to the window parent.
|
||||
* Translate these to root window coordinates.
|
||||
*/
|
||||
|
||||
XTranslateCoordinates(xfc->display, xfw->handle,
|
||||
RootWindowOfScreen(xfc->screen),
|
||||
0, 0, &xfw->left, &xfw->top, &childWindow);
|
||||
|
||||
xfw->width = event->xconfigure.width;
|
||||
xfw->height = event->xconfigure.height;
|
||||
xfw->right = xfw->left + xfw->width - 1;
|
||||
xfw->bottom = xfw->top + xfw->height - 1;
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
/*
|
||||
* Additonal checks for not in a local move and not ignoring configure to send
|
||||
* ConfigureNotify coordinates are expressed relative to the window parent.
|
||||
* Translate these to root window coordinates.
|
||||
*/
|
||||
|
||||
XTranslateCoordinates(xfc->display, appWindow->handle,
|
||||
RootWindowOfScreen(xfc->screen),
|
||||
0, 0, &appWindow->x, &appWindow->y, &childWindow);
|
||||
|
||||
appWindow->width = event->xconfigure.width;
|
||||
appWindow->height = event->xconfigure.height;
|
||||
|
||||
/*
|
||||
* Additional 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).
|
||||
* send to server yet (i.e. resizing using window decoration).
|
||||
* The server will be updated when the window gets refocused.
|
||||
*/
|
||||
if (app && xfw->decorations)
|
||||
if (appWindow->decorations)
|
||||
{
|
||||
/* moving resizing using window decoration */
|
||||
xf_rail_adjust_position(xfc, window);
|
||||
window->windowOffsetX = xfw->left;
|
||||
|
||||
xf_rail_adjust_position(xfc, appWindow);
|
||||
|
||||
window->windowOffsetX = appWindow->x;
|
||||
window->visibleOffsetX = window->windowOffsetX;
|
||||
window->windowOffsetY = xfw->top;
|
||||
window->windowOffsetY = appWindow->y;
|
||||
window->visibleOffsetY = window->windowOffsetY;
|
||||
window->windowWidth = xfw->width;
|
||||
window->windowHeight = xfw->height;
|
||||
window->windowWidth = appWindow->width;
|
||||
window->windowHeight = appWindow->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (app && (!event->xconfigure.send_event || xfc->window->local_move.state == LMS_NOT_ACTIVE)
|
||||
&& !xfw->rail_ignore_configure && xfc->focused)
|
||||
xf_rail_adjust_position(xfc, window);
|
||||
if ((!event->xconfigure.send_event || appWindow->local_move.state == LMS_NOT_ACTIVE)
|
||||
&& !appWindow->rail_ignore_configure && xfc->focused)
|
||||
xf_rail_adjust_position(xfc, appWindow);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app)
|
||||
|
@ -732,8 +738,8 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
*/
|
||||
|
||||
//xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE);
|
||||
xfWindow* xfw = (xfWindow*) window->extra;
|
||||
xfw->is_mapped = TRUE;
|
||||
xfAppWindow* appWindow = (xfAppWindow*) window->extra;
|
||||
appWindow->is_mapped = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,8 +764,8 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
|
||||
if (window)
|
||||
{
|
||||
xfWindow* xfw = (xfWindow*) window->extra;
|
||||
xfw->is_mapped = FALSE;
|
||||
xfAppWindow* appWindow = (xfAppWindow*) window->extra;
|
||||
appWindow->is_mapped = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,11 +783,14 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
if (app)
|
||||
{
|
||||
rdpWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
window = xf_rdpWindowFromWindow(xfc, event->xproperty.window);
|
||||
|
||||
if (!window)
|
||||
return TRUE;
|
||||
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
|
||||
(((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete)))
|
||||
|
@ -836,19 +845,19 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
}
|
||||
|
||||
|
||||
if (maxVert && maxHorz && !minimized && (xfc->window->rail_state != WINDOW_SHOW_MAXIMIZED))
|
||||
if (maxVert && maxHorz && !minimized && (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED))
|
||||
{
|
||||
xfc->window->rail_state = WINDOW_SHOW_MAXIMIZED;
|
||||
appWindow->rail_state = WINDOW_SHOW_MAXIMIZED;
|
||||
xf_rail_send_client_system_command(xfc, window->windowId, SC_MAXIMIZE);
|
||||
}
|
||||
else if (minimized && (xfc->window->rail_state != WINDOW_SHOW_MINIMIZED))
|
||||
else if (minimized && (appWindow->rail_state != WINDOW_SHOW_MINIMIZED))
|
||||
{
|
||||
xfc->window->rail_state = WINDOW_SHOW_MINIMIZED;
|
||||
appWindow->rail_state = WINDOW_SHOW_MINIMIZED;
|
||||
xf_rail_send_client_system_command(xfc, window->windowId, SC_MINIMIZE);
|
||||
}
|
||||
else if (!minimized && !maxVert && !maxHorz && (xfc->window->rail_state != WINDOW_SHOW))
|
||||
else if (!minimized && !maxVert && !maxHorz && (appWindow->rail_state != WINDOW_SHOW))
|
||||
{
|
||||
xfc->window->rail_state = WINDOW_SHOW;
|
||||
appWindow->rail_state = WINDOW_SHOW;
|
||||
xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE);
|
||||
}
|
||||
}
|
||||
|
@ -857,21 +866,21 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*event)
|
||||
static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEvent* event)
|
||||
{
|
||||
if (!xfc->remote_app)
|
||||
return FALSE;
|
||||
|
||||
switch (xfc->window->local_move.state)
|
||||
switch (appWindow->local_move.state)
|
||||
{
|
||||
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) && xfc->window->rail_ignore_configure)
|
||||
if ((event->type == ConfigureNotify) && appWindow->rail_ignore_configure)
|
||||
{
|
||||
xfc->window->rail_ignore_configure = FALSE;
|
||||
appWindow->rail_ignore_configure = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -879,11 +888,11 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
|
|||
|
||||
case LMS_STARTING:
|
||||
/* Local move initiated by RDP server, but we have not yet seen any updates from the X server */
|
||||
switch(event->type)
|
||||
switch (event->type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
/* Starting to see move events from the X server. Local move is now in progress. */
|
||||
xfc->window->local_move.state = LMS_ACTIVE;
|
||||
appWindow->local_move.state = LMS_ACTIVE;
|
||||
|
||||
/* Allow these events to be processed during move to keep our state up to date. */
|
||||
break;
|
||||
|
@ -911,7 +920,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
|
|||
|
||||
case LMS_ACTIVE:
|
||||
/* Local move is in progress */
|
||||
switch(event->type)
|
||||
switch (event->type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
case VisibilityNotify:
|
||||
|
@ -922,7 +931,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
|
|||
break;
|
||||
default:
|
||||
/* Any other event terminates move */
|
||||
xf_rail_end_local_move(xfc, window);
|
||||
xf_rail_end_local_move(xfc, appWindow);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -950,9 +959,9 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
|
|||
if (window)
|
||||
{
|
||||
/* Update "current" window for cursor change orders */
|
||||
xfc->window = (xfWindow*) window->extra;
|
||||
xfc->appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
if (xf_event_suppress_events(xfc, window, event))
|
||||
if (xf_event_suppress_events(xfc, xfc->appWindow, event))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -975,6 +984,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
|
|||
case MotionNotify:
|
||||
status = xf_event_MotionNotify(xfc, event, xfc->remote_app);
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
status = xf_event_ButtonPress(xfc, event, xfc->remote_app);
|
||||
break;
|
||||
|
|
|
@ -283,10 +283,12 @@ static BOOL xf_keyboard_set_key_state(xfContext* xfc, BOOL on, int keysym)
|
|||
return FALSE;
|
||||
|
||||
keysymMask = xf_keyboard_get_keymask(xfc, keysym);
|
||||
|
||||
if (!keysymMask)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return XkbLockModifiers(xfc->display, XkbUseCoreKbd, keysymMask, on ? keysymMask : 0);
|
||||
}
|
||||
|
||||
|
@ -321,7 +323,18 @@ void xf_keyboard_focus_in(xfContext* xfc)
|
|||
{
|
||||
input = xfc->instance->input;
|
||||
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
|
||||
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state);
|
||||
|
||||
if (!xfc->remote_app)
|
||||
{
|
||||
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy,
|
||||
&mouseX, &mouseY, &dummy, &dummy, &state);
|
||||
}
|
||||
else
|
||||
{
|
||||
XQueryPointer(xfc->display, DefaultRootWindow(xfc->display),
|
||||
&wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
|
||||
}
|
||||
|
||||
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ void xf_rail_enable_remoteapp_mode(xfContext* xfc)
|
|||
{
|
||||
xfc->remote_app = TRUE;
|
||||
xfc->drawable = DefaultRootWindow(xfc->display);
|
||||
xf_DestroyWindow(xfc, xfc->window);
|
||||
xf_DestroyDesktopWindow(xfc, xfc->window);
|
||||
xfc->window = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -86,11 +86,10 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
|
|||
{
|
||||
int index;
|
||||
int count;
|
||||
xfWindow* xfw = NULL;
|
||||
RECTANGLE_16 updateRect;
|
||||
RECTANGLE_16 windowRect;
|
||||
ULONG_PTR* pKeys = NULL;
|
||||
xfRailWindow* railWindow;
|
||||
xfAppWindow* appWindow;
|
||||
const RECTANGLE_16* extents;
|
||||
REGION16 windowInvalidRegion;
|
||||
|
||||
|
@ -100,14 +99,14 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
|
|||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);
|
||||
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);
|
||||
|
||||
if (railWindow)
|
||||
if (appWindow)
|
||||
{
|
||||
windowRect.left = railWindow->x;
|
||||
windowRect.top = railWindow->y;
|
||||
windowRect.right = railWindow->x + railWindow->width;
|
||||
windowRect.bottom = railWindow->y + railWindow->height;
|
||||
windowRect.left = appWindow->x;
|
||||
windowRect.top = appWindow->y;
|
||||
windowRect.right = appWindow->x + appWindow->width;
|
||||
windowRect.bottom = appWindow->y + appWindow->height;
|
||||
|
||||
region16_clear(&windowInvalidRegion);
|
||||
region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);
|
||||
|
@ -116,14 +115,14 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
|
|||
{
|
||||
extents = region16_extents(&windowInvalidRegion);
|
||||
|
||||
updateRect.left = extents->left - railWindow->x;
|
||||
updateRect.top = extents->top - railWindow->y;
|
||||
updateRect.right = extents->right - railWindow->x;
|
||||
updateRect.bottom = extents->bottom - railWindow->y;
|
||||
updateRect.left = extents->left - appWindow->x;
|
||||
updateRect.top = extents->top - appWindow->y;
|
||||
updateRect.right = extents->right - appWindow->x;
|
||||
updateRect.bottom = extents->bottom - appWindow->y;
|
||||
|
||||
if (xfw)
|
||||
if (appWindow)
|
||||
{
|
||||
xf_UpdateWindowArea(xfc, xfw, updateRect.left, updateRect.top,
|
||||
xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top,
|
||||
updateRect.right - updateRect.left,
|
||||
updateRect.bottom - updateRect.top);
|
||||
}
|
||||
|
@ -137,8 +136,8 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
|
|||
void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom)
|
||||
{
|
||||
rdpRail* rail;
|
||||
xfWindow* xfw;
|
||||
rdpWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
BOOL intersect;
|
||||
UINT32 iwidth, iheight;
|
||||
INT32 ileft, itop;
|
||||
|
@ -173,7 +172,7 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
|
|||
while (window_list_has_next(rail->list))
|
||||
{
|
||||
window = window_list_get_next(rail->list);
|
||||
xfw = (xfWindow*) window->extra;
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
/* RDP can have zero width or height windows. X cannot, so we ignore these. */
|
||||
|
||||
|
@ -196,7 +195,7 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
|
|||
|
||||
if (intersect)
|
||||
{
|
||||
xf_UpdateWindowArea(xfc, xfw, ileft - wleft, itop - wtop, iwidth, iheight);
|
||||
xf_UpdateWindowArea(xfc, appWindow, ileft - wleft, itop - wtop, iwidth, iheight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,116 +205,128 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
|
|||
static void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
|
||||
xf_rail_enable_remoteapp_mode(xfc);
|
||||
|
||||
xfw = xf_CreateWindow(xfc, window, window->windowOffsetX, window->windowOffsetY,
|
||||
appWindow = xf_CreateWindow(xfc, window, window->windowOffsetX, window->windowOffsetY,
|
||||
window->windowWidth, window->windowHeight, window->windowId);
|
||||
|
||||
xf_SetWindowStyle(xfc, xfw, window->style, window->extendedStyle);
|
||||
xf_SetWindowText(xfc, xfw, window->title);
|
||||
window->extra = (void*) xfw;
|
||||
window->extraId = (void*) xfw->handle;
|
||||
xf_SetWindowStyle(xfc, appWindow, window->style, window->extendedStyle);
|
||||
xf_SetWindowText(xfc, appWindow, window->title);
|
||||
|
||||
window->extra = (void*) appWindow;
|
||||
window->extraId = (void*) appWindow->handle;
|
||||
}
|
||||
|
||||
static void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
appWindow = (xfAppWindow*) 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 don't
|
||||
* update our local window when that rail window state is minimized
|
||||
*/
|
||||
if (xfw->rail_state == WINDOW_SHOW_MINIMIZED)
|
||||
if (appWindow->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)
|
||||
if (appWindow->x == window->visibleOffsetX &&
|
||||
appWindow->y == window->visibleOffsetY &&
|
||||
appWindow->width == window->windowWidth &&
|
||||
appWindow->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(xfc, xfw, 0, 0, window->windowWidth, window->windowHeight);
|
||||
xf_UpdateWindowArea(xfc, appWindow, 0, 0, window->windowWidth, window->windowHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
xf_MoveWindow(xfc, xfw, window->visibleOffsetX, window->visibleOffsetY,
|
||||
xf_MoveWindow(xfc, appWindow, window->visibleOffsetX, window->visibleOffsetY,
|
||||
window->windowWidth, window->windowHeight);
|
||||
}
|
||||
|
||||
static void xf_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xf_ShowWindow(xfc, xfw, state);
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
xf_ShowWindow(xfc, appWindow, state);
|
||||
}
|
||||
|
||||
static void xf_rail_SetWindowText(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xf_SetWindowText(xfc, xfw, window->title);
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
xf_SetWindowText(xfc, appWindow, window->title);
|
||||
}
|
||||
|
||||
static void xf_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
icon->extra = freerdp_icon_convert(icon->entry->bitsColor, NULL, icon->entry->bitsMask,
|
||||
icon->entry->width, icon->entry->height, icon->entry->bpp, rail->clrconv);
|
||||
|
||||
xf_SetWindowIcon(xfc, xfw, icon);
|
||||
xf_SetWindowIcon(xfc, appWindow, icon);
|
||||
}
|
||||
|
||||
static void xf_rail_SetWindowRects(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfWindow* xfw;
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xf_SetWindowRects(xfc, xfw, window->windowRects, window->numWindowRects);
|
||||
xfc = (xfContext*) rail->extra;
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
xf_SetWindowRects(xfc, appWindow, window->windowRects, window->numWindowRects);
|
||||
}
|
||||
|
||||
static void xf_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfWindow* xfw;
|
||||
xfContext* xfc;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xf_SetWindowVisibilityRects(xfc, xfw, window->windowRects, window->numWindowRects);
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
xf_SetWindowVisibilityRects(xfc, appWindow, window->windowRects, window->numWindowRects);
|
||||
}
|
||||
|
||||
static void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfWindow* xfw;
|
||||
xfContext* xfc;
|
||||
xfAppWindow* appWindow;
|
||||
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfw = (xfWindow*) window->extra;
|
||||
xf_DestroyWindow(xfc, xfw);
|
||||
appWindow = (xfAppWindow*) window->extra;
|
||||
|
||||
xf_DestroyWindow(xfc, appWindow);
|
||||
}
|
||||
|
||||
void xf_rail_DesktopNonMonitored(rdpRail* rail, rdpWindow* window)
|
||||
{
|
||||
xfContext* xfc;
|
||||
xfc = (xfContext*) rail->extra;
|
||||
xfContext* xfc = (xfContext*) rail->extra;
|
||||
xf_rail_disable_remoteapp_mode(xfc);
|
||||
}
|
||||
|
||||
|
@ -369,21 +380,21 @@ void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16
|
|||
* send an update to the RDP server informing it of the new window position
|
||||
* and size.
|
||||
*/
|
||||
void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window)
|
||||
void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
|
||||
{
|
||||
xfWindow* xfw;
|
||||
rdpWindow* window;
|
||||
RAIL_WINDOW_MOVE_ORDER windowMove;
|
||||
|
||||
xfw = (xfWindow*) window->extra;
|
||||
window = appWindow->window;
|
||||
|
||||
if (! xfw->is_mapped || xfw->local_move.state != LMS_NOT_ACTIVE)
|
||||
if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE)
|
||||
return;
|
||||
|
||||
/* If current window position disagrees with RDP window position, send update to RDP server */
|
||||
if (xfw->left != window->visibleOffsetX ||
|
||||
xfw->top != window->visibleOffsetY ||
|
||||
xfw->width != window->windowWidth ||
|
||||
xfw->height != window->windowHeight)
|
||||
if (appWindow->x != window->visibleOffsetX ||
|
||||
appWindow->y != window->visibleOffsetY ||
|
||||
appWindow->width != window->windowWidth ||
|
||||
appWindow->height != window->windowHeight)
|
||||
{
|
||||
/*
|
||||
* Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
|
||||
|
@ -409,28 +420,28 @@ void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window)
|
|||
* Calculate new offsets for the rail server window
|
||||
* Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset)
|
||||
*/
|
||||
windowMove.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
|
||||
windowMove.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
|
||||
windowMove.right = windowMove.left + xfw->width;
|
||||
windowMove.bottom = windowMove.top + xfw->height;
|
||||
windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
|
||||
windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
|
||||
windowMove.right = windowMove.left + appWindow->width;
|
||||
windowMove.bottom = windowMove.top + appWindow->height;
|
||||
|
||||
xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
|
||||
void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
|
||||
{
|
||||
int x, y;
|
||||
int child_x;
|
||||
int child_y;
|
||||
xfWindow* xfw;
|
||||
rdpWindow* window;
|
||||
unsigned int mask;
|
||||
Window root_window;
|
||||
Window child_window;
|
||||
RAIL_WINDOW_MOVE_ORDER window_move;
|
||||
RAIL_WINDOW_MOVE_ORDER windowMove;
|
||||
rdpInput* input = xfc->instance->input;
|
||||
|
||||
xfw = (xfWindow*) window->extra;
|
||||
window = appWindow->window;
|
||||
|
||||
/*
|
||||
* Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
|
||||
|
@ -449,31 +460,30 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
|
|||
/*
|
||||
* For keyboard moves send and explicit update to RDP server
|
||||
*/
|
||||
window_move.windowId = window->windowId;
|
||||
windowMove.windowId = window->windowId;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
|
||||
windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
|
||||
windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */
|
||||
windowMove.bottom = windowMove.top + appWindow->height;
|
||||
|
||||
xfc->rail->ClientWindowMove(xfc->rail, &window_move);
|
||||
xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
|
||||
|
||||
/*
|
||||
* Simulate button up at new position to end the local move (per RDP spec)
|
||||
*/
|
||||
XQueryPointer(xfc->display, xfw->handle,
|
||||
&root_window, &child_window,
|
||||
&x, &y, &child_x, &child_y, &mask);
|
||||
XQueryPointer(xfc->display, appWindow->handle,
|
||||
&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))
|
||||
if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
|
||||
(appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
|
||||
{
|
||||
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
|
||||
}
|
||||
|
@ -483,11 +493,11 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
|
|||
* 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 = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
|
||||
window->windowOffsetY = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
|
||||
window->windowWidth = xfw->width;
|
||||
window->windowHeight = xfw->height;
|
||||
xfw->local_move.state = LMS_TERMINATING;
|
||||
window->windowOffsetX = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
|
||||
window->windowOffsetY = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
|
||||
window->windowWidth = appWindow->width;
|
||||
window->windowHeight = appWindow->height;
|
||||
appWindow->local_move.state = LMS_TERMINATING;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -496,13 +506,13 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
|
|||
|
||||
static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
xfRailWindow* railWindow = NULL;
|
||||
xfAppWindow* railWindow = NULL;
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
UINT32 fieldFlags = orderInfo->fieldFlags;
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_STATE_NEW)
|
||||
{
|
||||
railWindow = (xfRailWindow*) calloc(1, sizeof(xfRailWindow));
|
||||
railWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow));
|
||||
|
||||
if (!railWindow)
|
||||
return;
|
||||
|
@ -541,7 +551,7 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
|
|||
}
|
||||
else
|
||||
{
|
||||
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
}
|
||||
|
||||
|
@ -634,10 +644,10 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
|
|||
|
||||
static void xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
xfRailWindow* railWindow = NULL;
|
||||
xfAppWindow* railWindow = NULL;
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
|
||||
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
|
@ -651,10 +661,10 @@ static void xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderI
|
|||
static void xf_rail_window_icon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* windowIcon)
|
||||
{
|
||||
BOOL bigIcon;
|
||||
xfRailWindow* railWindow;
|
||||
xfAppWindow* railWindow;
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
|
||||
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
|
@ -842,11 +852,11 @@ static int xf_rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAK
|
|||
static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||
{
|
||||
rdpRail* rail;
|
||||
xfWindow* window;
|
||||
int x = 0, y = 0;
|
||||
int direction = 0;
|
||||
Window child_window;
|
||||
rdpWindow* rail_window;
|
||||
xfAppWindow* appWindow;
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
rail = ((rdpContext*) xfc)->rail;
|
||||
|
@ -856,7 +866,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
|
|||
if (!rail_window)
|
||||
return -1;
|
||||
|
||||
window = (xfWindow*) rail_window->extra;
|
||||
appWindow = (xfAppWindow*) rail_window->extra;
|
||||
|
||||
switch (localMoveSize->moveSizeType)
|
||||
{
|
||||
|
@ -910,7 +920,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
|
|||
|
||||
case RAIL_WMSZ_MOVE:
|
||||
direction = _NET_WM_MOVERESIZE_MOVE;
|
||||
XTranslateCoordinates(xfc->display, window->handle,
|
||||
XTranslateCoordinates(xfc->display, appWindow->handle,
|
||||
RootWindowOfScreen(xfc->screen),
|
||||
localMoveSize->posX, localMoveSize->posY, &x, &y, &child_window);
|
||||
break;
|
||||
|
@ -934,11 +944,11 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
|
|||
|
||||
if (localMoveSize->isMoveSizeStart)
|
||||
{
|
||||
xf_StartLocalMoveSize(xfc, window, direction, x, y);
|
||||
xf_StartLocalMoveSize(xfc, appWindow, direction, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
xf_EndLocalMoveSize(xfc, window);
|
||||
xf_EndLocalMoveSize(xfc, appWindow);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -947,7 +957,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
|
|||
static int xf_rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||
{
|
||||
rdpRail* rail;
|
||||
xfWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
rdpWindow* rail_window;
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
|
@ -958,9 +968,9 @@ static int xf_rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXIN
|
|||
if (!rail_window)
|
||||
return -1;
|
||||
|
||||
window = (xfWindow*) rail_window->extra;
|
||||
appWindow = (xfAppWindow*) rail_window->extra;
|
||||
|
||||
xf_SetWindowMinMaxInfo(xfc, window,
|
||||
xf_SetWindowMinMaxInfo(xfc, appWindow,
|
||||
minMaxInfo->maxWidth, minMaxInfo->maxHeight,
|
||||
minMaxInfo->maxPosX, minMaxInfo->maxPosY,
|
||||
minMaxInfo->minTrackWidth, minMaxInfo->minTrackHeight,
|
||||
|
|
|
@ -23,41 +23,13 @@
|
|||
#include "xf_client.h"
|
||||
#include "xfreerdp.h"
|
||||
|
||||
struct xf_rail_window
|
||||
{
|
||||
xfContext* xfc;
|
||||
|
||||
UINT32 id;
|
||||
DWORD dwStyle;
|
||||
DWORD dwExStyle;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
char* title;
|
||||
|
||||
GC gc;
|
||||
int shmid;
|
||||
Window handle;
|
||||
Window* xfwin;
|
||||
BOOL fullscreen;
|
||||
BOOL decorations;
|
||||
BOOL is_mapped;
|
||||
BOOL is_transient;
|
||||
xfLocalMove local_move;
|
||||
BYTE rail_state;
|
||||
BOOL rail_ignore_configure;
|
||||
};
|
||||
typedef struct xf_rail_window xfRailWindow;
|
||||
|
||||
#include <freerdp/client/rail.h>
|
||||
|
||||
void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom);
|
||||
void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command);
|
||||
void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled);
|
||||
void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window);
|
||||
void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window);
|
||||
void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow);
|
||||
void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow);
|
||||
void xf_rail_enable_remoteapp_mode(xfContext* xfc);
|
||||
void xf_rail_disable_remoteapp_mode(xfContext* xfc);
|
||||
|
||||
|
|
|
@ -60,12 +60,6 @@
|
|||
#define DEBUG_X11(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef WITH_DEBUG_X11_LOCAL_MOVESIZE
|
||||
#define DEBUG_X11_LMS(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_X11_LMS(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#include "FreeRDP_Icon_256px.h"
|
||||
#define xf_icon_prop FreeRDP_Icon_256px_prop
|
||||
|
||||
|
@ -269,57 +263,7 @@ void xf_SetWindowUnlisted(xfContext* xfc, Window window)
|
|||
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_state, 2);
|
||||
}
|
||||
|
||||
void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style)
|
||||
{
|
||||
Atom window_type;
|
||||
|
||||
if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
|
||||
{
|
||||
/*
|
||||
* Tooltips and menu items should be unmanaged windows
|
||||
* (called "override redirect" in X windows parlance)
|
||||
* If they are managed, there are issues with window focus that
|
||||
* cause the windows to behave improperly. For example, a mouse
|
||||
* press will dismiss a drop-down menu because the RDP server
|
||||
* sees that as a focus out event from the window owning the
|
||||
* dropdown.
|
||||
*/
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.override_redirect = True;
|
||||
XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &attrs);
|
||||
window->is_transient = TRUE;
|
||||
xf_SetWindowUnlisted(xfc, window->handle);
|
||||
window_type = xfc->_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 = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
|
||||
}
|
||||
else if (style & WS_POPUP)
|
||||
{
|
||||
/* this includes dialogs, popups, etc, that need to be full-fledged windows */
|
||||
window->is_transient = TRUE;
|
||||
window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
|
||||
|
||||
xf_SetWindowUnlisted(xfc, window->handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_WINDOW_TYPE,
|
||||
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_SetWindowText(xfContext* xfc, xfWindow* window, char* name)
|
||||
{
|
||||
XStoreName(xfc->display, window->handle, name);
|
||||
}
|
||||
|
||||
static void xf_SetWindowPID(xfContext* xfc, xfWindow* window, pid_t pid)
|
||||
static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid)
|
||||
{
|
||||
Atom am_wm_pid;
|
||||
|
||||
|
@ -328,14 +272,14 @@ static void xf_SetWindowPID(xfContext* xfc, xfWindow* window, pid_t pid)
|
|||
|
||||
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False);
|
||||
|
||||
XChangeProperty(xfc->display, window->handle, am_wm_pid, XA_CARDINAL,
|
||||
XChangeProperty(xfc->display, window, am_wm_pid, XA_CARDINAL,
|
||||
32, PropModeReplace, (BYTE*) &pid, 1);
|
||||
}
|
||||
|
||||
static const char* get_shm_id()
|
||||
{
|
||||
static char shm_id[64];
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
return shm_id;
|
||||
}
|
||||
|
||||
|
@ -358,7 +302,6 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
|
|||
window->height = height;
|
||||
window->fullscreen = FALSE;
|
||||
window->decorations = decorations;
|
||||
window->local_move.state = LMS_NOT_ACTIVE;
|
||||
window->is_mapped = FALSE;
|
||||
window->is_transient = FALSE;
|
||||
|
||||
|
@ -410,7 +353,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
|
|||
|
||||
xf_ResizeDesktopWindow(xfc, window, width, height);
|
||||
xf_SetWindowDecorations(xfc, window->handle, decorations);
|
||||
xf_SetWindowPID(xfc, window, 0);
|
||||
xf_SetWindowPID(xfc, window->handle, 0);
|
||||
|
||||
input_mask =
|
||||
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
|
||||
|
@ -443,7 +386,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
|
|||
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).
|
||||
* 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 (xfc->settings->RemoteApplicationMode)
|
||||
|
@ -478,6 +421,87 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei
|
|||
}
|
||||
}
|
||||
|
||||
void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window)
|
||||
{
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (xfc->window == window)
|
||||
xfc->window = NULL;
|
||||
|
||||
if (window->gc)
|
||||
XFreeGC(xfc->display, window->gc);
|
||||
|
||||
if (window->handle)
|
||||
{
|
||||
XUnmapWindow(xfc->display, window->handle);
|
||||
XDestroyWindow(xfc->display, window->handle);
|
||||
}
|
||||
|
||||
if (window->xfwin)
|
||||
munmap(0, sizeof(*window->xfwin));
|
||||
|
||||
if (window->shmid >= 0)
|
||||
close(window->shmid);
|
||||
|
||||
shm_unlink(get_shm_id());
|
||||
|
||||
window->xfwin = (Window*) -1;
|
||||
window->shmid = -1;
|
||||
|
||||
free(window);
|
||||
}
|
||||
|
||||
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style)
|
||||
{
|
||||
Atom window_type;
|
||||
|
||||
if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
|
||||
{
|
||||
/*
|
||||
* Tooltips and menu items should be unmanaged windows
|
||||
* (called "override redirect" in X windows parlance)
|
||||
* If they are managed, there are issues with window focus that
|
||||
* cause the windows to behave improperly. For example, a mouse
|
||||
* press will dismiss a drop-down menu because the RDP server
|
||||
* sees that as a focus out event from the window owning the
|
||||
* dropdown.
|
||||
*/
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.override_redirect = True;
|
||||
XChangeWindowAttributes(xfc->display, appWindow->handle, CWOverrideRedirect, &attrs);
|
||||
appWindow->is_transient = TRUE;
|
||||
xf_SetWindowUnlisted(xfc, appWindow->handle);
|
||||
window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP;
|
||||
}
|
||||
/*
|
||||
* TOPMOST window that is not a tool window is treated like a regular window (i.e. task manager).
|
||||
* Want to do this here, since the window may have type WS_POPUP
|
||||
*/
|
||||
else if (ex_style & WS_EX_TOPMOST)
|
||||
{
|
||||
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
|
||||
}
|
||||
else if (style & WS_POPUP)
|
||||
{
|
||||
/* this includes dialogs, popups, etc, that need to be full-fledged windows */
|
||||
appWindow->is_transient = TRUE;
|
||||
window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
|
||||
|
||||
xf_SetWindowUnlisted(xfc, appWindow->handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE,
|
||||
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
|
||||
{
|
||||
XStoreName(xfc->display, appWindow->handle, name);
|
||||
}
|
||||
|
||||
void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* height)
|
||||
{
|
||||
int vscreen_width;
|
||||
|
@ -513,46 +537,48 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* he
|
|||
}
|
||||
}
|
||||
|
||||
char rail_window_class[] = "RAIL:00000000";
|
||||
|
||||
xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id)
|
||||
xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id)
|
||||
{
|
||||
XGCValues gcv;
|
||||
int input_mask;
|
||||
xfWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
XWMHints* InputModeHint;
|
||||
XClassHint* class_hints;
|
||||
|
||||
window = (xfWindow*) calloc(1, sizeof(xfWindow));
|
||||
appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow));
|
||||
|
||||
if (!appWindow)
|
||||
return NULL;
|
||||
|
||||
xf_FixWindowCoordinates(xfc, &x, &y, &width, &height);
|
||||
|
||||
window->left = x;
|
||||
window->top = y;
|
||||
window->right = x + width - 1;
|
||||
window->bottom = y + height - 1;
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
appWindow->x = x;
|
||||
appWindow->y = y;
|
||||
appWindow->width = width;
|
||||
appWindow->height = height;
|
||||
|
||||
/*
|
||||
* WS_EX_DECORATIONS is used by XRDP and instructs
|
||||
* the client to use local window decorations
|
||||
*/
|
||||
window->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
|
||||
window->fullscreen = FALSE;
|
||||
window->window = wnd;
|
||||
window->local_move.state = LMS_NOT_ACTIVE;
|
||||
window->is_mapped = FALSE;
|
||||
window->is_transient = FALSE;
|
||||
window->rail_state = 0;
|
||||
window->rail_ignore_configure = FALSE;
|
||||
appWindow->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
|
||||
appWindow->fullscreen = FALSE;
|
||||
appWindow->window = wnd;
|
||||
appWindow->local_move.state = LMS_NOT_ACTIVE;
|
||||
appWindow->is_mapped = FALSE;
|
||||
appWindow->is_transient = FALSE;
|
||||
appWindow->rail_state = 0;
|
||||
appWindow->rail_ignore_configure = FALSE;
|
||||
|
||||
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
|
||||
x, y, window->width, window->height, 0, xfc->depth,
|
||||
appWindow->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
|
||||
x, y, appWindow->width, appWindow->height, 0, xfc->depth,
|
||||
InputOutput, xfc->visual, 0, &xfc->attribs);
|
||||
|
||||
if (!appWindow->handle)
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(&gcv, sizeof(gcv));
|
||||
window->gc = XCreateGC(xfc->display, window->handle, GCGraphicsExposures, &gcv);
|
||||
appWindow->gc = XCreateGC(xfc->display, appWindow->handle, GCGraphicsExposures, &gcv);
|
||||
|
||||
class_hints = XAllocClassHint();
|
||||
|
||||
|
@ -566,13 +592,13 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
|
|||
}
|
||||
else
|
||||
{
|
||||
class = malloc(sizeof(rail_window_class));
|
||||
snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id);
|
||||
class = malloc(sizeof("RAIL:00000000"));
|
||||
snprintf(class, sizeof("RAIL:00000000"), "RAIL:%08X", id);
|
||||
class_hints->res_class = class;
|
||||
}
|
||||
|
||||
class_hints->res_name = "RAIL";
|
||||
XSetClassHint(xfc->display, window->handle, class_hints);
|
||||
XSetClassHint(xfc->display, appWindow->handle, class_hints);
|
||||
XFree(class_hints);
|
||||
|
||||
if (class)
|
||||
|
@ -584,10 +610,10 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
|
|||
InputModeHint->flags = (1L << 0);
|
||||
InputModeHint->input = True;
|
||||
|
||||
XSetWMHints(xfc->display, window->handle, InputModeHint);
|
||||
XSetWMHints(xfc->display, appWindow->handle, InputModeHint);
|
||||
XFree(InputModeHint);
|
||||
|
||||
XSetWMProtocols(xfc->display, window->handle, &(xfc->WM_DELETE_WINDOW), 1);
|
||||
XSetWMProtocols(xfc->display, appWindow->handle, &(xfc->WM_DELETE_WINDOW), 1);
|
||||
|
||||
input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
|
||||
ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
|
||||
|
@ -598,23 +624,23 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
|
|||
SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
|
||||
ColormapChangeMask | OwnerGrabButtonMask;
|
||||
|
||||
XSelectInput(xfc->display, window->handle, input_mask);
|
||||
XSelectInput(xfc->display, appWindow->handle, input_mask);
|
||||
|
||||
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
|
||||
xf_SetWindowStyle(xfc, window, wnd->style, wnd->extendedStyle);
|
||||
xf_SetWindowPID(xfc, window, 0);
|
||||
xf_ShowWindow(xfc, window, WINDOW_SHOW);
|
||||
xf_SetWindowDecorations(xfc, appWindow->handle, appWindow->decorations);
|
||||
xf_SetWindowStyle(xfc, appWindow, wnd->style, wnd->extendedStyle);
|
||||
xf_SetWindowPID(xfc, appWindow->handle, 0);
|
||||
xf_ShowWindow(xfc, appWindow, WINDOW_SHOW);
|
||||
|
||||
XClearWindow(xfc->display, window->handle);
|
||||
XMapWindow(xfc->display, window->handle);
|
||||
XClearWindow(xfc->display, appWindow->handle);
|
||||
XMapWindow(xfc->display, appWindow->handle);
|
||||
|
||||
/* Move doesn't seem to work until window is mapped. */
|
||||
xf_MoveWindow(xfc, window, x, y, width, height);
|
||||
xf_MoveWindow(xfc, appWindow, x, y, width, height);
|
||||
|
||||
return window;
|
||||
return appWindow;
|
||||
}
|
||||
|
||||
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
|
||||
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow,
|
||||
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
|
||||
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight)
|
||||
{
|
||||
|
@ -630,28 +656,28 @@ void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
|
|||
size_hints->max_height = maxTrackHeight;
|
||||
/* to speedup window drawing we need to select optimal value for sizing step. */
|
||||
size_hints->width_inc = size_hints->height_inc = 1;
|
||||
XSetWMNormalHints(xfc->display, window->handle, size_hints);
|
||||
XSetWMNormalHints(xfc->display, appWindow->handle, size_hints);
|
||||
XFree(size_hints);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y)
|
||||
void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y)
|
||||
{
|
||||
if (window->local_move.state != LMS_NOT_ACTIVE)
|
||||
if (appWindow->local_move.state != LMS_NOT_ACTIVE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Save original mouse location relative to root. This will be needed
|
||||
* to end local move to RDP server and/or X server
|
||||
*/
|
||||
window->local_move.root_x = x;
|
||||
window->local_move.root_y = y;
|
||||
window->local_move.state = LMS_STARTING;
|
||||
window->local_move.direction = direction;
|
||||
appWindow->local_move.root_x = x;
|
||||
appWindow->local_move.root_y = y;
|
||||
appWindow->local_move.state = LMS_STARTING;
|
||||
appWindow->local_move.direction = direction;
|
||||
|
||||
XUngrabPointer(xfc->display, CurrentTime);
|
||||
|
||||
xf_SendClientEvent(xfc, window->handle,
|
||||
xf_SendClientEvent(xfc, appWindow->handle,
|
||||
xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */
|
||||
5, /* 5 arguments to follow */
|
||||
x, /* x relative to root window */
|
||||
|
@ -661,12 +687,12 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
|
|||
1); /* 1 == application request per extended ICCM */
|
||||
}
|
||||
|
||||
void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window)
|
||||
void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow)
|
||||
{
|
||||
if (window->local_move.state == LMS_NOT_ACTIVE)
|
||||
if (appWindow->local_move.state == LMS_NOT_ACTIVE)
|
||||
return;
|
||||
|
||||
if (window->local_move.state == LMS_STARTING)
|
||||
if (appWindow->local_move.state == LMS_STARTING)
|
||||
{
|
||||
/*
|
||||
* The move never was property started. This can happen due to race
|
||||
|
@ -674,63 +700,61 @@ void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window)
|
|||
* RDP server for local moves. We must cancel the X window manager move.
|
||||
* Per ICCM, the X client can ask to cancel an active move.
|
||||
*/
|
||||
xf_SendClientEvent(xfc, window->handle,
|
||||
xf_SendClientEvent(xfc, appWindow->handle,
|
||||
xfc->_NET_WM_MOVERESIZE, /* request X window manager to abort a local move */
|
||||
5, /* 5 arguments to follow */
|
||||
window->local_move.root_x, /* x relative to root window */
|
||||
window->local_move.root_y, /* y relative to root window */
|
||||
appWindow->local_move.root_x, /* x relative to root window */
|
||||
appWindow->local_move.root_y, /* y relative to root window */
|
||||
_NET_WM_MOVERESIZE_CANCEL, /* extended ICCM direction flag */
|
||||
1, /* simulated mouse button 1 */
|
||||
1); /* 1 == application request per extended ICCM */
|
||||
}
|
||||
|
||||
window->local_move.state = LMS_NOT_ACTIVE;
|
||||
appWindow->local_move.state = LMS_NOT_ACTIVE;
|
||||
}
|
||||
|
||||
void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
|
||||
void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
|
||||
{
|
||||
BOOL resize = FALSE;
|
||||
|
||||
if ((width * height) < 1)
|
||||
return;
|
||||
|
||||
if ((window->width != width) || (window->height != height))
|
||||
if ((appWindow->width != width) || (appWindow->height != height))
|
||||
resize = TRUE;
|
||||
|
||||
if (window->local_move.state == LMS_STARTING ||
|
||||
window->local_move.state == LMS_ACTIVE)
|
||||
if (appWindow->local_move.state == LMS_STARTING ||
|
||||
appWindow->local_move.state == LMS_ACTIVE)
|
||||
return;
|
||||
|
||||
window->left = x;
|
||||
window->top = y;
|
||||
window->right = x + width - 1;
|
||||
window->bottom = y + height - 1;
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
appWindow->x = x;
|
||||
appWindow->y = y;
|
||||
appWindow->width = width;
|
||||
appWindow->height = height;
|
||||
|
||||
if (resize)
|
||||
XMoveResizeWindow(xfc->display, window->handle, x, y, width, height);
|
||||
XMoveResizeWindow(xfc->display, appWindow->handle, x, y, width, height);
|
||||
else
|
||||
XMoveWindow(xfc->display, window->handle, x, y);
|
||||
XMoveWindow(xfc->display, appWindow->handle, x, y);
|
||||
|
||||
xf_UpdateWindowArea(xfc, window, 0, 0, width, height);
|
||||
xf_UpdateWindowArea(xfc, appWindow, 0, 0, width, height);
|
||||
}
|
||||
|
||||
void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
|
||||
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case WINDOW_HIDE:
|
||||
XWithdrawWindow(xfc->display, window->handle, xfc->screen_number);
|
||||
XWithdrawWindow(xfc->display, appWindow->handle, xfc->screen_number);
|
||||
break;
|
||||
|
||||
case WINDOW_SHOW_MINIMIZED:
|
||||
XIconifyWindow(xfc->display, window->handle, xfc->screen_number);
|
||||
XIconifyWindow(xfc->display, appWindow->handle, xfc->screen_number);
|
||||
break;
|
||||
|
||||
case WINDOW_SHOW_MAXIMIZED:
|
||||
/* Set the window as maximized */
|
||||
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, 1,
|
||||
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 1,
|
||||
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
|
||||
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
|
||||
/*
|
||||
|
@ -739,13 +763,13 @@ void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
|
|||
* 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(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
|
||||
if (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED)
|
||||
xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->window->windowWidth, appWindow->window->windowHeight);
|
||||
break;
|
||||
|
||||
case WINDOW_SHOW:
|
||||
/* Ensure the window is not maximized */
|
||||
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, 0,
|
||||
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 0,
|
||||
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
|
||||
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
|
||||
/*
|
||||
|
@ -754,20 +778,20 @@ void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
|
|||
* 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 (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED)
|
||||
appWindow->rail_ignore_configure = TRUE;
|
||||
|
||||
if (window->is_transient)
|
||||
xf_SetWindowUnlisted(xfc, window->handle);
|
||||
if (appWindow->is_transient)
|
||||
xf_SetWindowUnlisted(xfc, appWindow->handle);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Save the current rail state of this window */
|
||||
window->rail_state = state;
|
||||
appWindow->rail_state = state;
|
||||
XFlush(xfc->display);
|
||||
}
|
||||
|
||||
void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
|
||||
void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon)
|
||||
{
|
||||
int x, y;
|
||||
int pixels;
|
||||
|
@ -795,7 +819,7 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
|
|||
}
|
||||
}
|
||||
|
||||
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
|
||||
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
|
||||
PropModeReplace, (BYTE *) propdata, propsize);
|
||||
|
||||
XFlush(xfc->display);
|
||||
|
@ -803,7 +827,7 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
|
|||
free(propdata);
|
||||
}
|
||||
|
||||
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects)
|
||||
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects)
|
||||
{
|
||||
int i;
|
||||
XRectangle* xrects;
|
||||
|
@ -811,7 +835,7 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
|
|||
if (nrects < 1)
|
||||
return;
|
||||
|
||||
xrects = malloc(sizeof(XRectangle) * nrects);
|
||||
xrects = (XRectangle*) calloc(nrects, sizeof(XRectangle));
|
||||
|
||||
for (i = 0; i < nrects; i++)
|
||||
{
|
||||
|
@ -822,17 +846,13 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
|
|||
}
|
||||
|
||||
#ifdef WITH_XEXT
|
||||
/*
|
||||
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
|
||||
*
|
||||
* Marc: enabling it works, and is required for round corners.
|
||||
*/
|
||||
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
|
||||
XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
|
||||
#endif
|
||||
|
||||
free(xrects);
|
||||
}
|
||||
|
||||
void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16 *rects, int nrects)
|
||||
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects)
|
||||
{
|
||||
int i;
|
||||
XRectangle* xrects;
|
||||
|
@ -840,7 +860,7 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16
|
|||
if (nrects < 1)
|
||||
return;
|
||||
|
||||
xrects = malloc(sizeof(XRectangle) * nrects);
|
||||
xrects = (XRectangle*) calloc(nrects, sizeof(XRectangle));
|
||||
|
||||
for (i = 0; i < nrects; i++)
|
||||
{
|
||||
|
@ -849,91 +869,71 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16
|
|||
xrects[i].width = rects[i].right - rects[i].left;
|
||||
xrects[i].height = rects[i].bottom - rects[i].top;
|
||||
}
|
||||
|
||||
#ifdef WITH_XEXT
|
||||
/*
|
||||
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
|
||||
*
|
||||
* Marc: enabling it works, and is required for round corners.
|
||||
*/
|
||||
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
|
||||
XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
|
||||
#endif
|
||||
|
||||
free(xrects);
|
||||
}
|
||||
|
||||
void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
|
||||
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
|
||||
{
|
||||
int ax, ay;
|
||||
rdpWindow* wnd;
|
||||
|
||||
wnd = window->window;
|
||||
wnd = appWindow->window;
|
||||
|
||||
/* RemoteApp mode uses visibleOffset instead of windowOffset */
|
||||
ax = x + wnd->visibleOffsetX;
|
||||
ay = y + wnd->visibleOffsetY;
|
||||
|
||||
if (!xfc->remote_app)
|
||||
{
|
||||
ax = x + wnd->windowOffsetX;
|
||||
ay = y + wnd->windowOffsetY;
|
||||
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 (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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
WaitForSingleObject(xfc->mutex, INFINITE);
|
||||
xf_lock_x11(xfc, TRUE);
|
||||
|
||||
if (xfc->settings->SoftwareGdi)
|
||||
{
|
||||
XPutImage(xfc->display, xfc->primary, window->gc, xfc->image,
|
||||
ax, ay, ax, ay, width, height);
|
||||
XPutImage(xfc->display, xfc->primary, appWindow->gc, xfc->image,
|
||||
ax, ay, ax, ay, width, height);
|
||||
}
|
||||
|
||||
XCopyArea(xfc->display, xfc->primary, window->handle, window->gc,
|
||||
ax, ay, width, height, x, y);
|
||||
XCopyArea(xfc->display, xfc->primary, appWindow->handle, appWindow->gc,
|
||||
ax, ay, width, height, x, y);
|
||||
|
||||
XFlush(xfc->display);
|
||||
ReleaseMutex(xfc->mutex);
|
||||
|
||||
xf_unlock_x11(xfc, TRUE);
|
||||
}
|
||||
|
||||
void xf_DestroyWindow(xfContext* xfc, xfWindow* window)
|
||||
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow)
|
||||
{
|
||||
if (!window)
|
||||
if (!appWindow)
|
||||
return;
|
||||
|
||||
if (xfc->window == window)
|
||||
xfc->window = NULL;
|
||||
if (appWindow->gc)
|
||||
XFreeGC(xfc->display, appWindow->gc);
|
||||
|
||||
if (window->gc)
|
||||
XFreeGC(xfc->display, window->gc);
|
||||
|
||||
if (window->handle)
|
||||
if (appWindow->handle)
|
||||
{
|
||||
XUnmapWindow(xfc->display, window->handle);
|
||||
XDestroyWindow(xfc->display, window->handle);
|
||||
XUnmapWindow(xfc->display, appWindow->handle);
|
||||
XDestroyWindow(xfc->display, appWindow->handle);
|
||||
}
|
||||
|
||||
if (window->xfwin)
|
||||
munmap(0, sizeof(*window->xfwin));
|
||||
if (appWindow->xfwin)
|
||||
munmap(0, sizeof(*appWindow->xfwin));
|
||||
|
||||
if (window->shmid >= 0)
|
||||
close(window->shmid);
|
||||
if (appWindow->shmid >= 0)
|
||||
close(appWindow->shmid);
|
||||
|
||||
shm_unlink(get_shm_id());
|
||||
|
||||
window->xfwin = (Window*) -1;
|
||||
window->shmid = -1;
|
||||
appWindow->xfwin = (Window*) -1;
|
||||
appWindow->shmid = -1;
|
||||
|
||||
free(window);
|
||||
free(appWindow);
|
||||
}
|
||||
|
||||
rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd)
|
||||
|
@ -947,7 +947,7 @@ rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd)
|
|||
rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
if (rail)
|
||||
return window_list_get_by_extra_id(rail->list, (void*)(long) wnd);
|
||||
return window_list_get_by_extra_id(rail->list, (void*) (long) wnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
typedef struct xf_app_window xfAppWindow;
|
||||
|
||||
typedef struct xf_localmove xfLocalMove;
|
||||
typedef struct xf_window xfWindow;
|
||||
|
||||
|
@ -79,6 +81,26 @@ struct xf_window
|
|||
BOOL decorations;
|
||||
BOOL is_mapped;
|
||||
BOOL is_transient;
|
||||
};
|
||||
|
||||
struct xf_app_window
|
||||
{
|
||||
xfContext* xfc;
|
||||
rdpWindow* window;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
GC gc;
|
||||
int shmid;
|
||||
Window handle;
|
||||
Window* xfwin;
|
||||
BOOL fullscreen;
|
||||
BOOL decorations;
|
||||
BOOL is_mapped;
|
||||
BOOL is_transient;
|
||||
xfLocalMove local_move;
|
||||
BYTE rail_state;
|
||||
BOOL rail_ignore_configure;
|
||||
|
@ -95,26 +117,27 @@ void xf_SetWindowUnlisted(xfContext* xfc, Window window);
|
|||
|
||||
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations);
|
||||
void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
|
||||
void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window);
|
||||
|
||||
BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
|
||||
unsigned long* nitems, unsigned long* bytes, BYTE** prop);
|
||||
void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...);
|
||||
|
||||
xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
|
||||
void xf_SetWindowText(xfContext* xfc, xfWindow* window, char* name);
|
||||
void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
|
||||
void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state);
|
||||
void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon);
|
||||
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
|
||||
void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
|
||||
void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style);
|
||||
void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
|
||||
void xf_DestroyWindow(xfContext* xfc, xfWindow* window);
|
||||
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
|
||||
xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
|
||||
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name);
|
||||
void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
|
||||
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state);
|
||||
void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon);
|
||||
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
|
||||
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
|
||||
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style);
|
||||
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
|
||||
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);
|
||||
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow,
|
||||
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
|
||||
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
|
||||
void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y);
|
||||
void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window);
|
||||
void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y);
|
||||
void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow);
|
||||
rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd);
|
||||
|
||||
#endif /* __XF_WINDOW_H */
|
||||
|
|
|
@ -106,6 +106,7 @@ struct xf_context
|
|||
BOOL unobscured;
|
||||
BOOL debug;
|
||||
xfWindow* window;
|
||||
xfAppWindow* appWindow;
|
||||
xfPointer* pointer;
|
||||
xfWorkArea workArea;
|
||||
int current_desktop;
|
||||
|
|
Loading…
Reference in New Issue