static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) { int x, y; int w, h; rdpSettings* settings = xfc->context.settings; if (!app && (settings->SmartSizing || settings->MultiTouchGestures)) { x = 0; y = 0; w = settings->DesktopWidth; h = settings->DesktopHeight; } else { x = event->xexpose.x; y = event->xexpose.y; w = event->xexpose.width; h = event->xexpose.height; } if (xfc->gfx) { xf_OutputExpose(xfc, x, y, w, h); return TRUE; } if (!app) { xf_draw_screen(xfc, x, y, w, h); } else { xfAppWindow* appWindow; appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (appWindow) { xf_UpdateWindowArea(xfc, appWindow, x, y, w, h); } } return TRUE; }
BOOL xf_hw_end_paint(rdpContext* context) { INT32 x, y; UINT32 w, h; xfContext* xfc = (xfContext*) context; if (!xfc->remote_app) { if (!xfc->complex_regions) { if (xfc->hdc->hwnd->invalid->null) return TRUE; x = xfc->hdc->hwnd->invalid->x; y = xfc->hdc->hwnd->invalid->y; w = xfc->hdc->hwnd->invalid->w; h = xfc->hdc->hwnd->invalid->h; xf_lock_x11(xfc, FALSE); xf_draw_screen(xfc, x, y, w, h); xf_unlock_x11(xfc, FALSE); } else { int i; int ninvalid; HGDI_RGN cinvalid; if (xfc->hdc->hwnd->ninvalid < 1) return TRUE; ninvalid = xfc->hdc->hwnd->ninvalid; cinvalid = xfc->hdc->hwnd->cinvalid; xf_lock_x11(xfc, FALSE); for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; xf_draw_screen(xfc, x, y, w, h); } XFlush(xfc->display); xf_unlock_x11(xfc, FALSE); } } else { if (xfc->hdc->hwnd->invalid->null) return TRUE; x = xfc->hdc->hwnd->invalid->x; y = xfc->hdc->hwnd->invalid->y; w = xfc->hdc->hwnd->invalid->w; h = xfc->hdc->hwnd->invalid->h; xf_lock_x11(xfc, FALSE); xf_rail_paint(xfc, x, y, x + w, y + h); xf_unlock_x11(xfc, FALSE); } return TRUE; }
BOOL xf_sw_end_paint(rdpContext* context) { int i; INT32 x, y; UINT32 w, h; int ninvalid; HGDI_RGN cinvalid; xfContext* xfc = (xfContext*) context; rdpGdi* gdi = context->gdi; x = gdi->primary->hdc->hwnd->invalid->x; y = gdi->primary->hdc->hwnd->invalid->y; w = gdi->primary->hdc->hwnd->invalid->w; h = gdi->primary->hdc->hwnd->invalid->h; ninvalid = gdi->primary->hdc->hwnd->ninvalid; cinvalid = gdi->primary->hdc->hwnd->cinvalid; if (!xfc->remote_app) { if (!xfc->complex_regions) { if (gdi->primary->hdc->hwnd->invalid->null) return TRUE; xf_lock_x11(xfc, FALSE); XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); xf_draw_screen(xfc, x, y, w, h); xf_unlock_x11(xfc, FALSE); } else { if (gdi->primary->hdc->hwnd->ninvalid < 1) return TRUE; xf_lock_x11(xfc, FALSE); for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); xf_draw_screen(xfc, x, y, w, h); } XFlush(xfc->display); xf_unlock_x11(xfc, FALSE); } } else { if (gdi->primary->hdc->hwnd->invalid->null) return TRUE; xf_lock_x11(xfc, FALSE); xf_rail_paint(xfc, x, y, x + w, y + h); xf_unlock_x11(xfc, FALSE); } return TRUE; }
static int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) { UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = surfaceX; surfaceRect.top = surfaceY; surfaceRect.right = surfaceX + surface->width; surfaceRect.bottom = surfaceY + surface->height; XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); if (!region16_is_empty(&surface->invalidRegion)) { extents = region16_extents(&surface->invalidRegion); width = extents->right - extents->left; height = extents->bottom - extents->top; if (width > surface->width) width = surface->width; if (height > surface->height) height = surface->height; if (surface->stage) { freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0, surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL); } #ifdef WITH_XRENDER if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height); xf_draw_screen(xfc, extents->left, extents->top, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height); } } region16_clear(&surface->invalidRegion); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, False); return 1; }
static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) { Window childWindow; xfAppWindow* appWindow; rdpSettings* settings = xfc->context.settings; if (!app) { if (xfc->window->left != event->xconfigure.x) xfc->window->left = event->xconfigure.x; if (xfc->window->top != event->xconfigure.y) xfc->window->top = event->xconfigure.y; if (xfc->window->width != event->xconfigure.width || xfc->window->height != event->xconfigure.height) { xfc->window->width = event->xconfigure.width; xfc->window->height = event->xconfigure.height; #ifdef WITH_XRENDER xfc->offset_x = 0; xfc->offset_y = 0; if (xfc->context.settings->SmartSizing || xfc->context.settings->MultiTouchGestures) { xfc->scaledWidth = xfc->window->width; xfc->scaledHeight = xfc->window->height; xf_draw_screen(xfc, 0, 0, settings->DesktopWidth, settings->DesktopHeight); } else { xfc->scaledWidth = settings->DesktopWidth; xfc->scaledHeight = settings->DesktopHeight; } #endif } return TRUE; } appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (appWindow) { /* * 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 (i.e. resizing using window decoration). * The server will be updated when the window gets refocused. */ if (appWindow->decorations) { /* moving resizing using window decoration */ xf_rail_adjust_position(xfc, appWindow); } else { 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; }
BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) { XF_MODIFIER_KEYS mod = { 0 }; xk_keyboard_get_modifier_keys(xfc, &mod); if (!xf_keyboard_execute_action_script(xfc, &mod, keysym)) { return TRUE; } if(!xfc->remote_app && xfc->fullscreen_toggle) { if (keysym == XK_Return) { WLog_DBG(TAG, "X keycode 0x%x, Ctrl: %d, Alt: %d", keysym, mod.Ctrl, mod.Alt); if (mod.Ctrl && mod.Alt) { /* Ctrl-Alt-Enter: toggle full screen */ xf_toggle_fullscreen(xfc); return TRUE; } } } if (!xfc->remote_app) { if ((keysym == XK_Tab) || (keysym == XK_Left) || (keysym == XK_Right)) { WLog_DBG(TAG, "X keycode 0x%x, Ctrl: %d, Alt: %d", keysym, mod.Ctrl, mod.Alt); if (mod.Ctrl && mod.Alt) { /* Works in either full screen or windowed. * If in fullscreen or cursor inside window - need to do * "double" ctrl-alt-* key press and release... * 1st ctrl-alt-[tab-left-right] releases from x11 key binding * 2nd ctrl-alt-[tab-left-right] executes OS system key binding * Note: If windowed and cursor is not in freerdp window, ie., * on tile bar, this doesnt apply and ctrl-alt-[tab-left-right] * key press will work as OS system key binding. */ XUngrabKeyboard(xfc->display, CurrentTime); return TRUE; } } } if ((keysym == XK_c) || (keysym == XK_C)) { if (mod.Ctrl && mod.Alt) { /* Ctrl-Alt-C: toggle control */ xf_toggle_control(xfc); return TRUE; } } #if 0 /* set to 1 to enable multi touch gesture simulation via keyboard */ #ifdef WITH_XRENDER if (!xfc->remote_app && xfc->settings->MultiTouchGestures) { if (mod.Ctrl && mod.Alt) { int pdx = 0; int pdy = 0; int zdx = 0; int zdy = 0; switch(keysym) { case XK_0: /* Ctrl-Alt-0: Reset scaling and panning */ xfc->scaledWidth = xfc->sessionWidth; xfc->scaledHeight = xfc->sessionHeight; xfc->offset_x = 0; xfc->offset_y = 0; if (!xfc->fullscreen && (xfc->sessionWidth != xfc->window->width || xfc->sessionHeight != xfc->window->height)) { xf_ResizeDesktopWindow(xfc, xfc->window, xfc->sessionWidth, xfc->sessionHeight); } xf_draw_screen(xfc, 0, 0, xfc->sessionWidth, xfc->sessionHeight); return TRUE; case XK_1: /* Ctrl-Alt-1: Zoom in */ zdx = zdy = 10; break; case XK_2: /* Ctrl-Alt-2: Zoom out */ zdx = zdy = -10; break; case XK_3: /* Ctrl-Alt-3: Pan left */ pdx = -10; break; case XK_4: /* Ctrl-Alt-4: Pan right */ pdx = 10; break; case XK_5: /* Ctrl-Alt-5: Pan up */ pdy = -10; break; case XK_6: /* Ctrl-Alt-6: Pan up */ pdy = 10; break; } if (pdx != 0 || pdy != 0) { PanningChangeEventArgs e; EventArgsInit(&e, "xfreerdp"); e.dx = pdx; e.dy = pdy; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); return TRUE; } if (zdx != 0 || zdy != 0) { ZoomingChangeEventArgs e; EventArgsInit(&e, "xfreerdp"); e.dx = zdx; e.dy = zdy; PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); return TRUE; } } } #endif /* WITH_XRENDER defined */ #endif /* pinch/zoom/pan simulation */ return FALSE; }
int xf_OutputUpdate(xfContext* xfc) { UINT16 width, height; xfGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; if (!xfc->graphicsReset) return 1; surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId); if (!surface) return -1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = xfc->width; surfaceRect.bottom = xfc->height; region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); if (!region16_is_empty(&(xfc->invalidRegion))) { extents = region16_extents(&(xfc->invalidRegion)); width = extents->right - extents->left; height = extents->bottom - extents->top; if (width > xfc->width) width = xfc->width; if (height > xfc->height) height = xfc->height; if (surface->stage) { freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0, surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL); } #ifdef WITH_XRENDER if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); xf_draw_screen(xfc, extents->left, extents->top, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); } } region16_clear(&(xfc->invalidRegion)); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, True); return 1; }
static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) { UINT rc = ERROR_INTERNAL_ERROR; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; rdpGdi* gdi; UINT32 nbRects, x; const RECTANGLE_16* rects; gdi = xfc->context.gdi; surfaceX = surface->gdi.outputOriginX; surfaceY = surface->gdi.outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->gdi.width; surfaceRect.bottom = surface->gdi.height; XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); region16_intersect_rect(&(surface->gdi.invalidRegion), &(surface->gdi.invalidRegion), &surfaceRect); if (!(rects = region16_rects(&surface->gdi.invalidRegion, &nbRects))) return CHANNEL_RC_OK; for (x = 0; x < nbRects; x++) { const UINT32 nXSrc = rects[x].left; const UINT32 nYSrc = rects[x].top; const UINT32 width = rects[x].right - nXSrc; const UINT32 height = rects[x].bottom - nYSrc; const UINT32 nXDst = surfaceX + nXSrc; const UINT32 nYDst = surfaceY + nYSrc; if (surface->stage) { if (!freerdp_image_copy(surface->stage, gdi->dstFormat, surface->stageScanline, nXSrc, nYSrc, width, height, surface->gdi.data, surface->gdi.format, surface->gdi.scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) goto fail; } if (xfc->remote_app) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); xf_lock_x11(xfc, FALSE); xf_rail_paint(xfc, nXDst, nYDst, nXDst + width, nYDst + height); xf_unlock_x11(xfc, FALSE); } else #ifdef WITH_XRENDER if (xfc->context.settings->SmartSizing || xfc->context.settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); xf_draw_screen(xfc, nXDst, nYDst, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); } } rc = CHANNEL_RC_OK; fail: region16_clear(&surface->gdi.invalidRegion); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, False); return rc; }
BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) { XF_MODIFIER_KEYS mod = { 0 }; xk_keyboard_get_modifier_keys(xfc, &mod); if (!xf_keyboard_execute_action_script(xfc, &mod, keysym)) { return TRUE; } if(xfc->fullscreen_toggle) { if (keysym == XK_Return) { if (mod.Ctrl && mod.Alt) { /* Ctrl-Alt-Enter: toggle full screen */ xf_toggle_fullscreen(xfc); return TRUE; } } } if ((keysym == XK_c) || (keysym == XK_C)) { if (mod.Ctrl && mod.Alt) { /* Ctrl-Alt-C: toggle control */ xf_toggle_control(xfc); return TRUE; } } #if 0 /* set to 1 to enable multi touch gesture simulation via keyboard */ #ifdef WITH_XRENDER if (!xfc->remote_app && xfc->settings->MultiTouchGestures) { if (mod.Ctrl && mod.Alt) { int pdx = 0; int pdy = 0; int zdx = 0; int zdy = 0; switch(keysym) { case XK_0: /* Ctrl-Alt-0: Reset scaling and panning */ xfc->scaledWidth = xfc->sessionWidth; xfc->scaledHeight = xfc->sessionHeight; xfc->offset_x = 0; xfc->offset_y = 0; if (!xfc->fullscreen && (xfc->sessionWidth != xfc->window->width || xfc->sessionHeight != xfc->window->height)) { xf_ResizeDesktopWindow(xfc, xfc->window, xfc->sessionWidth, xfc->sessionHeight); } xf_draw_screen(xfc, 0, 0, xfc->sessionWidth, xfc->sessionHeight); return TRUE; case XK_1: /* Ctrl-Alt-1: Zoom in */ zdx = zdy = 10; break; case XK_2: /* Ctrl-Alt-2: Zoom out */ zdx = zdy = -10; break; case XK_3: /* Ctrl-Alt-3: Pan left */ pdx = -10; break; case XK_4: /* Ctrl-Alt-4: Pan right */ pdx = 10; break; case XK_5: /* Ctrl-Alt-5: Pan up */ pdy = -10; break; case XK_6: /* Ctrl-Alt-6: Pan up */ pdy = 10; break; } if (pdx != 0 || pdy != 0) { PanningChangeEventArgs e; EventArgsInit(&e, "xfreerdp"); e.dx = pdx; e.dy = pdy; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); return TRUE; } if (zdx != 0 || zdy != 0) { ZoomingChangeEventArgs e; EventArgsInit(&e, "xfreerdp"); e.dx = zdx; e.dy = zdy; PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); return TRUE; } } } #endif /* WITH_XRENDER defined */ #endif /* pinch/zoom/pan simulation */ return FALSE; }