📄 events.c
字号:
/************************************************************Copyright (c) 1987 X ConsortiumPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER INAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR INCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.Except as contained in this notice, the name of the X Consortium shall not beused in advertising or otherwise to promote the sale, use or other dealingsin this Software without prior written authorization from the X Consortium.Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights ReservedPermission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and thatboth that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not beused in advertising or publicity pertaining to distribution of thesoftware without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDINGALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALLDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ORANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THISSOFTWARE.********************************************************//* $XConsortium: events.c /main/187 1996/09/25 00:47:41 dpw $ *//* $XFree86: xc/programs/Xserver/dix/events.c,v 3.11 1996/12/24 02:23:45 dawes Exp $ */#include "X.h"#include "misc.h"#include "resource.h"#define NEED_EVENTS#define NEED_REPLIES#include "Xproto.h"#include "windowstr.h"#include "inputstr.h"#include "scrnintstr.h"#include "cursorstr.h"#include "dixstruct.h"#ifdef XKB#include "XKBsrv.h"#endif#ifdef XCSECURITY#define _SECURITY_SERVER#include "extensions/security.h"#endif#include "XIproto.h"#include "exevents.h"#include "extnsionst.h"#include "dixevents.h"#include "dixgrabs.h"#include "dispatch.h"extern WindowPtr *WindowTable;#define EXTENSION_EVENT_BASE 64#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )#define AllButtonsMask ( \ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )#define MotionMask ( \ PointerMotionMask | Button1MotionMask | \ Button2MotionMask | Button3MotionMask | Button4MotionMask | \ Button5MotionMask | ButtonMotionMask )#define PropagateMask ( \ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ MotionMask )#define PointerGrabMask ( \ ButtonPressMask | ButtonReleaseMask | \ EnterWindowMask | LeaveWindowMask | \ PointerMotionHintMask | KeymapStateMask | \ MotionMask )#define AllModifiersMask ( \ ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ Mod3Mask | Mod4Mask | Mod5Mask )#define AllEventMasks (lastEventMask|(lastEventMask-1))/* * The following relies on the fact that the Button<n>MotionMasks are equal * to the corresponding Button<n>Masks from the current modifier/button state. */#define Motion_Filter(class) (PointerMotionMask | \ (class)->state | (class)->motionMask)#define WID(w) ((w) ? ((w)->drawable.id) : 0)#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])CallbackListPtr EventCallback;CallbackListPtr DeviceEventCallback;#define DNPMCOUNT 8Mask DontPropagateMasks[DNPMCOUNT];static int DontPropagateRefCnts[DNPMCOUNT];#ifdef DEBUGstatic debug_events = 0;#endifInputInfo inputInfo;static struct { QdEventPtr pending, *pendtail; DeviceIntPtr replayDev; /* kludgy rock to put flag for */ WindowPtr replayWin; /* ComputeFreezes */ Bool playingEvents; TimeStamp time;} syncEvents;/* * The window trace information is used to avoid having to compute all the * windows between the root and the current pointer window each time a button * or key goes down. The grabs on each of those windows must be checked. */static WindowPtr *spriteTrace = (WindowPtr *)NULL;#define ROOT spriteTrace[0]static int spriteTraceSize = 0;static int spriteTraceGood;typedef struct { int x, y; ScreenPtr pScreen;} HotSpot;static struct { CursorPtr current; BoxRec hotLimits; /* logical constraints of hot spot */ Bool confined; /* confined to screen */#ifdef SHAPE RegionPtr hotShape; /* additional logical shape constraint */#endif BoxRec physLimits; /* physical constraints of hot spot */ WindowPtr win; /* window of logical position */ HotSpot hot; /* logical pointer position */ HotSpot hotPhys; /* physical pointer position */} sprite; /* info about the cursor sprite */static void DoEnterLeaveEvents(#if NeedFunctionPrototypes WindowPtr /*fromWin*/, WindowPtr /*toWin*/, int /*mode*/#endif);static WindowPtr XYToWindow(#if NeedFunctionPrototypes int /*x*/, int /*y*/#endif);extern Bool permitOldBugs;extern Bool Must_have_memory;extern int lastEvent;#ifdef XINPUTextern int DeviceMotionNotify, DeviceButtonPress, DeviceKeyPress;#endifstatic Mask lastEventMask;#define CantBeFiltered NoEventMaskstatic Mask filters[128] ={ NoSuchEvent, /* 0 */ NoSuchEvent, /* 1 */ KeyPressMask, /* KeyPress */ KeyReleaseMask, /* KeyRelease */ ButtonPressMask, /* ButtonPress */ ButtonReleaseMask, /* ButtonRelease */ PointerMotionMask, /* MotionNotify (initial state) */ EnterWindowMask, /* EnterNotify */ LeaveWindowMask, /* LeaveNotify */ FocusChangeMask, /* FocusIn */ FocusChangeMask, /* FocusOut */ KeymapStateMask, /* KeymapNotify */ ExposureMask, /* Expose */ CantBeFiltered, /* GraphicsExpose */ CantBeFiltered, /* NoExpose */ VisibilityChangeMask, /* VisibilityNotify */ SubstructureNotifyMask, /* CreateNotify */ StructureAndSubMask, /* DestroyNotify */ StructureAndSubMask, /* UnmapNotify */ StructureAndSubMask, /* MapNotify */ SubstructureRedirectMask, /* MapRequest */ StructureAndSubMask, /* ReparentNotify */ StructureAndSubMask, /* ConfigureNotify */ SubstructureRedirectMask, /* ConfigureRequest */ StructureAndSubMask, /* GravityNotify */ ResizeRedirectMask, /* ResizeRequest */ StructureAndSubMask, /* CirculateNotify */ SubstructureRedirectMask, /* CirculateRequest */ PropertyChangeMask, /* PropertyNotify */ CantBeFiltered, /* SelectionClear */ CantBeFiltered, /* SelectionRequest */ CantBeFiltered, /* SelectionNotify */ ColormapChangeMask, /* ColormapNotify */ CantBeFiltered, /* ClientMessage */ CantBeFiltered /* MappingNotify */};static CARD8 criticalEvents[32] ={ 0x3c /* key and button events */};MaskGetNextEventMask(){ lastEventMask <<= 1; return lastEventMask;}voidSetMaskForEvent(mask, event) Mask mask; int event;{ if ((event < LASTEvent) || (event >= 128)) FatalError("SetMaskForEvent: bogus event number"); filters[event] = mask;}voidSetCriticalEvent(event) int event;{ if (event >= 128) FatalError("SetCriticalEvent: bogus event number"); criticalEvents[event >> 3] |= 1 << (event & 7);}static void#if NeedFunctionPrototypesSyntheticMotion(int x, int y)#elseSyntheticMotion(x, y) int x, y;#endif{ xEvent xE; xE.u.keyButtonPointer.rootX = x; xE.u.keyButtonPointer.rootY = y; if (syncEvents.playingEvents) xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; else xE.u.keyButtonPointer.time = currentTime.milliseconds; xE.u.u.type = MotionNotify; (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);}#ifdef SHAPEstatic void#if NeedFunctionPrototypesConfineToShape(RegionPtr shape, int *px, int *py)#elseConfineToShape(shape, px, py) RegionPtr shape; int *px, *py;#endif{ BoxRec box; int x = *px, y = *py; int incx = 1, incy = 1; if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) return; box = *REGION_EXTENTS(sprite.hot.pScreen, shape); /* this is rather crude */ do { x += incx; if (x >= box.x2) { incx = -1; x = *px - 1; } else if (x < box.x1) { incx = 1; x = *px; y += incy; if (y >= box.y2) { incy = -1; y = *py - 1; } else if (y < box.y1) return; /* should never get here! */ } } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); *px = x; *py = y;}#endifstatic void#if NeedFunctionPrototypesCheckPhysLimits( CursorPtr cursor, Bool generateEvents, Bool confineToScreen, ScreenPtr pScreen)#elseCheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen) CursorPtr cursor; Bool generateEvents; Bool confineToScreen; ScreenPtr pScreen;#endif{ HotSpot new; if (!cursor) return; new = sprite.hotPhys; if (pScreen) new.pScreen = pScreen; else pScreen = new.pScreen; (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, &sprite.physLimits); sprite.confined = confineToScreen; (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); if (new.x < sprite.physLimits.x1) new.x = sprite.physLimits.x1; else if (new.x >= sprite.physLimits.x2) new.x = sprite.physLimits.x2 - 1; if (new.y < sprite.physLimits.y1) new.y = sprite.physLimits.y1; else if (new.y >= sprite.physLimits.y2) new.y = sprite.physLimits.y2 - 1;#ifdef SHAPE if (sprite.hotShape) ConfineToShape(sprite.hotShape, &new.x, &new.y);#endif if ((pScreen != sprite.hotPhys.pScreen) || (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) { if (pScreen != sprite.hotPhys.pScreen) sprite.hotPhys = new; (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); if (!generateEvents) SyntheticMotion(new.x, new.y); }}static void#if NeedFunctionPrototypesCheckVirtualMotion( register QdEventPtr qe, register WindowPtr pWin)#elseCheckVirtualMotion(qe, pWin) register QdEventPtr qe; register WindowPtr pWin;#endif{ if (qe) { sprite.hot.pScreen = qe->pScreen; sprite.hot.x = qe->event->u.keyButtonPointer.rootX; sprite.hot.y = qe->event->u.keyButtonPointer.rootY; pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : NullWindow; } if (pWin) { BoxRec lims; if (sprite.hot.pScreen != pWin->drawable.pScreen) { sprite.hot.pScreen = pWin->drawable.pScreen; sprite.hot.x = sprite.hot.y = 0; } lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); if (sprite.hot.x < lims.x1) sprite.hot.x = lims.x1; else if (sprite.hot.x >= lims.x2) sprite.hot.x = lims.x2 - 1; if (sprite.hot.y < lims.y1) sprite.hot.y = lims.y1; else if (sprite.hot.y >= lims.y2) sprite.hot.y = lims.y2 - 1;#ifdef SHAPE if (wBoundingShape(pWin)) ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);#endif if (qe) { qe->pScreen = sprite.hot.pScreen; qe->event->u.keyButtonPointer.rootX = sprite.hot.x; qe->event->u.keyButtonPointer.rootY = sprite.hot.y; } } ROOT = WindowTable[sprite.hot.pScreen->myNum];}voidConfineCursorToWindow(pWin, generateEvents, confineToScreen) WindowPtr pWin; Bool generateEvents; Bool confineToScreen;{ ScreenPtr pScreen = pWin->drawable.pScreen; if (syncEvents.playingEvents) { CheckVirtualMotion((QdEventPtr)NULL, pWin); SyntheticMotion(sprite.hot.x, sprite.hot.y); } else { sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);#ifdef SHAPE sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize : NullRegion;#endif CheckPhysLimits(sprite.current, generateEvents, confineToScreen, pScreen); }}BoolPointerConfinedToScreen(){ return sprite.confined;}static void#if NeedFunctionPrototypesChangeToCursor(CursorPtr cursor)#elseChangeToCursor(cursor) CursorPtr cursor;#endif{ if (cursor != sprite.current) { if ((sprite.current->bits->xhot != cursor->bits->xhot) || (sprite.current->bits->yhot != cursor->bits->yhot)) CheckPhysLimits(cursor, FALSE, PointerConfinedToScreen(), (ScreenPtr)NULL); (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, cursor); sprite.current = cursor; }}/* returns true if b is a descendent of a */BoolIsParent(a, b) register WindowPtr a, b;{ for (b = b->parent; b; b = b->parent) if (b == a) return TRUE; return FALSE;}static void#if NeedFunctionPrototypesPostNewCursor(void)#elsePostNewCursor()#endif{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -