boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpWindow* window; window = window_list_get_by_extra_id(xfi->rail->list, (void*) event->xconfigure.window); if (window != NULL) { xfWindow* xfw; xfw = (xfWindow*) window->extra; DEBUG_X11_LMS("ConfigureNotify: send_event=%d eventWindow=0x%X window=0x%X above=0x%X rc={l=%d t=%d r=%d b=%d} " "w=%d h=%d override_redirect=%d", event->xconfigure.send_event, (uint32)event->xconfigure.event, (uint32)event->xconfigure.window, (uint32)event->xconfigure.above, event->xconfigure.x, event->xconfigure.y, event->xconfigure.x + event->xconfigure.width - 1, event->xconfigure.y + event->xconfigure.height - 1, event->xconfigure.width, event->xconfigure.height, event->xconfigure.override_redirect); if (xfw->isLocalMoveSizeModeEnabled && event->xconfigure.above != 0) { uint32 left = event->xconfigure.x; uint32 top = event->xconfigure.y; uint32 right = event->xconfigure.x + event->xconfigure.width; uint32 bottom = event->xconfigure.y + event->xconfigure.height; DEBUG_X11_LMS("MoveSendToServer: windowId=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d \n", (uint32)xfw->handle, left, top, right, bottom, event->xconfigure.width, event->xconfigure.height); xf_rail_send_windowmove(xfi, window->windowId, left, top, right, bottom); } XPutImage(xfi->display, xfi->primary, xfw->gc, xfi->image, xfw->left, xfw->top, xfw->left, xfw->top, xfw->width, xfw->height); XCopyArea(xfi->display, xfi->primary, xfw->handle, xfw->gc, xfw->left, xfw->top, xfw->width, xfw->height, 0, 0); XFlush(xfi->display); } return True; }
void xf_process_rail_server_localmovesize_event(xfInfo* xfi, rdpChanMan* chanman, RDP_EVENT* event) { RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->user_data; rdpWindow* rail_window = NULL; rail_window = window_list_get_by_id(xfi->rail->list, movesize->windowId); if (rail_window != NULL) { xfWindow * window = NULL; window = (xfWindow *) rail_window->extra; DEBUG_X11_LMS("windowId=0x%X isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d", movesize->windowId, movesize->isMoveSizeStart, movetype_names[movesize->moveSizeType], (sint16)movesize->posX, (sint16)movesize->posY); #if 1 if (movesize->isMoveSizeStart) xf_StartLocalMoveSize(xfi, window, movesize->moveSizeType, (int) movesize->posX, (int) movesize->posY); else xf_StopLocalMoveSize(xfi, window, movesize->moveSizeType, (int) movesize->posX, (int) movesize->posY); #endif } }
void xf_process_rail_server_minmaxinfo_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { rdpRail* rail; rdpWindow* rail_window = NULL; RAIL_MINMAXINFO_ORDER* minmax = (RAIL_MINMAXINFO_ORDER*) event->user_data; rail = ((rdpContext*) xfi->context)->rail; rail_window = window_list_get_by_id(rail->list, minmax->windowId); if (rail_window != NULL) { xfWindow * window = NULL; window = (xfWindow *) rail_window->extra; DEBUG_X11_LMS("windowId=0x%X maxWidth=%d maxHeight=%d maxPosX=%d maxPosY=%d " "minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d", minmax->windowId, minmax->maxWidth, minmax->maxHeight, (sint16)minmax->maxPosX, (sint16)minmax->maxPosY, minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); xf_SetWindowMinMaxInfo(xfi, window, minmax->maxWidth, minmax->maxHeight, minmax->maxPosX, minmax->maxPosY, minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); } }
/** * The position of the X window can become out of sync with the RDP window * if the X window is moved locally by the window manager. In this event * 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) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; xfw = (xfWindow*) window->extra; channels = ((rdpContext*) xfc)->channels; if (! xfw->is_mapped || xfw->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) { /* * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 * when attempting to adjust the rail window. */ UINT32 offsetX = 0; UINT32 offsetY = 0; if (window->windowOffsetX < 0) offsetX = offsetX - window->windowOffsetX; if (window->windowOffsetY < 0) offsetY = offsetY - window->windowOffsetY; /* * windowOffset corresponds to the window location on the rail server * but our local window is based on the visibleOffset since using the windowOffset * can result in blank areas for a maximized window */ window_move.windowId = window->windowId; /* * Calculate new offsets for the rail server window * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) */ window_move.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX); window_move.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY); window_move.right = window_move.left + xfw->width; window_move.bottom = window_move.top + xfw->height; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u" " RDP=0x%X rc={l=%d t=%d} w=%d h=%d", (UINT32) xfw->handle, window_move.left, window_move.top, window_move.right, window_move.bottom, xfw->width, xfw->height, window->windowId, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); xf_send_rail_client_event(channels, RailChannel_ClientWindowMove, &window_move); } }
void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; int x,y; rdpInput* input = xfi->instance->input; xfw = (xfWindow*) window->extra; channels = xfi->_context->channels; // Send RDP client event to inform RDP server window_move.windowId = window->windowId; window_move.left = xfw->left; window_move.top = xfw->top; window_move.right = xfw->right + 1; // In the update to RDP the position is one past the window window_move.bottom = xfw->bottom + 1; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height); xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move); // Send synthetic button up event to the RDP server. This is per the RDP spec to // indicate a local move has finished. x = xfw->left + xfw->local_move.window_x; y = xfw->top + xfw->local_move.window_y; input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); // Proactively update the RAIL window dimensions. There is a race condition where // we can start to receive GDI orders for the new window dimensions before we // receive the RAIL ORDER for the new window size. This avoids that race condition. window->windowOffsetX = xfw->left; window->windowOffsetY = xfw->top; window->windowWidth = xfw->width; window->windowHeight = xfw->height; xfw->local_move.state = LMS_TERMINATING; }
boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window); if (window != NULL) { xfWindow* xfw; Window childWindow; xfw = (xfWindow*) window->extra; /* * ConfigureNotify coordinates are expressed relative to the window parent. * Translate these to root window coordinates. */ XTranslateCoordinates(xfi->display, xfw->handle, RootWindowOfScreen(xfi->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; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u send_event=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height, event->xconfigure.send_event); if (app && ! event->xconfigure.send_event) xf_rail_adjust_position(xfi, window); } return True; }
/** * The position of the X window can become out of sync with the RDP window * if the X window is moved locally by the window manager. In this event * send an update to the RDP server informing it of the new window position * and size. */ void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; xfw = (xfWindow*) window->extra; channels = xfi->_context->channels; if (! xfw->is_mapped || xfw->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->windowOffsetX || xfw->top != window->windowOffsetY || xfw->width != window->windowWidth || xfw->height != window->windowHeight) { window_move.windowId = window->windowId; window_move.left = xfw->left; window_move.top = xfw->top; window_move.right = xfw->right; window_move.bottom = xfw->bottom; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u" " RDP=0x%X rc={l=%d t=%d} w=%d h=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height, window->windowId, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move); } }
static BOOL xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*event) { if (!xfi->remote_app) return FALSE; switch (xfi->window->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) && xfi->window->rail_ignore_configure) { DEBUG_X11_LMS("ConfigureNotify Event Ignored"); xfi->window->rail_ignore_configure = FALSE; return TRUE; } break; case LMS_STARTING: /* Local move initiated by RDP server, but we have not yet seen any updates from the X server */ switch(event->type) { case ConfigureNotify: /* Starting to see move events from the X server. Local move is now in progress. */ xfi->window->local_move.state = LMS_ACTIVE; /* Allow these events to be processed during move to keep our state up to date. */ break; case ButtonPress: case ButtonRelease: case KeyPress: case KeyRelease: case UnmapNotify: /* * A button release event means the X window server did not grab the * mouse before the user released it. In this case we must cancel the * local move. The event will be processed below as normal, below. */ break; case VisibilityNotify: case PropertyNotify: case Expose: /* Allow these events to pass */ break; default: /* Eat any other events */ return TRUE; } break; case LMS_ACTIVE: /* Local move is in progress */ switch(event->type) { case ConfigureNotify: case VisibilityNotify: case PropertyNotify: case Expose: case GravityNotify: /* Keep us up to date on position */ break; default: DEBUG_X11_LMS("Event Type to break LMS: %s", X11_EVENT_STRINGS[event->type]); /* Any other event terminates move */ xf_rail_end_local_move(xfi, window); break; } break; case LMS_TERMINATING: /* Already sent RDP end move to server. Allow events to pass. */ break; } return FALSE; }
static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app) { /* * This section handles sending the appropriate commands to the rail server * when the window has been minimized, maximized, restored locally * ie. not using the buttons on the rail window itself */ if (app) { rdpWindow* window; window = xf_rdpWindowFromWindow(xfi, event->xproperty.window); if (window == NULL) return TRUE; if ((((Atom) event->xproperty.atom == xfi->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) || (((Atom) event->xproperty.atom == xfi->WM_STATE) && (event->xproperty.state != PropertyDelete))) { int i; BOOL status; BOOL maxVert = FALSE; BOOL maxHorz = FALSE; BOOL minimized = FALSE; unsigned long nitems; unsigned long bytes; unsigned char* prop; if ((Atom) event->xproperty.atom == xfi->_NET_WM_STATE) { status = xf_GetWindowProperty(xfi, event->xproperty.window, xfi->_NET_WM_STATE, 12, &nitems, &bytes, &prop); if (!status) { DEBUG_X11_LMS("No return _NET_WM_STATE, window is not maximized"); } for (i = 0; i < nitems; i++) { if ((Atom) ((UINT16**) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False)) { maxVert = TRUE; } if ((Atom) ((UINT16**) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False)) { maxHorz = TRUE; } } XFree(prop); } if ((Atom) event->xproperty.atom == xfi->WM_STATE) { status = xf_GetWindowProperty(xfi, event->xproperty.window, xfi->WM_STATE, 1, &nitems, &bytes, &prop); if (!status) { DEBUG_X11_LMS("No return WM_STATE, window is not minimized"); } else { /* If the window is in the iconic state */ if (((UINT32) *prop == 3)) minimized = TRUE; else minimized = FALSE; XFree(prop); } } if (maxVert && maxHorz && !minimized && (xfi->window->rail_state != WINDOW_SHOW_MAXIMIZED)) { DEBUG_X11_LMS("Send SC_MAXIMIZE command to rail server."); xfi->window->rail_state = WINDOW_SHOW_MAXIMIZED; xf_rail_send_client_system_command(xfi, window->windowId, SC_MAXIMIZE); } else if (minimized && (xfi->window->rail_state != WINDOW_SHOW_MINIMIZED)) { DEBUG_X11_LMS("Send SC_MINIMIZE command to rail server."); xfi->window->rail_state = WINDOW_SHOW_MINIMIZED; xf_rail_send_client_system_command(xfi, window->windowId, SC_MINIMIZE); } else if (!minimized && !maxVert && !maxHorz && (xfi->window->rail_state != WINDOW_SHOW)) { DEBUG_X11_LMS("Send SC_RESTORE command to rail server"); xfi->window->rail_state = WINDOW_SHOW; xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE); } } } else { if (xf_cliprdr_process_property_notify(xfi, event)) return TRUE; } return TRUE; }
static BOOL xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, BOOL app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; if (xfi->width != event->xconfigure.width) { xfi->scale = (double) event->xconfigure.width / (double) xfi->originalWidth; xfi->currentWidth = event->xconfigure.width; xfi->currentHeight = event->xconfigure.width; xf_draw_screen_scaled(xfi); } window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window); if (window != NULL) { xfWindow* xfw; Window childWindow; xfw = (xfWindow*) window->extra; /* * ConfigureNotify coordinates are expressed relative to the window parent. * Translate these to root window coordinates. */ XTranslateCoordinates(xfi->display, xfw->handle, RootWindowOfScreen(xfi->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; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u send_event=%d", (UINT32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height, event->xconfigure.send_event); /* * Additonal checks for not in a local move and not ignoring configure to send * position update to server, also should the window not be focused then do not * send to server yet(ie. resizing using window decoration). * The server will be updated when the window gets refocused. */ if (app && xfw->decorations) { /* moving resizing using window decoration */ xf_rail_adjust_position(xfi, window); window->windowOffsetX = xfw->left; window->visibleOffsetX = window->windowOffsetX; window->windowOffsetY = xfw->top; window->visibleOffsetY = window->windowOffsetY; window->windowWidth = xfw->width; window->windowHeight = xfw->height; } else { if (app && (!event->xconfigure.send_event || xfi->window->local_move.state == LMS_NOT_ACTIVE) && !xfw->rail_ignore_configure && xfi->focused) xf_rail_adjust_position(xfi, window); } } return True; }
void xf_process_rail_server_localmovesize_event(xfContext* xfc, rdpChannels* channels, wMessage* event) { int x = 0, y = 0; rdpRail* rail; int direction = 0; Window child_window; rdpWindow* rail_window = NULL; RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->wParam; rail = ((rdpContext*) xfc)->rail; rail_window = window_list_get_by_id(rail->list, movesize->windowId); if (rail_window != NULL) { xfWindow* xfw = NULL; xfw = (xfWindow*) rail_window->extra; DEBUG_X11_LMS("windowId=0x%X isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d", movesize->windowId, movesize->isMoveSizeStart, movetype_names[movesize->moveSizeType], (INT16) movesize->posX, (INT16) movesize->posY); switch (movesize->moveSizeType) { case RAIL_WMSZ_LEFT: //0x1 direction = _NET_WM_MOVERESIZE_SIZE_LEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_RIGHT: //0x2 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOP: //0x3 direction = _NET_WM_MOVERESIZE_SIZE_TOP; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOPLEFT: //0x4 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOPRIGHT: //0x5 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOM: //0x6 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOMLEFT: //0x7 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOMRIGHT: //0x8 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_MOVE: //0x9 direction = _NET_WM_MOVERESIZE_MOVE; XTranslateCoordinates(xfc->display, xfw->handle, RootWindowOfScreen(xfc->screen), movesize->posX, movesize->posY, &x, &y, &child_window); break; case RAIL_WMSZ_KEYMOVE: //0xA direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD; x = movesize->posX; y = movesize->posY; /* FIXME: local keyboard moves not working */ return; case RAIL_WMSZ_KEYSIZE: //0xB direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD; x = movesize->posX; y = movesize->posY; /* FIXME: local keyboard moves not working */ return; } if (movesize->isMoveSizeStart) { xf_StartLocalMoveSize(xfc, xfw, direction, x, y); } else { xf_EndLocalMoveSize(xfc, xfw); } } }
void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; rdpInput* input = xfc->instance->input; int x,y; Window root_window; Window child_window; unsigned int mask; int child_x; int child_y; xfw = (xfWindow*) window->extra; channels = ((rdpContext*) xfc)->channels; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d", (UINT32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height); /* * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when * attempting to adjust the rail window. */ UINT32 offsetX = 0; UINT32 offsetY = 0; if (window->windowOffsetX < 0) offsetX = offsetX - window->windowOffsetX; if (window->windowOffsetY < 0) offsetY = offsetY - window->windowOffsetY; /* * For keyboard moves send and explicit update to RDP server */ window_move.windowId = window->windowId; /* * Calculate new offsets for the rail server window * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) */ window_move.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX); window_move.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY); window_move.right = window_move.left + xfw->width; /* In the update to RDP the position is one past the window */ window_move.bottom = window_move.top + xfw->height; xf_send_rail_client_event(channels, RailChannel_ClientWindowMove, &window_move); /* * 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); input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); /* only send the mouse coordinates if not a keyboard move or size */ if ((xfw->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) && (xfw->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD)) { input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); DEBUG_X11_LMS("Mouse coordinates. x= %i, y= %i", x, y); } /* * Proactively update the RAIL window dimensions. There is a race condition where * we can start to receive GDI orders for the new window dimensions before we * receive the RAIL ORDER for the new window size. This avoids that race condition. */ window->windowOffsetX = 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; }