--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original 2015-02-13 14:03:44.744441510 +0100 +++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c 2015-02-10 19:13:13.788686485 +0100 @@ -1,3 +1,20 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + /* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */ /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */ /************************************************************ @@ -116,6 +133,7 @@ #endif #include +#include "Xlib.h" #include "misc.h" #include "resource.h" #define NEED_EVENTS @@ -163,7 +181,22 @@ #include "dixevents.h" #include "dixgrabs.h" -#include "dispatch.h" +#include "../../dix/dispatch.h" + +#include "NXlib.h" + +#include "Events.h" +#include "Windows.h" +#include "Args.h" + +#ifdef NX_DEBUG_INPUT +extern int nxagentDebugInput; +extern int nxagentDebugInputDevices; +#endif + +extern Display *nxagentDisplay; + +extern WindowPtr nxagentLastEnteredWindow; #define EXTENSION_EVENT_BASE 64 @@ -1322,6 +1355,51 @@ mouse->fromPassiveGrab = autoGrab; PostNewCursor(); CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + + #ifdef NXAGENT_SERVER + + /* + * If grab is synchronous, events are delivered to clients only if they send + * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the + * delivered event is saved in a queue and replayed later, when grab is released. + * We should export sync grab to X as async in order to avoid events to be + * queued twice, in the agent and in the X server. This solution have a drawback: + * replayed events are not delivered to that application that are not clients of + * the agent. + * A different solution could be to make the grab asynchronous in the agent and + * to export it as synchronous. But this seems to be less safe. + * + * To make internal grab asynchronous, change previous line as follows. + * + * if (nxagentOption(Rootless)) + * { + * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode); + * } + * else + * { + * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + * } + */ + + if (nxagentOption(Rootless) == 1) + { + /* + * FIXME: We should use the correct value + * for the cursor. Temporarily we set it + * to None. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window), + 1, grab -> eventMask & PointerGrabMask, + GrabModeAsync, GrabModeAsync, (grab -> confineTo) ? + nxagentWindow(grab -> confineTo) : None, + None, CurrentTime); + } + + #endif } void @@ -1346,6 +1424,22 @@ if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); ComputeFreezes(); + + #ifdef NXAGENT_SERVER + + if (nxagentOption(Rootless) == 1) + { + XUngrabPointer(nxagentDisplay, CurrentTime); + + if (sprite.win == ROOT) + { + mouse -> button -> state &= + ~(Button1Mask | Button2Mask | Button3Mask | + Button4Mask | Button5Mask); + } + } + + #endif } void @@ -1546,6 +1640,17 @@ client->errorValue = stuff->mode; return BadValue; } + + /* + * This is not necessary if we export grab to X as asynchronous. + * + * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard && + * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard) + * { + * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime); + * } + */ + return Success; } @@ -1582,11 +1687,28 @@ int i; int type; -#ifdef DEBUG +#ifdef NX_DEBUG_INPUT + if (grab && nxagentDebugInput && grab->window) + { + fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n", + (unsigned int)grab->window->drawable.id); + if (!SameClient(grab, client)) + fprintf(stderr, "TryClientEvents: Events are going to be " + "discarded.\n"); + } +#endif +#if defined(DEBUG) || defined(NX_DEBUG_INPUT) +#ifdef NX_DEBUG_INPUT + if (nxagentDebugInput == 1) + fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask, + client->index); +#else if (debug_events) ErrorF( "Event([%d, %d], mask=0x%x), client=%d", pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); #endif +#endif if ((client) && (client != serverClient) && (!client->clientGone) && ((filter == CantBeFiltered) || (mask & filter))) { @@ -1600,10 +1722,17 @@ if (WID(inputInfo.pointer->valuator->motionHintWindow) == pEvents->u.keyButtonPointer.event) { -#ifdef DEBUG +#if defined(DEBUG) || defined(NX_DEBUG_INPUT) +#ifdef NX_DEBUG_INPUT + if (nxagentDebugInput == 1) + { + fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n"); + } +#else if (debug_events) ErrorF("\n"); fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); #endif +#endif return 1; /* don't send, but pretend we did */ } pEvents->u.u.detail = NotifyHint; @@ -1640,16 +1769,26 @@ } WriteEventsToClient(client, count, pEvents); -#ifdef DEBUG +#if defined(DEBUG) || defined(NX_DEBUG_INPUT) +#ifdef NX_DEBUG_INPUT + if (nxagentDebugInput == 1) + fprintf(stderr, " delivered\n"); +#else if (debug_events) ErrorF( " delivered\n"); #endif +#endif return 1; } else { -#ifdef DEBUG +#if defined(DEBUG) || defined(NX_DEBUG_INPUT) +#ifdef NX_DEBUG_INPUT + if (nxagentDebugInput == 1) + fprintf(stderr, "\n"); +#else if (debug_events) ErrorF("\n"); #endif +#endif return 0; } } @@ -1727,6 +1866,12 @@ tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "DeliverEventsToWindow: Activating passive grab on pointer.\n"); + } + #endif (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, currentTime, TRUE); } @@ -1999,7 +2144,26 @@ BoxRec box; spriteTraceGood = 1; /* root window still there */ - pWin = ROOT->firstChild; + + if (nxagentOption(Rootless)) + { + if (nxagentLastEnteredWindow == NULL) + { + return ROOT; + } + + pWin = ROOT->lastChild; + + while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow) + { + pWin = pWin->prevSib; + } + } + else + { + pWin = ROOT->firstChild; + } + while (pWin) { if ((pWin->mapped) && @@ -2090,13 +2254,22 @@ ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); #endif sprite.hotPhys = sprite.hot; - if ((sprite.hotPhys.x != XE_KBPTR.rootX) || - (sprite.hotPhys.y != XE_KBPTR.rootY)) - { - (*sprite.hotPhys.pScreen->SetCursorPosition)( - sprite.hotPhys.pScreen, - sprite.hotPhys.x, sprite.hotPhys.y, FALSE); - } + + /* + * This code force cursor position to be inside the + * root window of the agent. We can't view a reason + * to do this and it interacts in an undesirable way + * with toggling fullscreen. + * + * if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + * (sprite.hotPhys.y != XE_KBPTR.rootY)) + * { + * (*sprite.hotPhys.pScreen->SetCursorPosition)( + * sprite.hotPhys.pScreen, + * sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + * } + */ + XE_KBPTR.rootX = sprite.hot.x; XE_KBPTR.rootY = sprite.hot.y; } @@ -2176,6 +2349,10 @@ DefineInitialRootWindow(register WindowPtr win) { register ScreenPtr pScreen = win->drawable.pScreen; + #ifdef VIEWPORT_FRAME + extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr); + #endif + extern int nxagentShadowInit(ScreenPtr, WindowPtr); sprite.hotPhys.pScreen = pScreen; sprite.hotPhys.x = pScreen->width / 2; @@ -2215,6 +2392,18 @@ REGION_NULL(pScreen, &sprite.Reg2); } #endif + + #ifdef VIEWPORT_FRAME + nxagentInitViewportFrame(pScreen, win); + #endif + + if (nxagentOption(Shadow)) + { + if (nxagentShadowInit(pScreen, win) == -1) + { + FatalError("Failed to connect to display '%s'", nxagentShadowDisplayName); + } + } } /* @@ -2553,6 +2742,13 @@ tempGrab.modifiersDetail.exact&(~0x1f00); } #endif + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "CheckPassiveGrabsOnWindow: Activating passive grab on %s.\n", + device == inputInfo.keyboard ? "keyboard" : "pointer"); + } + #endif (*device->ActivateGrab)(device, grab, currentTime, TRUE); FixUpEventFromWindow(xE, grab->window, None, TRUE); @@ -2911,7 +3107,17 @@ else DeliverFocusedEvent(keybd, xE, sprite.win, count); if (deactivateGrab) + #ifdef NX_DEBUG_INPUT + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcessKeyboardEvent: Deactivating grab on keyboard.\n"); + } + #endif (*keybd->DeactivateGrab)(keybd); + #ifdef NX_DEBUG_INPUT + } + #endif } #ifdef XKB @@ -2961,7 +3167,9 @@ Bool deactivateGrab = FALSE; register ButtonClassPtr butc = mouse->button; #ifdef XKB - XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; + XkbSrvInfoPtr xkbi; + + xkbi = inputInfo.keyboard->key->xkbInfo; #endif #ifdef XEVIE if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && @@ -2970,6 +3178,12 @@ xevieEventSent = 0; else { xeviemouse = mouse; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: Going to send XEVIE event.\n"); + } + #endif WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); return; } @@ -3024,14 +3238,38 @@ #if !defined(XFree86Server) || !defined(XINPUT) xE->u.u.detail = butc->map[key]; #endif + #ifdef NX_DEBUG_INPUT + if (xE->u.u.detail == 0) + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0" + " for ButtonPress.\n"); + } + return; + } + #else if (xE->u.u.detail == 0) return; + #endif if (xE->u.u.detail <= 5) butc->state |= (Button1Mask >> 1) << xE->u.u.detail; filters[MotionNotify] = Motion_Filter(butc); if (!grab) + #ifdef NX_DEBUG_INPUT + if (CheckDeviceGrabs(mouse, xE, 0, count)) + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: CheckDeviceGrabs" + " returned True for ButtonPress.\n"); + } + return; + } + #else if (CheckDeviceGrabs(mouse, xE, 0, count)) return; + #endif break; case ButtonRelease: mouse->valuator->motionHintWindow = NullWindow; @@ -3043,8 +3281,20 @@ #if !defined(XFree86Server) || !defined(XINPUT) xE->u.u.detail = butc->map[key]; #endif + #ifdef NX_DEBUG_INPUT if (xE->u.u.detail == 0) + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0" + " for ButtonRelease.\n"); + } return; + } + #else + if (xE->u.u.detail == 0) + return; + #endif if (xE->u.u.detail <= 5) butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); filters[MotionNotify] = Motion_Filter(butc); @@ -3055,6 +3305,36 @@ FatalError("bogus pointer event from ddx"); } } + #ifdef NX_DEBUG_INPUT + else if (!CheckMotion(xE)) + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: CheckMotion returned False" + " for MotionNotify.\n"); + } + return; + } + if (grab) + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: Going to deliver grabbed " + "events (count = %d).\n", count); + } + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + } + else + { + if (nxagentDebugInput == 1) + { + fprintf(stderr, "ProcessPointerEvent: Going to deliver device " + "events (count = %d).\n", count); + } + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + } + #else else if (!CheckMotion(xE)) return; if (grab) @@ -3062,8 +3342,19 @@ else DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, mouse, count); + #endif if (deactivateGrab) + #ifdef NX_DEBUG_INPUT + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcessPointerEvent: Deactivating grab on pointer.\n"); + } + #endif (*mouse->DeactivateGrab)(mouse); + #ifdef NX_DEBUG_INPUT + } + #endif } #define AtMostOneClient \ @@ -3784,6 +4075,12 @@ pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); if (!pWin) return BadWindow; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcGrabPointer: pWin [%p] client [%d].\n", pWin, client -> index); + } + #endif if (stuff->confineTo == None) confineTo = NullWindow; else @@ -3843,6 +4140,12 @@ tempGrab.keyboardMode = stuff->keyboardMode; tempGrab.pointerMode = stuff->pointerMode; tempGrab.device = device; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcGrabPointer: Activating active grab on pointer.\n"); + } + #endif (*device->ActivateGrab)(device, &tempGrab, time, FALSE); if (oldCursor) FreeCursor (oldCursor, (Cursor)0); @@ -3906,6 +4209,12 @@ TimeStamp time; REQUEST(xResourceReq); + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabPointer: client [%d].\n", client -> index); + } + #endif REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); grab = device->grab; @@ -3913,7 +4222,25 @@ if ((CompareTimeStamps(time, currentTime) != LATER) && (CompareTimeStamps(time, device->grabTime) != EARLIER) && (grab) && SameClient(grab, client)) + #ifdef NX_DEBUG_INPUT + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabPointer: Deactivating grab on pointer.\n"); + } + #endif (*device->DeactivateGrab)(device); + #ifdef NX_DEBUG_INPUT + } + else + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabPointer: current time [%lu] request time [%lu] grab time [%lu].\n", + currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds); + } + } + #endif return Success; } @@ -3968,6 +4295,12 @@ tempGrab.pointerMode = other_mode; tempGrab.eventMask = mask; tempGrab.device = dev; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "GrabDevice: Activating active grab on keyboard.\n"); + } + #endif (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); *status = GrabSuccess; } @@ -3981,6 +4314,12 @@ REQUEST(xGrabKeyboardReq); int result; + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcGrabKeyboard: client [%d].\n", client -> index); + } + #endif REQUEST_SIZE_MATCH(xGrabKeyboardReq); #ifdef XCSECURITY if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) @@ -4011,6 +4350,12 @@ TimeStamp time; REQUEST(xResourceReq); + #ifdef NX_DEBUG_INPUT + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabKeyboard: client [%d].\n", client -> index); + } + #endif REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); grab = device->grab; @@ -4018,7 +4363,25 @@ if ((CompareTimeStamps(time, currentTime) != LATER) && (CompareTimeStamps(time, device->grabTime) != EARLIER) && (grab) && SameClient(grab, client)) + #ifdef NX_DEBUG_INPUT + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabKeyboard: Deactivating grab on keyboard.\n"); + } + #endif (*device->DeactivateGrab)(device); + #ifdef NX_DEBUG_INPUT + } + else + { + if (nxagentDebugInputDevices == 1) + { + fprintf(stderr, "ProcUngrabKeyboard: current time [%lu] request time [%lu] grab time [%lu].\n", + currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds); + } + } + #endif return Success; } @@ -4152,6 +4515,17 @@ /* The client's event type must be a core event type or one defined by an extension. */ + +#ifdef NXAGENT_CLIPBOARD + + if (stuff -> event.u.u.type == SelectionNotify) + { + extern int nxagentSendNotify(xEvent*); + if (nxagentSendNotify(&stuff->event) == 1) + return Success; + } +#endif + if ( ! ((stuff->event.u.u.type > X_Reply && stuff->event.u.u.type < LASTEvent) || (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&